瀏覽代碼

Merge pull request #6566 from BabylonJS/node-massive-rework

Node massive rework
David Catuhe 6 年之前
父節點
當前提交
e2a645fca1
共有 67 個文件被更改,包括 5326 次插入5129 次删除
  1. 390 348
      Playground/babylon.d.txt
  2. 1 0
      Tools/Config/config.json
  3. 15 15
      Tools/Gulp/helpers/gulp-validateImports.js
  4. 1 0
      Tools/Publisher/tasks/processEs6Packages.js
  5. 404 357
      dist/preview release/babylon.d.ts
  6. 842 731
      dist/preview release/babylon.module.d.ts
  7. 404 357
      dist/preview release/documentation.d.ts
  8. 40 40
      dist/preview release/gui/babylon.gui.js
  9. 1 1
      dist/preview release/gui/babylon.gui.js.map
  10. 11 10
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  11. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  12. 103 140
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  13. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  14. 27 24
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  15. 842 731
      dist/preview release/viewer/babylon.module.d.ts
  16. 746 1186
      localDev/src/webgl-debug.js
  17. 1 33
      nodeEditor/src/components/diagram/defaultNodeModel.ts
  18. 67 19
      nodeEditor/src/components/diagram/diagram.scss
  19. 8 37
      nodeEditor/src/components/diagram/generic/genericNodeWidget.tsx
  20. 5 6
      nodeEditor/src/components/diagram/input/inputNodeModel.tsx
  21. 26 41
      nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx
  22. 28 49
      nodeEditor/src/components/diagram/input/inputNodeWidget.tsx
  23. 2 2
      nodeEditor/src/components/diagram/light/lightNodeModel.tsx
  24. 4 35
      nodeEditor/src/components/diagram/light/lightNodeWidget.tsx
  25. 61 0
      nodeEditor/src/components/diagram/portHelper.tsx
  26. 6 6
      nodeEditor/src/components/diagram/texture/textureNodeModel.tsx
  27. 4 33
      nodeEditor/src/components/diagram/texture/textureNodeWidget.tsx
  28. 3 2
      nodeEditor/src/components/diagram/texture/texturePropertyTabComponent.tsx
  29. 18 0
      nodeEditor/src/components/nodeList/nodeList.scss
  30. 7 34
      nodeEditor/src/components/nodeList/nodeListComponent.tsx
  31. 3 3
      nodeEditor/src/components/propertyTab/properties/color3PropertyTabComponent.tsx
  32. 3 3
      nodeEditor/src/components/propertyTab/properties/floatPropertyTabComponent.tsx
  33. 3 3
      nodeEditor/src/components/propertyTab/properties/vector2PropertyTabComponent.tsx
  34. 3 3
      nodeEditor/src/components/propertyTab/properties/vector3PropertyTabComponent.tsx
  35. 3 0
      nodeEditor/src/components/propertyTab/propertyTabComponent.tsx
  36. 1 0
      nodeEditor/src/globalState.ts
  37. 245 102
      nodeEditor/src/graphEditor.tsx
  38. 7 0
      nodeEditor/src/main.scss
  39. 23 0
      nodeEditor/src/sharedComponents/draggableLineComponent.tsx
  40. 2 1
      package.json
  41. 21 26
      src/Materials/Node/Blocks/Dual/fogBlock.ts
  42. 2 1
      src/Materials/Node/Blocks/Dual/index.ts
  43. 28 23
      src/Materials/Node/Blocks/Dual/lightBlock.ts
  44. 185 0
      src/Materials/Node/Blocks/Dual/textureBlock.ts
  45. 4 2
      src/Materials/Node/Blocks/Fragment/fragmentOutputBlock.ts
  46. 0 1
      src/Materials/Node/Blocks/Fragment/index.ts
  47. 0 209
      src/Materials/Node/Blocks/Fragment/textureBlock.ts
  48. 1 0
      src/Materials/Node/Blocks/Input/index.ts
  49. 426 0
      src/Materials/Node/Blocks/Input/inputBlock.ts
  50. 21 10
      src/Materials/Node/Blocks/Vertex/bonesBlock.ts
  51. 16 5
      src/Materials/Node/Blocks/Vertex/instancesBlock.ts
  52. 18 8
      src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts
  53. 2 1
      src/Materials/Node/Blocks/addBlock.ts
  54. 2 1
      src/Materials/Node/Blocks/clampBlock.ts
  55. 1 0
      src/Materials/Node/Blocks/index.ts
  56. 2 1
      src/Materials/Node/Blocks/multiplyBlock.ts
  57. 1 1
      src/Materials/Node/Blocks/vector2TransformBlock.ts
  58. 1 1
      src/Materials/Node/Blocks/vector3TransformBlock.ts
  59. 1 1
      src/Materials/Node/Blocks/vector4TransformBlock.ts
  60. 57 36
      src/Materials/Node/nodeMaterial.ts
  61. 82 44
      src/Materials/Node/nodeMaterialBlock.ts
  62. 48 251
      src/Materials/Node/nodeMaterialBlockConnectionPoint.ts
  63. 6 8
      src/Materials/Node/nodeMaterialBlockConnectionPointTypes.ts
  64. 2 0
      src/Materials/Node/nodeMaterialBlockTargets.ts
  65. 26 141
      src/Materials/Node/nodeMaterialBuildState.ts
  66. 9 2
      src/Materials/Node/nodeMaterialBuildStateSharedData.ts
  67. 2 2
      src/Materials/Node/nodeMaterialWellKnownValues.ts

+ 390 - 348
Playground/babylon.d.txt

@@ -50022,10 +50022,6 @@ declare module BABYLON {
         Color4 = 64,
         /** Matrix */
         Matrix = 128,
-        /** Texture */
-        Texture = 256,
-        /** Texture3D */
-        Texture3D = 512,
         /** Vector3 or Color3 */
         Vector3OrColor3 = 40,
         /** Vector3 or Vector4 */
@@ -50034,222 +50030,16 @@ declare module BABYLON {
         Vector4OrColor4 = 80,
         /** Color3 or Color4 */
         Color3OrColor4 = 96,
-        /** Vector3 or Color3 */
+        /** Vector2 or Color3 or Color4 */
+        Vector2OrColor3OrColor4 = 100,
+        /** Vector3 or Color3 or Color4 or Vector4 */
         Vector3OrColor3OrVector4OrColor4 = 120,
+        /** Vector2 or Vector3 or Color3 or Color4 or Vector4 */
+        Vector2OrVector3OrColor3OrVector4OrColor4 = 124,
         /** Detect type based on connection */
         AutoDetect = 1024,
         /** Output type that will be defined by input type */
-        BasedOnInput = 2048,
-        /** Light */
-        Light = 4096
-    }
-}
-declare module BABYLON {
-    /**
-     * Enum used to define well known values e.g. values automatically provided by the system
-     */
-    export enum NodeMaterialWellKnownValues {
-        /** World */
-        World = 1,
-        /** View */
-        View = 2,
-        /** Projection */
-        Projection = 3,
-        /** ViewProjection */
-        ViewProjection = 4,
-        /** WorldView */
-        WorldView = 5,
-        /** WorldViewProjection */
-        WorldViewProjection = 6,
-        /** CameraPosition */
-        CameraPosition = 7,
-        /** Will be filled by the block itself */
-        Automatic = 8
-    }
-}
-declare module BABYLON {
-    /**
-     * Enum defining the mode of a NodeMaterialBlockConnectionPoint
-     */
-    export enum NodeMaterialBlockConnectionPointMode {
-        /** Value is an uniform */
-        Uniform = 0,
-        /** Value is a mesh attribute */
-        Attribute = 1,
-        /** Value is a varying between vertex and fragment shaders */
-        Varying = 2,
-        /** Mode is undefined */
-        Undefined = 3
-    }
-}
-declare module BABYLON {
-    /**
-     * Class used to store shared data between 2 NodeMaterialBuildState
-     */
-    export class NodeMaterialBuildStateSharedData {
-        /**
-         * Gets the list of emitted varyings
-         */
-        varyings: string[];
-        /**
-         * Gets the varying declaration string
-         */
-        varyingDeclaration: string;
-        /**
-         * Uniform connection points
-         */
-        uniformConnectionPoints: NodeMaterialConnectionPoint[];
-        /**
-         * Bindable blocks (Blocks that need to set data to the effect)
-         */
-        bindableBlocks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can provide a compilation fallback
-         */
-        blocksWithFallbacks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can provide a define update
-         */
-        blocksWithDefines: NodeMaterialBlock[];
-        /**
-        * List of blocks that can provide a repeatable content
-        */
-        repeatableContentBlocks: NodeMaterialBlock[];
-        /**
-        * List of blocks that can provide a dynamic list of uniforms
-        */
-        dynamicUniformBlocks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can block the isReady function for the material
-         */
-        blockingBlocks: NodeMaterialBlock[];
-        /**
-         * Build Id used to avoid multiple recompilations
-         */
-        buildId: number;
-        /** List of emitted variables */
-        variableNames: {
-            [key: string]: number;
-        };
-        /** List of emitted defines */
-        defineNames: {
-            [key: string]: number;
-        };
-        /** Should emit comments? */
-        emitComments: boolean;
-        /** Emit build activity */
-        verbose: boolean;
-        /**
-         * Gets the compilation hints emitted at compilation time
-         */
-        hints: {
-            needWorldViewMatrix: boolean;
-            needWorldViewProjectionMatrix: boolean;
-            needAlphaBlending: boolean;
-            needAlphaTesting: boolean;
-        };
-        /**
-         * List of compilation checks
-         */
-        checks: {
-            emitVertex: boolean;
-            emitFragment: boolean;
-            notConnectedNonOptionalInputs: NodeMaterialConnectionPoint[];
-        };
-        /** Creates a new shared data */
-        constructor();
-        /**
-         * Emits console errors and exceptions if there is a failing check
-         */
-        emitErrors(): void;
-    }
-}
-declare module BABYLON {
-    /**
-     * Class used to store node based material build state
-     */
-    export class NodeMaterialBuildState {
-        /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
-        supportUniformBuffers: boolean;
-        /**
-         * Gets the list of emitted attributes
-         */
-        attributes: string[];
-        /**
-         * Gets the list of emitted uniforms
-         */
-        uniforms: string[];
-        /**
-         * Gets the list of emitted uniform buffers
-         */
-        uniformBuffers: string[];
-        /**
-         * Gets the list of emitted samplers
-         */
-        samplers: string[];
-        /**
-         * Gets the list of emitted functions
-         */
-        functions: {
-            [key: string]: string;
-        };
-        /**
-         * Gets the target of the compilation state
-         */
-        target: NodeMaterialBlockTargets;
-        /**
-         * Gets the list of emitted counters
-         */
-        counters: {
-            [key: string]: number;
-        };
-        /**
-         * Shared data between multiple NodeMaterialBuildState instances
-         */
-        sharedData: NodeMaterialBuildStateSharedData;
-        /** @hidden */
private _vertexState: NodeMaterialBuildState;
-        private _attributeDeclaration;
-        private _uniformDeclaration;
-        private _samplerDeclaration;
-        private _varyingTransfer;
-        private _repeatableContentAnchorIndex;
-        /** @hidden */
private _builtCompilationString: string;
-        /**
-         * Gets the emitted compilation strings
-         */
-        compilationString: string;
-        /**
-         * Finalize the compilation strings
-         * @param state defines the current compilation state
-         */
-        finalize(state: NodeMaterialBuildState): void;
-        /** @hidden */
protected readonly _repeatableContentAnchor: string;
-        /** @hidden */
private _getFreeVariableName(prefix: string): string;
-        /** @hidden */
private _getFreeDefineName(prefix: string): string;
-        /** @hidden */
private _excludeVariableName(name: string): void;
-        /** @hidden */
private _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
-        /** @hidden */
private _emitFunction(name: string, code: string, comments: string): void;
-        /** @hidden */
private _emitCodeFromInclude(includeName: string, comments: string, options?: {
-            replaceStrings?: {
-                search: RegExp;
-                replace: string;
-            }[];
-            repeatKey?: string;
-        }): string;
-        /** @hidden */
private _emitFunctionFromInclude(includeName: string, comments: string, options?: {
-            repeatKey?: string;
-            removeAttributes?: boolean;
-            removeUniforms?: boolean;
-            removeVaryings?: boolean;
-            removeIfDef?: boolean;
-            replaceStrings?: {
-                search: RegExp;
-                replace: string;
-            }[];
-        }, storeKey?: string): void;
-        /** @hidden */
private _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
-        private _emitDefine;
-        /** @hidden */
private _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
+        BasedOnInput = 2048
     }
 }
 declare module BABYLON {
@@ -50406,7 +50196,6 @@ declare module BABYLON {
         private _buildWasSuccessful;
         private _cachedWorldViewMatrix;
         private _cachedWorldViewProjectionMatrix;
-        private _textureConnectionPoints;
         private _optimizers;
         /** Define the URl to load node editor script */
         static EditorURL: string;
@@ -50555,19 +50344,235 @@ declare module BABYLON {
         /** Creates the node editor window. */
         private _createNodeEditor;
         /**
-         * Launch the node material editor
-         * @param config Define the configuration of the editor
-         * @return a promise fulfilled when the node editor is visible
+         * Launch the node material editor
+         * @param config Define the configuration of the editor
+         * @return a promise fulfilled when the node editor is visible
+         */
+        edit(config?: INodeMaterialEditorOptions): Promise<void>;
+        /**
+         * Clear the current material
+         */
+        clear(): void;
+        /**
+         * Clear the current material and set it to a default state
+         */
+        setToDefault(): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to read a texture from a sampler
+     */
+    export class TextureBlock extends NodeMaterialBlock {
+        private _defineName;
+        private _samplerName;
+        private _transformedUVName;
+        private _textureTransformName;
+        private _textureInfoName;
+        private _mainUVName;
+        private _mainUVDefineName;
+        /**
+         * Gets or sets the texture associated with the node
+         */
+        texture: Nullable<BaseTexture>;
+        /**
+         * Create a new TextureBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(): void;
+        initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        isReady(): boolean;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
+        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to store shared data between 2 NodeMaterialBuildState
+     */
+    export class NodeMaterialBuildStateSharedData {
+        /**
+         * Gets the list of emitted varyings
+         */
+        varyings: string[];
+        /**
+         * Gets the varying declaration string
+         */
+        varyingDeclaration: string;
+        /**
+         * Input blocks
+         */
+        inputBlocks: InputBlock[];
+        /**
+         * Input blocks
+         */
+        textureBlocks: TextureBlock[];
+        /**
+         * Bindable blocks (Blocks that need to set data to the effect)
+         */
+        bindableBlocks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can provide a compilation fallback
+         */
+        blocksWithFallbacks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can provide a define update
+         */
+        blocksWithDefines: NodeMaterialBlock[];
+        /**
+        * List of blocks that can provide a repeatable content
+        */
+        repeatableContentBlocks: NodeMaterialBlock[];
+        /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can block the isReady function for the material
+         */
+        blockingBlocks: NodeMaterialBlock[];
+        /**
+         * Build Id used to avoid multiple recompilations
+         */
+        buildId: number;
+        /** List of emitted variables */
+        variableNames: {
+            [key: string]: number;
+        };
+        /** List of emitted defines */
+        defineNames: {
+            [key: string]: number;
+        };
+        /** Should emit comments? */
+        emitComments: boolean;
+        /** Emit build activity */
+        verbose: boolean;
+        /**
+         * Gets the compilation hints emitted at compilation time
+         */
+        hints: {
+            needWorldViewMatrix: boolean;
+            needWorldViewProjectionMatrix: boolean;
+            needAlphaBlending: boolean;
+            needAlphaTesting: boolean;
+        };
+        /**
+         * List of compilation checks
+         */
+        checks: {
+            emitVertex: boolean;
+            emitFragment: boolean;
+            notConnectedNonOptionalInputs: NodeMaterialConnectionPoint[];
+        };
+        /** Creates a new shared data */
+        constructor();
+        /**
+         * Emits console errors and exceptions if there is a failing check
+         */
+        emitErrors(): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to store node based material build state
+     */
+    export class NodeMaterialBuildState {
+        /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
+        supportUniformBuffers: boolean;
+        /**
+         * Gets the list of emitted attributes
+         */
+        attributes: string[];
+        /**
+         * Gets the list of emitted uniforms
+         */
+        uniforms: string[];
+        /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
+         * Gets the list of emitted samplers
+         */
+        samplers: string[];
+        /**
+         * Gets the list of emitted functions
+         */
+        functions: {
+            [key: string]: string;
+        };
+        /**
+         * Gets the target of the compilation state
+         */
+        target: NodeMaterialBlockTargets;
+        /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
+         * Shared data between multiple NodeMaterialBuildState instances
          */
-        edit(config?: INodeMaterialEditorOptions): Promise<void>;
+        sharedData: NodeMaterialBuildStateSharedData;
+        /** @hidden */
private _vertexState: NodeMaterialBuildState;
+        /** @hidden */
private _attributeDeclaration: string;
+        /** @hidden */
private _uniformDeclaration: string;
+        /** @hidden */
private _samplerDeclaration: string;
+        /** @hidden */
private _varyingTransfer: string;
+        private _repeatableContentAnchorIndex;
+        /** @hidden */
private _builtCompilationString: string;
         /**
-         * Clear the current material
+         * Gets the emitted compilation strings
          */
-        clear(): void;
+        compilationString: string;
         /**
-         * Clear the current material and set it to a default state
+         * Finalize the compilation strings
+         * @param state defines the current compilation state
          */
-        setToDefault(): void;
+        finalize(state: NodeMaterialBuildState): void;
+        /** @hidden */
protected readonly _repeatableContentAnchor: string;
+        /** @hidden */
private _getFreeVariableName(prefix: string): string;
+        /** @hidden */
private _getFreeDefineName(prefix: string): string;
+        /** @hidden */
private _excludeVariableName(name: string): void;
+        /** @hidden */
private _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
+        /** @hidden */
private _emitFunction(name: string, code: string, comments: string): void;
+        /** @hidden */
private _emitCodeFromInclude(includeName: string, comments: string, options?: {
+            replaceStrings?: {
+                search: RegExp;
+                replace: string;
+            }[];
+            repeatKey?: string;
+        }): string;
+        /** @hidden */
private _emitFunctionFromInclude(includeName: string, comments: string, options?: {
+            repeatKey?: string;
+            removeAttributes?: boolean;
+            removeUniforms?: boolean;
+            removeVaryings?: boolean;
+            removeIfDef?: boolean;
+            replaceStrings?: {
+                search: RegExp;
+                replace: string;
+            }[];
+        }, storeKey?: string): void;
+        /** @hidden */
private _emitVaryingFromString(name: string, type: string, define?: string, notDefine?: boolean): void;
+        /** @hidden */
private _emitUniformFromString(name: string, type: string, define?: string, notDefine?: boolean): void;
     }
 }
 declare module BABYLON {
@@ -50576,8 +50581,10 @@ declare module BABYLON {
      */
     export class NodeMaterialBlock {
         private _buildId;
+        private _buildTarget;
         private _target;
         private _isFinalMerger;
+        private _isInput;
         /** @hidden */
private _inputs: NodeMaterialConnectionPoint[];
         /** @hidden */
private _outputs: NodeMaterialConnectionPoint[];
         /**
@@ -50589,6 +50596,10 @@ declare module BABYLON {
          */
         readonly isFinalMerger: boolean;
         /**
+         * Gets a boolean indicating that this block is an input (e.g. it sends data to the shader)
+         */
+        readonly isInput: boolean;
+        /**
          * Gets or sets the build Id
          */
         buildId: number;
@@ -50619,8 +50630,9 @@ declare module BABYLON {
          * @param name defines the block name
          * @param target defines the target of that block (Vertex by default)
          * @param isFinalMerger defines a boolean indicating that this block is an end block (e.g. it is generating a system value). Default is false
+         * @param isInput defines a boolean indicating that this block is an input (e.g. it sends data to the shader). Default is false
          */
-        constructor(name: string, target?: NodeMaterialBlockTargets, isFinalMerger?: boolean);
+        constructor(name: string, target?: NodeMaterialBlockTargets, isFinalMerger?: boolean, isInput?: boolean);
         /**
          * Initialize the block and prepare the context for build
          * @param state defines the state that will be used for the build
@@ -50704,6 +50716,14 @@ declare module BABYLON {
          */
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         /**
+         * Initialize defines for shader compilation
+         * @param mesh defines the mesh to be rendered
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to be prepared
+         * @param useInstances specifies that instances should be used
+         */
+        initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
+        /**
          * Lets the block try to connect some inputs automatically
          */
         autoConfigure(): void;
@@ -50724,53 +50744,92 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        private _processBuild;
         /**
          * Compile the current node and generate the shader code
          * @param state defines the current compilation state (uniforms, samplers, current string)
-         * @returns the current block
+         * @param contextSwitched indicates that the previous block was built for a different context (vertex vs. fragment)
+         * @returns true if already built
          */
-        build(state: NodeMaterialBuildState): this | undefined;
+        build(state: NodeMaterialBuildState, contextSwitched?: boolean): boolean;
     }
 }
 declare module BABYLON {
     /**
-     * Defines a connection point for a block
+     * Enum defining the mode of a NodeMaterialBlockConnectionPoint
      */
-    export class NodeMaterialConnectionPoint {
-        /** @hidden */
private _ownerBlock: NodeMaterialBlock;
-        /** @hidden */
private _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
+    export enum NodeMaterialBlockConnectionPointMode {
+        /** Value is an uniform */
+        Uniform = 0,
+        /** Value is a mesh attribute */
+        Attribute = 1,
+        /** Value is a varying between vertex and fragment shaders */
+        Varying = 2,
+        /** Mode is undefined */
+        Undefined = 3
+    }
+}
+declare module BABYLON {
+    /**
+     * Enum used to define well known values e.g. values automatically provided by the system
+     */
+    export enum NodeMaterialWellKnownValues {
+        /** World */
+        World = 1,
+        /** View */
+        View = 2,
+        /** Projection */
+        Projection = 3,
+        /** ViewProjection */
+        ViewProjection = 4,
+        /** WorldView */
+        WorldView = 5,
+        /** WorldViewProjection */
+        WorldViewProjection = 6,
+        /** CameraPosition */
+        CameraPosition = 7,
+        /** Fog Color */
+        FogColor = 8
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to expose an input value
+     */
+    export class InputBlock extends NodeMaterialBlock {
+        private _mode;
         private _associatedVariableName;
-        private _endpoints;
         private _storedValue;
         private _valueCallback;
-        private _mode;
-        /** @hidden */
private _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
-        /** @hidden */
private _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
-        /** @hidden */
private _needToEmitVarying: boolean;
-        /** @hidden */
private _forceUniformInVertexShaderOnly: boolean;
         private _type;
+        /** @hidden */
private _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         /**
          * Gets or sets the connection point type (default is float)
          */
-        type: NodeMaterialBlockConnectionPointTypes;
+        readonly type: NodeMaterialBlockConnectionPointTypes;
         /**
-         * Gets or sets the connection point name
+         * Creates a new InputBlock
+         * @param name defines the block name
+         * @param target defines the target of that block (Vertex by default)
+         * @param type defines the type of the input (can be set to NodeMaterialBlockConnectionPointTypes.AutoDetect)
          */
-        name: string;
+        constructor(name: string, target?: NodeMaterialBlockTargets, type?: NodeMaterialBlockConnectionPointTypes);
         /**
-         * Gets or sets the swizzle to apply to this connection point when reading or writing
+         * Gets the output component
          */
-        swizzle: string;
+        readonly output: NodeMaterialConnectionPoint;
         /**
-         * Gets or sets a boolean indicating that this connection point can be omitted
+         * Set the source of this connection point to a vertex attribute
+         * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
+         * @returns the current connection point
          */
-        isOptional: boolean;
+        setAsAttribute(attributeName?: string): InputBlock;
         /**
-         * Gets or sets a string indicating that this uniform must be defined under a #ifdef
+         * 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
+         * @returns the current connection point
          */
-        define: string;
-        /** Gets or sets the target of that connection point */
-        target: NodeMaterialBlockTargets;
+        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock;
         /**
          * Gets or sets the value of that point.
          * Please note that this value will be ignored if valueCallback is defined
@@ -50806,6 +50865,80 @@ declare module BABYLON {
          * Can only be set on exit points
          */
         isVarying: boolean;
+        /**
+         * Gets a boolean indicating that the current connection point is a well known value
+         */
+        readonly isWellKnownValue: boolean;
+        /**
+         * Gets or sets the current well known value or null if not defined as well know value
+         */
+        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        private _emitDefine;
+        /**
+         * Set the input block to its default value (based on its type)
+         */
+        setDefaultValue(): void;
+        private _emit;
+        /** @hidden */
private _transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix): void;
+        /** @hidden */
private _transmit(effect: Effect, scene: Scene): void;
+        protected _buildBlock(state: NodeMaterialBuildState): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Defines a connection point for a block
+     */
+    export class NodeMaterialConnectionPoint {
+        /** @hidden */
private _ownerBlock: NodeMaterialBlock;
+        /** @hidden */
private _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
+        private _endpoints;
+        private _associatedVariableName;
+        /** @hidden */
private _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        private _type;
+        /** @hidden */
private _enforceAssociatedVariableName: boolean;
+        /**
+         * Gets or sets the associated variable name in the shader
+         */
+        associatedVariableName: string;
+        /**
+         * Gets or sets the connection point type (default is float)
+         */
+        type: NodeMaterialBlockConnectionPointTypes;
+        /**
+         * Gets or sets the connection point name
+         */
+        name: string;
+        /**
+         * Gets or sets the swizzle to apply to this connection point when reading or writing
+         */
+        swizzle: string;
+        /**
+         * Gets or sets a boolean indicating that this connection point can be omitted
+         */
+        isOptional: boolean;
+        /**
+         * Gets or sets a string indicating that this uniform must be defined under a #ifdef
+         */
+        define: string;
+        /** Gets or sets the target of that connection point */
+        target: NodeMaterialBlockTargets;
+        /**
+         * Gets a boolean indicating that the current point is connected
+         */
+        readonly isConnected: boolean;
+        /**
+         * Gets a boolean indicating that the current point is connected to an input block
+         */
+        readonly isConnectedToInput: boolean;
+        /**
+         * Gets a the connected input block (if any)
+         */
+        readonly connectInputBlock: Nullable<InputBlock>;
         /** Get the other side of the connection (if any) */
         readonly connectedPoint: Nullable<NodeMaterialConnectionPoint>;
         /** Get the block that owns this connection point */
@@ -50814,6 +50947,8 @@ declare module BABYLON {
         readonly sourceBlock: Nullable<NodeMaterialBlock>;
         /** Get the block connected on the endpoints of this connection (if any) */
         readonly connectedBlocks: Array<NodeMaterialBlock>;
+        /** Gets the list of connected endpoints */
+        readonly endpoints: NodeMaterialConnectionPoint[];
         /**
          * Creates a new connection point
          * @param name defines the connection point name
@@ -50825,26 +50960,6 @@ declare module BABYLON {
          * @returns the class name
          */
         getClassName(): string;
-        /**
-         * Set the source of this connection point to a vertex attribute
-         * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
-         * @returns the current connection point
-         */
-        setAsAttribute(attributeName?: string): NodeMaterialConnectionPoint;
-        /**
-         * 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
-         * @returns the current connection point
-         */
-        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): NodeMaterialConnectionPoint;
-        /**
-         * Gets a boolean indicating that the current connection point is a well known value
-         */
-        readonly isWellKnownValue: boolean;
-        /**
-         * Gets or sets the current well known value or null if not defined as well know value
-         */
-        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
          * Gets an boolean indicating if the current point can be connected to another point
@@ -50864,20 +50979,6 @@ declare module BABYLON {
          * @returns the current connection point
          */
         disconnectFrom(endpoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
-        /**
-         * When connection point is an uniform, this function will send its value to the effect
-         * @param effect defines the effect to transmit value to
-         * @param world defines the world matrix
-         * @param worldView defines the worldxview matrix
-         * @param worldViewProjection defines the worldxviewxprojection matrix
-         */
-        transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix): void;
-        /**
-         * When connection point is an uniform, this function will send its value to the effect
-         * @param effect defines the effect to transmit value to
-         * @param scene defines the hosting scene
-         */
-        transmit(effect: Effect, scene: Scene): void;
     }
 }
 declare module BABYLON {
@@ -51181,62 +51282,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Block used to read a texture from a sampler
-     */
-    export class TextureBlock extends NodeMaterialBlock {
-        private _defineName;
-        /**
-         * Gets or sets a boolean indicating that the block can automatically fetch the texture matrix
-         */
-        autoConnectTextureMatrix: boolean;
-        /**
-         * Gets or sets a boolean indicating that the block can automatically select the uv channel based on texture
-         */
-        autoSelectUV: boolean;
-        /**
-         * Create a new TextureBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the uv input component
-         */
-        readonly uv: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture information input component
-         */
-        readonly textureInfo: NodeMaterialConnectionPoint;
-        /**
-         * Gets the transformed uv input component
-         */
-        readonly transformedUV: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture input component
-         */
-        readonly texture: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture transform input component
-         */
-        readonly textureTransform: NodeMaterialConnectionPoint;
-        /**
-         * Gets the output component
-         */
-        readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
-        initialize(state: NodeMaterialBuildState): void;
-        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
-        isReady(): boolean;
-        private _injectVertexCode;
-        protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
      * Block used to add image processing support to fragment shader
      */
     export class ImageProcessingBlock extends NodeMaterialBlock {
@@ -51274,6 +51319,8 @@ declare module BABYLON {
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {
+        private _fogDistanceName;
+        private _fogParameters;
         /**
          * Create a new FogBlock
          * @param name defines the block name
@@ -51301,10 +51348,6 @@ declare module BABYLON {
          */
         readonly fogColor: NodeMaterialConnectionPoint;
         /**
-         * Gets the for parameter input component
-         */
-        readonly fogParameters: NodeMaterialConnectionPoint;
-        /**
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
@@ -51321,6 +51364,10 @@ declare module BABYLON {
     export class LightBlock extends NodeMaterialBlock {
         private _lightId;
         /**
+         * Gets or sets the light associated with this block
+         */
+        light: Nullable<Light>;
+        /**
          * Create a new LightBlock
          * @param name defines the block name
          */
@@ -51339,11 +51386,6 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component.
-        * If not defined, all lights will be considered
-        */
-        readonly light: NodeMaterialConnectionPoint;
-        /**
         * Gets the camera (or eye) position component
         */
         readonly cameraPosition: NodeMaterialConnectionPoint;

+ 1 - 0
Tools/Config/config.json

@@ -596,6 +596,7 @@
             "uncheckedLintImports": [
                 "react",
                 "react-dom",
+                "dagre",
                 "re-resizable",
                 "glTF"
             ],

+ 15 - 15
Tools/Gulp/helpers/gulp-validateImports.js

@@ -10,7 +10,7 @@ var config = require("../../Config/config");
 const indexExlclusion = ["States", "EmitterTypes"];
 const forbiddenImports = ["meshBuilder"];
 
-const mapping = { };
+const mapping = {};
 config.modules.forEach(moduleName => {
     mapping[config[moduleName].build.umd.packageName] = moduleName;
 });
@@ -196,7 +196,7 @@ var validateImports = function(data, fileLocation, options) {
 function gulpValidateImports(options) {
     var globalErrors = [];
 
-    return through.obj(function (file, enc, cb) {
+    return through.obj(function(file, enc, cb) {
         if (file.isNull()) {
             cb(null, file);
             return;
@@ -204,7 +204,7 @@ function gulpValidateImports(options) {
         if (file.isStream()) {
             cb(new PluginError("Validate imports", "Streaming not supported."));
         }
-        
+
         let data = file.contents.toString();
         let result = validateImports(data, file.path, options);
 
@@ -218,20 +218,20 @@ function gulpValidateImports(options) {
         }
 
         return cb();
-    }, 
-    function endStream(cb) {
-        if (globalErrors.length > 0) {
-            for (let error of globalErrors) {
-                colorConsole.error(error.message + " " + error.path);
-            }
-            colorConsole.error(`Import validation failed with ${globalErrors.length} errors.`);
+    },
+        function endStream(cb) {
+            if (globalErrors.length > 0) {
+                for (let error of globalErrors) {
+                    colorConsole.error(error.message + " " + error.path);
+                }
+                colorConsole.error(`Import validation failed with ${globalErrors.length} errors.`);
 
-            var finalMessage = new PluginError('gulp-validateImports', `gulp-validateImports: ${globalErrors.length} errors found.`);
-            this.emit('error', finalMessage);
-        }
+                var finalMessage = new PluginError('gulp-validateImports', `gulp-validateImports: ${globalErrors.length} errors found.`);
+                this.emit('error', finalMessage);
+            }
 
-        cb();
-    });
+            cb();
+        });
 }
 
 module.exports = gulpValidateImports;

+ 1 - 0
Tools/Publisher/tasks/processEs6Packages.js

@@ -98,6 +98,7 @@ function processEs6Packages(version) {
         var mainPackageJSON = fs.readJSONSync(mainPackageJSONPath);
         var tslibSemver = mainPackageJSON["devDependencies"]["tslib"];
         colorConsole.log("    Adding tslib version: ", tslibSemver.yellow);
+        umdPackageJson["dependencies"] = umdPackageJson["dependencies"] || {};
         umdPackageJson["dependencies"]["tslib"] = tslibSemver;
 
         let packageJSONPath = path.join(packagePath, "package.json");

+ 404 - 357
dist/preview release/babylon.d.ts

@@ -50797,10 +50797,6 @@ declare module BABYLON {
         Color4 = 64,
         /** Matrix */
         Matrix = 128,
-        /** Texture */
-        Texture = 256,
-        /** Texture3D */
-        Texture3D = 512,
         /** Vector3 or Color3 */
         Vector3OrColor3 = 40,
         /** Vector3 or Vector4 */
@@ -50809,234 +50805,16 @@ declare module BABYLON {
         Vector4OrColor4 = 80,
         /** Color3 or Color4 */
         Color3OrColor4 = 96,
-        /** Vector3 or Color3 */
+        /** Vector2 or Color3 or Color4 */
+        Vector2OrColor3OrColor4 = 100,
+        /** Vector3 or Color3 or Color4 or Vector4 */
         Vector3OrColor3OrVector4OrColor4 = 120,
+        /** Vector2 or Vector3 or Color3 or Color4 or Vector4 */
+        Vector2OrVector3OrColor3OrVector4OrColor4 = 124,
         /** Detect type based on connection */
         AutoDetect = 1024,
         /** Output type that will be defined by input type */
-        BasedOnInput = 2048,
-        /** Light */
-        Light = 4096
-    }
-}
-declare module BABYLON {
-    /**
-     * Enum used to define well known values e.g. values automatically provided by the system
-     */
-    export enum NodeMaterialWellKnownValues {
-        /** World */
-        World = 1,
-        /** View */
-        View = 2,
-        /** Projection */
-        Projection = 3,
-        /** ViewProjection */
-        ViewProjection = 4,
-        /** WorldView */
-        WorldView = 5,
-        /** WorldViewProjection */
-        WorldViewProjection = 6,
-        /** CameraPosition */
-        CameraPosition = 7,
-        /** Will be filled by the block itself */
-        Automatic = 8
-    }
-}
-declare module BABYLON {
-    /**
-     * Enum defining the mode of a NodeMaterialBlockConnectionPoint
-     */
-    export enum NodeMaterialBlockConnectionPointMode {
-        /** Value is an uniform */
-        Uniform = 0,
-        /** Value is a mesh attribute */
-        Attribute = 1,
-        /** Value is a varying between vertex and fragment shaders */
-        Varying = 2,
-        /** Mode is undefined */
-        Undefined = 3
-    }
-}
-declare module BABYLON {
-    /**
-     * Class used to store shared data between 2 NodeMaterialBuildState
-     */
-    export class NodeMaterialBuildStateSharedData {
-        /**
-         * Gets the list of emitted varyings
-         */
-        varyings: string[];
-        /**
-         * Gets the varying declaration string
-         */
-        varyingDeclaration: string;
-        /**
-         * Uniform connection points
-         */
-        uniformConnectionPoints: NodeMaterialConnectionPoint[];
-        /**
-         * Bindable blocks (Blocks that need to set data to the effect)
-         */
-        bindableBlocks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can provide a compilation fallback
-         */
-        blocksWithFallbacks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can provide a define update
-         */
-        blocksWithDefines: NodeMaterialBlock[];
-        /**
-        * List of blocks that can provide a repeatable content
-        */
-        repeatableContentBlocks: NodeMaterialBlock[];
-        /**
-        * List of blocks that can provide a dynamic list of uniforms
-        */
-        dynamicUniformBlocks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can block the isReady function for the material
-         */
-        blockingBlocks: NodeMaterialBlock[];
-        /**
-         * Build Id used to avoid multiple recompilations
-         */
-        buildId: number;
-        /** List of emitted variables */
-        variableNames: {
-            [key: string]: number;
-        };
-        /** List of emitted defines */
-        defineNames: {
-            [key: string]: number;
-        };
-        /** Should emit comments? */
-        emitComments: boolean;
-        /** Emit build activity */
-        verbose: boolean;
-        /**
-         * Gets the compilation hints emitted at compilation time
-         */
-        hints: {
-            needWorldViewMatrix: boolean;
-            needWorldViewProjectionMatrix: boolean;
-            needAlphaBlending: boolean;
-            needAlphaTesting: boolean;
-        };
-        /**
-         * List of compilation checks
-         */
-        checks: {
-            emitVertex: boolean;
-            emitFragment: boolean;
-            notConnectedNonOptionalInputs: NodeMaterialConnectionPoint[];
-        };
-        /** Creates a new shared data */
-        constructor();
-        /**
-         * Emits console errors and exceptions if there is a failing check
-         */
-        emitErrors(): void;
-    }
-}
-declare module BABYLON {
-    /**
-     * Class used to store node based material build state
-     */
-    export class NodeMaterialBuildState {
-        /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
-        supportUniformBuffers: boolean;
-        /**
-         * Gets the list of emitted attributes
-         */
-        attributes: string[];
-        /**
-         * Gets the list of emitted uniforms
-         */
-        uniforms: string[];
-        /**
-         * Gets the list of emitted uniform buffers
-         */
-        uniformBuffers: string[];
-        /**
-         * Gets the list of emitted samplers
-         */
-        samplers: string[];
-        /**
-         * Gets the list of emitted functions
-         */
-        functions: {
-            [key: string]: string;
-        };
-        /**
-         * Gets the target of the compilation state
-         */
-        target: NodeMaterialBlockTargets;
-        /**
-         * Gets the list of emitted counters
-         */
-        counters: {
-            [key: string]: number;
-        };
-        /**
-         * Shared data between multiple NodeMaterialBuildState instances
-         */
-        sharedData: NodeMaterialBuildStateSharedData;
-        /** @hidden */
-        _vertexState: NodeMaterialBuildState;
-        private _attributeDeclaration;
-        private _uniformDeclaration;
-        private _samplerDeclaration;
-        private _varyingTransfer;
-        private _repeatableContentAnchorIndex;
-        /** @hidden */
-        _builtCompilationString: string;
-        /**
-         * Gets the emitted compilation strings
-         */
-        compilationString: string;
-        /**
-         * Finalize the compilation strings
-         * @param state defines the current compilation state
-         */
-        finalize(state: NodeMaterialBuildState): void;
-        /** @hidden */
-        readonly _repeatableContentAnchor: string;
-        /** @hidden */
-        _getFreeVariableName(prefix: string): string;
-        /** @hidden */
-        _getFreeDefineName(prefix: string): string;
-        /** @hidden */
-        _excludeVariableName(name: string): void;
-        /** @hidden */
-        _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
-        /** @hidden */
-        _emitFunction(name: string, code: string, comments: string): void;
-        /** @hidden */
-        _emitCodeFromInclude(includeName: string, comments: string, options?: {
-            replaceStrings?: {
-                search: RegExp;
-                replace: string;
-            }[];
-            repeatKey?: string;
-        }): string;
-        /** @hidden */
-        _emitFunctionFromInclude(includeName: string, comments: string, options?: {
-            repeatKey?: string;
-            removeAttributes?: boolean;
-            removeUniforms?: boolean;
-            removeVaryings?: boolean;
-            removeIfDef?: boolean;
-            replaceStrings?: {
-                search: RegExp;
-                replace: string;
-            }[];
-        }, storeKey?: string): void;
-        /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
-        private _emitDefine;
-        /** @hidden */
-        _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
+        BasedOnInput = 2048
     }
 }
 declare module BABYLON {
@@ -51193,7 +50971,6 @@ declare module BABYLON {
         private _buildWasSuccessful;
         private _cachedWorldViewMatrix;
         private _cachedWorldViewProjectionMatrix;
-        private _textureConnectionPoints;
         private _optimizers;
         /** Define the URl to load node editor script */
         static EditorURL: string;
@@ -51361,12 +51138,246 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to read a texture from a sampler
+     */
+    export class TextureBlock extends NodeMaterialBlock {
+        private _defineName;
+        private _samplerName;
+        private _transformedUVName;
+        private _textureTransformName;
+        private _textureInfoName;
+        private _mainUVName;
+        private _mainUVDefineName;
+        /**
+         * Gets or sets the texture associated with the node
+         */
+        texture: Nullable<BaseTexture>;
+        /**
+         * Create a new TextureBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(): void;
+        initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        isReady(): boolean;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
+        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to store shared data between 2 NodeMaterialBuildState
+     */
+    export class NodeMaterialBuildStateSharedData {
+        /**
+         * Gets the list of emitted varyings
+         */
+        varyings: string[];
+        /**
+         * Gets the varying declaration string
+         */
+        varyingDeclaration: string;
+        /**
+         * Input blocks
+         */
+        inputBlocks: InputBlock[];
+        /**
+         * Input blocks
+         */
+        textureBlocks: TextureBlock[];
+        /**
+         * Bindable blocks (Blocks that need to set data to the effect)
+         */
+        bindableBlocks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can provide a compilation fallback
+         */
+        blocksWithFallbacks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can provide a define update
+         */
+        blocksWithDefines: NodeMaterialBlock[];
+        /**
+        * List of blocks that can provide a repeatable content
+        */
+        repeatableContentBlocks: NodeMaterialBlock[];
+        /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can block the isReady function for the material
+         */
+        blockingBlocks: NodeMaterialBlock[];
+        /**
+         * Build Id used to avoid multiple recompilations
+         */
+        buildId: number;
+        /** List of emitted variables */
+        variableNames: {
+            [key: string]: number;
+        };
+        /** List of emitted defines */
+        defineNames: {
+            [key: string]: number;
+        };
+        /** Should emit comments? */
+        emitComments: boolean;
+        /** Emit build activity */
+        verbose: boolean;
+        /**
+         * Gets the compilation hints emitted at compilation time
+         */
+        hints: {
+            needWorldViewMatrix: boolean;
+            needWorldViewProjectionMatrix: boolean;
+            needAlphaBlending: boolean;
+            needAlphaTesting: boolean;
+        };
+        /**
+         * List of compilation checks
+         */
+        checks: {
+            emitVertex: boolean;
+            emitFragment: boolean;
+            notConnectedNonOptionalInputs: NodeMaterialConnectionPoint[];
+        };
+        /** Creates a new shared data */
+        constructor();
+        /**
+         * Emits console errors and exceptions if there is a failing check
+         */
+        emitErrors(): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to store node based material build state
+     */
+    export class NodeMaterialBuildState {
+        /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
+        supportUniformBuffers: boolean;
+        /**
+         * Gets the list of emitted attributes
+         */
+        attributes: string[];
+        /**
+         * Gets the list of emitted uniforms
+         */
+        uniforms: string[];
+        /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
+         * Gets the list of emitted samplers
+         */
+        samplers: string[];
+        /**
+         * Gets the list of emitted functions
+         */
+        functions: {
+            [key: string]: string;
+        };
+        /**
+         * Gets the target of the compilation state
+         */
+        target: NodeMaterialBlockTargets;
+        /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
+         * Shared data between multiple NodeMaterialBuildState instances
+         */
+        sharedData: NodeMaterialBuildStateSharedData;
+        /** @hidden */
+        _vertexState: NodeMaterialBuildState;
+        /** @hidden */
+        _attributeDeclaration: string;
+        /** @hidden */
+        _uniformDeclaration: string;
+        /** @hidden */
+        _samplerDeclaration: string;
+        /** @hidden */
+        _varyingTransfer: string;
+        private _repeatableContentAnchorIndex;
+        /** @hidden */
+        _builtCompilationString: string;
+        /**
+         * Gets the emitted compilation strings
+         */
+        compilationString: string;
+        /**
+         * Finalize the compilation strings
+         * @param state defines the current compilation state
+         */
+        finalize(state: NodeMaterialBuildState): void;
+        /** @hidden */
+        readonly _repeatableContentAnchor: string;
+        /** @hidden */
+        _getFreeVariableName(prefix: string): string;
+        /** @hidden */
+        _getFreeDefineName(prefix: string): string;
+        /** @hidden */
+        _excludeVariableName(name: string): void;
+        /** @hidden */
+        _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
+        /** @hidden */
+        _emitFunction(name: string, code: string, comments: string): void;
+        /** @hidden */
+        _emitCodeFromInclude(includeName: string, comments: string, options?: {
+            replaceStrings?: {
+                search: RegExp;
+                replace: string;
+            }[];
+            repeatKey?: string;
+        }): string;
+        /** @hidden */
+        _emitFunctionFromInclude(includeName: string, comments: string, options?: {
+            repeatKey?: string;
+            removeAttributes?: boolean;
+            removeUniforms?: boolean;
+            removeVaryings?: boolean;
+            removeIfDef?: boolean;
+            replaceStrings?: {
+                search: RegExp;
+                replace: string;
+            }[];
+        }, storeKey?: string): void;
+        /** @hidden */
+        _emitVaryingFromString(name: string, type: string, define?: string, notDefine?: boolean): void;
+        /** @hidden */
+        _emitUniformFromString(name: string, type: string, define?: string, notDefine?: boolean): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Defines a block that can be used inside a node based material
      */
     export class NodeMaterialBlock {
         private _buildId;
+        private _buildTarget;
         private _target;
         private _isFinalMerger;
+        private _isInput;
         /** @hidden */
         _inputs: NodeMaterialConnectionPoint[];
         /** @hidden */
@@ -51380,6 +51391,10 @@ declare module BABYLON {
          */
         readonly isFinalMerger: boolean;
         /**
+         * Gets a boolean indicating that this block is an input (e.g. it sends data to the shader)
+         */
+        readonly isInput: boolean;
+        /**
          * Gets or sets the build Id
          */
         buildId: number;
@@ -51410,8 +51425,9 @@ declare module BABYLON {
          * @param name defines the block name
          * @param target defines the target of that block (Vertex by default)
          * @param isFinalMerger defines a boolean indicating that this block is an end block (e.g. it is generating a system value). Default is false
+         * @param isInput defines a boolean indicating that this block is an input (e.g. it sends data to the shader). Default is false
          */
-        constructor(name: string, target?: NodeMaterialBlockTargets, isFinalMerger?: boolean);
+        constructor(name: string, target?: NodeMaterialBlockTargets, isFinalMerger?: boolean, isInput?: boolean);
         /**
          * Initialize the block and prepare the context for build
          * @param state defines the state that will be used for the build
@@ -51495,6 +51511,14 @@ declare module BABYLON {
          */
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         /**
+         * Initialize defines for shader compilation
+         * @param mesh defines the mesh to be rendered
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to be prepared
+         * @param useInstances specifies that instances should be used
+         */
+        initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
+        /**
          * Lets the block try to connect some inputs automatically
          */
         autoConfigure(): void;
@@ -51515,59 +51539,93 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        private _processBuild;
         /**
          * Compile the current node and generate the shader code
          * @param state defines the current compilation state (uniforms, samplers, current string)
-         * @returns the current block
+         * @param contextSwitched indicates that the previous block was built for a different context (vertex vs. fragment)
+         * @returns true if already built
          */
-        build(state: NodeMaterialBuildState): this | undefined;
+        build(state: NodeMaterialBuildState, contextSwitched?: boolean): boolean;
     }
 }
 declare module BABYLON {
     /**
-     * Defines a connection point for a block
+     * Enum defining the mode of a NodeMaterialBlockConnectionPoint
      */
-    export class NodeMaterialConnectionPoint {
-        /** @hidden */
-        _ownerBlock: NodeMaterialBlock;
-        /** @hidden */
-        _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
+    export enum NodeMaterialBlockConnectionPointMode {
+        /** Value is an uniform */
+        Uniform = 0,
+        /** Value is a mesh attribute */
+        Attribute = 1,
+        /** Value is a varying between vertex and fragment shaders */
+        Varying = 2,
+        /** Mode is undefined */
+        Undefined = 3
+    }
+}
+declare module BABYLON {
+    /**
+     * Enum used to define well known values e.g. values automatically provided by the system
+     */
+    export enum NodeMaterialWellKnownValues {
+        /** World */
+        World = 1,
+        /** View */
+        View = 2,
+        /** Projection */
+        Projection = 3,
+        /** ViewProjection */
+        ViewProjection = 4,
+        /** WorldView */
+        WorldView = 5,
+        /** WorldViewProjection */
+        WorldViewProjection = 6,
+        /** CameraPosition */
+        CameraPosition = 7,
+        /** Fog Color */
+        FogColor = 8
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to expose an input value
+     */
+    export class InputBlock extends NodeMaterialBlock {
+        private _mode;
         private _associatedVariableName;
-        private _endpoints;
         private _storedValue;
         private _valueCallback;
-        private _mode;
+        private _type;
         /** @hidden */
         _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
-        /** @hidden */
-        _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
-        /** @hidden */
-        _needToEmitVarying: boolean;
-        /** @hidden */
-        _forceUniformInVertexShaderOnly: boolean;
-        private _type;
         /**
          * Gets or sets the connection point type (default is float)
          */
-        type: NodeMaterialBlockConnectionPointTypes;
+        readonly type: NodeMaterialBlockConnectionPointTypes;
         /**
-         * Gets or sets the connection point name
+         * Creates a new InputBlock
+         * @param name defines the block name
+         * @param target defines the target of that block (Vertex by default)
+         * @param type defines the type of the input (can be set to NodeMaterialBlockConnectionPointTypes.AutoDetect)
          */
-        name: string;
+        constructor(name: string, target?: NodeMaterialBlockTargets, type?: NodeMaterialBlockConnectionPointTypes);
         /**
-         * Gets or sets the swizzle to apply to this connection point when reading or writing
+         * Gets the output component
          */
-        swizzle: string;
+        readonly output: NodeMaterialConnectionPoint;
         /**
-         * Gets or sets a boolean indicating that this connection point can be omitted
+         * Set the source of this connection point to a vertex attribute
+         * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
+         * @returns the current connection point
          */
-        isOptional: boolean;
+        setAsAttribute(attributeName?: string): InputBlock;
         /**
-         * Gets or sets a string indicating that this uniform must be defined under a #ifdef
+         * 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
+         * @returns the current connection point
          */
-        define: string;
-        /** Gets or sets the target of that connection point */
-        target: NodeMaterialBlockTargets;
+        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock;
         /**
          * Gets or sets the value of that point.
          * Please note that this value will be ignored if valueCallback is defined
@@ -51603,6 +51661,86 @@ declare module BABYLON {
          * Can only be set on exit points
          */
         isVarying: boolean;
+        /**
+         * Gets a boolean indicating that the current connection point is a well known value
+         */
+        readonly isWellKnownValue: boolean;
+        /**
+         * Gets or sets the current well known value or null if not defined as well know value
+         */
+        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        private _emitDefine;
+        /**
+         * Set the input block to its default value (based on its type)
+         */
+        setDefaultValue(): void;
+        private _emit;
+        /** @hidden */
+        _transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix): void;
+        /** @hidden */
+        _transmit(effect: Effect, scene: Scene): void;
+        protected _buildBlock(state: NodeMaterialBuildState): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Defines a connection point for a block
+     */
+    export class NodeMaterialConnectionPoint {
+        /** @hidden */
+        _ownerBlock: NodeMaterialBlock;
+        /** @hidden */
+        _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
+        private _endpoints;
+        private _associatedVariableName;
+        /** @hidden */
+        _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        private _type;
+        /** @hidden */
+        _enforceAssociatedVariableName: boolean;
+        /**
+         * Gets or sets the associated variable name in the shader
+         */
+        associatedVariableName: string;
+        /**
+         * Gets or sets the connection point type (default is float)
+         */
+        type: NodeMaterialBlockConnectionPointTypes;
+        /**
+         * Gets or sets the connection point name
+         */
+        name: string;
+        /**
+         * Gets or sets the swizzle to apply to this connection point when reading or writing
+         */
+        swizzle: string;
+        /**
+         * Gets or sets a boolean indicating that this connection point can be omitted
+         */
+        isOptional: boolean;
+        /**
+         * Gets or sets a string indicating that this uniform must be defined under a #ifdef
+         */
+        define: string;
+        /** Gets or sets the target of that connection point */
+        target: NodeMaterialBlockTargets;
+        /**
+         * Gets a boolean indicating that the current point is connected
+         */
+        readonly isConnected: boolean;
+        /**
+         * Gets a boolean indicating that the current point is connected to an input block
+         */
+        readonly isConnectedToInput: boolean;
+        /**
+         * Gets a the connected input block (if any)
+         */
+        readonly connectInputBlock: Nullable<InputBlock>;
         /** Get the other side of the connection (if any) */
         readonly connectedPoint: Nullable<NodeMaterialConnectionPoint>;
         /** Get the block that owns this connection point */
@@ -51611,6 +51749,8 @@ declare module BABYLON {
         readonly sourceBlock: Nullable<NodeMaterialBlock>;
         /** Get the block connected on the endpoints of this connection (if any) */
         readonly connectedBlocks: Array<NodeMaterialBlock>;
+        /** Gets the list of connected endpoints */
+        readonly endpoints: NodeMaterialConnectionPoint[];
         /**
          * Creates a new connection point
          * @param name defines the connection point name
@@ -51622,26 +51762,6 @@ declare module BABYLON {
          * @returns the class name
          */
         getClassName(): string;
-        /**
-         * Set the source of this connection point to a vertex attribute
-         * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
-         * @returns the current connection point
-         */
-        setAsAttribute(attributeName?: string): NodeMaterialConnectionPoint;
-        /**
-         * 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
-         * @returns the current connection point
-         */
-        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): NodeMaterialConnectionPoint;
-        /**
-         * Gets a boolean indicating that the current connection point is a well known value
-         */
-        readonly isWellKnownValue: boolean;
-        /**
-         * Gets or sets the current well known value or null if not defined as well know value
-         */
-        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
          * Gets an boolean indicating if the current point can be connected to another point
@@ -51661,20 +51781,6 @@ declare module BABYLON {
          * @returns the current connection point
          */
         disconnectFrom(endpoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
-        /**
-         * When connection point is an uniform, this function will send its value to the effect
-         * @param effect defines the effect to transmit value to
-         * @param world defines the world matrix
-         * @param worldView defines the worldxview matrix
-         * @param worldViewProjection defines the worldxviewxprojection matrix
-         */
-        transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix): void;
-        /**
-         * When connection point is an uniform, this function will send its value to the effect
-         * @param effect defines the effect to transmit value to
-         * @param scene defines the hosting scene
-         */
-        transmit(effect: Effect, scene: Scene): void;
     }
 }
 declare module BABYLON {
@@ -51978,62 +52084,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Block used to read a texture from a sampler
-     */
-    export class TextureBlock extends NodeMaterialBlock {
-        private _defineName;
-        /**
-         * Gets or sets a boolean indicating that the block can automatically fetch the texture matrix
-         */
-        autoConnectTextureMatrix: boolean;
-        /**
-         * Gets or sets a boolean indicating that the block can automatically select the uv channel based on texture
-         */
-        autoSelectUV: boolean;
-        /**
-         * Create a new TextureBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the uv input component
-         */
-        readonly uv: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture information input component
-         */
-        readonly textureInfo: NodeMaterialConnectionPoint;
-        /**
-         * Gets the transformed uv input component
-         */
-        readonly transformedUV: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture input component
-         */
-        readonly texture: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture transform input component
-         */
-        readonly textureTransform: NodeMaterialConnectionPoint;
-        /**
-         * Gets the output component
-         */
-        readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
-        initialize(state: NodeMaterialBuildState): void;
-        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
-        isReady(): boolean;
-        private _injectVertexCode;
-        protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
      * Block used to add image processing support to fragment shader
      */
     export class ImageProcessingBlock extends NodeMaterialBlock {
@@ -52071,6 +52121,8 @@ declare module BABYLON {
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {
+        private _fogDistanceName;
+        private _fogParameters;
         /**
          * Create a new FogBlock
          * @param name defines the block name
@@ -52098,10 +52150,6 @@ declare module BABYLON {
          */
         readonly fogColor: NodeMaterialConnectionPoint;
         /**
-         * Gets the for parameter input component
-         */
-        readonly fogParameters: NodeMaterialConnectionPoint;
-        /**
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
@@ -52118,6 +52166,10 @@ declare module BABYLON {
     export class LightBlock extends NodeMaterialBlock {
         private _lightId;
         /**
+         * Gets or sets the light associated with this block
+         */
+        light: Nullable<Light>;
+        /**
          * Create a new LightBlock
          * @param name defines the block name
          */
@@ -52136,11 +52188,6 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component.
-        * If not defined, all lights will be considered
-        */
-        readonly light: NodeMaterialConnectionPoint;
-        /**
         * Gets the camera (or eye) position component
         */
         readonly cameraPosition: NodeMaterialConnectionPoint;

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


+ 404 - 357
dist/preview release/documentation.d.ts

@@ -50797,10 +50797,6 @@ declare module BABYLON {
         Color4 = 64,
         /** Matrix */
         Matrix = 128,
-        /** Texture */
-        Texture = 256,
-        /** Texture3D */
-        Texture3D = 512,
         /** Vector3 or Color3 */
         Vector3OrColor3 = 40,
         /** Vector3 or Vector4 */
@@ -50809,234 +50805,16 @@ declare module BABYLON {
         Vector4OrColor4 = 80,
         /** Color3 or Color4 */
         Color3OrColor4 = 96,
-        /** Vector3 or Color3 */
+        /** Vector2 or Color3 or Color4 */
+        Vector2OrColor3OrColor4 = 100,
+        /** Vector3 or Color3 or Color4 or Vector4 */
         Vector3OrColor3OrVector4OrColor4 = 120,
+        /** Vector2 or Vector3 or Color3 or Color4 or Vector4 */
+        Vector2OrVector3OrColor3OrVector4OrColor4 = 124,
         /** Detect type based on connection */
         AutoDetect = 1024,
         /** Output type that will be defined by input type */
-        BasedOnInput = 2048,
-        /** Light */
-        Light = 4096
-    }
-}
-declare module BABYLON {
-    /**
-     * Enum used to define well known values e.g. values automatically provided by the system
-     */
-    export enum NodeMaterialWellKnownValues {
-        /** World */
-        World = 1,
-        /** View */
-        View = 2,
-        /** Projection */
-        Projection = 3,
-        /** ViewProjection */
-        ViewProjection = 4,
-        /** WorldView */
-        WorldView = 5,
-        /** WorldViewProjection */
-        WorldViewProjection = 6,
-        /** CameraPosition */
-        CameraPosition = 7,
-        /** Will be filled by the block itself */
-        Automatic = 8
-    }
-}
-declare module BABYLON {
-    /**
-     * Enum defining the mode of a NodeMaterialBlockConnectionPoint
-     */
-    export enum NodeMaterialBlockConnectionPointMode {
-        /** Value is an uniform */
-        Uniform = 0,
-        /** Value is a mesh attribute */
-        Attribute = 1,
-        /** Value is a varying between vertex and fragment shaders */
-        Varying = 2,
-        /** Mode is undefined */
-        Undefined = 3
-    }
-}
-declare module BABYLON {
-    /**
-     * Class used to store shared data between 2 NodeMaterialBuildState
-     */
-    export class NodeMaterialBuildStateSharedData {
-        /**
-         * Gets the list of emitted varyings
-         */
-        varyings: string[];
-        /**
-         * Gets the varying declaration string
-         */
-        varyingDeclaration: string;
-        /**
-         * Uniform connection points
-         */
-        uniformConnectionPoints: NodeMaterialConnectionPoint[];
-        /**
-         * Bindable blocks (Blocks that need to set data to the effect)
-         */
-        bindableBlocks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can provide a compilation fallback
-         */
-        blocksWithFallbacks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can provide a define update
-         */
-        blocksWithDefines: NodeMaterialBlock[];
-        /**
-        * List of blocks that can provide a repeatable content
-        */
-        repeatableContentBlocks: NodeMaterialBlock[];
-        /**
-        * List of blocks that can provide a dynamic list of uniforms
-        */
-        dynamicUniformBlocks: NodeMaterialBlock[];
-        /**
-         * List of blocks that can block the isReady function for the material
-         */
-        blockingBlocks: NodeMaterialBlock[];
-        /**
-         * Build Id used to avoid multiple recompilations
-         */
-        buildId: number;
-        /** List of emitted variables */
-        variableNames: {
-            [key: string]: number;
-        };
-        /** List of emitted defines */
-        defineNames: {
-            [key: string]: number;
-        };
-        /** Should emit comments? */
-        emitComments: boolean;
-        /** Emit build activity */
-        verbose: boolean;
-        /**
-         * Gets the compilation hints emitted at compilation time
-         */
-        hints: {
-            needWorldViewMatrix: boolean;
-            needWorldViewProjectionMatrix: boolean;
-            needAlphaBlending: boolean;
-            needAlphaTesting: boolean;
-        };
-        /**
-         * List of compilation checks
-         */
-        checks: {
-            emitVertex: boolean;
-            emitFragment: boolean;
-            notConnectedNonOptionalInputs: NodeMaterialConnectionPoint[];
-        };
-        /** Creates a new shared data */
-        constructor();
-        /**
-         * Emits console errors and exceptions if there is a failing check
-         */
-        emitErrors(): void;
-    }
-}
-declare module BABYLON {
-    /**
-     * Class used to store node based material build state
-     */
-    export class NodeMaterialBuildState {
-        /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
-        supportUniformBuffers: boolean;
-        /**
-         * Gets the list of emitted attributes
-         */
-        attributes: string[];
-        /**
-         * Gets the list of emitted uniforms
-         */
-        uniforms: string[];
-        /**
-         * Gets the list of emitted uniform buffers
-         */
-        uniformBuffers: string[];
-        /**
-         * Gets the list of emitted samplers
-         */
-        samplers: string[];
-        /**
-         * Gets the list of emitted functions
-         */
-        functions: {
-            [key: string]: string;
-        };
-        /**
-         * Gets the target of the compilation state
-         */
-        target: NodeMaterialBlockTargets;
-        /**
-         * Gets the list of emitted counters
-         */
-        counters: {
-            [key: string]: number;
-        };
-        /**
-         * Shared data between multiple NodeMaterialBuildState instances
-         */
-        sharedData: NodeMaterialBuildStateSharedData;
-        /** @hidden */
-        _vertexState: NodeMaterialBuildState;
-        private _attributeDeclaration;
-        private _uniformDeclaration;
-        private _samplerDeclaration;
-        private _varyingTransfer;
-        private _repeatableContentAnchorIndex;
-        /** @hidden */
-        _builtCompilationString: string;
-        /**
-         * Gets the emitted compilation strings
-         */
-        compilationString: string;
-        /**
-         * Finalize the compilation strings
-         * @param state defines the current compilation state
-         */
-        finalize(state: NodeMaterialBuildState): void;
-        /** @hidden */
-        readonly _repeatableContentAnchor: string;
-        /** @hidden */
-        _getFreeVariableName(prefix: string): string;
-        /** @hidden */
-        _getFreeDefineName(prefix: string): string;
-        /** @hidden */
-        _excludeVariableName(name: string): void;
-        /** @hidden */
-        _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
-        /** @hidden */
-        _emitFunction(name: string, code: string, comments: string): void;
-        /** @hidden */
-        _emitCodeFromInclude(includeName: string, comments: string, options?: {
-            replaceStrings?: {
-                search: RegExp;
-                replace: string;
-            }[];
-            repeatKey?: string;
-        }): string;
-        /** @hidden */
-        _emitFunctionFromInclude(includeName: string, comments: string, options?: {
-            repeatKey?: string;
-            removeAttributes?: boolean;
-            removeUniforms?: boolean;
-            removeVaryings?: boolean;
-            removeIfDef?: boolean;
-            replaceStrings?: {
-                search: RegExp;
-                replace: string;
-            }[];
-        }, storeKey?: string): void;
-        /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
-        private _emitDefine;
-        /** @hidden */
-        _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
+        BasedOnInput = 2048
     }
 }
 declare module BABYLON {
@@ -51193,7 +50971,6 @@ declare module BABYLON {
         private _buildWasSuccessful;
         private _cachedWorldViewMatrix;
         private _cachedWorldViewProjectionMatrix;
-        private _textureConnectionPoints;
         private _optimizers;
         /** Define the URl to load node editor script */
         static EditorURL: string;
@@ -51361,12 +51138,246 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to read a texture from a sampler
+     */
+    export class TextureBlock extends NodeMaterialBlock {
+        private _defineName;
+        private _samplerName;
+        private _transformedUVName;
+        private _textureTransformName;
+        private _textureInfoName;
+        private _mainUVName;
+        private _mainUVDefineName;
+        /**
+         * Gets or sets the texture associated with the node
+         */
+        texture: Nullable<BaseTexture>;
+        /**
+         * Create a new TextureBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(): void;
+        initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        isReady(): boolean;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
+        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to store shared data between 2 NodeMaterialBuildState
+     */
+    export class NodeMaterialBuildStateSharedData {
+        /**
+         * Gets the list of emitted varyings
+         */
+        varyings: string[];
+        /**
+         * Gets the varying declaration string
+         */
+        varyingDeclaration: string;
+        /**
+         * Input blocks
+         */
+        inputBlocks: InputBlock[];
+        /**
+         * Input blocks
+         */
+        textureBlocks: TextureBlock[];
+        /**
+         * Bindable blocks (Blocks that need to set data to the effect)
+         */
+        bindableBlocks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can provide a compilation fallback
+         */
+        blocksWithFallbacks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can provide a define update
+         */
+        blocksWithDefines: NodeMaterialBlock[];
+        /**
+        * List of blocks that can provide a repeatable content
+        */
+        repeatableContentBlocks: NodeMaterialBlock[];
+        /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
+         * List of blocks that can block the isReady function for the material
+         */
+        blockingBlocks: NodeMaterialBlock[];
+        /**
+         * Build Id used to avoid multiple recompilations
+         */
+        buildId: number;
+        /** List of emitted variables */
+        variableNames: {
+            [key: string]: number;
+        };
+        /** List of emitted defines */
+        defineNames: {
+            [key: string]: number;
+        };
+        /** Should emit comments? */
+        emitComments: boolean;
+        /** Emit build activity */
+        verbose: boolean;
+        /**
+         * Gets the compilation hints emitted at compilation time
+         */
+        hints: {
+            needWorldViewMatrix: boolean;
+            needWorldViewProjectionMatrix: boolean;
+            needAlphaBlending: boolean;
+            needAlphaTesting: boolean;
+        };
+        /**
+         * List of compilation checks
+         */
+        checks: {
+            emitVertex: boolean;
+            emitFragment: boolean;
+            notConnectedNonOptionalInputs: NodeMaterialConnectionPoint[];
+        };
+        /** Creates a new shared data */
+        constructor();
+        /**
+         * Emits console errors and exceptions if there is a failing check
+         */
+        emitErrors(): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to store node based material build state
+     */
+    export class NodeMaterialBuildState {
+        /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
+        supportUniformBuffers: boolean;
+        /**
+         * Gets the list of emitted attributes
+         */
+        attributes: string[];
+        /**
+         * Gets the list of emitted uniforms
+         */
+        uniforms: string[];
+        /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
+         * Gets the list of emitted samplers
+         */
+        samplers: string[];
+        /**
+         * Gets the list of emitted functions
+         */
+        functions: {
+            [key: string]: string;
+        };
+        /**
+         * Gets the target of the compilation state
+         */
+        target: NodeMaterialBlockTargets;
+        /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
+         * Shared data between multiple NodeMaterialBuildState instances
+         */
+        sharedData: NodeMaterialBuildStateSharedData;
+        /** @hidden */
+        _vertexState: NodeMaterialBuildState;
+        /** @hidden */
+        _attributeDeclaration: string;
+        /** @hidden */
+        _uniformDeclaration: string;
+        /** @hidden */
+        _samplerDeclaration: string;
+        /** @hidden */
+        _varyingTransfer: string;
+        private _repeatableContentAnchorIndex;
+        /** @hidden */
+        _builtCompilationString: string;
+        /**
+         * Gets the emitted compilation strings
+         */
+        compilationString: string;
+        /**
+         * Finalize the compilation strings
+         * @param state defines the current compilation state
+         */
+        finalize(state: NodeMaterialBuildState): void;
+        /** @hidden */
+        readonly _repeatableContentAnchor: string;
+        /** @hidden */
+        _getFreeVariableName(prefix: string): string;
+        /** @hidden */
+        _getFreeDefineName(prefix: string): string;
+        /** @hidden */
+        _excludeVariableName(name: string): void;
+        /** @hidden */
+        _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
+        /** @hidden */
+        _emitFunction(name: string, code: string, comments: string): void;
+        /** @hidden */
+        _emitCodeFromInclude(includeName: string, comments: string, options?: {
+            replaceStrings?: {
+                search: RegExp;
+                replace: string;
+            }[];
+            repeatKey?: string;
+        }): string;
+        /** @hidden */
+        _emitFunctionFromInclude(includeName: string, comments: string, options?: {
+            repeatKey?: string;
+            removeAttributes?: boolean;
+            removeUniforms?: boolean;
+            removeVaryings?: boolean;
+            removeIfDef?: boolean;
+            replaceStrings?: {
+                search: RegExp;
+                replace: string;
+            }[];
+        }, storeKey?: string): void;
+        /** @hidden */
+        _emitVaryingFromString(name: string, type: string, define?: string, notDefine?: boolean): void;
+        /** @hidden */
+        _emitUniformFromString(name: string, type: string, define?: string, notDefine?: boolean): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Defines a block that can be used inside a node based material
      */
     export class NodeMaterialBlock {
         private _buildId;
+        private _buildTarget;
         private _target;
         private _isFinalMerger;
+        private _isInput;
         /** @hidden */
         _inputs: NodeMaterialConnectionPoint[];
         /** @hidden */
@@ -51380,6 +51391,10 @@ declare module BABYLON {
          */
         readonly isFinalMerger: boolean;
         /**
+         * Gets a boolean indicating that this block is an input (e.g. it sends data to the shader)
+         */
+        readonly isInput: boolean;
+        /**
          * Gets or sets the build Id
          */
         buildId: number;
@@ -51410,8 +51425,9 @@ declare module BABYLON {
          * @param name defines the block name
          * @param target defines the target of that block (Vertex by default)
          * @param isFinalMerger defines a boolean indicating that this block is an end block (e.g. it is generating a system value). Default is false
+         * @param isInput defines a boolean indicating that this block is an input (e.g. it sends data to the shader). Default is false
          */
-        constructor(name: string, target?: NodeMaterialBlockTargets, isFinalMerger?: boolean);
+        constructor(name: string, target?: NodeMaterialBlockTargets, isFinalMerger?: boolean, isInput?: boolean);
         /**
          * Initialize the block and prepare the context for build
          * @param state defines the state that will be used for the build
@@ -51495,6 +51511,14 @@ declare module BABYLON {
          */
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         /**
+         * Initialize defines for shader compilation
+         * @param mesh defines the mesh to be rendered
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to be prepared
+         * @param useInstances specifies that instances should be used
+         */
+        initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
+        /**
          * Lets the block try to connect some inputs automatically
          */
         autoConfigure(): void;
@@ -51515,59 +51539,93 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        private _processBuild;
         /**
          * Compile the current node and generate the shader code
          * @param state defines the current compilation state (uniforms, samplers, current string)
-         * @returns the current block
+         * @param contextSwitched indicates that the previous block was built for a different context (vertex vs. fragment)
+         * @returns true if already built
          */
-        build(state: NodeMaterialBuildState): this | undefined;
+        build(state: NodeMaterialBuildState, contextSwitched?: boolean): boolean;
     }
 }
 declare module BABYLON {
     /**
-     * Defines a connection point for a block
+     * Enum defining the mode of a NodeMaterialBlockConnectionPoint
      */
-    export class NodeMaterialConnectionPoint {
-        /** @hidden */
-        _ownerBlock: NodeMaterialBlock;
-        /** @hidden */
-        _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
+    export enum NodeMaterialBlockConnectionPointMode {
+        /** Value is an uniform */
+        Uniform = 0,
+        /** Value is a mesh attribute */
+        Attribute = 1,
+        /** Value is a varying between vertex and fragment shaders */
+        Varying = 2,
+        /** Mode is undefined */
+        Undefined = 3
+    }
+}
+declare module BABYLON {
+    /**
+     * Enum used to define well known values e.g. values automatically provided by the system
+     */
+    export enum NodeMaterialWellKnownValues {
+        /** World */
+        World = 1,
+        /** View */
+        View = 2,
+        /** Projection */
+        Projection = 3,
+        /** ViewProjection */
+        ViewProjection = 4,
+        /** WorldView */
+        WorldView = 5,
+        /** WorldViewProjection */
+        WorldViewProjection = 6,
+        /** CameraPosition */
+        CameraPosition = 7,
+        /** Fog Color */
+        FogColor = 8
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to expose an input value
+     */
+    export class InputBlock extends NodeMaterialBlock {
+        private _mode;
         private _associatedVariableName;
-        private _endpoints;
         private _storedValue;
         private _valueCallback;
-        private _mode;
+        private _type;
         /** @hidden */
         _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
-        /** @hidden */
-        _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
-        /** @hidden */
-        _needToEmitVarying: boolean;
-        /** @hidden */
-        _forceUniformInVertexShaderOnly: boolean;
-        private _type;
         /**
          * Gets or sets the connection point type (default is float)
          */
-        type: NodeMaterialBlockConnectionPointTypes;
+        readonly type: NodeMaterialBlockConnectionPointTypes;
         /**
-         * Gets or sets the connection point name
+         * Creates a new InputBlock
+         * @param name defines the block name
+         * @param target defines the target of that block (Vertex by default)
+         * @param type defines the type of the input (can be set to NodeMaterialBlockConnectionPointTypes.AutoDetect)
          */
-        name: string;
+        constructor(name: string, target?: NodeMaterialBlockTargets, type?: NodeMaterialBlockConnectionPointTypes);
         /**
-         * Gets or sets the swizzle to apply to this connection point when reading or writing
+         * Gets the output component
          */
-        swizzle: string;
+        readonly output: NodeMaterialConnectionPoint;
         /**
-         * Gets or sets a boolean indicating that this connection point can be omitted
+         * Set the source of this connection point to a vertex attribute
+         * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
+         * @returns the current connection point
          */
-        isOptional: boolean;
+        setAsAttribute(attributeName?: string): InputBlock;
         /**
-         * Gets or sets a string indicating that this uniform must be defined under a #ifdef
+         * 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
+         * @returns the current connection point
          */
-        define: string;
-        /** Gets or sets the target of that connection point */
-        target: NodeMaterialBlockTargets;
+        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock;
         /**
          * Gets or sets the value of that point.
          * Please note that this value will be ignored if valueCallback is defined
@@ -51603,6 +51661,86 @@ declare module BABYLON {
          * Can only be set on exit points
          */
         isVarying: boolean;
+        /**
+         * Gets a boolean indicating that the current connection point is a well known value
+         */
+        readonly isWellKnownValue: boolean;
+        /**
+         * Gets or sets the current well known value or null if not defined as well know value
+         */
+        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        private _emitDefine;
+        /**
+         * Set the input block to its default value (based on its type)
+         */
+        setDefaultValue(): void;
+        private _emit;
+        /** @hidden */
+        _transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix): void;
+        /** @hidden */
+        _transmit(effect: Effect, scene: Scene): void;
+        protected _buildBlock(state: NodeMaterialBuildState): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Defines a connection point for a block
+     */
+    export class NodeMaterialConnectionPoint {
+        /** @hidden */
+        _ownerBlock: NodeMaterialBlock;
+        /** @hidden */
+        _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
+        private _endpoints;
+        private _associatedVariableName;
+        /** @hidden */
+        _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        private _type;
+        /** @hidden */
+        _enforceAssociatedVariableName: boolean;
+        /**
+         * Gets or sets the associated variable name in the shader
+         */
+        associatedVariableName: string;
+        /**
+         * Gets or sets the connection point type (default is float)
+         */
+        type: NodeMaterialBlockConnectionPointTypes;
+        /**
+         * Gets or sets the connection point name
+         */
+        name: string;
+        /**
+         * Gets or sets the swizzle to apply to this connection point when reading or writing
+         */
+        swizzle: string;
+        /**
+         * Gets or sets a boolean indicating that this connection point can be omitted
+         */
+        isOptional: boolean;
+        /**
+         * Gets or sets a string indicating that this uniform must be defined under a #ifdef
+         */
+        define: string;
+        /** Gets or sets the target of that connection point */
+        target: NodeMaterialBlockTargets;
+        /**
+         * Gets a boolean indicating that the current point is connected
+         */
+        readonly isConnected: boolean;
+        /**
+         * Gets a boolean indicating that the current point is connected to an input block
+         */
+        readonly isConnectedToInput: boolean;
+        /**
+         * Gets a the connected input block (if any)
+         */
+        readonly connectInputBlock: Nullable<InputBlock>;
         /** Get the other side of the connection (if any) */
         readonly connectedPoint: Nullable<NodeMaterialConnectionPoint>;
         /** Get the block that owns this connection point */
@@ -51611,6 +51749,8 @@ declare module BABYLON {
         readonly sourceBlock: Nullable<NodeMaterialBlock>;
         /** Get the block connected on the endpoints of this connection (if any) */
         readonly connectedBlocks: Array<NodeMaterialBlock>;
+        /** Gets the list of connected endpoints */
+        readonly endpoints: NodeMaterialConnectionPoint[];
         /**
          * Creates a new connection point
          * @param name defines the connection point name
@@ -51622,26 +51762,6 @@ declare module BABYLON {
          * @returns the class name
          */
         getClassName(): string;
-        /**
-         * Set the source of this connection point to a vertex attribute
-         * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
-         * @returns the current connection point
-         */
-        setAsAttribute(attributeName?: string): NodeMaterialConnectionPoint;
-        /**
-         * 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
-         * @returns the current connection point
-         */
-        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): NodeMaterialConnectionPoint;
-        /**
-         * Gets a boolean indicating that the current connection point is a well known value
-         */
-        readonly isWellKnownValue: boolean;
-        /**
-         * Gets or sets the current well known value or null if not defined as well know value
-         */
-        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
          * Gets an boolean indicating if the current point can be connected to another point
@@ -51661,20 +51781,6 @@ declare module BABYLON {
          * @returns the current connection point
          */
         disconnectFrom(endpoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
-        /**
-         * When connection point is an uniform, this function will send its value to the effect
-         * @param effect defines the effect to transmit value to
-         * @param world defines the world matrix
-         * @param worldView defines the worldxview matrix
-         * @param worldViewProjection defines the worldxviewxprojection matrix
-         */
-        transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix): void;
-        /**
-         * When connection point is an uniform, this function will send its value to the effect
-         * @param effect defines the effect to transmit value to
-         * @param scene defines the hosting scene
-         */
-        transmit(effect: Effect, scene: Scene): void;
     }
 }
 declare module BABYLON {
@@ -51978,62 +52084,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Block used to read a texture from a sampler
-     */
-    export class TextureBlock extends NodeMaterialBlock {
-        private _defineName;
-        /**
-         * Gets or sets a boolean indicating that the block can automatically fetch the texture matrix
-         */
-        autoConnectTextureMatrix: boolean;
-        /**
-         * Gets or sets a boolean indicating that the block can automatically select the uv channel based on texture
-         */
-        autoSelectUV: boolean;
-        /**
-         * Create a new TextureBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the uv input component
-         */
-        readonly uv: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture information input component
-         */
-        readonly textureInfo: NodeMaterialConnectionPoint;
-        /**
-         * Gets the transformed uv input component
-         */
-        readonly transformedUV: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture input component
-         */
-        readonly texture: NodeMaterialConnectionPoint;
-        /**
-         * Gets the texture transform input component
-         */
-        readonly textureTransform: NodeMaterialConnectionPoint;
-        /**
-         * Gets the output component
-         */
-        readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
-        initialize(state: NodeMaterialBuildState): void;
-        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
-        isReady(): boolean;
-        private _injectVertexCode;
-        protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
      * Block used to add image processing support to fragment shader
      */
     export class ImageProcessingBlock extends NodeMaterialBlock {
@@ -52071,6 +52121,8 @@ declare module BABYLON {
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {
+        private _fogDistanceName;
+        private _fogParameters;
         /**
          * Create a new FogBlock
          * @param name defines the block name
@@ -52098,10 +52150,6 @@ declare module BABYLON {
          */
         readonly fogColor: NodeMaterialConnectionPoint;
         /**
-         * Gets the for parameter input component
-         */
-        readonly fogParameters: NodeMaterialConnectionPoint;
-        /**
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
@@ -52118,6 +52166,10 @@ declare module BABYLON {
     export class LightBlock extends NodeMaterialBlock {
         private _lightId;
         /**
+         * Gets or sets the light associated with this block
+         */
+        light: Nullable<Light>;
+        /**
          * Create a new LightBlock
          * @param name defines the block name
          */
@@ -52136,11 +52188,6 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component.
-        * If not defined, all lights will be considered
-        */
-        readonly light: NodeMaterialConnectionPoint;
-        /**
         * Gets the camera (or eye) position component
         */
         readonly cameraPosition: NodeMaterialConnectionPoint;

+ 40 - 40
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_observable__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_tools__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -355,7 +355,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_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -498,7 +498,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -1619,7 +1619,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -1800,7 +1800,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -3187,7 +3187,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/observable");
+/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/tools");
 /* 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");
@@ -3592,7 +3592,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -5783,7 +5783,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 
 
@@ -6239,7 +6239,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -7014,7 +7014,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -8023,7 +8023,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* 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");
@@ -8291,7 +8291,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/observable");
+/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/tools");
 /* 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");
@@ -8558,7 +8558,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -8903,7 +8903,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/observable");
+/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Misc/tools");
 /* 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");
@@ -9994,7 +9994,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -10895,7 +10895,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* 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");
@@ -11153,7 +11153,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -11593,7 +11593,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
@@ -11974,7 +11974,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -12198,7 +12198,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 
 
@@ -12331,7 +12331,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -12474,7 +12474,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -12781,7 +12781,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/observable");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -12824,7 +12824,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* 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");
@@ -13001,7 +13001,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/observable");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -13158,7 +13158,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -13564,7 +13564,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* 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");
@@ -13649,7 +13649,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* 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");
@@ -14125,7 +14125,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* 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");
@@ -14180,7 +14180,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* 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");
@@ -14307,7 +14307,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* 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");
@@ -14392,7 +14392,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -14517,7 +14517,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/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -14708,7 +14708,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/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* 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");
 
@@ -14975,7 +14975,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/observable");
+/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/tools");
 /* 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");
@@ -15297,7 +15297,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/observable");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/tools");
 /* 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';
@@ -15319,7 +15319,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/observable");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/tools");
 /* 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';
@@ -15342,7 +15342,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/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -15636,14 +15636,14 @@ if (typeof globalObject !== "undefined") {
 
 /***/ }),
 
-/***/ "babylonjs/Misc/observable":
+/***/ "babylonjs/Misc/tools":
 /*!****************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   \****************************************************************************************************/
 /*! no static exports found */
 /***/ (function(module, exports) {
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_tools__;
 
 /***/ })
 

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


+ 11 - 10
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts

@@ -265,14 +265,14 @@ declare module NODEEDITOR {
 }
 declare module NODEEDITOR {
     /**
-     * BABYLON.Texture node model which stores information about a node editor block
+     * Texture node model which stores information about a node editor block
      */
     export class TextureNodeModel extends DefaultNodeModel {
         private _block;
         /**
-         * BABYLON.Texture for the node if it exists
+         * Texture for the node if it exists
          */
-        texture: BABYLON.Nullable<BABYLON.Texture>;
+        texture: BABYLON.Nullable<BABYLON.BaseTexture>;
         /**
          * Constructs the node model
          */
@@ -408,7 +408,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IVector2PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class Vector2PropertyTabComponent extends React.Component<IVector2PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -448,7 +448,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IVector3PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class Vector3PropertyTabComponent extends React.Component<IVector3PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -514,7 +514,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IColor3PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class Color3PropertyTabComponent extends React.Component<IColor3PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -549,7 +549,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IFloatPropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class FloatPropertyTabComponent extends React.Component<IFloatPropertyTabComponentProps> {
         render(): JSX.Element;
@@ -581,12 +581,13 @@ declare module NODEEDITOR {
      * Generic node model which stores information about a node editor block
      */
     export class InputNodeModel extends DefaultNodeModel {
-        connection?: BABYLON.NodeMaterialConnectionPoint;
+        outputType: BABYLON.NodeMaterialBlockConnectionPointTypes;
+        readonly inputBlock: BABYLON.InputBlock;
         /**
          * Constructs the node model
          */
         constructor();
-        renderProperties(globalState: GlobalState): JSX.Element | null;
+        renderProperties(globalState: GlobalState): JSX.Element;
     }
 }
 declare module NODEEDITOR {
@@ -729,7 +730,7 @@ declare module NODEEDITOR {
     }
     export class NodeCreationOptions {
         column: number;
-        nodeMaterialBlock?: BABYLON.NodeMaterialBlock;
+        nodeMaterialBlock: BABYLON.NodeMaterialBlock;
         type?: string;
         connection?: BABYLON.NodeMaterialConnectionPoint;
     }

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


+ 103 - 140
dist/preview release/nodeEditor/babylon.nodeEditor.max.js

@@ -46879,13 +46879,10 @@ var DefaultNodeModel = /** @class */ (function (_super) {
                     model.addAll(link);
                 }
             }
-            else if (!connection.isUndefined) {
+            else {
                 // Create value node for the connection
                 var type = "";
-                if (connection.type == babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Texture) {
-                    type = "Texture";
-                }
-                else if (connection.type == babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Matrix) {
+                if (connection.type == babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Matrix) {
                     type = "Matrix";
                 }
                 else if (connection.type & babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Vector3OrColor3) {
@@ -47328,10 +47325,14 @@ var InputNodeModel = /** @class */ (function (_super) {
     function InputNodeModel() {
         return _super.call(this, "input") || this;
     }
+    Object.defineProperty(InputNodeModel.prototype, "inputBlock", {
+        get: function () {
+            return this.block;
+        },
+        enumerable: true,
+        configurable: true
+    });
     InputNodeModel.prototype.renderProperties = function (globalState) {
-        if (!this.connection) {
-            return null;
-        }
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_inputNodePropertyComponent__WEBPACK_IMPORTED_MODULE_3__["InputPropertyTabComponentProps"], { globalState: globalState, inputNode: this }));
     };
     return InputNodeModel;
@@ -47378,51 +47379,35 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
-
 var InputPropertyTabComponentProps = /** @class */ (function (_super) {
     tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](InputPropertyTabComponentProps, _super);
     function InputPropertyTabComponentProps(props) {
         return _super.call(this, props) || this;
     }
     InputPropertyTabComponentProps.prototype.renderValue = function (globalState) {
-        var connection = this.props.inputNode.connection;
-        switch (connection.type) {
+        var inputBlock = this.props.inputNode.inputBlock;
+        switch (inputBlock.type) {
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Float:
-                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_floatPropertyTabComponent__WEBPACK_IMPORTED_MODULE_9__["FloatPropertyTabComponent"], { globalState: globalState, connection: connection }));
+                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_floatPropertyTabComponent__WEBPACK_IMPORTED_MODULE_9__["FloatPropertyTabComponent"], { globalState: globalState, inputBlock: inputBlock }));
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Vector2:
-                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_vector2PropertyTabComponent__WEBPACK_IMPORTED_MODULE_2__["Vector2PropertyTabComponent"], { globalState: globalState, connection: connection }));
+                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_vector2PropertyTabComponent__WEBPACK_IMPORTED_MODULE_2__["Vector2PropertyTabComponent"], { globalState: globalState, inputBlock: inputBlock }));
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Color3:
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Color3OrColor4:
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Color4:
-                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_color3PropertyTabComponent__WEBPACK_IMPORTED_MODULE_8__["Color3PropertyTabComponent"], { globalState: globalState, connection: connection }));
+                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_color3PropertyTabComponent__WEBPACK_IMPORTED_MODULE_8__["Color3PropertyTabComponent"], { globalState: globalState, inputBlock: inputBlock }));
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Vector3:
             case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Vector3OrColor3:
-                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_vector3PropertyTabComponent__WEBPACK_IMPORTED_MODULE_3__["Vector3PropertyTabComponent"], { globalState: globalState, connection: connection }));
+                return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_propertyTab_properties_vector3PropertyTabComponent__WEBPACK_IMPORTED_MODULE_3__["Vector3PropertyTabComponent"], { globalState: globalState, inputBlock: inputBlock }));
         }
         return null;
     };
     InputPropertyTabComponentProps.prototype.setDefaultValue = function () {
-        var connection = this.props.inputNode.connection;
-        switch (connection.type) {
-            case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Float:
-                connection.value = 0;
-                break;
-            case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Vector2:
-                connection.value = babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["Vector2"].Zero();
-                break;
-            case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Vector3:
-            case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Color3:
-            case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Vector3OrColor3:
-                connection.value = babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["Vector3"].Zero();
-                break;
-            case babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialBlockConnectionPointTypes"].Matrix:
-                connection.value = babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["Matrix"].Identity();
-                break;
-        }
+        var inputBlock = this.props.inputNode.inputBlock;
+        inputBlock.setDefaultValue();
     };
     InputPropertyTabComponentProps.prototype.render = function () {
         var _this = this;
-        var connection = this.props.inputNode.connection;
+        var inputBlock = this.props.inputNode.inputBlock;
         var wellKnownOptions = [
             { label: "World", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].World },
             { label: "WorldxView", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].WorldView },
@@ -47431,7 +47416,7 @@ var InputPropertyTabComponentProps = /** @class */ (function (_super) {
             { label: "ViewxProjection", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].ViewProjection },
             { label: "Projection", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].Projection },
             { label: "Camera position", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].CameraPosition },
-            { label: "Automatic", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].Automatic },
+            { label: "Fog color", value: babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].FogColor },
         ];
         var attributeOptions = [
             { label: "position", value: "position" },
@@ -47443,42 +47428,42 @@ var InputPropertyTabComponentProps = /** @class */ (function (_super) {
         ];
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", null,
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_10__["LineContainerComponent"], { title: "GENERAL" },
-                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_textLineComponent__WEBPACK_IMPORTED_MODULE_7__["TextLineComponent"], { label: "Type", value: _stringTools__WEBPACK_IMPORTED_MODULE_11__["StringTools"].GetBaseType(connection.type) })),
+                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_textLineComponent__WEBPACK_IMPORTED_MODULE_7__["TextLineComponent"], { label: "Type", value: _stringTools__WEBPACK_IMPORTED_MODULE_11__["StringTools"].GetBaseType(this.props.inputNode.outputType) })),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_10__["LineContainerComponent"], { title: "PROPERTIES" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_checkBoxLineComponent__WEBPACK_IMPORTED_MODULE_4__["CheckBoxLineComponent"], { label: "Is mesh attribute", onSelect: function (value) {
                         if (!value) {
-                            connection.isUniform = true;
+                            inputBlock.isUniform = true;
                             _this.setDefaultValue();
                         }
                         else {
-                            connection.isAttribute = true;
+                            inputBlock.isAttribute = true;
                         }
                         _this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         _this.forceUpdate();
-                    }, isSelected: function () { return connection.isAttribute; } }),
-                connection.isAttribute &&
-                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_optionsLineComponent__WEBPACK_IMPORTED_MODULE_6__["OptionsLineComponent"], { label: "Attribute", valuesAreStrings: true, options: attributeOptions, target: connection, propertyName: "name", onSelect: function (value) {
-                            connection.setAsAttribute(value);
+                    }, isSelected: function () { return inputBlock.isAttribute; } }),
+                inputBlock.isAttribute &&
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_optionsLineComponent__WEBPACK_IMPORTED_MODULE_6__["OptionsLineComponent"], { label: "Attribute", valuesAreStrings: true, options: attributeOptions, target: inputBlock, propertyName: "name", onSelect: function (value) {
+                            inputBlock.setAsAttribute(value);
                             _this.forceUpdate();
                             _this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         } }),
-                connection.isUniform &&
+                inputBlock.isUniform &&
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_checkBoxLineComponent__WEBPACK_IMPORTED_MODULE_4__["CheckBoxLineComponent"], { label: "Is well known value", onSelect: function (value) {
                             if (value) {
-                                connection.setAsWellKnownValue(babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].World);
+                                inputBlock.setAsWellKnownValue(babylonjs_Materials_Node_nodeMaterialBlockConnectionPointTypes__WEBPACK_IMPORTED_MODULE_5__["NodeMaterialWellKnownValues"].World);
                             }
                             else {
-                                connection.setAsWellKnownValue(null);
+                                inputBlock.setAsWellKnownValue(null);
                                 _this.setDefaultValue();
                             }
                             _this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                             _this.forceUpdate();
-                        }, isSelected: function () { return connection.isWellKnownValue; } }),
-                connection.isUniform && !connection.isWellKnownValue &&
+                        }, isSelected: function () { return inputBlock.isWellKnownValue; } }),
+                inputBlock.isUniform && !inputBlock.isWellKnownValue &&
                     this.renderValue(this.props.globalState),
-                connection.isUniform && connection.isWellKnownValue &&
-                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_optionsLineComponent__WEBPACK_IMPORTED_MODULE_6__["OptionsLineComponent"], { label: "Well known value", options: wellKnownOptions, target: connection, propertyName: "wellKnownValue", onSelect: function (value) {
-                            connection.setAsWellKnownValue(value);
+                inputBlock.isUniform && inputBlock.isWellKnownValue &&
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_optionsLineComponent__WEBPACK_IMPORTED_MODULE_6__["OptionsLineComponent"], { label: "Well known value", options: wellKnownOptions, target: inputBlock, propertyName: "wellKnownValue", onSelect: function (value) {
+                            inputBlock.setAsWellKnownValue(value);
                             _this.forceUpdate();
                             _this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         } }))));
@@ -47540,15 +47525,15 @@ var InputNodeWidget = /** @class */ (function (_super) {
         if (value) {
             return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", null, value));
         }
-        var connection = this.props.node.connection;
-        if (!connection || !connection.isUniform) {
+        var inputBlock = this.props.node.inputBlock;
+        if (!inputBlock || !inputBlock.isUniform) {
             return null;
         }
-        switch (connection.type) {
+        switch (inputBlock.type) {
             case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialBlockConnectionPointTypes"].Color3:
             case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialBlockConnectionPointTypes"].Color3OrColor4:
             case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialBlockConnectionPointTypes"].Color4: {
-                var color = connection.value;
+                var color = inputBlock.value;
                 return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "fullColor", style: { background: color.toHexString() } }));
             }
         }
@@ -47567,16 +47552,15 @@ var InputNodeWidget = /** @class */ (function (_super) {
                 break;
             }
         }
-        var connection = this.props.node.connection;
+        var inputBlock = this.props.node.inputBlock;
         var value = "";
-        var name = "";
-        if (connection) {
-            name = _stringTools__WEBPACK_IMPORTED_MODULE_4__["StringTools"].GetBaseType(connection.type);
-            if (connection.isAttribute) {
-                value = "mesh." + connection.name;
+        var name = _stringTools__WEBPACK_IMPORTED_MODULE_4__["StringTools"].GetBaseType(this.props.node.outputType);
+        if (inputBlock) {
+            if (inputBlock.isAttribute) {
+                value = "mesh." + inputBlock.name;
             }
-            else if (connection.isWellKnownValue) {
-                switch (connection.wellKnownValue) {
+            else if (inputBlock.isWellKnownValue) {
+                switch (inputBlock.wellKnownValue) {
                     case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialWellKnownValues"].World:
                         value = "World";
                         break;
@@ -47598,7 +47582,7 @@ var InputNodeWidget = /** @class */ (function (_super) {
                     case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialWellKnownValues"].CameraPosition:
                         value = "Camera position";
                         break;
-                    case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialWellKnownValues"].Automatic:
+                    case babylonjs_Materials_Node_nodeMaterialWellKnownValues__WEBPACK_IMPORTED_MODULE_3__["NodeMaterialWellKnownValues"].FogColor:
                         value = "Automatic";
                         break;
                 }
@@ -47607,7 +47591,7 @@ var InputNodeWidget = /** @class */ (function (_super) {
         else {
             name = "Not connected input";
         }
-        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "diagramBlock input" + (connection && connection.isAttribute ? " attribute" : "") },
+        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "diagramBlock input" + (inputBlock && inputBlock.isAttribute ? " attribute" : "") },
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "header" }, name),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "outputs" }, outputPorts),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "value" }, this.renderValue(value))));
@@ -47712,10 +47696,10 @@ var LightNodeModel = /** @class */ (function (_super) {
          * Light for the node if it exists
          */
         get: function () {
-            return this._block.light.value;
+            return this._block.light;
         },
         set: function (value) {
-            this._block.light.value = value;
+            this._block.light = value;
         },
         enumerable: true,
         configurable: true
@@ -47960,10 +47944,10 @@ var TextureNodeModel = /** @class */ (function (_super) {
          * Texture for the node if it exists
          */
         get: function () {
-            return this._block.texture.value;
+            return this._block.texture;
         },
         set: function (value) {
-            this._block.texture.value = value;
+            this._block.texture = value;
         },
         enumerable: true,
         configurable: true
@@ -48072,9 +48056,9 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "../../node_modules/react/index.js");
 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/Textures/texture */ "babylonjs/Misc/observable");
-/* harmony import */ var babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _sharedComponents_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../sharedComponents/fileButtonLineComponent */ "./sharedComponents/fileButtonLineComponent.tsx");
+/* harmony import */ var _sharedComponents_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../sharedComponents/fileButtonLineComponent */ "./sharedComponents/fileButtonLineComponent.tsx");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_3__);
 /* harmony import */ var _sharedComponents_textLineComponent__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../sharedComponents/textLineComponent */ "./sharedComponents/textLineComponent.tsx");
 /* harmony import */ var _sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../sharedComponents/lineContainerComponent */ "./sharedComponents/lineContainerComponent.tsx");
 /* harmony import */ var _sharedComponents_textInputLineComponent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../sharedComponents/textInputLineComponent */ "./sharedComponents/textInputLineComponent.tsx");
@@ -48105,10 +48089,10 @@ var TexturePropertyTabComponent = /** @class */ (function (_super) {
         }
         var texture = this.props.node.texture;
         if (!texture) {
-            this.props.node.texture = new babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_2__["Texture"](null, babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_2__["Engine"].LastCreatedScene);
+            this.props.node.texture = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_3__["Texture"](null, babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_3__["Engine"].LastCreatedScene);
             texture = this.props.node.texture;
         }
-        babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_2__["Tools"].ReadFile(file, function (data) {
+        babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_3__["Tools"].ReadFile(file, function (data) {
             var blob = new Blob([data], { type: "octet/stream" });
             var url = URL.createObjectURL(blob);
             if (texture.isCube) {
@@ -48136,7 +48120,7 @@ var TexturePropertyTabComponent = /** @class */ (function (_super) {
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_textInputLineComponent__WEBPACK_IMPORTED_MODULE_6__["TextInputLineComponent"], { label: "Name", propertyName: "name", target: this.props.node.block, onChange: function () { return _this.props.globalState.onUpdateRequiredObservable.notifyObservers(); } })),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_5__["LineContainerComponent"], { title: "PROPERTIES" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_checkBoxLineComponent__WEBPACK_IMPORTED_MODULE_7__["CheckBoxLineComponent"], { label: "Auto select UV", propertyName: "autoSelectUV", target: this.props.node.block }),
-                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_3__["FileButtonLineComponent"], { label: "Replace texture", onClick: function (file) { return _this.replaceTexture(file); }, accept: ".jpg, .png, .tga, .dds, .env" }))));
+                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_2__["FileButtonLineComponent"], { label: "Replace texture", onClick: function (file) { return _this.replaceTexture(file); }, accept: ".jpg, .png, .tga, .dds, .env" }))));
     };
     return TexturePropertyTabComponent;
 }(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
@@ -48371,7 +48355,7 @@ var Color3PropertyTabComponent = /** @class */ (function (_super) {
     }
     Color3PropertyTabComponent.prototype.render = function () {
         var _this = this;
-        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_color3LineComponent__WEBPACK_IMPORTED_MODULE_2__["Color3LineComponent"], { label: "Value", target: this.props.connection, propertyName: "value", onChange: function () {
+        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_color3LineComponent__WEBPACK_IMPORTED_MODULE_2__["Color3LineComponent"], { label: "Value", target: this.props.inputBlock, propertyName: "value", onChange: function () {
                 _this.props.globalState.onUpdateRequiredObservable.notifyObservers();
             } }));
     };
@@ -48405,7 +48389,7 @@ var FloatPropertyTabComponent = /** @class */ (function (_super) {
         return _super !== null && _super.apply(this, arguments) || this;
     }
     FloatPropertyTabComponent.prototype.render = function () {
-        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_floatLineComponent__WEBPACK_IMPORTED_MODULE_2__["FloatLineComponent"], { label: "Value", target: this.props.connection, propertyName: "value" }));
+        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_floatLineComponent__WEBPACK_IMPORTED_MODULE_2__["FloatLineComponent"], { label: "Value", target: this.props.inputBlock, propertyName: "value" }));
     };
     return FloatPropertyTabComponent;
 }(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
@@ -48437,7 +48421,7 @@ var Vector2PropertyTabComponent = /** @class */ (function (_super) {
         return _super !== null && _super.apply(this, arguments) || this;
     }
     Vector2PropertyTabComponent.prototype.render = function () {
-        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_vector2LineComponent__WEBPACK_IMPORTED_MODULE_2__["Vector2LineComponent"], { label: "Value", target: this.props.connection, propertyName: "value" }));
+        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_vector2LineComponent__WEBPACK_IMPORTED_MODULE_2__["Vector2LineComponent"], { label: "Value", target: this.props.inputBlock, propertyName: "value" }));
     };
     return Vector2PropertyTabComponent;
 }(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
@@ -48469,7 +48453,7 @@ var Vector3PropertyTabComponent = /** @class */ (function (_super) {
         return _super !== null && _super.apply(this, arguments) || this;
     }
     Vector3PropertyTabComponent.prototype.render = function () {
-        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_vector3LineComponent__WEBPACK_IMPORTED_MODULE_2__["Vector3LineComponent"], { label: "Value", target: this.props.connection, propertyName: "value" }));
+        return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_vector3LineComponent__WEBPACK_IMPORTED_MODULE_2__["Vector3LineComponent"], { label: "Value", target: this.props.inputBlock, propertyName: "value" }));
     };
     return Vector3PropertyTabComponent;
 }(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
@@ -48738,6 +48722,7 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
+
 __webpack_require__(/*! storm-react-diagrams/dist/style.min.css */ "../../node_modules/storm-react-diagrams/dist/style.min.css");
 __webpack_require__(/*! ./main.scss */ "./main.scss");
 __webpack_require__(/*! ./components/diagram/diagram.scss */ "./components/diagram/diagram.scss");
@@ -48804,27 +48789,24 @@ var GraphEditor = /** @class */ (function (_super) {
         // Create new node in the graph
         var newNode;
         var filterInputs = [];
-        if (options.nodeMaterialBlock) {
-            if (options.nodeMaterialBlock instanceof babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["TextureBlock"]) {
-                newNode = new _components_diagram_texture_textureNodeModel__WEBPACK_IMPORTED_MODULE_9__["TextureNodeModel"]();
-                filterInputs.push("uv");
-            }
-            else if (options.nodeMaterialBlock instanceof babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["LightBlock"]) {
-                newNode = new _components_diagram_light_lightNodeModel__WEBPACK_IMPORTED_MODULE_15__["LightNodeModel"]();
-                filterInputs.push("worldPosition");
-                filterInputs.push("worldNormal");
-                filterInputs.push("cameraPosition");
-            }
-            else {
-                newNode = new _components_diagram_generic_genericNodeModel__WEBPACK_IMPORTED_MODULE_4__["GenericNodeModel"]();
-            }
-            if (options.nodeMaterialBlock.isFinalMerger) {
-                this.props.globalState.nodeMaterial.addOutputNode(options.nodeMaterialBlock);
-            }
+        if (options.nodeMaterialBlock instanceof babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["TextureBlock"]) {
+            newNode = new _components_diagram_texture_textureNodeModel__WEBPACK_IMPORTED_MODULE_9__["TextureNodeModel"]();
+            filterInputs.push("uv");
         }
-        else {
+        else if (options.nodeMaterialBlock instanceof babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["LightBlock"]) {
+            newNode = new _components_diagram_light_lightNodeModel__WEBPACK_IMPORTED_MODULE_15__["LightNodeModel"]();
+            filterInputs.push("worldPosition");
+            filterInputs.push("worldNormal");
+            filterInputs.push("cameraPosition");
+        }
+        else if (options.nodeMaterialBlock instanceof babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["InputBlock"]) {
             newNode = new _components_diagram_input_inputNodeModel__WEBPACK_IMPORTED_MODULE_12__["InputNodeModel"]();
-            newNode.connection = options.connection;
+        }
+        else {
+            newNode = new _components_diagram_generic_genericNodeModel__WEBPACK_IMPORTED_MODULE_4__["GenericNodeModel"]();
+        }
+        if (options.nodeMaterialBlock.isFinalMerger) {
+            this.props.globalState.nodeMaterial.addOutputNode(options.nodeMaterialBlock);
         }
         this._nodes.push(newNode);
         newNode.setPosition(1600 - (300 * options.column), 210 * this._rowPos[options.column]);
@@ -48887,14 +48869,6 @@ var GraphEditor = /** @class */ (function (_super) {
                                 link.input.syncWithNodeMaterialConnectionPoint(link.input.connection);
                                 link.output.syncWithNodeMaterialConnectionPoint(link.output.connection);
                             }
-                            else {
-                                var inputNode = link.output.parent;
-                                inputNode.connection = undefined;
-                                if (link.input.connection.value) {
-                                    inputNode.ports[link.output.name].defaultValue = link.input.connection.value;
-                                    link.input.connection.value = null;
-                                }
-                            }
                         }
                     }
                 }
@@ -48909,15 +48883,6 @@ var GraphEditor = /** @class */ (function (_super) {
                             if (link.output.connection && link.input.connection) {
                                 link.output.connection.connectTo(link.input.connection);
                             }
-                            else if (link.input.connection) {
-                                if (!link.output.connection) { // Input Node
-                                    var name_1 = link.output.name;
-                                    link.output.syncWithNodeMaterialConnectionPoint(link.input.connection);
-                                    link.output.name = name_1;
-                                    link.output.getNode().connection = link.output.connection;
-                                    link.input.connection.value = link.output.defaultValue;
-                                }
-                            }
                             if (_this.props.globalState.nodeMaterial) {
                                 _this.buildMaterial();
                             }
@@ -48962,34 +48927,32 @@ var GraphEditor = /** @class */ (function (_super) {
     };
     GraphEditor.prototype.addValueNode = function (type, column, connection) {
         if (column === void 0) { column = 0; }
-        var localNode = this.createNodeFromObject({ column: column, type: type, connection: connection });
-        var outPort = new _components_diagram_defaultPortModel__WEBPACK_IMPORTED_MODULE_10__["DefaultPortModel"](type, "output");
-        localNode.addPort(outPort);
-        if (!connection) {
-            switch (type) {
-                case "Float":
-                    outPort.defaultValue = 0;
-                    break;
-                case "Vector2":
-                    outPort.defaultValue = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["Vector2"].Zero();
-                    break;
-                case "Vector3":
-                    outPort.defaultValue = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["Vector3"].Zero();
-                    break;
-                case "Vector4":
-                    outPort.defaultValue = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["Vector4"].Zero();
-                    break;
-                case "Matrix":
-                    outPort.defaultValue = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["Matrix"].Identity();
-                    break;
-                case "Color3":
-                    outPort.defaultValue = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["Color3"].White();
-                    break;
-                case "Color4":
-                    outPort.defaultValue = new babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["Color4"](1, 1, 1, 1);
-                    break;
-            }
+        var nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Vector3;
+        switch (type) {
+            case "Float":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Float;
+                break;
+            case "Vector2":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Vector2;
+                break;
+            case "Vector3":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Vector3;
+                break;
+            case "Vector4":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Vector4;
+                break;
+            case "Matrix":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Matrix;
+                break;
+            case "Color3":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Color3;
+                break;
+            case "Color4":
+                nodeType = babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["NodeMaterialBlockConnectionPointTypes"].Color4;
+                break;
         }
+        var newInputBlock = new babylonjs_Materials_Node_Blocks_Fragment_textureBlock__WEBPACK_IMPORTED_MODULE_13__["InputBlock"](type, undefined, nodeType);
+        var localNode = this.createNodeFromObject({ column: column, type: type, connection: connection, nodeMaterialBlock: newInputBlock });
         return localNode;
     };
     GraphEditor.prototype.onPointerDown = function (evt) {

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


+ 27 - 24
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts

@@ -304,7 +304,7 @@ declare module "babylonjs-node-editor/components/diagram/texture/textureProperty
 }
 declare module "babylonjs-node-editor/components/diagram/texture/textureNodeModel" {
     import { Nullable } from 'babylonjs/types';
-    import { Texture } from 'babylonjs/Materials/Textures/texture';
+    import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
     import { DefaultNodeModel } from "babylonjs-node-editor/components/diagram/defaultNodeModel";
     import { GlobalState } from "babylonjs-node-editor/globalState";
     import { NodeCreationOptions, GraphEditor } from "babylonjs-node-editor/graphEditor";
@@ -317,7 +317,7 @@ declare module "babylonjs-node-editor/components/diagram/texture/textureNodeMode
         /**
          * Texture for the node if it exists
          */
-        texture: Nullable<Texture>;
+        texture: Nullable<BaseTexture>;
         /**
          * Constructs the node model
          */
@@ -467,10 +467,10 @@ declare module "babylonjs-node-editor/sharedComponents/vector2LineComponent" {
 declare module "babylonjs-node-editor/components/propertyTab/properties/vector2PropertyTabComponent" {
     import * as React from "react";
     import { GlobalState } from "babylonjs-node-editor/globalState";
-    import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+    import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
     interface IVector2PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: NodeMaterialConnectionPoint;
+        inputBlock: InputBlock;
     }
     export class Vector2PropertyTabComponent extends React.Component<IVector2PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -514,10 +514,10 @@ declare module "babylonjs-node-editor/sharedComponents/vector3LineComponent" {
 declare module "babylonjs-node-editor/components/propertyTab/properties/vector3PropertyTabComponent" {
     import * as React from "react";
     import { GlobalState } from "babylonjs-node-editor/globalState";
-    import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+    import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
     interface IVector3PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: NodeMaterialConnectionPoint;
+        inputBlock: InputBlock;
     }
     export class Vector3PropertyTabComponent extends React.Component<IVector3PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -590,10 +590,10 @@ declare module "babylonjs-node-editor/sharedComponents/color3LineComponent" {
 declare module "babylonjs-node-editor/components/propertyTab/properties/color3PropertyTabComponent" {
     import * as React from "react";
     import { GlobalState } from "babylonjs-node-editor/globalState";
-    import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+    import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
     interface IColor3PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: NodeMaterialConnectionPoint;
+        inputBlock: InputBlock;
     }
     export class Color3PropertyTabComponent extends React.Component<IColor3PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -631,10 +631,10 @@ declare module "babylonjs-node-editor/sharedComponents/floatLineComponent" {
 declare module "babylonjs-node-editor/components/propertyTab/properties/floatPropertyTabComponent" {
     import * as React from "react";
     import { GlobalState } from "babylonjs-node-editor/globalState";
-    import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+    import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
     interface IFloatPropertyTabComponentProps {
         globalState: GlobalState;
-        connection: NodeMaterialConnectionPoint;
+        inputBlock: InputBlock;
     }
     export class FloatPropertyTabComponent extends React.Component<IFloatPropertyTabComponentProps> {
         render(): JSX.Element;
@@ -667,18 +667,20 @@ declare module "babylonjs-node-editor/components/diagram/input/inputNodeProperty
 }
 declare module "babylonjs-node-editor/components/diagram/input/inputNodeModel" {
     import { DefaultNodeModel } from "babylonjs-node-editor/components/diagram/defaultNodeModel";
-    import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
     import { GlobalState } from "babylonjs-node-editor/globalState";
+    import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
+    import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
     /**
      * Generic node model which stores information about a node editor block
      */
     export class InputNodeModel extends DefaultNodeModel {
-        connection?: NodeMaterialConnectionPoint;
+        outputType: NodeMaterialBlockConnectionPointTypes;
+        readonly inputBlock: InputBlock;
         /**
          * Constructs the node model
          */
         constructor();
-        renderProperties(globalState: GlobalState): JSX.Element | null;
+        renderProperties(globalState: GlobalState): JSX.Element;
     }
 }
 declare module "babylonjs-node-editor/components/diagram/input/inputNodeWidget" {
@@ -852,7 +854,7 @@ declare module "babylonjs-node-editor/graphEditor" {
     }
     export class NodeCreationOptions {
         column: number;
-        nodeMaterialBlock?: NodeMaterialBlock;
+        nodeMaterialBlock: NodeMaterialBlock;
         type?: string;
         connection?: NodeMaterialConnectionPoint;
     }
@@ -1234,14 +1236,14 @@ declare module NODEEDITOR {
 }
 declare module NODEEDITOR {
     /**
-     * BABYLON.Texture node model which stores information about a node editor block
+     * Texture node model which stores information about a node editor block
      */
     export class TextureNodeModel extends DefaultNodeModel {
         private _block;
         /**
-         * BABYLON.Texture for the node if it exists
+         * Texture for the node if it exists
          */
-        texture: BABYLON.Nullable<BABYLON.Texture>;
+        texture: BABYLON.Nullable<BABYLON.BaseTexture>;
         /**
          * Constructs the node model
          */
@@ -1377,7 +1379,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IVector2PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class Vector2PropertyTabComponent extends React.Component<IVector2PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -1417,7 +1419,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IVector3PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class Vector3PropertyTabComponent extends React.Component<IVector3PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -1483,7 +1485,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IColor3PropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class Color3PropertyTabComponent extends React.Component<IColor3PropertyTabComponentProps> {
         render(): JSX.Element;
@@ -1518,7 +1520,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     interface IFloatPropertyTabComponentProps {
         globalState: GlobalState;
-        connection: BABYLON.NodeMaterialConnectionPoint;
+        inputBlock: BABYLON.InputBlock;
     }
     export class FloatPropertyTabComponent extends React.Component<IFloatPropertyTabComponentProps> {
         render(): JSX.Element;
@@ -1550,12 +1552,13 @@ declare module NODEEDITOR {
      * Generic node model which stores information about a node editor block
      */
     export class InputNodeModel extends DefaultNodeModel {
-        connection?: BABYLON.NodeMaterialConnectionPoint;
+        outputType: BABYLON.NodeMaterialBlockConnectionPointTypes;
+        readonly inputBlock: BABYLON.InputBlock;
         /**
          * Constructs the node model
          */
         constructor();
-        renderProperties(globalState: GlobalState): JSX.Element | null;
+        renderProperties(globalState: GlobalState): JSX.Element;
     }
 }
 declare module NODEEDITOR {
@@ -1698,7 +1701,7 @@ declare module NODEEDITOR {
     }
     export class NodeCreationOptions {
         column: number;
-        nodeMaterialBlock?: BABYLON.NodeMaterialBlock;
+        nodeMaterialBlock: BABYLON.NodeMaterialBlock;
         type?: string;
         connection?: BABYLON.NodeMaterialConnectionPoint;
     }

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


File diff suppressed because it is too large
+ 746 - 1186
localDev/src/webgl-debug.js


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

@@ -1,7 +1,6 @@
 import { NodeModel, DiagramModel } from "storm-react-diagrams";
 import { Nullable } from 'babylonjs/types';
 import { NodeMaterialBlock } from 'babylonjs/Materials/Node/nodeMaterialBlock';
-import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { GraphEditor, NodeCreationOptions } from '../../graphEditor';
 import { GlobalState } from '../../globalState';
 import { DefaultPortModel } from './defaultPortModel';
@@ -52,7 +51,7 @@ export class DefaultNodeModel extends NodeModel {
                 var connectedNode;
                 var existingNodes = nodes.filter((n) => { return n.block === (connection as any)._connectedPoint._ownerBlock });
                 if (existingNodes.length == 0) {
-                    connectedNode = graphEditor.createNodeFromObject({ column: options.column + 1, nodeMaterialBlock: connection.connectedPoint._ownerBlock });
+                    connectedNode = graphEditor.createNodeFromObject({ nodeMaterialBlock: connection.connectedPoint._ownerBlock });
                 } else {
                     connectedNode = existingNodes[0];
                 }
@@ -63,37 +62,6 @@ export class DefaultNodeModel extends NodeModel {
                 } else {
                     model.addAll(link);
                 }
-            } else if (!connection.isUndefined) {
-                // Create value node for the connection
-                var type = ""
-                if (connection.type == NodeMaterialBlockConnectionPointTypes.Texture) {
-                    type = "Texture"
-                } else if (connection.type == NodeMaterialBlockConnectionPointTypes.Matrix) {
-                    type = "Matrix"
-                } else if (connection.type & NodeMaterialBlockConnectionPointTypes.Vector3OrColor3) {
-                    type = "Vector3"
-                } else if (connection.type & NodeMaterialBlockConnectionPointTypes.Vector2) {
-                    type = "Vector2"
-                } else if (connection.type & NodeMaterialBlockConnectionPointTypes.Vector3OrColor3OrVector4OrColor4) {
-                    type = "Vector4"
-                }
-                else if (connection.type & NodeMaterialBlockConnectionPointTypes.Float) {
-                    type = "Float"
-                }
-
-                // Create links
-                var localNode = graphEditor.addValueNode(type, options.column + 1, connection);
-                if (localNode) {
-                    var ports = localNode.getPorts()
-                    for (var key in ports) {
-                        let link = (ports[key] as DefaultPortModel).link(inputPort);
-                        if (graphEditor._toAdd) {
-                            graphEditor._toAdd.push(link);
-                        } else {
-                            model.addAll(link);
-                        }
-                    }
-                }
             }
         });
     }

+ 67 - 19
nodeEditor/src/components/diagram/diagram.scss

@@ -2,18 +2,45 @@
     width: 200px;
 }
 
+.srd-node--selected > * {
+    border: 4px solid  rgb(0, 192, 255) !important;
+    border-radius: 20px;
+}
+          
+.srd-port {
+    background: rgb(0, 192, 255);
+    border-radius: 10px;
+    border: black 4px solid;
+
+    &.connected {
+        background: #CAB422;
+    }
+}
+
 .diagramBlock {
     background: white;
     width: 100%;
     border: 4px solid black;
+    border-radius: 20px;
+    display: grid;
+    grid-template-rows: 30px auto;
+    grid-template-columns: 50% 50%;
 
     &.input {
-        background: green;
+        background: #40866E;
         color:white;
+
+        .value {
+            grid-row: 2;
+        }
+
+        .outputs {
+            transform: translateY(5px);
+        }
     }
 
     &.attribute {
-        background: orange;
+        background: #40866E;
     }
 
     &.output {
@@ -25,31 +52,51 @@
         }
     }
 
-    .header {
-        margin: 10px;
+    .header {            
+        grid-row: 1;
+        grid-column: 1 / span 2;
+        border: 4px solid black;
+        border-top-right-radius: 16px;
+        border-top-left-radius: 16px;
         font-size: 16px;
         text-align: center;
+        margin: -1px;
         
         white-space: nowrap;
         text-overflow: ellipsis;
         overflow: hidden;
+        background: black;
+        color: white;
     }
 
     .value {
+        grid-row: 3;
+        grid-column: 1 / span 2;
         height: 34px;
         text-align: center;
-        font-size: 20px;
+        font-size: 18px;
         font-weight: bold;
+        margin: 0 10px;
 
-        .fullColor {
-            height: 100%;
+        .value-text {
+            white-space: nowrap;
+            text-overflow: ellipsis;
+            overflow: hidden;
         }
     }
 
+    .preview {
+        border-bottom-left-radius: 16px;
+        border-bottom-right-radius: 16px;
+        padding-top: 2px;
+    }
+
     .inputs {
+        grid-row: 2;
+        grid-column: 1;
         .input-port {
             display: grid;
-            grid-template-columns: 4px calc(100% - 4px);
+            grid-template-columns: 10px calc(100% - 10px);
             grid-template-rows: 100%;
 
             .input-port-plug {
@@ -58,25 +105,27 @@
                 display: grid;
                 align-content: center;
                 margin-left: -11px;
-                
-                .srd-port {
-                    background: grey;
-                }
+
             }
 
             .input-port-label {
                 margin-left: 10px;
                 grid-column: 2;
                 grid-row: 1;         
-                margin-bottom: 2px;       
+                margin-bottom: 2px;    
+                overflow: hidden;
+                white-space: nowrap;
+                text-overflow: ellipsis;   
             }
         }
     }
 
     .outputs {
+        grid-row: 2;
+        grid-column: 2;
         .output-port {
             display: grid;
-            grid-template-columns: calc(100% - 4px) 4px;
+            grid-template-columns: calc(100% - 10px) 10px;
             grid-template-rows: 100%;
 
             .output-port-plug {
@@ -84,10 +133,6 @@
                 grid-row: 1;
                 display: grid;
                 align-content: center;
-
-                .srd-port {
-                    background: grey;
-                }
             }
 
             .output-port-label {
@@ -95,7 +140,10 @@
                 margin-right: 10px;
                 grid-column: 1;
                 grid-row: 1;                        
-                margin-bottom: 2px;        
+                margin-bottom: 2px;   
+                overflow: hidden;
+                white-space: nowrap;
+                text-overflow: ellipsis;   
             }
         }
     }

+ 8 - 37
nodeEditor/src/components/diagram/generic/genericNodeWidget.tsx

@@ -1,9 +1,8 @@
 import * as React from "react";
-import { PortWidget } from "storm-react-diagrams";
-import { DefaultPortModel } from '../defaultPortModel';
 import { Nullable } from 'babylonjs/types';
 import { GlobalState } from '../../../globalState';
 import { GenericNodeModel } from './genericNodeModel';
+import { PortHelper } from '../portHelper';
 
 /**
  * GenericNodeWidgetProps
@@ -43,44 +42,16 @@ export class GenericNodeWidget extends React.Component<GenericNodeWidgetProps, G
     }
 
     render() {
+        // Header label
         var header = "";
-        var inputPorts = new Array<JSX.Element>()
-        var outputPorts = new Array<JSX.Element>()
-        if (this.props.node) {
-            // Header label
-            if (this.props.node.block) {
-                header = this.props.node.block.name;
-            }
-
-            // Input/Output ports
-            for (var key in this.props.node.ports) {
-                var port = this.props.node.ports[key] as DefaultPortModel;
-                if (port.position === "input") {
-                    inputPorts.push(
-                        <div key={key} className="input-port">
-                            <div className="input-port-plug">
-                                <PortWidget key={key} name={port.name} node={this.props.node} />
-                            </div>
-                            <div className="input-port-label">
-                                {port.name}
-                            </div>
-                        </div>
-                    )
-                } else {
-                    outputPorts.push(
-                        <div key={key} className="output-port">
-                            <div className="output-port-label">
-                                {port.name}
-                            </div>
-                            <div className="output-port-plug">
-                                <PortWidget key={key} name={port.name} node={this.props.node} />
-                            </div>
-                        </div>
-                    )
-                }
-            }
+        if (this.props.node && this.props.node.block) {
+            header = this.props.node.block.name;
         }
 
+        // Input/Output ports
+        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, false);
+        var inputPorts = PortHelper.GenerateInputPorts(this.props.node);
+
         return (
             <div className={"diagramBlock" + (outputPorts.length === 0 ? " output" : "")}>
                 <div className="header">

+ 5 - 6
nodeEditor/src/components/diagram/input/inputNodeModel.tsx

@@ -1,14 +1,17 @@
 import * as React from "react";
 import { DefaultNodeModel } from '../defaultNodeModel';
-import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
 import { GlobalState } from '../../../globalState';
 import { InputPropertyTabComponentProps } from './inputNodePropertyComponent';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 
 /**
  * Generic node model which stores information about a node editor block
  */
 export class InputNodeModel extends DefaultNodeModel {
-    public connection?: NodeMaterialConnectionPoint;
+
+    public get inputBlock(): InputBlock {
+        return this.block as InputBlock;
+    }
 
 	/**
 	 * Constructs the node model
@@ -18,10 +21,6 @@ export class InputNodeModel extends DefaultNodeModel {
     }
 
     renderProperties(globalState: GlobalState) {
-        if (!this.connection) {
-            return null;
-        }
-
         return (
             <InputPropertyTabComponentProps globalState={globalState} inputNode={this} />
         );

+ 26 - 41
nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx

@@ -8,7 +8,6 @@ import { InputNodeModel } from './inputNodeModel';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { OptionsLineComponent } from '../../../sharedComponents/optionsLineComponent';
 import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
-import { Vector2, Vector3, Matrix } from 'babylonjs/Maths/math';
 import { TextLineComponent } from '../../../sharedComponents/textLineComponent';
 import { Color3PropertyTabComponent } from '../../propertyTab/properties/color3PropertyTabComponent';
 import { FloatPropertyTabComponent } from '../../propertyTab/properties/floatPropertyTabComponent';
@@ -27,53 +26,39 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
     }
 
     renderValue(globalState: GlobalState) {
-        let connection = this.props.inputNode.connection!;
-        switch (connection.type) {
+        let inputBlock = this.props.inputNode.inputBlock;
+        switch (inputBlock.type) {
             case NodeMaterialBlockConnectionPointTypes.Float:
                 return (
-                    <FloatPropertyTabComponent globalState={globalState} connection={connection} />
+                    <FloatPropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
                 );
             case NodeMaterialBlockConnectionPointTypes.Vector2:
                 return (
-                    <Vector2PropertyTabComponent globalState={globalState} connection={connection} />
+                    <Vector2PropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
                 );
             case NodeMaterialBlockConnectionPointTypes.Color3:
             case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
             case NodeMaterialBlockConnectionPointTypes.Color4:
                 return (
-                    <Color3PropertyTabComponent globalState={globalState} connection={connection} />
+                    <Color3PropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
                 );
             case NodeMaterialBlockConnectionPointTypes.Vector3:
             case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3:
                 return (
-                    <Vector3PropertyTabComponent globalState={globalState} connection={connection} />
+                    <Vector3PropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
                 );
         }
+
         return null;
     }
 
     setDefaultValue() {
-        let connection = this.props.inputNode.connection!;
-        switch (connection.type) {
-            case NodeMaterialBlockConnectionPointTypes.Float:
-                connection.value = 0;
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Vector2:
-                connection.value = Vector2.Zero();
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Vector3:
-            case NodeMaterialBlockConnectionPointTypes.Color3:
-            case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3:
-                connection.value = Vector3.Zero();
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Matrix:
-                connection.value = Matrix.Identity();
-                break;
-        }
+        let inputBlock = this.props.inputNode.inputBlock;
+        inputBlock.setDefaultValue();
     }
 
     render() {
-        let connection = this.props.inputNode.connection!;
+        let inputBlock = this.props.inputNode.inputBlock;
 
         var wellKnownOptions = [
             { label: "World", value: NodeMaterialWellKnownValues.World },
@@ -83,7 +68,7 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
             { label: "ViewxProjection", value: NodeMaterialWellKnownValues.ViewProjection },
             { label: "Projection", value: NodeMaterialWellKnownValues.Projection },
             { label: "Camera position", value: NodeMaterialWellKnownValues.CameraPosition },
-            { label: "Automatic", value: NodeMaterialWellKnownValues.Automatic },
+            { label: "Fog color", value: NodeMaterialWellKnownValues.FogColor },
         ];
 
         var attributeOptions = [
@@ -98,48 +83,48 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
         return (
             <div>
                 <LineContainerComponent title="GENERAL">
-                    <TextLineComponent label="Type" value={StringTools.GetBaseType(connection.type)} />
+                    <TextLineComponent label="Type" value={StringTools.GetBaseType(inputBlock.type)} />
                 </LineContainerComponent>
                 <LineContainerComponent title="PROPERTIES">
                     <CheckBoxLineComponent label="Is mesh attribute" onSelect={value => {
                         if (!value) {
-                            connection.isUniform = true;
+                            inputBlock.isUniform = true;
                             this.setDefaultValue();
                         } else {
-                            connection.isAttribute = true;
+                            inputBlock.isAttribute = true;
                         }
                         this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         this.forceUpdate();
-                    }} isSelected={() => connection!.isAttribute} />
+                    }} isSelected={() => inputBlock.isAttribute} />
                     {
-                        connection.isAttribute &&
-                        <OptionsLineComponent label="Attribute" valuesAreStrings={true} options={attributeOptions} target={connection} propertyName="name" onSelect={(value: any) => {
-                            connection.setAsAttribute(value);
+                        inputBlock.isAttribute &&
+                        <OptionsLineComponent label="Attribute" valuesAreStrings={true} options={attributeOptions} target={inputBlock} propertyName="name" onSelect={(value: any) => {
+                            inputBlock.setAsAttribute(value);
                             this.forceUpdate();
                             this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         }} />
                     }
                     {
-                        connection.isUniform &&
+                        inputBlock.isUniform &&
                         <CheckBoxLineComponent label="Is well known value" onSelect={value => {
                             if (value) {
-                                connection!.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+                                inputBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
                             } else {
-                                connection!.setAsWellKnownValue(null);
+                                inputBlock.setAsWellKnownValue(null);
                                 this.setDefaultValue();
                             }
                             this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                             this.forceUpdate();
-                        }} isSelected={() => connection!.isWellKnownValue} />
+                        }} isSelected={() => inputBlock.isWellKnownValue} />
                     }
                     {
-                        connection.isUniform && !connection.isWellKnownValue &&
+                        inputBlock.isUniform && !inputBlock.isWellKnownValue &&
                         this.renderValue(this.props.globalState)
                     }
                     {
-                        connection.isUniform && connection.isWellKnownValue &&
-                        <OptionsLineComponent label="Well known value" options={wellKnownOptions} target={connection} propertyName="wellKnownValue" onSelect={(value: any) => {
-                            connection.setAsWellKnownValue(value);
+                        inputBlock.isUniform && inputBlock.isWellKnownValue &&
+                        <OptionsLineComponent label="Well known value" options={wellKnownOptions} target={inputBlock} propertyName="wellKnownValue" onSelect={(value: any) => {
+                            inputBlock.setAsWellKnownValue(value);
                             this.forceUpdate();
                             this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         }} />

+ 28 - 49
nodeEditor/src/components/diagram/input/inputNodeWidget.tsx

@@ -1,13 +1,12 @@
 import * as React from "react";
-import { PortWidget } from "storm-react-diagrams";
 import { InputNodeModel } from './inputNodeModel';
 import { Nullable } from 'babylonjs/types';
 import { GlobalState } from '../../../globalState';
-import { DefaultPortModel } from '../defaultPortModel';
 import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { Color3 } from 'babylonjs/Maths/math';
 import { StringTools } from '../../../stringTools';
+import { PortHelper } from '../portHelper';
 
 /**
  * GenericNodeWidgetProps
@@ -42,62 +41,28 @@ export class InputNodeWidget extends React.Component<InputNodeWidgetProps> {
     renderValue(value: string) {
         if (value) {
             return (
-                <div>
+                <div className="value-text">
                     {value}
                 </div>
             )
         }
 
-        let connection = this.props.node!.connection;
-        if (!connection || !connection.isUniform) {
-            return null;
-        }
-
-        switch (connection.type) {
-            case NodeMaterialBlockConnectionPointTypes.Color3:
-            case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
-            case NodeMaterialBlockConnectionPointTypes.Color4: {
-                let color = connection.value as Color3;
-                return (
-                    <div className="fullColor" style={{ background: color.toHexString() }}></div>
-                )
-            }
-        }
-
         return null;
     }
 
     render() {
-        var outputPorts = new Array<JSX.Element>()
-        let port: DefaultPortModel;
-        if (this.props.node) {
-            for (var key in this.props.node.ports) {
-                port = this.props.node.ports[key] as DefaultPortModel;
-
-                outputPorts.push(
-                    <div key={key} className="output-port">
-                        <div className="output-port-label">
-                        </div>
-                        <div className="output-port-plug">
-                            <PortWidget key={key} name={port.name} node={this.props.node} />
-                        </div>
-                    </div>
-                );
-                break;
-            }
-        }
+        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, true);
 
-        let connection = this.props.node!.connection;
+        let inputBlock = this.props.node!.inputBlock;
         let value = "";
-        let name = "";
+        let name = StringTools.GetBaseType(inputBlock.output.type);
+        let color = "";
 
-        if (connection) {
-            name = StringTools.GetBaseType(connection.type)
-
-            if (connection.isAttribute) {
-                value = "mesh." + connection.name;
-            } else if (connection.isWellKnownValue) {
-                switch (connection.wellKnownValue) {
+        if (inputBlock) {
+            if (inputBlock.isAttribute) {
+                value = "mesh." + inputBlock.name;
+            } else if (inputBlock.isWellKnownValue) {
+                switch (inputBlock.wellKnownValue) {
                     case NodeMaterialWellKnownValues.World:
                         value = "World";
                         break;
@@ -119,17 +84,31 @@ export class InputNodeWidget extends React.Component<InputNodeWidgetProps> {
                     case NodeMaterialWellKnownValues.CameraPosition:
                         value = "Camera position";
                         break;
-                    case NodeMaterialWellKnownValues.Automatic:
-                        value = "Automatic";
+                    case NodeMaterialWellKnownValues.FogColor:
+                        value = "Fog color";
                         break;
                 }
+            } else {
+                if (!inputBlock || !inputBlock.isUniform) {
+                    return null;
+                }
+
+                switch (inputBlock.type) {
+                    case NodeMaterialBlockConnectionPointTypes.Color3:
+                    case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
+                    case NodeMaterialBlockConnectionPointTypes.Color4: {
+                        color = (inputBlock.value as Color3).toHexString();
+                    }
+                }
             }
         } else {
             name = "Not connected input";
         }
 
         return (
-            <div className={"diagramBlock input" + (connection && connection.isAttribute ? " attribute" : "")}>
+            <div className={"diagramBlock input" + (inputBlock && inputBlock.isAttribute ? " attribute" : "")} style={{
+                background: color
+            }}>
                 <div className="header">
                     {name}
                 </div>

+ 2 - 2
nodeEditor/src/components/diagram/light/lightNodeModel.tsx

@@ -18,11 +18,11 @@ export class LightNodeModel extends DefaultNodeModel {
 	 * Light for the node if it exists
 	 */
     public get light(): Nullable<Light> {
-        return this._block.light.value;
+        return this._block.light;
     }
 
     public set light(value: Nullable<Light>) {
-        this._block.light.value = value;
+        this._block.light = value;
     }
 
 	/**

+ 4 - 35
nodeEditor/src/components/diagram/light/lightNodeWidget.tsx

@@ -1,9 +1,8 @@
 import * as React from "react";
-import { PortWidget } from "storm-react-diagrams";
 import { LightNodeModel } from './lightNodeModel';
 import { Nullable } from 'babylonjs/types';
 import { GlobalState } from '../../../globalState';
-import { DefaultPortModel } from '../defaultPortModel';
+import { PortHelper } from '../portHelper';
 
 /**
  * GenericNodeWidgetProps
@@ -36,39 +35,9 @@ export class LightNodeWidget extends React.Component<ILightNodeWidgetProps> {
     }
 
     render() {
-        var inputPorts = new Array<JSX.Element>();
-        var outputPorts = new Array<JSX.Element>();
-        if (this.props.node) {
-            // Input/Output ports
-            for (var key in this.props.node.ports) {
-                var port = this.props.node.ports[key] as DefaultPortModel;
-                if (port.position === "input") {
-                    if (port.name !== "light") {
-                        inputPorts.push(
-                            <div key={key} className="input-port">
-                                <div className="input-port-plug">
-                                    <PortWidget key={key} name={port.name} node={this.props.node} />
-                                </div>
-                                <div className="input-port-label">
-                                    {port.name}
-                                </div>
-                            </div>
-                        )
-                    }
-                } else {
-                    outputPorts.push(
-                        <div key={key} className="output-port">
-                            <div className="output-port-label">
-                                {port.name}
-                            </div>
-                            <div className="output-port-plug">
-                                <PortWidget key={key} name={port.name} node={this.props.node} />
-                            </div>
-                        </div>
-                    )
-                }
-            }
-        }
+        // Input/Output ports
+        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, false);
+        var inputPorts = PortHelper.GenerateInputPorts(this.props.node);
 
         return (
             <div className={"diagramBlock"}>

+ 61 - 0
nodeEditor/src/components/diagram/portHelper.tsx

@@ -0,0 +1,61 @@
+import * as React from "react";
+import { PortWidget } from "storm-react-diagrams";
+import { DefaultNodeModel } from './defaultNodeModel';
+import { DefaultPortModel } from './defaultPortModel';
+import { Nullable } from 'babylonjs/types';
+
+
+export class PortHelper {
+    public static GenerateOutputPorts(node: Nullable<DefaultNodeModel>, ignoreLabel: boolean) {
+        if (!node) {
+            return new Array<JSX.Element>();
+        }
+        let outputPorts = [];
+        for (var key in node.ports) {
+            let port = node.ports[key] as DefaultPortModel;
+            if (port.position === "output") {
+                outputPorts.push(
+                    <div key={key} className="output-port">
+                        {
+                            !ignoreLabel &&
+                            <div className="output-port-label">
+                                {port.name}
+                            </div>
+                        }
+                        <div className="output-port-plug">
+                            <PortWidget key={key} name={port.name} node={node} className={port.connection && port.connection.endpoints.length > 0 ? "connected" : ""} />
+                        </div>
+                    </div>
+                );
+            }
+        }
+
+        return outputPorts;
+    }
+
+    public static GenerateInputPorts(node: Nullable<DefaultNodeModel>, includeOnly?: string[]) {
+        if (!node) {
+            return new Array<JSX.Element>();
+        }
+        let inputPorts = [];
+        for (var key in node.ports) {
+            let port = node.ports[key] as DefaultPortModel;
+            if (port.position === "input") {
+                if (!includeOnly || includeOnly.indexOf(port.name) !== -1) {
+                    inputPorts.push(
+                        <div key={key} className="input-port">
+                            <div className="input-port-plug">
+                                <PortWidget key={key} name={port.name} node={node} className={port.connection && port.connection.connectedPoint ? "connected" : ""} />
+                            </div>
+                            <div className="input-port-label">
+                                {port.name}
+                            </div>
+                        </div>
+                    );
+                }
+            }
+        }
+
+        return inputPorts;
+    }
+}

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

@@ -1,12 +1,12 @@
 import * as React from 'react';
 import { Nullable } from 'babylonjs/types';
-import { Texture } from 'babylonjs/Materials/Textures/texture';
+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/Fragment/textureBlock';
+import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Dual/textureBlock';
 
 /**
  * Texture node model which stores information about a node editor block
@@ -17,12 +17,12 @@ export class TextureNodeModel extends DefaultNodeModel {
 	/**
 	 * Texture for the node if it exists
 	 */
-    public get texture(): Nullable<Texture> {
-        return this._block.texture.value;
+    public get texture(): Nullable<BaseTexture> {
+        return this._block.texture;
     }
 
-    public set texture(value: Nullable<Texture>) {
-        this._block.texture.value = value;
+    public set texture(value: Nullable<BaseTexture>) {
+        this._block.texture = value;
     }
 
 	/**

+ 4 - 33
nodeEditor/src/components/diagram/texture/textureNodeWidget.tsx

@@ -1,10 +1,9 @@
 import * as React from "react";
-import { PortWidget } from "storm-react-diagrams";
 import { TextureNodeModel } from './textureNodeModel';
 import { TextureLineComponent } from "../../../sharedComponents/textureLineComponent"
 import { Nullable } from 'babylonjs/types';
 import { GlobalState } from '../../../globalState';
-import { DefaultPortModel } from '../defaultPortModel';
+import { PortHelper } from '../portHelper';
 
 /**
  * GenericNodeWidgetProps
@@ -37,37 +36,9 @@ export class TextureNodeWidget extends React.Component<ITextureNodeWidgetProps>
     }
 
     render() {
-        var inputPorts = new Array<JSX.Element>();
-        var outputPorts = new Array<JSX.Element>();
-        if (this.props.node) {
-            // Input/Output ports
-            for (var key in this.props.node.ports) {
-                var port = this.props.node.ports[key] as DefaultPortModel;
-                if (port.position === "output") {
-                    outputPorts.push(
-                        <div key={key} className="output-port">
-                            <div className="output-port-label">
-                                {port.name}
-                            </div>
-                            <div className="output-port-plug">
-                                <PortWidget key={key} name={port.name} node={this.props.node} />
-                            </div>
-                        </div>
-                    );
-                } else if (port.name === "uv") {
-                    inputPorts.push(
-                        <div key={key} className="input-port">
-                            <div className="input-port-plug">
-                                <PortWidget key={key} name={port.name} node={this.props.node} />
-                            </div>
-                            <div className="input-port-label">
-                                {port.name}
-                            </div>
-                        </div>
-                    )
-                }
-            }
-        }
+        // Input/Output ports
+        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, false);
+        var inputPorts = PortHelper.GenerateInputPorts(this.props.node, ["uv"]);
 
         return (
             <div className={"diagramBlock"}>

+ 3 - 2
nodeEditor/src/components/diagram/texture/texturePropertyTabComponent.tsx

@@ -1,7 +1,7 @@
 
 import * as React from "react";
 import { GlobalState } from '../../../globalState';
-import { Texture } from 'babylonjs/Materials/Textures/texture';
+import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
 import { FileButtonLineComponent } from '../../../sharedComponents/fileButtonLineComponent';
 import { Tools } from 'babylonjs/Misc/tools';
 import { Engine } from 'babylonjs/Engines/engine';
@@ -10,6 +10,7 @@ import { TextLineComponent } from '../../../sharedComponents/textLineComponent';
 import { LineContainerComponent } from '../../../sharedComponents/lineContainerComponent';
 import { TextInputLineComponent } from '../../../sharedComponents/textInputLineComponent';
 import { CheckBoxLineComponent } from '../../../sharedComponents/checkBoxLineComponent';
+import { Texture } from 'babylonjs/Materials/Textures/texture';
 
 interface ITexturePropertyTabComponentProps {
     globalState: GlobalState;
@@ -27,7 +28,7 @@ export class TexturePropertyTabComponent extends React.Component<ITexturePropert
             return;
         }
 
-        let texture = this.props.node.texture as Texture;
+        let texture = this.props.node.texture as BaseTexture;
         if (!texture) {
             this.props.node.texture = new Texture(null, Engine.LastCreatedScene)
             texture = this.props.node.texture;

+ 18 - 0
nodeEditor/src/components/nodeList/nodeList.scss

@@ -22,6 +22,24 @@
         .underline {
             border-bottom: 0.5px solid rgba(255, 255, 255, 0.5);
         }
+
+        .draggableLine {
+            height: 30px;
+            display: grid;
+            align-items: center;
+            justify-items: stretch;
+            background: #222222;
+            border: 1px solid rgb(51, 122, 183) !important;
+            text-align: center;
+            margin: 4px 20px;
+            box-sizing: border-box;
+            border-radius: 10px;
+
+            &:hover {
+                background: rgb(51, 122, 183);
+                color: white;
+            }
+        }
     
         .buttonLine {
             height: 30px;

+ 7 - 34
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -2,57 +2,30 @@
 import * as React from "react";
 import { GlobalState } from '../../globalState';
 import { LineContainerComponent } from '../../sharedComponents/lineContainerComponent';
-import { ButtonLineComponent } from '../../sharedComponents/buttonLineComponent';
-import { AlphaTestBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock';
-import { FragmentOutputBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock';
-import { ImageProcessingBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock';
-import { RGBAMergerBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/rgbaMergerBlock';
-import { RGBASplitterBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/rgbaSplitterBlock';
-import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/textureBlock';
-import { BonesBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/bonesBlock';
-import { InstancesBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/instancesBlock';
-import { MorphTargetsBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/morphTargetsBlock';
-import { VertexOutputBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/vertexOutputBlock';
-import { FogBlock } from 'babylonjs/Materials/Node/Blocks/Dual/fogBlock';
-import { AddBlock } from 'babylonjs/Materials/Node/Blocks/addBlock';
-import { ClampBlock } from 'babylonjs/Materials/Node/Blocks/clampBlock';
-import { MultiplyBlock } from 'babylonjs/Materials/Node/Blocks/multiplyBlock';
-import { Vector2TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector2TransformBlock';
-import { Vector3TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector3TransformBlock';
-import { Vector4TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector4TransformBlock';
-import { NodeMaterialBlock } from 'babylonjs/Materials/Node/nodeMaterialBlock';
-import { LightBlock } from 'babylonjs/Materials/Node/Blocks/Dual/lightBlock';
+import { DraggableLineComponent } from '../../sharedComponents/draggableLineComponent';
 
 require("./nodeList.scss");
 
 interface INodeListComponentProps {
     globalState: GlobalState;
-    onAddValueNode: (b: string) => void;
-    onAddNodeFromClass: (ObjectClass: typeof NodeMaterialBlock) => void;
 }
 
 export class NodeListComponent extends React.Component<INodeListComponentProps> {
     render() {
         // Block types used to create the menu from
         const allBlocks = {
-            Vertex: [BonesBlock, InstancesBlock, MorphTargetsBlock],
-            Fragment: [AlphaTestBlock, , ImageProcessingBlock, RGBAMergerBlock, RGBASplitterBlock, TextureBlock, LightBlock],
-            Outputs: [VertexOutputBlock, FragmentOutputBlock],
-            Dual: [FogBlock],
-            Math: [AddBlock, ClampBlock, MultiplyBlock, Vector2TransformBlock, Vector3TransformBlock, Vector4TransformBlock],
+            Vertex: ["BonesBlock", "InstancesBlock", "MorphTargetsBlock"],
+            Fragment: ["AlphaTestBlock", "ImageProcessingBlock", "RGBAMergerBlock", "RGBASplitterBlock", "TextureBlock", "LightBlock", "FogBlock"],
+            Outputs: ["VertexOutputBlock", "FragmentOutputBlock"],
+            Math: ["AddBlock", "ClampBlock", "MultiplyBlock", "Vector2TransformBlock", "Vector3TransformBlock", "Vector4TransformBlock"],
             Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "Matrix"],
         }
 
         // Create node menu
         var blockMenu = []
         for (var key in allBlocks) {
-            var blockList = (allBlocks as any)[key].map((b: any) => {
-                var label = typeof b === "string" ? b : b.prototype.getClassName().replace("Block", "")
-                var onClick = typeof b === "string" ? () => {
-                    this.props.onAddValueNode(b);
-                    this.props.globalState.onUpdateRequiredObservable.notifyObservers();
-                } : () => { this.props.onAddNodeFromClass(b) };
-                return <ButtonLineComponent key={label} label={label} onClick={onClick} />
+            var blockList = (allBlocks as any)[key].map((block: any, i: number) => {
+                return <DraggableLineComponent key={block} data={block} />
             })
             blockMenu.push(
                 <LineContainerComponent key={key + " blocks"} title={key + " blocks"} closed={false}>

+ 3 - 3
nodeEditor/src/components/propertyTab/properties/color3PropertyTabComponent.tsx

@@ -1,19 +1,19 @@
 
 import * as React from "react";
 import { GlobalState } from '../../../globalState';
-import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
 import { Color3LineComponent } from '../../../sharedComponents/color3LineComponent';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 
 interface IColor3PropertyTabComponentProps {
     globalState: GlobalState;
-    connection: NodeMaterialConnectionPoint;
+    inputBlock: InputBlock;
 }
 
 export class Color3PropertyTabComponent extends React.Component<IColor3PropertyTabComponentProps> {
 
     render() {
         return (
-            <Color3LineComponent label="Value" target={this.props.connection} propertyName="value" onChange={() => {
+            <Color3LineComponent label="Value" target={this.props.inputBlock} propertyName="value" onChange={() => {
                 this.props.globalState.onUpdateRequiredObservable.notifyObservers();
             }}></Color3LineComponent>
         );

+ 3 - 3
nodeEditor/src/components/propertyTab/properties/floatPropertyTabComponent.tsx

@@ -1,19 +1,19 @@
 
 import * as React from "react";
 import { GlobalState } from '../../../globalState';
-import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
 import { FloatLineComponent } from '../../../sharedComponents/floatLineComponent';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 
 interface IFloatPropertyTabComponentProps {
     globalState: GlobalState;
-    connection: NodeMaterialConnectionPoint;
+    inputBlock: InputBlock;
 }
 
 export class FloatPropertyTabComponent extends React.Component<IFloatPropertyTabComponentProps> {
 
     render() {
         return (
-            <FloatLineComponent label="Value" target={this.props.connection} propertyName="value"></FloatLineComponent>
+            <FloatLineComponent label="Value" target={this.props.inputBlock} propertyName="value"></FloatLineComponent>
         );
     }
 }

+ 3 - 3
nodeEditor/src/components/propertyTab/properties/vector2PropertyTabComponent.tsx

@@ -2,18 +2,18 @@
 import * as React from "react";
 import { GlobalState } from '../../../globalState';
 import { Vector2LineComponent } from '../../../sharedComponents/vector2LineComponent';
-import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 
 interface IVector2PropertyTabComponentProps {
     globalState: GlobalState;
-    connection: NodeMaterialConnectionPoint;
+    inputBlock: InputBlock;
 }
 
 export class Vector2PropertyTabComponent extends React.Component<IVector2PropertyTabComponentProps> {
 
     render() {
         return (
-            <Vector2LineComponent label="Value" target={this.props.connection} propertyName="value"></Vector2LineComponent>
+            <Vector2LineComponent label="Value" target={this.props.inputBlock} propertyName="value"></Vector2LineComponent>
         );
     }
 }

+ 3 - 3
nodeEditor/src/components/propertyTab/properties/vector3PropertyTabComponent.tsx

@@ -2,18 +2,18 @@
 import * as React from "react";
 import { GlobalState } from '../../../globalState';
 import { Vector3LineComponent } from '../../../sharedComponents/vector3LineComponent';
-import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 
 interface IVector3PropertyTabComponentProps {
     globalState: GlobalState;
-    connection: NodeMaterialConnectionPoint;
+    inputBlock: InputBlock;
 }
 
 export class Vector3PropertyTabComponent extends React.Component<IVector3PropertyTabComponentProps> {
 
     render() {
         return (
-            <Vector3LineComponent label="Value" target={this.props.connection} propertyName="value"></Vector3LineComponent>
+            <Vector3LineComponent label="Value" target={this.props.inputBlock} propertyName="value"></Vector3LineComponent>
         );
     }
 }

+ 3 - 0
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -61,6 +61,9 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                         <ButtonLineComponent label="Zoom to fit" onClick={() => {
                             this.props.globalState.onZoomToFitRequiredObservable.notifyObservers();
                         }} />
+                        <ButtonLineComponent label="Reorganize" onClick={() => {
+                            this.props.globalState.onReOrganizedRequiredObservable.notifyObservers();
+                        }} />
                     </LineContainerComponent>
                 </div>
             </div>

+ 1 - 0
nodeEditor/src/globalState.ts

@@ -13,5 +13,6 @@ export class GlobalState {
     onResetRequiredObservable = new Observable<void>();
     onUpdateRequiredObservable = new Observable<void>();
     onZoomToFitRequiredObservable = new Observable<void>();
+    onReOrganizedRequiredObservable = new Observable<void>();
     onLogRequiredObservable = new Observable<LogEntry>();
 }

+ 245 - 102
nodeEditor/src/graphEditor.tsx

@@ -2,11 +2,11 @@ import {
     DiagramEngine,
     DiagramModel,
     DiagramWidget,
-    MoveCanvasAction,
     LinkModel
 } from "storm-react-diagrams";
 
 import * as React from "react";
+import * as dagre from "dagre";
 import { GlobalState } from './globalState';
 
 import { GenericNodeFactory } from './components/diagram/generic/genericNodeFactory';
@@ -22,13 +22,31 @@ import { TextureNodeModel } from './components/diagram/texture/textureNodeModel'
 import { DefaultPortModel } from './components/diagram/defaultPortModel';
 import { InputNodeFactory } from './components/diagram/input/inputNodeFactory';
 import { InputNodeModel } from './components/diagram/input/inputNodeModel';
-import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/textureBlock';
-import { Vector2, Vector3, Vector4, Matrix, Color3, Color4 } from 'babylonjs/Maths/math';
+import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Dual/textureBlock';
 import { LogComponent, LogEntry } from './components/log/logComponent';
 import { LightBlock } from 'babylonjs/Materials/Node/Blocks/Dual/lightBlock';
 import { LightNodeModel } from './components/diagram/light/lightNodeModel';
 import { LightNodeFactory } from './components/diagram/light/lightNodeFactory';
 import { DataStorage } from './dataStorage';
+import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
+import { Nullable } from 'babylonjs/types';
+import { BonesBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/bonesBlock';
+import { InstancesBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/instancesBlock';
+import { MorphTargetsBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/morphTargetsBlock';
+import { AlphaTestBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock';
+import { ImageProcessingBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock';
+import { RGBAMergerBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/rgbaMergerBlock';
+import { RGBASplitterBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/rgbaSplitterBlock';
+import { FogBlock } from 'babylonjs/Materials/Node/Blocks/Dual/fogBlock';
+import { VertexOutputBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/vertexOutputBlock';
+import { FragmentOutputBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock';
+import { AddBlock } from 'babylonjs/Materials/Node/Blocks/addBlock';
+import { ClampBlock } from 'babylonjs/Materials/Node/Blocks/clampBlock';
+import { MultiplyBlock } from 'babylonjs/Materials/Node/Blocks/multiplyBlock';
+import { Vector2TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector2TransformBlock';
+import { Vector3TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector3TransformBlock';
+import { Vector4TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector4TransformBlock';
 
 require("storm-react-diagrams/dist/style.min.css");
 require("./main.scss");
@@ -53,8 +71,7 @@ interface IGraphEditorProps {
 }
 
 export class NodeCreationOptions {
-    column: number;
-    nodeMaterialBlock?: NodeMaterialBlock;
+    nodeMaterialBlock: NodeMaterialBlock;
     type?: string;
     connection?: NodeMaterialConnectionPoint;
 }
@@ -69,49 +86,33 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
     public _toAdd: LinkModel[] | null = [];
 
     /**
-     * Current row/column position used when adding new nodes
-     */
-    private _rowPos = new Array<number>();
-
-    /**
      * Creates a node and recursivly creates its parent nodes from it's input
      * @param nodeMaterialBlock 
      */
     public createNodeFromObject(options: NodeCreationOptions) {
-        // Update rows/columns
-        if (this._rowPos[options.column] == undefined) {
-            this._rowPos[options.column] = 0;
-        } else {
-            this._rowPos[options.column]++;
-        }
-
         // Create new node in the graph
         var newNode: DefaultNodeModel;
         var filterInputs = [];
 
-        if (options.nodeMaterialBlock) {
-            if (options.nodeMaterialBlock instanceof TextureBlock) {
-                newNode = new TextureNodeModel();
-                filterInputs.push("uv");
-            } else if (options.nodeMaterialBlock instanceof LightBlock) {
-                newNode = new LightNodeModel();
-                filterInputs.push("worldPosition");
-                filterInputs.push("worldNormal");
-                filterInputs.push("cameraPosition");
-            } else {
-                newNode = new GenericNodeModel();
-            }
-
-            if (options.nodeMaterialBlock.isFinalMerger) {
-                this.props.globalState.nodeMaterial!.addOutputNode(options.nodeMaterialBlock);
-            }
-
-        } else {
+        if (options.nodeMaterialBlock instanceof TextureBlock) {
+            newNode = new TextureNodeModel();
+            filterInputs.push("uv");
+        } else if (options.nodeMaterialBlock instanceof LightBlock) {
+            newNode = new LightNodeModel();
+            filterInputs.push("worldPosition");
+            filterInputs.push("worldNormal");
+            filterInputs.push("cameraPosition");
+        } else if (options.nodeMaterialBlock instanceof InputBlock) {
             newNode = new InputNodeModel();
-            (newNode as InputNodeModel).connection = options.connection;
+        } else {
+            newNode = new GenericNodeModel();
+        }
+
+        if (options.nodeMaterialBlock.isFinalMerger) {
+            this.props.globalState.nodeMaterial!.addOutputNode(options.nodeMaterialBlock);
         }
+
         this._nodes.push(newNode)
-        newNode.setPosition(1600 - (300 * options.column), 210 * this._rowPos[options.column])
         this._model.addAll(newNode);
 
         if (options.nodeMaterialBlock) {
@@ -155,7 +156,6 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
         });
 
         this.props.globalState.onResetRequiredObservable.add(() => {
-            this._rowPos = [];
             this.build();
             if (this.props.globalState.nodeMaterial) {
                 this.buildMaterial();
@@ -170,9 +170,67 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             this._engine.zoomToFit();
         });
 
+        this.props.globalState.onReOrganizedRequiredObservable.add(() => {
+            this.reOrganize();
+        })
+
         this.build();
     }
 
+    distributeGraph() {
+        let nodes = this.mapElements();
+        let edges = this.mapEdges();
+        let graph = new dagre.graphlib.Graph();
+        graph.setGraph({});
+        graph.setDefaultEdgeLabel(() => ({}));
+        graph.graph().rankdir = "LR";
+        //add elements to dagre graph
+        nodes.forEach(node => {
+            graph.setNode(node.id, node.metadata);
+        });
+        edges.forEach(edge => {
+            if (edge.from && edge.to) {
+                graph.setEdge(edge.from.id, edge.to.id);
+            }
+        });
+        //auto-distribute
+        dagre.layout(graph);
+        return graph.nodes().map(node => graph.node(node));
+    }
+
+    mapElements() {
+        let output = [];
+
+        // dagre compatible format
+        for (var nodeName in this._model.nodes) {
+            let node = this._model.nodes[nodeName];
+            let size = {
+                width: node.width,
+                height: node.height
+            };
+            output.push({ id: node.id, metadata: { ...size, id: node.id } });
+        }
+
+        return output;
+    }
+
+    mapEdges() {
+        // returns links which connects nodes
+        // we check are there both from and to nodes in the model. Sometimes links can be detached
+        let output = [];
+
+        for (var linkName in this._model.links) {
+            let link = this._model.links[linkName];
+
+            output.push({
+                from: link.sourcePort!.parent,
+                to: link.targetPort!.parent
+            });
+        }
+
+        return output;
+    }
+
     buildMaterial() {
         if (!this.props.globalState.nodeMaterial) {
             return;
@@ -201,6 +259,8 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                     if (targetBlock && targetBlock.isFinalMerger) {
                         this.props.globalState.nodeMaterial!.removeOutputNode(targetBlock);
                     }
+
+                    this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
                 }
             },
             linksUpdated: (e) => {
@@ -215,22 +275,15 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                                 link.output.connection.disconnectFrom(link.input.connection)
                                 link.input.syncWithNodeMaterialConnectionPoint(link.input.connection)
                                 link.output.syncWithNodeMaterialConnectionPoint(link.output.connection)
-                            } else {
-                                let inputNode = link.output.parent as InputNodeModel
-                                inputNode.connection = undefined;
-
-                                if (link.input.connection.value) {
-                                    inputNode.ports[link.output.name].defaultValue = link.input.connection.value;
-                                    link.input.connection.value = null;
-                                }
                             }
                         }
                     }
+                    this.forceUpdate();
+                    return;
                 }
 
                 e.link.addListener({
                     sourcePortChanged: () => {
-                        console.log("port change")
                     },
                     targetPortChanged: () => {
                         // Link is created with a target port
@@ -238,15 +291,18 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
 
                         if (link) {
                             if (link.output.connection && link.input.connection) {
-                                link.output.connection.connectTo(link.input.connection)
-                            } else if (link.input.connection) {
-                                if (!link.output.connection) { // Input Node
-                                    let name = link.output.name;
-                                    link.output.syncWithNodeMaterialConnectionPoint(link.input.connection);
-                                    link.output.name = name;
-                                    (link.output.getNode() as InputNodeModel).connection = link.output.connection!;
-                                    link.input.connection.value = link.output.defaultValue;
+                                // Disconnect previous connection
+                                for (var key in link.input.links) {
+                                    let other = link.input.links[key];
+
+                                    if (other.getSourcePort() !== link.output) {
+                                        other.remove();
+                                    }
                                 }
+
+                                link.output.connection.connectTo(link.input.connection);
+
+                                this.forceUpdate();
                             }
                             if (this.props.globalState.nodeMaterial) {
                                 this.buildMaterial();
@@ -261,10 +317,10 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
         if (this.props.globalState.nodeMaterial) {
             var material: any = this.props.globalState.nodeMaterial;
             material._vertexOutputNodes.forEach((n: any) => {
-                this.createNodeFromObject({ column: 0, nodeMaterialBlock: n });
+                this.createNodeFromObject({ nodeMaterialBlock: n });
             })
             material._fragmentOutputNodes.forEach((n: any) => {
-                this.createNodeFromObject({ column: 0, nodeMaterialBlock: n });
+                this.createNodeFromObject({ nodeMaterialBlock: n });
             })
         }
 
@@ -275,58 +331,58 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             }
             this._toAdd = null;
             this._engine.setDiagramModel(this._model);
-            this.forceUpdate();
-        }, 550);
-    }
-
-    addNodeFromClass(ObjectClass: typeof NodeMaterialBlock) {
-        var block = new ObjectClass(ObjectClass.prototype.getClassName())
-        var localNode = this.createNodeFromObject({ column: 0, nodeMaterialBlock: block })
-        var widget = (this.refs["test"] as DiagramWidget);
 
-        this.forceUpdate();
+            this.forceUpdate();
 
-        // This is needed to fix link offsets when created, (eg. create a fog block)
-        // Todo figure out how to correct this without this
-        setTimeout(() => {
-            widget.startFiringAction(new MoveCanvasAction(1, 0, this._model));
+            this.reOrganize();
         }, 500);
-
-        return localNode;
     }
 
-    addValueNode(type: string, column = 0, connection?: NodeMaterialConnectionPoint) {
-        var localNode = this.createNodeFromObject({ column: column, type: type, connection: connection })
-        var outPort = new DefaultPortModel(type, "output");
-
-        localNode.addPort(outPort);
+    reOrganize() {
+        let nodes = this.distributeGraph();
+        nodes.forEach(node => {
+            for (var nodeName in this._model.nodes) {
+                let modelNode = this._model.nodes[nodeName];
 
-        if (!connection) {
-            switch (type) {
-                case "Float":
-                    outPort.defaultValue = 0;
-                    break;
-                case "Vector2":
-                    outPort.defaultValue = Vector2.Zero();
-                    break;
-                case "Vector3":
-                    outPort.defaultValue = Vector3.Zero();
-                    break;
-                case "Vector4":
-                    outPort.defaultValue = Vector4.Zero();
-                    break;
-                case "Matrix":
-                    outPort.defaultValue = Matrix.Identity();
-                    break;
-                case "Color3":
-                    outPort.defaultValue = Color3.White();
-                    break;
-                case "Color4":
-                    outPort.defaultValue = new Color4(1, 1, 1, 1);
-                    break;
+                if (modelNode.id === node.id) {
+                    modelNode.setPosition(node.x - node.width / 2, node.y - node.height / 2);
+                    return;
+                }
             }
+        });
+        this.forceUpdate();
+    }
+
+    addValueNode(type: string) {
+        let nodeType: NodeMaterialBlockConnectionPointTypes = NodeMaterialBlockConnectionPointTypes.Vector3;
+        switch (type) {
+            case "Float":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Float;
+                break;
+            case "Vector2":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Vector2;
+                break;
+            case "Vector3":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Vector3;
+                break;
+            case "Vector4":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Vector4;
+                break;
+            case "Matrix":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Matrix;
+                break;
+            case "Color3":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Color3;
+                break;
+            case "Color4":
+                nodeType = NodeMaterialBlockConnectionPointTypes.Color4;
+                break;
         }
 
+        let newInputBlock = new InputBlock(type, undefined, nodeType);
+        newInputBlock.setDefaultValue();
+        var localNode = this.createNodeFromObject({ type: type, nodeMaterialBlock: newInputBlock })
+
         return localNode;
     }
 
@@ -375,6 +431,84 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
         return `${this._leftWidth}px 4px calc(100% - ${this._leftWidth + 8 + this._rightWidth}px) 4px ${this._rightWidth}px`;
     }
 
+    emitNewBlock(event: React.DragEvent<HTMLDivElement>) {
+        var data = event.dataTransfer.getData("babylonjs-material-node") as string;
+
+        if (data.indexOf("Block") === -1) {
+            this.addValueNode(data);
+        } else {
+            let block: Nullable<NodeMaterialBlock> = null;
+
+            switch (data) {
+                case "BonesBlock":
+                    block = new BonesBlock("Bones");
+                    break;
+                case "InstancesBlock":
+                    block = new InstancesBlock("Instances");
+                    break;
+                case "MorphTargetsBlock":
+                    block = new MorphTargetsBlock("MorphTargets");
+                    break;
+                case "AlphaTestBlock":
+                    block = new AlphaTestBlock("AlphaTest");
+                    break;
+                case "ImageProcessingBlock":
+                    block = new ImageProcessingBlock("ImageProcessing");
+                    break;
+                case "RGBAMergerBlock":
+                    block = new RGBAMergerBlock("RGBAMerger");
+                    break;
+                case "RGBASplitterBlock":
+                    block = new RGBASplitterBlock("RGBASplitter");
+                    break;
+                case "TextureBlock":
+                    block = new TextureBlock("Texture");
+                    break;
+                case "LightBlock":
+                    block = new LightBlock("Light");
+                    break;
+                case "FogBlock":
+                    block = new FogBlock("Fog");
+                    break;
+                case "VertexOutputBlock":
+                    block = new VertexOutputBlock("VertexOutput");
+                    break;
+                case "FragmentOutputBlock":
+                    block = new FragmentOutputBlock("FragmentOutput");
+                    break;
+                case "AddBlock":
+                    block = new AddBlock("Add");
+                    break;
+                case "ClampBlock":
+                    block = new ClampBlock("Clamp");
+                    break;
+                case "MultiplyBlock":
+                    block = new MultiplyBlock("Multiply");
+                    break;
+                case "Vector2TransformBlock":
+                    block = new Vector2TransformBlock("Vector2Transform");
+                    break;
+                case "Vector3TransformBlock":
+                    block = new Vector3TransformBlock("Vector3Transform");
+                    break;
+                case "Vector4TransformBlock":
+                    block = new Vector4TransformBlock("Vector4Transform");
+                    break;
+            }
+
+            if (block) {
+                let nodeModel = this.createNodeFromObject({ nodeMaterialBlock: block });
+                const zoomLevel = this._engine.diagramModel.getZoomLevel() / 100.0;
+
+                let x = (event.clientX - event.currentTarget.offsetLeft - this._engine.diagramModel.getOffsetX()) / zoomLevel;
+                let y = (event.clientY - event.currentTarget.offsetTop - this._engine.diagramModel.getOffsetY()) / zoomLevel;
+                nodeModel.setPosition(x, y);
+            }
+        };
+
+        this.forceUpdate();
+    }
+
     render() {
         return (
             <Portal globalState={this.props.globalState}>
@@ -384,7 +518,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                     }
                 }>
                     {/* Node creation menu */}
-                    <NodeListComponent globalState={this.props.globalState} onAddValueNode={b => this.addValueNode(b)} onAddNodeFromClass={b => this.addNodeFromClass(b)} />
+                    <NodeListComponent globalState={this.props.globalState} />
 
                     <div id="leftGrab"
                         onPointerDown={evt => this.onPointerDown(evt)}
@@ -393,7 +527,16 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                     ></div>
 
                     {/* The node graph diagram */}
-                    <DiagramWidget deleteKeys={[46]} ref={"test"} inverseZoom={true} className="diagram-container" diagramEngine={this._engine} maxNumberPointsPerLink={0} />
+                    <div className="diagram-container"
+                        onDrop={event => {
+                            this.emitNewBlock(event);
+                        }}
+                        onDragOver={event => {
+                            event.preventDefault();
+                        }}
+                    >
+                        <DiagramWidget className="diagram" deleteKeys={[46]} ref={"test"} inverseZoom={true} diagramEngine={this._engine} maxNumberPointsPerLink={0} />
+                    </div>
 
                     <div id="rightGrab"
                         onPointerDown={evt => this.onPointerDown(evt)}

+ 7 - 0
nodeEditor/src/main.scss

@@ -28,6 +28,13 @@
     grid-row: 1;
     grid-column: 3;
     background: #222222;
+    width: 100%;
+    height: 100%;
+
+    .diagram {
+        width: 100%;
+        height: 100%;
+    }
 }
 
 #propertyTab {

+ 23 - 0
nodeEditor/src/sharedComponents/draggableLineComponent.tsx

@@ -0,0 +1,23 @@
+import * as React from "react";
+
+export interface IButtonLineComponentProps {
+    data: string;
+}
+
+export class DraggableLineComponent extends React.Component<IButtonLineComponentProps> {
+    constructor(props: IButtonLineComponentProps) {
+        super(props);
+    }
+
+    render() {
+        return (
+            <div className="draggableLine"
+                draggable={true}
+                onDragStart={event => {
+                    event.dataTransfer.setData("babylonjs-material-node", this.props.data);
+                }}>
+                {this.props.data}
+            </div>
+        );
+    }
+}

+ 2 - 1
package.json

@@ -35,7 +35,6 @@
     },
     "readme": "Babylon.js is a 3D engine based on webgl and javascript",
     "readmeFilename": "README.md",
-    "dependencies": {},
     "devDependencies": {
         "@fortawesome/fontawesome-svg-core": "~1.2.8",
         "@fortawesome/free-regular-svg-icons": "~5.4.1",
@@ -47,6 +46,7 @@
         "@types/react": "~16.7.3",
         "@types/react-dom": "~16.0.9",
         "@types/sinon": "^4.1.3",
+        "@types/dagre": "^0.7.42",
         "ajv": "^6.9.1",
         "awesome-typescript-loader": "^5.2.1",
         "base64-font-loader": "0.0.4",
@@ -91,6 +91,7 @@
         "sinon": "^6.1.4",
         "split.js": "^1.5.9",
         "storm-react-diagrams": "^5.2.1",
+        "dagre": "0.8.4",
         "style-loader": "^0.21.0",
         "through2": "~2.0.3",
         "ts-loader": "^5.2.1",

+ 21 - 26
src/Materials/Node/Blocks/Dual/fogBlock.ts

@@ -9,11 +9,15 @@ import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPo
 import { AbstractMesh } from '../../../../Meshes/abstractMesh';
 import { MaterialHelper } from '../../../materialHelper';
 import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { InputBlock } from '../Input/inputBlock';
 
 /**
  * Block used to add support for scene fog
  */
 export class FogBlock extends NodeMaterialBlock {
+    private _fogDistanceName: string;
+    private _fogParameters: string;
+
     /**
      * Create a new FogBlock
      * @param name defines the block name
@@ -25,12 +29,9 @@ export class FogBlock extends NodeMaterialBlock {
         this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
         this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Vertex);
 
-        this.registerOutput("vFogDistance", NodeMaterialBlockConnectionPointTypes.Vector3, NodeMaterialBlockTargets.Vertex);
-
         // Fragment
         this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3OrColor4, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("fogColor", NodeMaterialBlockConnectionPointTypes.Color3, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("fogParameters", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Fragment);
 
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
     }
@@ -72,13 +73,6 @@ export class FogBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the for parameter input component
-     */
-    public get fogParameters(): NodeMaterialConnectionPoint {
-        return this._inputs[4];
-    }
-
-    /**
      * Gets the output component
      */
     public get output(): NodeMaterialConnectionPoint {
@@ -86,16 +80,16 @@ export class FogBlock extends NodeMaterialBlock {
     }
 
     public autoConfigure() {
-        if (this.view.isUndefined) {
-            this.view.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+        if (!this.view.isConnected) {
+            let viewInput = new InputBlock("view");
+            viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            viewInput.output.connectTo(this.view);
         }
-        if (this.fogColor.isUndefined) {
-            this.fogColor.setAsWellKnownValue(NodeMaterialWellKnownValues.Automatic);
+        if (!this.fogColor.isConnected) {
+            let fogColorInput = new InputBlock("fogColor", undefined, NodeMaterialBlockConnectionPointTypes.Color3);
+            fogColorInput.setAsWellKnownValue(NodeMaterialWellKnownValues.FogColor);
+            fogColorInput.output.connectTo(this.fogColor);
         }
-        if (this.fogParameters.isUndefined) {
-            this.fogParameters.setAsWellKnownValue(NodeMaterialWellKnownValues.Automatic);
-        }
-        this._outputs[0].isVarying = true;
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
@@ -109,8 +103,7 @@ export class FogBlock extends NodeMaterialBlock {
         }
 
         const scene = mesh.getScene();
-        effect.setColor3("u_fogColor", scene.fogColor);
-        effect.setFloat4("u_fogParameters", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+        effect.setFloat4(this._fogParameters, scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
     }
 
     protected _buildBlock(state: NodeMaterialBuildState) {
@@ -131,20 +124,22 @@ export class FogBlock extends NodeMaterialBlock {
             let tempFogVariablename = state._getFreeVariableName("fog");
             let color = this.color;
             let fogColor = this.fogColor;
-            let fogParameters = this.fogParameters;
-            let output = this._outputs[1];
-            let vFogDistance = this._outputs[0];
+            this._fogParameters = state._getFreeVariableName("fogParameters");
+            let output = this._outputs[0];
+
+            state._emitUniformFromString(this._fogParameters, "vec4");
 
             state.compilationString += `#ifdef FOG\r\n`;
-            state.compilationString += `float ${tempFogVariablename} = CalcFogFactor(${vFogDistance.associatedVariableName}, ${fogParameters.associatedVariableName});\r\n`;
+            state.compilationString += `float ${tempFogVariablename} = CalcFogFactor(${this._fogDistanceName}, ${this._fogParameters});\r\n`;
             state.compilationString += this._declareOutput(output, state) + ` = ${tempFogVariablename} * ${color.associatedVariableName}.rgb + (1.0 - ${tempFogVariablename}) * ${fogColor.associatedVariableName};\r\n`;
             state.compilationString += `#else\r\n${this._declareOutput(output, state)} =  ${color.associatedVariableName}.rgb;\r\n`;
             state.compilationString += `#endif\r\n`;
         } else {
             let worldPos = this.worldPosition;
             let view = this.view;
-            let vFogDistance = this._outputs[0];
-            state.compilationString += this._declareOutput(vFogDistance, state) + ` = (${view.associatedVariableName} * ${worldPos.associatedVariableName}).xyz;\r\n`;
+            this._fogDistanceName = state._getFreeVariableName("vFogDistance");
+            state._emitVaryingFromString(this._fogDistanceName, "vec3");
+            state.compilationString += `${this._fogDistanceName} = (${view.associatedVariableName} * ${worldPos.associatedVariableName}).xyz;\r\n`;
         }
 
         return this;

+ 2 - 1
src/Materials/Node/Blocks/Dual/index.ts

@@ -1,3 +1,4 @@
 
 export * from "./fogBlock";
-export * from "./lightBlock";
+export * from "./lightBlock";
+export * from "./textureBlock";

+ 28 - 23
src/Materials/Node/Blocks/Dual/lightBlock.ts

@@ -9,6 +9,9 @@ import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
 import { Effect } from '../../../effect';
 import { Mesh } from '../../../../Meshes/mesh';
 import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
+import { InputBlock } from '../Input/inputBlock';
+import { Light } from '../../../../Lights/light';
+import { Nullable } from '../../../../types';
 
 /**
  * Block used to add light in the fragment shader
@@ -17,6 +20,11 @@ export class LightBlock extends NodeMaterialBlock {
     private _lightId: number;
 
     /**
+     * Gets or sets the light associated with this block
+     */
+    public light: Nullable<Light>;
+
+    /**
      * Create a new LightBlock
      * @param name defines the block name
      */
@@ -26,7 +34,6 @@ export class LightBlock extends NodeMaterialBlock {
         this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
         this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
 
-        this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("diffuseOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("specularOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
@@ -55,18 +62,10 @@ export class LightBlock extends NodeMaterialBlock {
     }
 
     /**
-    * Gets the light input component.
-    * If not defined, all lights will be considered
-    */
-    public get light(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
     * Gets the camera (or eye) position component
     */
     public get cameraPosition(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
+        return this._inputs[2];
     }
 
     /**
@@ -84,15 +83,21 @@ export class LightBlock extends NodeMaterialBlock {
     }
 
     public autoConfigure() {
-        if (this.cameraPosition.isUndefined) {
-            this.cameraPosition.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+        if (!this.cameraPosition.isConnected) {
+            let cameraPositionInput = new InputBlock("cameraPosition");
+            cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            cameraPositionInput.output.connectTo(this.cameraPosition);
         }
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        if (!defines._areLightsDirty) {
+            return;
+        }
+
         const scene = mesh.getScene();
 
-        if (!this.light.value) {
+        if (!this.light) {
             MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, nodeMaterial.maxSimultaneousLights);
         } else {
             let state = {
@@ -103,7 +108,7 @@ export class LightBlock extends NodeMaterialBlock {
                 specularEnabled: false
             };
 
-            MaterialHelper.PrepareDefinesForLight(scene, mesh, this.light.value, this._lightId, defines, true, state);
+            MaterialHelper.PrepareDefinesForLight(scene, mesh, this.light, this._lightId, defines, true, state);
 
             if (state.needRebuild) {
                 defines.rebuild();
@@ -127,10 +132,10 @@ export class LightBlock extends NodeMaterialBlock {
 
         const scene = mesh.getScene();
 
-        if (!this.light.value) {
+        if (!this.light) {
             MaterialHelper.BindLights(scene, mesh, effect, true, nodeMaterial.maxSimultaneousLights, false);
         } else {
-            MaterialHelper.BindLight(this.light.value, this._lightId, scene, mesh, effect, true, false);
+            MaterialHelper.BindLight(this.light, this._lightId, scene, mesh, effect, true, false);
         }
     }
 
@@ -140,10 +145,10 @@ export class LightBlock extends NodeMaterialBlock {
 
         // Inject code in vertex
         let worldPosVaryingName = "v_" + worldPos.associatedVariableName;
-        state._emitVaryings(worldPos, undefined, true, false, worldPosVaryingName, NodeMaterialBlockConnectionPointTypes.Vector3);
+        state._emitVaryingFromString(worldPosVaryingName, "vec3");
 
         let worldNormalVaryingName = "v_" + worldNormal.associatedVariableName;
-        state._emitVaryings(worldNormal, undefined, true, false, worldNormalVaryingName, NodeMaterialBlockConnectionPointTypes.Vector3);
+        state._emitVaryingFromString(worldNormalVaryingName, "vec3");
 
         state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName}.xyz;\r\n`;
         state.compilationString += `${worldNormalVaryingName} = ${worldNormal.associatedVariableName}.xyz;\r\n`;
@@ -153,12 +158,12 @@ export class LightBlock extends NodeMaterialBlock {
         super._buildBlock(state);
 
         if (state.target !== NodeMaterialBlockTargets.Fragment) {
+            // Vertex
+            this._injectVertexCode(state);
+
             return;
         }
 
-        // Vertex
-        this._injectVertexCode(state._vertexState);
-
         // Fragment
         state.sharedData.bindableBlocks.push(this);
         state.sharedData.blocksWithDefines.push(this);
@@ -172,7 +177,7 @@ export class LightBlock extends NodeMaterialBlock {
             ]
         });
 
-        if (!this.light.value) { // Emit for all lights
+        if (!this.light) { // Emit for all lights
             state._emitFunctionFromInclude(state.supportUniformBuffers ? "lightUboDeclaration" : "lightFragmentDeclaration", comments, {
                 repeatKey: "maxSimultaneousLights"
             });
@@ -203,7 +208,7 @@ export class LightBlock extends NodeMaterialBlock {
             state.compilationString += `vec3 normalW = v_${this.worldNormal.associatedVariableName};\r\n`;
         }
 
-        if (this.light.value) {
+        if (this.light) {
             state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {
                 replaceStrings: [
                     { search: /{X}/g, replace: this._lightId.toString() }

+ 185 - 0
src/Materials/Node/Blocks/Dual/textureBlock.ts

@@ -0,0 +1,185 @@
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
+import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
+import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
+import { BaseTexture } from '../../../Textures/baseTexture';
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { InputBlock } from '../Input/inputBlock';
+import { Effect } from '../../../effect';
+import { Mesh } from '../../../../Meshes/mesh';
+import { Nullable } from '../../../../types';
+
+/**
+ * Block used to read a texture from a sampler
+ */
+export class TextureBlock extends NodeMaterialBlock {
+    private _defineName: string;
+    private _samplerName: string;
+    private _transformedUVName: string;
+    private _textureTransformName: string;
+    private _textureInfoName: string;
+    private _mainUVName: string;
+    private _mainUVDefineName: string;
+
+    /**
+     * Gets or sets the texture associated with the node
+     */
+    public texture: Nullable<BaseTexture>;
+
+    /**
+     * Create a new TextureBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.VertexAndFragment);
+
+        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false, NodeMaterialBlockTargets.Vertex);
+
+        this.registerOutput("color", NodeMaterialBlockConnectionPointTypes.Color4, NodeMaterialBlockTargets.Fragment);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "TextureBlock";
+    }
+
+    /**
+     * Gets the uv input component
+     */
+    public get uv(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+     * Gets the output component
+     */
+    public get output(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    public autoConfigure() {
+        if (!this.uv.isConnected) {
+            let uvInput = new InputBlock("uv");
+            uvInput.setAsAttribute();
+            uvInput.output.connectTo(this.uv);
+        }
+    }
+
+    public initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances: boolean = false) {
+        if (!defines._areTexturesDirty) {
+            return;
+        }
+
+        defines.setValue(this._mainUVDefineName, false);
+    }
+
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        if (!defines._areTexturesDirty) {
+            return;
+        }
+
+        if (!this.texture || !this.texture.getTextureMatrix) {
+            return;
+        }
+
+        if (!this.texture.getTextureMatrix().isIdentityAs3x2()) {
+            defines.setValue(this._defineName, true);
+        } else {
+            defines.setValue(this._defineName, false);
+            defines.setValue(this._mainUVDefineName, true);
+        }
+    }
+
+    public isReady() {
+        if (this.texture && !this.texture.isReadyOrNotBlocking()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh) {
+        if (!mesh || !this.texture) {
+            return;
+        }
+
+        effect.setFloat(this._textureInfoName, this.texture.level);
+        effect.setMatrix(this._textureTransformName, this.texture.getTextureMatrix());
+        effect.setTexture(this._samplerName, this.texture);
+    }
+
+    private _injectVertexCode(state: NodeMaterialBuildState) {
+        let uvInput = this.uv;
+
+        // Inject code in vertex
+        this._defineName = state._getFreeDefineName("UVTRANSFORM");
+        this._mainUVDefineName = state._getFreeDefineName("vMain" + uvInput.associatedVariableName);
+
+        if (uvInput.connectedPoint!.ownerBlock.isInput) {
+            let uvInputOwnerBlock = uvInput.connectedPoint!.ownerBlock as InputBlock;
+
+            if (!uvInputOwnerBlock.isAttribute) {
+                state._emitUniformFromString(uvInput.associatedVariableName, "vec2");
+            }
+        }
+
+        this._mainUVName = "vMain" + uvInput.associatedVariableName;
+        this._transformedUVName = state._getFreeVariableName("transformedUV");
+        this._textureTransformName = state._getFreeVariableName("textureTransform");
+        this._textureInfoName = state._getFreeVariableName("textureInfoName");
+
+        state._emitVaryingFromString(this._transformedUVName, "vec2", this._defineName);
+        state._emitVaryingFromString(this._mainUVName, "vec2", this._mainUVDefineName);
+
+        state._emitUniformFromString(this._textureTransformName, "mat4", this._defineName);
+
+        if (state.sharedData.emitComments) {
+            state.compilationString += `\r\n//${this.name}\r\n`;
+        }
+        state.compilationString += `#ifdef ${this._defineName}\r\n`;
+        state.compilationString += `${this._transformedUVName} = vec2(${this._textureTransformName} * vec4(${uvInput.associatedVariableName}, 1.0, 0.0));\r\n`;
+        state.compilationString += `#else\r\n`;
+        state.compilationString += `${this._mainUVName} = ${uvInput.associatedVariableName};\r\n`;
+        state.compilationString += `#endif\r\n`;
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        if (state.target !== NodeMaterialBlockTargets.Fragment) {
+            // Vertex
+            this._injectVertexCode(state);
+            return;
+        }
+
+        state.sharedData.blockingBlocks.push(this);
+        state.sharedData.textureBlocks.push(this);
+
+        this._samplerName = state._getFreeVariableName(this.name + "Sampler");
+        state.samplers.push(this._samplerName);
+        state._samplerDeclaration += `uniform sampler2D ${this._samplerName};\r\n`;
+
+        // Fragment
+        state.sharedData.blocksWithDefines.push(this);
+        state.sharedData.bindableBlocks.push(this);
+
+        state._emitUniformFromString(this._textureInfoName, "float");
+
+        let uvInput = this.uv;
+        let output = this._outputs[0];
+        const complement = ` * ${this._textureInfoName}`;
+
+        state.compilationString += `#ifdef ${this._defineName}\r\n`;
+        state.compilationString += `vec4 ${output.associatedVariableName} = texture2D(${this._samplerName}, ${this._transformedUVName})${complement};\r\n`;
+        state.compilationString += `#else\r\n`;
+        state.compilationString += `vec4 ${output.associatedVariableName} = texture2D(${this._samplerName}, ${"vMain" + uvInput.associatedVariableName})${complement};\r\n`;
+        state.compilationString += `#endif\r\n`;
+
+        return this;
+    }
+}

+ 4 - 2
src/Materials/Node/Blocks/Fragment/fragmentOutputBlock.ts

@@ -19,7 +19,7 @@ export class FragmentOutputBlock extends NodeMaterialBlock {
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Fragment, true);
 
-        this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3OrColor4);
+        this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Vector2OrVector3OrColor3OrVector4OrColor4);
     }
 
     /**
@@ -43,7 +43,9 @@ export class FragmentOutputBlock extends NodeMaterialBlock {
         let input = this.color;
         state.sharedData.hints.needAlphaBlending = this.alphaBlendingEnabled;
 
-        if (input.connectedPoint && input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Color3) {
+        if (input.connectedPoint && input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Vector2) {
+            state.compilationString += `gl_FragColor = vec4(${input.associatedVariableName}.r, ${input.associatedVariableName}.g, 0., 1.0);\r\n`;
+        } else if (input.connectedPoint && (input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Color3 || input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Vector3)) {
             state.compilationString += `gl_FragColor = vec4(${input.associatedVariableName}, 1.0);\r\n`;
         } else {
             state.compilationString += `gl_FragColor = ${input.associatedVariableName};\r\n`;

+ 0 - 1
src/Materials/Node/Blocks/Fragment/index.ts

@@ -5,5 +5,4 @@ export * from "./rgbaMergerBlock";
 export * from "./rgbMergerBlock";
 export * from "./rgbaSplitterBlock";
 export * from "./rgbSplitterBlock";
-export * from "./textureBlock";
 export * from "./imageProcessingBlock";

+ 0 - 209
src/Materials/Node/Blocks/Fragment/textureBlock.ts

@@ -1,209 +0,0 @@
-import { NodeMaterialBlock } from '../../nodeMaterialBlock';
-import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
-import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
-import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
-import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
-import { BaseTexture } from '../../../Textures/baseTexture';
-import { AbstractMesh } from '../../../../Meshes/abstractMesh';
-import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
-
-/**
- * Block used to read a texture from a sampler
- */
-export class TextureBlock extends NodeMaterialBlock {
-    private _defineName: string;
-
-    /**
-     * Gets or sets a boolean indicating that the block can automatically fetch the texture matrix
-     */
-    public autoConnectTextureMatrix = true;
-
-    /**
-     * Gets or sets a boolean indicating that the block can automatically select the uv channel based on texture
-     */
-    public autoSelectUV = true;
-
-    /**
-     * Create a new TextureBlock
-     * @param name defines the block name
-     */
-    public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Fragment);
-
-        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2);
-        this.registerInput("textureInfo", NodeMaterialBlockConnectionPointTypes.Vector2, true);
-
-        this.registerInput("transformedUV", NodeMaterialBlockConnectionPointTypes.Vector2, false, NodeMaterialBlockTargets.Vertex);
-        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Texture, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("textureTransform", NodeMaterialBlockConnectionPointTypes.Matrix, true, NodeMaterialBlockTargets.Vertex);
-
-        this.registerOutput("color", NodeMaterialBlockConnectionPointTypes.Color4);
-
-        // Setup
-        this._inputs[0]._needToEmitVarying = false;
-        this._inputs[0]._forceUniformInVertexShaderOnly = true;
-    }
-
-    /**
-     * Gets the current class name
-     * @returns the class name
-     */
-    public getClassName() {
-        return "TextureBlock";
-    }
-
-    /**
-     * Gets the uv input component
-     */
-    public get uv(): NodeMaterialConnectionPoint {
-        return this._inputs[0];
-    }
-
-    /**
-     * Gets the texture information input component
-     */
-    public get textureInfo(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
-    /**
-     * Gets the transformed uv input component
-     */
-    public get transformedUV(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
-     * Gets the texture input component
-     */
-    public get texture(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
-    }
-
-    /**
-     * Gets the texture transform input component
-     */
-    public get textureTransform(): NodeMaterialConnectionPoint {
-        return this._inputs[4];
-    }
-
-    /**
-     * Gets the output component
-     */
-    public get output(): NodeMaterialConnectionPoint {
-        return this._outputs[0];
-    }
-
-    public autoConfigure() {
-        if (this.uv.isUndefined) {
-            this.uv.setAsAttribute();
-            this.uv.connectTo(this.transformedUV);
-        }
-
-        if (this.transformedUV.isUndefined) {
-            this.uv.connectTo(this.transformedUV);
-        }
-    }
-
-    public initialize(state: NodeMaterialBuildState) {
-        if (this.texture.value && this.texture.value.getTextureMatrix) {
-            const texture = this.texture.value as BaseTexture;
-
-            if (this.autoConnectTextureMatrix) {
-                this.textureTransform.valueCallback = () => texture.getTextureMatrix();
-            }
-            if (this.autoSelectUV) {
-                this.uv.setAsAttribute("uv" + (texture.coordinatesIndex ? (texture.coordinatesIndex + 1) : ""));
-            }
-        }
-    }
-
-    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
-        if (!this.texture.value || !this.texture.value.getTextureMatrix) {
-            return;
-        }
-
-        let uvInput = this.uv;
-        let textureTransform = this.textureTransform;
-        let isTextureTransformConnected = textureTransform.connectedPoint != null || textureTransform.isUniform;
-
-        const texture = this.texture.value as BaseTexture;
-        let mainUVName = ("vMain" + uvInput.associatedVariableName).toUpperCase();
-
-        if (isTextureTransformConnected && !texture.getTextureMatrix().isIdentityAs3x2()) {
-            defines.setValue(this._defineName, true);
-            defines.setValue(mainUVName, false);
-        } else {
-            defines.setValue(this._defineName, false);
-            defines.setValue(mainUVName, true);
-        }
-    }
-
-    public isReady() {
-        let texture = this.texture.value as BaseTexture;
-        if (texture && !texture.isReadyOrNotBlocking()) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private _injectVertexCode(state: NodeMaterialBuildState) {
-        let uvInput = this.uv;
-        let transformedUV = this.transformedUV;
-        let textureTransform = this.textureTransform;
-        let isTextureTransformConnected = textureTransform.connectedPoint != null || textureTransform.isUniform;
-
-        // Inject code in vertex
-        this._defineName = state._getFreeDefineName("UVTRANSFORM");
-        let mainUVName = "vMain" + uvInput.associatedVariableName;
-
-        transformedUV.associatedVariableName = state._getFreeVariableName(transformedUV.name);
-        state._emitVaryings(transformedUV, this._defineName, true);
-        state._emitVaryings(transformedUV, mainUVName.toUpperCase(), true, false, mainUVName);
-
-        textureTransform.associatedVariableName = state._getFreeVariableName(textureTransform.name);
-        state._emitUniformOrAttributes(textureTransform, this._defineName);
-
-        if (isTextureTransformConnected) {
-            if (state.sharedData.emitComments) {
-                state.compilationString += `\r\n//${this.name}\r\n`;
-            }
-            state.compilationString += `#ifdef ${this._defineName}\r\n`;
-            state.compilationString += `${transformedUV.associatedVariableName} = vec2(${textureTransform.associatedVariableName} * vec4(${uvInput.associatedVariableName}, 1.0, 0.0));\r\n`;
-            state.compilationString += `#else\r\n`;
-            state.compilationString += `${mainUVName} = ${uvInput.associatedVariableName};\r\n`;
-            state.compilationString += `#endif\r\n`;
-        } else {
-            state.compilationString += `${mainUVName} = ${uvInput.associatedVariableName};\r\n`;
-        }
-    }
-
-    protected _buildBlock(state: NodeMaterialBuildState) {
-        super._buildBlock(state);
-
-        state.sharedData.blockingBlocks.push(this);
-
-        // Vertex
-        this._injectVertexCode(state._vertexState);
-
-        // Fragment
-        state.sharedData.blocksWithDefines.push(this);
-
-        let uvInput = this.uv;
-        let transformedUV = this.transformedUV;
-        let textureInfo = this.textureInfo;
-        let samplerInput = this.texture;
-        let output = this._outputs[0];
-        let isTextureInfoConnected = textureInfo.connectedPoint != null || textureInfo.isUniform;
-        const complement = isTextureInfoConnected ? ` * ${textureInfo.associatedVariableName}.y` : "";
-
-        state.compilationString += `#ifdef ${this._defineName}\r\n`;
-        state.compilationString += `vec4 ${output.associatedVariableName} = texture2D(${samplerInput.associatedVariableName}, ${transformedUV.associatedVariableName})${complement};\r\n`;
-        state.compilationString += `#else\r\n`;
-        state.compilationString += `vec4 ${output.associatedVariableName} = texture2D(${samplerInput.associatedVariableName}, ${"vMain" + uvInput.associatedVariableName})${complement};\r\n`;
-        state.compilationString += `#endif\r\n`;
-
-        return this;
-    }
-}

+ 1 - 0
src/Materials/Node/Blocks/Input/index.ts

@@ -0,0 +1 @@
+export * from "./inputBlock";

+ 426 - 0
src/Materials/Node/Blocks/Input/inputBlock.ts

@@ -0,0 +1,426 @@
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBlockConnectionPointMode } from '../../NodeMaterialBlockConnectionPointMode';
+import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
+import { Nullable } from '../../../../types';
+import { Effect } from '../../../../Materials/effect';
+import { Matrix, Vector2, Vector3 } from '../../../../Maths/math';
+import { Scene } from '../../../../scene';
+import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
+import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
+
+/**
+ * Block used to expose an input value
+ */
+export class InputBlock extends NodeMaterialBlock {
+    private _mode = NodeMaterialBlockConnectionPointMode.Undefined;
+    private _associatedVariableName: string;
+    private _storedValue: any;
+    private _valueCallback: () => any;
+    private _type: NodeMaterialBlockConnectionPointTypes;
+
+    /** @hidden */
+    public _wellKnownValue: Nullable<NodeMaterialWellKnownValues> = null;
+
+    /**
+     * Gets or sets the connection point type (default is float)
+     */
+    public get type(): NodeMaterialBlockConnectionPointTypes {
+        if (this._type === NodeMaterialBlockConnectionPointTypes.AutoDetect) {
+            if (this.isUniform && this.value != null) {
+                if (!isNaN(this.value)) {
+                    return NodeMaterialBlockConnectionPointTypes.Float;
+                }
+
+                switch (this.value.getClassName()) {
+                    case "Vector2":
+                        return NodeMaterialBlockConnectionPointTypes.Vector2;
+                    case "Vector3":
+                        return NodeMaterialBlockConnectionPointTypes.Vector3;
+                    case "Vector4":
+                        return NodeMaterialBlockConnectionPointTypes.Vector4;
+                    case "Color3":
+                        return NodeMaterialBlockConnectionPointTypes.Color3;
+                    case "Color4":
+                        return NodeMaterialBlockConnectionPointTypes.Color4;
+                }
+            }
+
+            if (this.isAttribute) {
+                switch (this.name) {
+                    case "position":
+                    case "normal":
+                    case "tangent":
+                        return NodeMaterialBlockConnectionPointTypes.Vector3;
+                    case "uv":
+                    case "uv2":
+                        return NodeMaterialBlockConnectionPointTypes.Vector2;
+                }
+            }
+
+            if (this.isWellKnownValue) {
+                switch (this._wellKnownValue) {
+                    case NodeMaterialWellKnownValues.World:
+                    case NodeMaterialWellKnownValues.WorldView:
+                    case NodeMaterialWellKnownValues.WorldViewProjection:
+                    case NodeMaterialWellKnownValues.View:
+                    case NodeMaterialWellKnownValues.ViewProjection:
+                    case NodeMaterialWellKnownValues.Projection:
+                        return NodeMaterialBlockConnectionPointTypes.Matrix;
+                    case NodeMaterialWellKnownValues.CameraPosition:
+                        return NodeMaterialBlockConnectionPointTypes.Vector3;
+                }
+            }
+        }
+
+        return this._type;
+    }
+
+    /**
+     * Creates a new InputBlock
+     * @param name defines the block name
+     * @param target defines the target of that block (Vertex by default)
+     * @param type defines the type of the input (can be set to NodeMaterialBlockConnectionPointTypes.AutoDetect)
+     */
+    public constructor(name: string, target = NodeMaterialBlockTargets.Vertex, type: NodeMaterialBlockConnectionPointTypes = NodeMaterialBlockConnectionPointTypes.AutoDetect) {
+        super(name, target, false, true);
+
+        this._type = type;
+
+        this.registerOutput("output", type);
+    }
+
+    /**
+     * Gets the output component
+     */
+    public get output(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    /**
+     * Set the source of this connection point to a vertex attribute
+     * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
+     * @returns the current connection point
+     */
+    public setAsAttribute(attributeName?: string): InputBlock {
+        if (attributeName) {
+            this.name = attributeName;
+        }
+        this._mode = NodeMaterialBlockConnectionPointMode.Attribute;
+        return this;
+    }
+
+    /**
+     * 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
+     * @returns the current connection point
+     */
+    public setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock {
+        this.wellKnownValue = value;
+        return this;
+    }
+
+    /**
+     * Gets or sets the value of that point.
+     * Please note that this value will be ignored if valueCallback is defined
+     */
+    public get value(): any {
+        return this._storedValue;
+    }
+
+    public set value(value: any) {
+        this._storedValue = value;
+        this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
+    }
+
+    /**
+     * Gets or sets a callback used to get the value of that point.
+     * Please note that setting this value will force the connection point to ignore the value property
+     */
+    public get valueCallback(): () => any {
+        return this._valueCallback;
+    }
+
+    public set valueCallback(value: () => any) {
+        this._valueCallback = value;
+        this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
+    }
+
+    /**
+     * Gets or sets the associated variable name in the shader
+     */
+    public get associatedVariableName(): string {
+        return this._associatedVariableName;
+    }
+
+    public set associatedVariableName(value: string) {
+        this._associatedVariableName = value;
+    }
+
+    /**
+     * Gets a boolean indicating that this connection point not defined yet
+     */
+    public get isUndefined(): boolean {
+        return this._mode === NodeMaterialBlockConnectionPointMode.Undefined;
+    }
+
+    /**
+     * Gets or sets a boolean indicating that this connection point is coming from an uniform.
+     * In this case the connection point name must be the name of the uniform to use.
+     * Can only be set on inputs
+     */
+    public get isUniform(): boolean {
+        return this._mode === NodeMaterialBlockConnectionPointMode.Uniform;
+    }
+
+    public set isUniform(value: boolean) {
+        this._mode = value ? NodeMaterialBlockConnectionPointMode.Uniform : NodeMaterialBlockConnectionPointMode.Undefined;
+        this.associatedVariableName = "";
+    }
+
+    /**
+     * Gets or sets a boolean indicating that this connection point is coming from an attribute.
+     * In this case the connection point name must be the name of the attribute to use
+     * Can only be set on inputs
+     */
+    public get isAttribute(): boolean {
+        return this._mode === NodeMaterialBlockConnectionPointMode.Attribute;
+    }
+
+    public set isAttribute(value: boolean) {
+        this._mode = value ? NodeMaterialBlockConnectionPointMode.Attribute : NodeMaterialBlockConnectionPointMode.Undefined;
+        this.associatedVariableName = "";
+    }
+
+    /**
+     * Gets or sets a boolean indicating that this connection point is generating a varying variable.
+     * Can only be set on exit points
+     */
+    public get isVarying(): boolean {
+        return this._mode === NodeMaterialBlockConnectionPointMode.Varying;
+    }
+
+    public set isVarying(value: boolean) {
+        this._mode = value ? NodeMaterialBlockConnectionPointMode.Varying : NodeMaterialBlockConnectionPointMode.Undefined;
+        this.associatedVariableName = "";
+    }
+
+    /**
+     * Gets a boolean indicating that the current connection point is a well known value
+     */
+    public get isWellKnownValue(): boolean {
+        return this._wellKnownValue != null;
+    }
+
+    /**
+     * Gets or sets the current well known value or null if not defined as well know value
+     */
+    public get wellKnownValue(): Nullable<NodeMaterialWellKnownValues> {
+        return this._wellKnownValue;
+    }
+
+    public set wellKnownValue(value: Nullable<NodeMaterialWellKnownValues>) {
+        this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
+        this.associatedVariableName = "";
+        this._wellKnownValue = value;
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "InputBlock";
+    }
+
+    private _emitDefine(define: string): string {
+        if (define[0] === "!") {
+            return `#ifndef ${define.substring(1)}\r\n`;
+        }
+
+        return `#ifdef ${define}\r\n`;
+    }
+
+    /**
+     * Set the input block to its default value (based on its type)
+     */
+    public setDefaultValue() {
+        switch (this.type) {
+            case NodeMaterialBlockConnectionPointTypes.Float:
+                this.value = 0;
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Vector2:
+                this.value = Vector2.Zero();
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Vector3:
+            case NodeMaterialBlockConnectionPointTypes.Color3:
+            case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3:
+                this.value = Vector3.Zero();
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Matrix:
+                this.value = Matrix.Identity();
+                break;
+        }
+    }
+
+    private _emit(state: NodeMaterialBuildState, define?: string) {
+        // Uniforms
+        if (this.isUniform) {
+            if (!this.associatedVariableName) {
+                this.associatedVariableName = state._getFreeVariableName("u_" + this.name);
+            }
+
+            if (state.uniforms.indexOf(this.associatedVariableName) !== -1) {
+                return;
+            }
+
+            state.uniforms.push(this.associatedVariableName);
+            if (define) {
+                state._uniformDeclaration += this._emitDefine(define);
+            }
+            state._uniformDeclaration += `uniform ${state._getGLType(this.type)} ${this.associatedVariableName};\r\n`;
+            if (define) {
+                state._uniformDeclaration += `#endif\r\n`;
+            }
+
+            // well known
+            let hints = state.sharedData.hints;
+            if (this._wellKnownValue !== null) {
+                switch (this._wellKnownValue) {
+                    case NodeMaterialWellKnownValues.WorldView:
+                        hints.needWorldViewMatrix = true;
+                        break;
+                    case NodeMaterialWellKnownValues.WorldViewProjection:
+                        hints.needWorldViewProjectionMatrix = true;
+                        break;
+                }
+            }
+
+            return;
+        }
+
+        // Attribute
+        if (this.isAttribute) {
+            this.associatedVariableName = this.name;
+
+            if (this.target === NodeMaterialBlockTargets.Vertex && state._vertexState) { // Attribute for fragment need to be carried over by varyings
+                this._emit(state._vertexState, define);
+                return;
+            }
+
+            if (state.attributes.indexOf(this.associatedVariableName) !== -1) {
+                return;
+            }
+
+            state.attributes.push(this.associatedVariableName);
+            if (define) {
+                state._attributeDeclaration += this._emitDefine(define);
+            }
+            state._attributeDeclaration += `attribute ${state._getGLType(this.type)} ${this.associatedVariableName};\r\n`;
+            if (define) {
+                state._attributeDeclaration += `#endif\r\n`;
+            }
+        }
+    }
+
+    /** @hidden */
+    public _transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix) {
+        if (!this._wellKnownValue) {
+            return;
+        }
+
+        let variableName = this.associatedVariableName;
+        switch (this._wellKnownValue) {
+            case NodeMaterialWellKnownValues.World:
+                effect.setMatrix(variableName, world);
+                break;
+            case NodeMaterialWellKnownValues.WorldView:
+                effect.setMatrix(variableName, worldView);
+                break;
+            case NodeMaterialWellKnownValues.WorldViewProjection:
+                effect.setMatrix(variableName, worldViewProjection);
+                break;
+        }
+    }
+
+    /** @hidden */
+    public _transmit(effect: Effect, scene: Scene) {
+        if (this.isAttribute) {
+            return;
+        }
+
+        let variableName = this.associatedVariableName;
+        if (this._wellKnownValue) {
+            switch (this._wellKnownValue) {
+                case NodeMaterialWellKnownValues.World:
+                case NodeMaterialWellKnownValues.WorldView:
+                case NodeMaterialWellKnownValues.WorldViewProjection:
+                    return;
+                case NodeMaterialWellKnownValues.View:
+                    effect.setMatrix(variableName, scene.getViewMatrix());
+                    break;
+                case NodeMaterialWellKnownValues.Projection:
+                    effect.setMatrix(variableName, scene.getProjectionMatrix());
+                    break;
+                case NodeMaterialWellKnownValues.ViewProjection:
+                    effect.setMatrix(variableName, scene.getTransformMatrix());
+                    break;
+                case NodeMaterialWellKnownValues.CameraPosition:
+                    effect.setVector3(variableName, scene.activeCamera!.globalPosition);
+                    break;
+                case NodeMaterialWellKnownValues.FogColor:
+                    effect.setColor3(variableName, scene.fogColor);
+                    break;
+            }
+            return;
+        }
+
+        let value = this._valueCallback ? this._valueCallback() : this._storedValue;
+
+        if (value === null) {
+            return;
+        }
+
+        switch (this.type) {
+            case NodeMaterialBlockConnectionPointTypes.Float:
+                effect.setFloat(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Int:
+                effect.setInt(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Color3:
+                effect.setColor3(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Color4:
+                effect.setDirectColor4(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Vector2:
+                effect.setVector2(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Vector3:
+                effect.setVector3(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
+                effect.setFloat4(variableName, value.r, value.g, value.b, value.a || 1.0);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Vector4OrColor4:
+            case NodeMaterialBlockConnectionPointTypes.Vector4:
+                effect.setVector4(variableName, value);
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Matrix:
+                effect.setMatrix(variableName, value);
+                break;
+        }
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        if (this.isUniform || this.isWellKnownValue) {
+            state.sharedData.inputBlocks.push(this);
+        }
+
+        this._emit(state);
+    }
+}

+ 21 - 10
src/Materials/Node/Blocks/Vertex/bonesBlock.ts

@@ -9,6 +9,7 @@ import { Effect, EffectFallbacks } from '../../../effect';
 import { MaterialHelper } from '../../../materialHelper';
 import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
 import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { InputBlock } from '../Input/inputBlock';
 
 /**
  * Block used to add support for vertex skinning (bones)
@@ -92,20 +93,30 @@ export class BonesBlock extends NodeMaterialBlock {
     }
 
     public autoConfigure() {
-        if (this.matricesIndices.isUndefined) {
-            this.matricesIndices.setAsAttribute();
+        if (!this.matricesIndices.isConnected) {
+            let matricesIndicesInput = new InputBlock("matricesIndices", undefined, NodeMaterialBlockConnectionPointTypes.Vector4);
+            matricesIndicesInput.setAsAttribute("matricesIndices");
+            matricesIndicesInput.output.connectTo(this.matricesIndices);
         }
-        if (this.matricesWeights.isUndefined) {
-            this.matricesWeights.setAsAttribute();
+        if (!this.matricesWeights.isConnected) {
+            let matricesWeightsInput = new InputBlock("matricesWeights", undefined, NodeMaterialBlockConnectionPointTypes.Vector4);
+            matricesWeightsInput.setAsAttribute("matricesWeights");
+            matricesWeightsInput.output.connectTo(this.matricesWeights);
         }
-        if (this.matricesIndicesExtra.isUndefined) {
-            this.matricesIndicesExtra.setAsAttribute();
+        if (!this.matricesIndicesExtra.isConnected) {
+            let matricesIndicesExtraInput = new InputBlock("matricesIndicesExtra", undefined, NodeMaterialBlockConnectionPointTypes.Vector4);
+            matricesIndicesExtraInput.setAsAttribute("matricesIndicesExtra");
+            matricesIndicesExtraInput.output.connectTo(this.matricesIndicesExtra);
         }
-        if (this.matricesWeightsExtra.isUndefined) {
-            this.matricesWeightsExtra.setAsAttribute();
+        if (!this.matricesWeightsExtra.isConnected) {
+            let matricesWeightsExtraInput = new InputBlock("matricesWeightsExtra", undefined, NodeMaterialBlockConnectionPointTypes.Vector4);
+            matricesWeightsExtraInput.setAsAttribute("matricesWeightsExtra");
+            matricesWeightsExtraInput.output.connectTo(this.matricesWeightsExtra);
         }
-        if (this.world.isUndefined) {
-            this.world.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+        if (!this.world.isConnected) {
+            let worldInput = new InputBlock("world", undefined, NodeMaterialBlockConnectionPointTypes.Matrix);
+            worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            worldInput.output.connectTo(this.world);
         }
     }
 

+ 16 - 5
src/Materials/Node/Blocks/Vertex/instancesBlock.ts

@@ -6,6 +6,7 @@ import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
 import { AbstractMesh } from '../../../../Meshes/abstractMesh';
 import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
 import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
+import { InputBlock } from '../Input/inputBlock';
 
 /**
  * Block used to add support for instances
@@ -80,19 +81,29 @@ export class InstancesBlock extends NodeMaterialBlock {
 
     public autoConfigure() {
         if (!this.world0.connectedPoint) {
-            this.world0.setAsAttribute();
+            let world0Input = new InputBlock("world0");
+            world0Input.setAsAttribute("world0");
+            world0Input.output.connectTo(this.world0);
         }
         if (!this.world1.connectedPoint) {
-            this.world1.setAsAttribute();
+            let world1Input = new InputBlock("world1");
+            world1Input.setAsAttribute("world1");
+            world1Input.output.connectTo(this.world1);
         }
         if (!this.world2.connectedPoint) {
-            this.world2.setAsAttribute();
+            let world2Input = new InputBlock("world2");
+            world2Input.setAsAttribute("world2");
+            world2Input.output.connectTo(this.world2);
         }
         if (!this.world3.connectedPoint) {
-            this.world3.setAsAttribute();
+            let world3Input = new InputBlock("world3");
+            world3Input.setAsAttribute("world3");
+            world3Input.output.connectTo(this.world3);
         }
         if (!this.world.connectedPoint) {
-            this.world.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            let worldInput = new InputBlock("world");
+            worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            worldInput.output.connectTo(this.world);
         }
 
         this.world.define = "!INSTANCES";

+ 18 - 8
src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts

@@ -9,6 +9,7 @@ import { Effect } from '../../../effect';
 import { Mesh } from '../../../../Meshes/mesh';
 import { MaterialHelper } from '../../../materialHelper';
 import { VertexBuffer } from '../../../../Meshes/buffer';
+import { InputBlock } from '../Input/inputBlock';
 
 /**
  * Block used to add morph targets support to vertex shader
@@ -103,16 +104,25 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
     }
 
     public autoConfigure() {
-        if (this.position.isUndefined) {
-            this.position.setAsAttribute();
+        if (!this.position.isConnected) {
+            let positionInput = new InputBlock("position");
+            positionInput.setAsAttribute("position");
+            positionInput.output.connectTo(this.position);
         }
-        if (this.normal.isUndefined) {
-            this.normal.setAsAttribute();
-            this.normal.define = "NORMAL";
+        if (!this.normal.isConnected) {
+            let normalInput = new InputBlock("normal");
+            normalInput.setAsAttribute("normal");
+            normalInput.output.connectTo(this.normal);
         }
-        if (this.tangent.isUndefined) {
-            this.tangent.setAsAttribute();
-            this.tangent.define = "TANGENT";
+        if (!this.tangent.isConnected) {
+            let tangentInput = new InputBlock("tangent");
+            tangentInput.setAsAttribute("tangent");
+            tangentInput.output.connectTo(this.tangent);
+        }
+        if (!this.uv.isConnected) {
+            let uvInput = new InputBlock("uv");
+            uvInput.setAsAttribute("uv");
+            uvInput.output.connectTo(this.uv);
         }
     }
 

+ 2 - 1
src/Materials/Node/Blocks/addBlock.ts

@@ -2,6 +2,7 @@ import { NodeMaterialBlock } from '../nodeMaterialBlock';
 import { NodeMaterialBlockConnectionPointTypes } from '../nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
 import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../nodeMaterialBlockTargets';
 /**
  * Block used to add 2 vector4
  */
@@ -11,7 +12,7 @@ export class AddBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name);
+        super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("left", NodeMaterialBlockConnectionPointTypes.AutoDetect);
         this.registerInput("right", NodeMaterialBlockConnectionPointTypes.AutoDetect);

+ 2 - 1
src/Materials/Node/Blocks/clampBlock.ts

@@ -2,6 +2,7 @@ import { NodeMaterialBlock } from '../nodeMaterialBlock';
 import { NodeMaterialBlockConnectionPointTypes } from '../nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
 import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../nodeMaterialBlockTargets';
 /**
  * Block used to clamp a float
  */
@@ -17,7 +18,7 @@ export class ClampBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name);
+        super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("value", NodeMaterialBlockConnectionPointTypes.Float);
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Float);

+ 1 - 0
src/Materials/Node/Blocks/index.ts

@@ -1,6 +1,7 @@
 export * from "./Vertex/index";
 export * from "./Fragment/index";
 export * from "./Dual/index";
+export * from "./Input/index";
 export * from "./multiplyBlock";
 export * from "./addBlock";
 export * from "./clampBlock";

+ 2 - 1
src/Materials/Node/Blocks/multiplyBlock.ts

@@ -2,6 +2,7 @@ import { NodeMaterialBlock } from '../nodeMaterialBlock';
 import { NodeMaterialBlockConnectionPointTypes } from '../nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
 import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../nodeMaterialBlockTargets';
 /**
  * Block used to multiply 2 values
  */
@@ -11,7 +12,7 @@ export class MultiplyBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name);
+        super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("left", NodeMaterialBlockConnectionPointTypes.AutoDetect);
         this.registerInput("right", NodeMaterialBlockConnectionPointTypes.AutoDetect);

+ 1 - 1
src/Materials/Node/Blocks/vector2TransformBlock.ts

@@ -23,7 +23,7 @@ export class Vector2TransformBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Vertex);
+        super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("vector", NodeMaterialBlockConnectionPointTypes.Vector2);
         this.registerInput("transform", NodeMaterialBlockConnectionPointTypes.Matrix);

+ 1 - 1
src/Materials/Node/Blocks/vector3TransformBlock.ts

@@ -18,7 +18,7 @@ export class Vector3TransformBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Vertex);
+        super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("vector", NodeMaterialBlockConnectionPointTypes.Vector3);
         this.registerInput("transform", NodeMaterialBlockConnectionPointTypes.Matrix);

+ 1 - 1
src/Materials/Node/Blocks/vector4TransformBlock.ts

@@ -18,7 +18,7 @@ export class Vector4TransformBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Vertex);
+        super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("vector", NodeMaterialBlockConnectionPointTypes.Vector3OrVector4);
         this.registerInput("transform", NodeMaterialBlockConnectionPointTypes.Matrix);

+ 57 - 36
src/Materials/Node/nodeMaterial.ts

@@ -8,8 +8,6 @@ import { Engine } from '../../Engines/engine';
 import { NodeMaterialBuildState } from './nodeMaterialBuildState';
 import { EffectCreationOptions, EffectFallbacks } from '../effect';
 import { BaseTexture } from '../../Materials/Textures/baseTexture';
-import { NodeMaterialConnectionPoint } from './nodeMaterialBlockConnectionPoint';
-import { NodeMaterialBlockConnectionPointTypes } from './nodeMaterialBlockConnectionPointTypes';
 import { Observable, Observer } from '../../Misc/observable';
 import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
 import { NodeMaterialBuildStateSharedData } from './nodeMaterialBuildStateSharedData';
@@ -23,6 +21,7 @@ import { Tools } from '../../Misc/tools';
 import { Vector4TransformBlock } from './Blocks/vector4TransformBlock';
 import { VertexOutputBlock } from './Blocks/Vertex/vertexOutputBlock';
 import { FragmentOutputBlock } from './Blocks/Fragment/fragmentOutputBlock';
+import { InputBlock } from './Blocks/Input/inputBlock';
 
 // declare NODEEDITOR namespace for compilation issue
 declare var NODEEDITOR: any;
@@ -102,7 +101,6 @@ export class NodeMaterial extends PushMaterial {
     private _buildWasSuccessful = false;
     private _cachedWorldViewMatrix = new Matrix();
     private _cachedWorldViewProjectionMatrix = new Matrix();
-    private _textureConnectionPoints = new Array<NodeMaterialConnectionPoint>();
     private _optimizers = new Array<NodeMaterialOptimizer>();
 
     /** Define the URl to load node editor script */
@@ -375,19 +373,32 @@ export class NodeMaterial extends PushMaterial {
         return this._sharedData.hints.needAlphaTesting;
     }
 
-    private _initializeBlock(node: NodeMaterialBlock, state: NodeMaterialBuildState) {
+    private _initializeBlock(node: NodeMaterialBlock, state: NodeMaterialBuildState, nodesToProcessForOtherBuildState: NodeMaterialBlock[]) {
         node.initialize(state);
         node.autoConfigure();
 
-        for (var inputs of node.inputs) {
-            let connectedPoint = inputs.connectedPoint;
+        if (node.isInput) {
+            (node as InputBlock).associatedVariableName = "";
+        }
+
+        for (var input of node.inputs) {
+            input.associatedVariableName = "";
+
+            let connectedPoint = input.connectedPoint;
             if (connectedPoint) {
                 let block = connectedPoint.ownerBlock;
                 if (block !== node) {
-                    this._initializeBlock(block, state);
+                    if (block.target === NodeMaterialBlockTargets.VertexAndFragment) {
+                        nodesToProcessForOtherBuildState.push(block);
+                    }
+                    this._initializeBlock(block, state, nodesToProcessForOtherBuildState);
                 }
             }
         }
+
+        for (var output of node.outputs) {
+            output.associatedVariableName = "";
+        }
     }
 
     private _resetDualBlocks(node: NodeMaterialBlock, id: number) {
@@ -439,30 +450,35 @@ export class NodeMaterial extends PushMaterial {
         this._sharedData.verbose = verbose;
 
         // Initialize blocks
+        let vertexNodes: NodeMaterialBlock[] = [];
+        let fragmentNodes: NodeMaterialBlock[] = [];
+
         for (var vertexOutputNode of this._vertexOutputNodes) {
-            this._initializeBlock(vertexOutputNode, this._vertexCompilationState);
+            vertexNodes.push(vertexOutputNode);
+            this._initializeBlock(vertexOutputNode, this._vertexCompilationState, fragmentNodes);
         }
 
         for (var fragmentOutputNode of this._fragmentOutputNodes) {
-            this._initializeBlock(fragmentOutputNode, this._fragmentCompilationState);
+            fragmentNodes.push(fragmentOutputNode);
+            this._initializeBlock(fragmentOutputNode, this._fragmentCompilationState, vertexNodes);
         }
 
         // Optimize
         this.optimize();
 
         // Vertex
-        for (var vertexOutputNode of this._vertexOutputNodes) {
+        for (var vertexOutputNode of vertexNodes) {
             vertexOutputNode.build(this._vertexCompilationState);
         }
 
         // Fragment
         this._fragmentCompilationState._vertexState = this._vertexCompilationState;
 
-        for (var fragmentOutputNode of this._fragmentOutputNodes) {
+        for (var fragmentOutputNode of fragmentNodes) {
             this._resetDualBlocks(fragmentOutputNode, this._buildId - 1);
         }
 
-        for (var fragmentOutputNode of this._fragmentOutputNodes) {
+        for (var fragmentOutputNode of fragmentNodes) {
             fragmentOutputNode.build(this._fragmentCompilationState);
         }
 
@@ -470,10 +486,6 @@ export class NodeMaterial extends PushMaterial {
         this._vertexCompilationState.finalize(this._vertexCompilationState);
         this._fragmentCompilationState.finalize(this._fragmentCompilationState);
 
-        // Textures
-        this._textureConnectionPoints =
-            this._sharedData.uniformConnectionPoints.filter((u) => u.type === NodeMaterialBlockConnectionPointTypes.Texture || u.type === NodeMaterialBlockConnectionPointTypes.Texture3D);
-
         this._buildId++;
 
         // Errors
@@ -555,6 +567,10 @@ export class NodeMaterial extends PushMaterial {
 
         // Shared defines
         this._sharedData.blocksWithDefines.forEach((b) => {
+            b.initializeDefines(mesh, this, defines, useInstances);
+        });
+
+        this._sharedData.blocksWithDefines.forEach((b) => {
             b.prepareDefines(mesh, this, defines, useInstances);
         });
 
@@ -677,8 +693,8 @@ export class NodeMaterial extends PushMaterial {
         }
 
         // Connection points
-        for (var connectionPoint of this._sharedData.uniformConnectionPoints) {
-            connectionPoint.transmitWorld(this._activeEffect, world, this._cachedWorldViewMatrix, this._cachedWorldViewProjectionMatrix);
+        for (var inputBlock of this._sharedData.inputBlocks) {
+            inputBlock._transmitWorld(this._activeEffect, world, this._cachedWorldViewMatrix, this._cachedWorldViewProjectionMatrix);
         }
     }
 
@@ -710,8 +726,8 @@ export class NodeMaterial extends PushMaterial {
                 }
 
                 // Connection points
-                for (var connectionPoint of sharedData.uniformConnectionPoints) {
-                    connectionPoint.transmit(effect, scene);
+                for (var inputBlock of sharedData.inputBlocks) {
+                    inputBlock._transmit(effect, scene);
                 }
             }
         }
@@ -726,11 +742,7 @@ export class NodeMaterial extends PushMaterial {
     public getActiveTextures(): BaseTexture[] {
         var activeTextures = super.getActiveTextures();
 
-        for (var connectionPoint of this._textureConnectionPoints) {
-            if (connectionPoint.value) {
-                activeTextures.push(connectionPoint.value);
-            }
-        }
+        activeTextures.push(...this._sharedData.textureBlocks.filter((tb) => tb.texture).map((tb) => tb.texture!));
 
         return activeTextures;
     }
@@ -745,8 +757,8 @@ export class NodeMaterial extends PushMaterial {
             return true;
         }
 
-        for (var connectionPoint of this._textureConnectionPoints) {
-            if (connectionPoint.value === texture) {
+        for (var t of this._sharedData.textureBlocks) {
+            if (t.texture === texture) {
                 return true;
             }
         }
@@ -763,14 +775,11 @@ export class NodeMaterial extends PushMaterial {
     public dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, notBoundToMesh?: boolean): void {
 
         if (forceDisposeTextures) {
-            for (var connectionPoint of this._textureConnectionPoints) {
-                if (connectionPoint.value) {
-                    (connectionPoint.value as BaseTexture).dispose();
-                }
+            for (var texture of this._sharedData.textureBlocks.filter((tb) => tb.texture).map((tb) => tb.texture!)) {
+                texture.dispose();
             }
         }
 
-        this._textureConnectionPoints = [];
         this.onBuildObservable.clear();
 
         super.dispose(forceDisposeEffect, forceDisposeTextures, notBoundToMesh);
@@ -822,20 +831,32 @@ export class NodeMaterial extends PushMaterial {
     public setToDefault() {
         this.clear();
 
+        var positionInput = new InputBlock("position");
+        positionInput.setAsAttribute("position");
+
+        var worldInput = new InputBlock("world");
+        worldInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.World);
+
         var worldPos = new Vector4TransformBlock("worldPos");
-        worldPos.vector.setAsAttribute("position");
-        worldPos.transform.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.World);
+        positionInput.connectTo(worldPos);
+        worldInput.connectTo(worldPos);
+
+        var viewProjectionInput = new InputBlock("viewProjection");
+        viewProjectionInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.ViewProjection);
 
         var worldPosdMultipliedByViewProjection = new Vector4TransformBlock("worldPos * viewProjectionTransform");
         worldPos.connectTo(worldPosdMultipliedByViewProjection);
-        worldPosdMultipliedByViewProjection.transform.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.ViewProjection);
+        viewProjectionInput.connectTo(worldPosdMultipliedByViewProjection);
 
         var vertexOutput = new VertexOutputBlock("vertexOutput");
         worldPosdMultipliedByViewProjection.connectTo(vertexOutput);
 
         // Pixel
+        var pixelColor = new InputBlock("color");
+        pixelColor.value = new Color4(0.8, 0.8, 0.8, 1);
+
         var pixelOutput = new FragmentOutputBlock("pixelOutput");
-        pixelOutput.color.value = new Color4(0.8, 0.8, 0.8, 1);
+        pixelColor.connectTo(pixelOutput);
 
         // Add to nodes
         this.addOutputNode(vertexOutput);

+ 82 - 44
src/Materials/Node/nodeMaterialBlock.ts

@@ -7,14 +7,17 @@ import { Effect, EffectFallbacks } from '../effect';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Mesh } from '../../Meshes/mesh';
 import { NodeMaterial, NodeMaterialDefines } from './nodeMaterial';
+import { InputBlock } from './Blocks/Input/inputBlock';
 
 /**
  * Defines a block that can be used inside a node based material
  */
 export class NodeMaterialBlock {
     private _buildId: number;
+    private _buildTarget: NodeMaterialBlockTargets;
     private _target: NodeMaterialBlockTargets;
     private _isFinalMerger = false;
+    private _isInput = false;
 
     /** @hidden */
     public _inputs = new Array<NodeMaterialConnectionPoint>();
@@ -34,6 +37,13 @@ export class NodeMaterialBlock {
     }
 
     /**
+     * Gets a boolean indicating that this block is an input (e.g. it sends data to the shader)
+     */
+    public get isInput(): boolean {
+        return this._isInput;
+    }
+
+    /**
      * Gets or sets the build Id
      */
     public get buildId(): number {
@@ -105,15 +115,15 @@ export class NodeMaterialBlock {
      * @param name defines the block name
      * @param target defines the target of that block (Vertex by default)
      * @param isFinalMerger defines a boolean indicating that this block is an end block (e.g. it is generating a system value). Default is false
+     * @param isInput defines a boolean indicating that this block is an input (e.g. it sends data to the shader). Default is false
      */
-    public constructor(name: string, target = NodeMaterialBlockTargets.Vertex, isFinalMerger = false) {
+    public constructor(name: string, target = NodeMaterialBlockTargets.Vertex, isFinalMerger = false, isInput = false) {
         this.name = name;
 
         this._target = target;
 
-        if (isFinalMerger) {
-            this._isFinalMerger = true;
-        }
+        this._isFinalMerger = isFinalMerger;
+        this._isInput = isInput;
     }
 
     /**
@@ -135,9 +145,9 @@ export class NodeMaterialBlock {
     }
 
     protected _declareOutput(output: NodeMaterialConnectionPoint, state: NodeMaterialBuildState): string {
-        if (output.isVarying) {
-            return `${output.associatedVariableName}`;
-        }
+        // if (output.isVarying) {
+        //     return `${output.associatedVariableName}`;
+        // }
 
         return `${state._getGLType(output.type)} ${output.associatedVariableName}`;
     }
@@ -211,7 +221,7 @@ export class NodeMaterialBlock {
      */
     public getFirstAvailableInput(forOutput: Nullable<NodeMaterialConnectionPoint> = null) {
         for (var input of this._inputs) {
-            if (!input.isUniform && !input.isAttribute && !input.connectedPoint) {
+            if (!input.connectedPoint) {
                 if (!forOutput || (forOutput.type & input.type) !== 0 || input.type === NodeMaterialBlockConnectionPointTypes.AutoDetect) {
                     return input;
                 }
@@ -228,7 +238,7 @@ export class NodeMaterialBlock {
      */
     public getFirstAvailableOutput(forBlock: Nullable<NodeMaterialBlock> = null) {
         for (var output of this._outputs) {
-            if (!forBlock || !forBlock.target || (forBlock.target & output.target) !== 0) {
+            if (!forBlock || !forBlock.target || forBlock.target === NodeMaterialBlockTargets.Neutral || (forBlock.target & output.target) !== 0) {
                 return output;
             }
         }
@@ -299,6 +309,17 @@ export class NodeMaterialBlock {
     }
 
     /**
+     * Initialize defines for shader compilation
+     * @param mesh defines the mesh to be rendered
+     * @param nodeMaterial defines the node material requesting the update
+     * @param defines defines the material defines to be prepared
+     * @param useInstances specifies that instances should be used
+     */
+    public initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances: boolean = false) {
+        // Do nothing
+    }
+
+    /**
      * Lets the block try to connect some inputs automatically
      */
     public autoConfigure() {
@@ -328,41 +349,60 @@ export class NodeMaterialBlock {
         return true;
     }
 
+    private _processBuild(block: NodeMaterialBlock, state: NodeMaterialBuildState, input: NodeMaterialConnectionPoint) {
+        block.build(state);
+
+        if (state._vertexState && (block.target & this.target) === 0) { // context switch! We need a varying
+            if ((!block.isInput && state.target !== block._buildTarget) // block was already emitted by vertex shader
+                || (block.isInput && (block as InputBlock).isAttribute) // block is an attribute
+            ) {
+                let connectedPoint = input.connectedPoint!;
+                state._vertexState._emitVaryingFromString("v_" + connectedPoint.associatedVariableName, state._getGLType(connectedPoint.type));
+                state._vertexState.compilationString += `${"v_" + connectedPoint.associatedVariableName} = ${connectedPoint.associatedVariableName};\r\n`;
+                input.associatedVariableName = "v_" + connectedPoint.associatedVariableName;
+                input._enforceAssociatedVariableName = true;
+            }
+        }
+    }
+
     /**
      * Compile the current node and generate the shader code
      * @param state defines the current compilation state (uniforms, samplers, current string)
-     * @returns the current block
+     * @param contextSwitched indicates that the previous block was built for a different context (vertex vs. fragment)
+     * @returns true if already built
      */
-    public build(state: NodeMaterialBuildState) {
+    public build(state: NodeMaterialBuildState, contextSwitched = false): boolean {
         if (this._buildId === state.sharedData.buildId) {
-            return;
+            return true;
         }
 
         // Check if "parent" blocks are compiled
         for (var input of this._inputs) {
             if (!input.connectedPoint) {
-                if (!input.isOptional && !input.isAttribute && !input.isUniform) { // Emit a warning
+                if (!input.isOptional) { // Emit a warning
                     state.sharedData.checks.notConnectedNonOptionalInputs.push(input);
                 }
                 continue;
             }
 
-            if ((input.target & this.target!) === 0) {
-                continue;
-            }
+            if (this.target !== NodeMaterialBlockTargets.Neutral) {
+                if ((input.target & this.target!) === 0) {
+                    continue;
+                }
 
-            if ((input.target & state.target!) === 0) {
-                continue;
+                if ((input.target & state.target!) === 0) {
+                    continue;
+                }
             }
 
             let block = input.connectedPoint.ownerBlock;
-            if (block && block !== this && block.buildId !== state.sharedData.buildId) {
-                block.build(state);
+            if (block && block !== this) {
+                this._processBuild(block, state, input);
             }
         }
 
         if (this._buildId === state.sharedData.buildId) {
-            return; // Need to check again as inputs can be connected multiple time to this endpoint
+            return true; // Need to check again as inputs can be connected multiple time to this endpoint
         }
 
         // Logs
@@ -370,27 +410,22 @@ export class NodeMaterialBlock {
             console.log(`${state.target === NodeMaterialBlockTargets.Vertex ? "Vertex shader" : "Fragment shader"}: Building ${this.name} [${this.getClassName()}]`);
         }
 
-        /** Prepare outputs */
-        for (var output of this._outputs) {
-            if ((output.target & this.target!) === 0) {
-                continue;
-            }
-            if ((output.target & state.target!) === 0) {
-                continue;
-            }
-            output.associatedVariableName = state._getFreeVariableName(output.name);
-            state._emitVaryings(output);
-        }
+        if (!this.isInput) {
+            /** Prepare outputs */
+            for (var output of this._outputs) {
+                if (this.target !== NodeMaterialBlockTargets.Neutral) {
+                    if ((output.target & this.target!) === 0) {
+                        continue;
+                    }
+                    if ((output.target & state.target!) === 0) {
+                        continue;
+                    }
+                }
 
-        // Build
-        for (var input of this._inputs) {
-            if ((input.target & this.target!) === 0) {
-                continue;
-            }
-            if ((input.target & state.target!) === 0) {
-                continue;
+                if (!output.associatedVariableName) {
+                    output.associatedVariableName = state._getFreeVariableName(output.name);
+                }
             }
-            state._emitUniformOrAttributes(input);
         }
 
         // Checks final outputs
@@ -405,13 +440,14 @@ export class NodeMaterialBlock {
             }
         }
 
-        if (state.sharedData.emitComments) {
+        if (!this.isInput && state.sharedData.emitComments) {
             state.compilationString += `\r\n//${this.name}\r\n`;
         }
 
         this._buildBlock(state);
 
         this._buildId = state.sharedData.buildId;
+        this._buildTarget = state.target;
 
         // Compile connected blocks
         for (var output of this._outputs) {
@@ -419,12 +455,14 @@ export class NodeMaterialBlock {
                 continue;
             }
 
-            for (var block of output.connectedBlocks) {
+            for (var endpoint of output.endpoints) {
+                let block = endpoint.ownerBlock;
+
                 if (block && (block.target & state.target) !== 0) {
-                    block.build(state);
+                    this._processBuild(block, state, endpoint);
                 }
             }
         }
-        return this;
+        return false;
     }
 }

+ 48 - 251
src/Materials/Node/nodeMaterialBlockConnectionPoint.ts

@@ -1,11 +1,7 @@
 import { NodeMaterialBlockConnectionPointTypes } from './nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
 import { Nullable } from '../../types';
-import { Effect } from '../effect';
-import { NodeMaterialWellKnownValues } from './nodeMaterialWellKnownValues';
-import { Scene } from '../../scene';
-import { Matrix } from '../../Maths/math';
-import { NodeMaterialBlockConnectionPointMode } from './NodeMaterialBlockConnectionPointMode';
+import { InputBlock } from './Blocks/Input/inputBlock';
 
 declare type NodeMaterialBlock = import("./nodeMaterialBlock").NodeMaterialBlock;
 
@@ -16,52 +12,49 @@ export class NodeMaterialConnectionPoint {
     /** @hidden */
     public _ownerBlock: NodeMaterialBlock;
     /** @hidden */
-    public _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
-    private _associatedVariableName: string;
-    private _endpoints = new Array<NodeMaterialConnectionPoint>();
-    private _storedValue: any;
-    private _valueCallback: () => any;
-    private _mode = NodeMaterialBlockConnectionPointMode.Undefined;
+    public _connectedPoint: Nullable<NodeMaterialConnectionPoint> = null;
 
-    /** @hidden */
-    public _wellKnownValue: Nullable<NodeMaterialWellKnownValues> = null;
+    private _endpoints = new Array<NodeMaterialConnectionPoint>();
+    private _associatedVariableName: string;
 
     /** @hidden */
     public _typeConnectionSource: Nullable<NodeMaterialConnectionPoint> = null;
 
-    /** @hidden */
-    public _needToEmitVarying = true;
+    private _type = NodeMaterialBlockConnectionPointTypes.Float;
 
     /** @hidden */
-    public _forceUniformInVertexShaderOnly = false;
+    public _enforceAssociatedVariableName = false;
+
+    /**
+     * Gets or sets the associated variable name in the shader
+     */
+    public get associatedVariableName(): string {
+        if (this._ownerBlock.isInput) {
+            return (this._ownerBlock as InputBlock).associatedVariableName;
+        }
+
+        if (!this._enforceAssociatedVariableName && this._connectedPoint) {
+            return this._connectedPoint.associatedVariableName;
+        }
+
+        return this._associatedVariableName;
+    }
+
+    public set associatedVariableName(value: string) {
+        this._associatedVariableName = value;
+    }
 
-    private _type = NodeMaterialBlockConnectionPointTypes.Float;
     /**
      * Gets or sets the connection point type (default is float)
      */
     public get type(): NodeMaterialBlockConnectionPointTypes {
         if (this._type === NodeMaterialBlockConnectionPointTypes.AutoDetect) {
-            if (this._connectedPoint) {
-                return this._connectedPoint.type;
+            if (this._ownerBlock.isInput) {
+                return (this._ownerBlock as InputBlock).type;
             }
 
-            if (this.isUniform && this.value != null) {
-                if (!isNaN(this.value)) {
-                    return NodeMaterialBlockConnectionPointTypes.Float;
-                }
-
-                switch (this.value.getClassName()) {
-                    case "Vector2":
-                        return NodeMaterialBlockConnectionPointTypes.Vector2;
-                    case "Vector3":
-                        return NodeMaterialBlockConnectionPointTypes.Vector3;
-                    case "Vector4":
-                        return NodeMaterialBlockConnectionPointTypes.Vector4;
-                    case "Color3":
-                        return NodeMaterialBlockConnectionPointTypes.Color3;
-                    case "Color4":
-                        return NodeMaterialBlockConnectionPointTypes.Color4;
-                }
+            if (this._connectedPoint) {
+                return this._connectedPoint.type;
             }
         }
 
@@ -100,92 +93,28 @@ export class NodeMaterialConnectionPoint {
     public target: NodeMaterialBlockTargets = NodeMaterialBlockTargets.VertexAndFragment;
 
     /**
-     * Gets or sets the value of that point.
-     * Please note that this value will be ignored if valueCallback is defined
+     * Gets a boolean indicating that the current point is connected
      */
-    public get value(): any {
-        return this._storedValue;
-    }
-
-    public set value(value: any) {
-        this._storedValue = value;
-        this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
+    public get isConnected(): boolean {
+        return this.connectedPoint !== null;
     }
 
     /**
-     * Gets or sets a callback used to get the value of that point.
-     * Please note that setting this value will force the connection point to ignore the value property
+     * Gets a boolean indicating that the current point is connected to an input block
      */
-    public get valueCallback(): () => any {
-        return this._valueCallback;
-    }
-
-    public set valueCallback(value: () => any) {
-        this._valueCallback = value;
-        this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
+    public get isConnectedToInput(): boolean {
+        return this.connectedPoint !== null && this.connectedPoint.ownerBlock.isInput;
     }
 
     /**
-     * Gets or sets the associated variable name in the shader
+     * Gets a the connected input block (if any)
      */
-    public get associatedVariableName(): string {
-        if (!this._associatedVariableName && this._connectedPoint) {
-            return this._connectedPoint.associatedVariableName;
+    public get connectInputBlock(): Nullable<InputBlock> {
+        if (!this.isConnectedToInput) {
+            return null;
         }
 
-        return this._associatedVariableName;
-    }
-
-    public set associatedVariableName(value: string) {
-        this._associatedVariableName = value;
-    }
-
-    /**
-     * Gets a boolean indicating that this connection point not defined yet
-     */
-    public get isUndefined(): boolean {
-        return this._mode === NodeMaterialBlockConnectionPointMode.Undefined;
-    }
-
-    /**
-     * Gets or sets a boolean indicating that this connection point is coming from an uniform.
-     * In this case the connection point name must be the name of the uniform to use.
-     * Can only be set on inputs
-     */
-    public get isUniform(): boolean {
-        return this._mode === NodeMaterialBlockConnectionPointMode.Uniform;
-    }
-
-    public set isUniform(value: boolean) {
-        this._mode = value ? NodeMaterialBlockConnectionPointMode.Uniform : NodeMaterialBlockConnectionPointMode.Undefined;
-        this.associatedVariableName = "";
-    }
-
-    /**
-     * Gets or sets a boolean indicating that this connection point is coming from an attribute.
-     * In this case the connection point name must be the name of the attribute to use
-     * Can only be set on inputs
-     */
-    public get isAttribute(): boolean {
-        return this._mode === NodeMaterialBlockConnectionPointMode.Attribute;
-    }
-
-    public set isAttribute(value: boolean) {
-        this._mode = value ? NodeMaterialBlockConnectionPointMode.Attribute : NodeMaterialBlockConnectionPointMode.Undefined;
-        this.associatedVariableName = "";
-    }
-
-    /**
-     * Gets or sets a boolean indicating that this connection point is generating a varying variable.
-     * Can only be set on exit points
-     */
-    public get isVarying(): boolean {
-        return this._mode === NodeMaterialBlockConnectionPointMode.Varying;
-    }
-
-    public set isVarying(value: boolean) {
-        this._mode = value ? NodeMaterialBlockConnectionPointMode.Varying : NodeMaterialBlockConnectionPointMode.Undefined;
-        this.associatedVariableName = "";
+        return this.connectedPoint!.ownerBlock as InputBlock;
     }
 
     /** Get the other side of the connection (if any) */
@@ -216,6 +145,11 @@ export class NodeMaterialConnectionPoint {
         return this._endpoints.map((e) => e.ownerBlock);
     }
 
+    /** Gets the list of connected endpoints */
+    public get endpoints() {
+        return this, this._endpoints;
+    }
+
     /**
      * Creates a new connection point
      * @param name defines the connection point name
@@ -234,49 +168,6 @@ export class NodeMaterialConnectionPoint {
         return "NodeMaterialConnectionPoint";
     }
 
-    /**
-     * Set the source of this connection point to a vertex attribute
-     * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
-     * @returns the current connection point
-     */
-    public setAsAttribute(attributeName?: string): NodeMaterialConnectionPoint {
-        if (attributeName) {
-            this.name = attributeName;
-        }
-        this._mode = NodeMaterialBlockConnectionPointMode.Attribute;
-        return this;
-    }
-
-    /**
-     * 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
-     * @returns the current connection point
-     */
-    public setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): NodeMaterialConnectionPoint {
-        this.wellKnownValue = value;
-        return this;
-    }
-
-    /**
-     * Gets a boolean indicating that the current connection point is a well known value
-     */
-    public get isWellKnownValue(): boolean {
-        return this._wellKnownValue != null;
-    }
-
-    /**
-     * Gets or sets the current well known value or null if not defined as well know value
-     */
-    public get wellKnownValue(): Nullable<NodeMaterialWellKnownValues> {
-        return this._wellKnownValue;
-    }
-
-    public set wellKnownValue(value: Nullable<NodeMaterialWellKnownValues>) {
-        this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
-        this.associatedVariableName = "";
-        this._wellKnownValue = value;
-    }
-
     private _getTypeLength(type: NodeMaterialBlockConnectionPointTypes) {
         switch (type) {
             case NodeMaterialBlockConnectionPointTypes.Float:
@@ -330,6 +221,8 @@ export class NodeMaterialConnectionPoint {
 
         this._endpoints.push(connectionPoint);
         connectionPoint._connectedPoint = this;
+
+        this._enforceAssociatedVariableName = false;
         return this;
     }
 
@@ -347,103 +240,7 @@ export class NodeMaterialConnectionPoint {
 
         this._endpoints.splice(index, 1);
         endpoint._connectedPoint = null;
+        this._enforceAssociatedVariableName = false;
         return this;
     }
-
-    /**
-     * When connection point is an uniform, this function will send its value to the effect
-     * @param effect defines the effect to transmit value to
-     * @param world defines the world matrix
-     * @param worldView defines the worldxview matrix
-     * @param worldViewProjection defines the worldxviewxprojection matrix
-     */
-    public transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix) {
-        if (!this._wellKnownValue) {
-            return;
-        }
-
-        let variableName = this.associatedVariableName;
-        switch (this._wellKnownValue) {
-            case NodeMaterialWellKnownValues.World:
-                effect.setMatrix(variableName, world);
-                break;
-            case NodeMaterialWellKnownValues.WorldView:
-                effect.setMatrix(variableName, worldView);
-                break;
-            case NodeMaterialWellKnownValues.WorldViewProjection:
-                effect.setMatrix(variableName, worldViewProjection);
-                break;
-        }
-    }
-
-    /**
-     * When connection point is an uniform, this function will send its value to the effect
-     * @param effect defines the effect to transmit value to
-     * @param scene defines the hosting scene
-     */
-    public transmit(effect: Effect, scene: Scene) {
-        let variableName = this.associatedVariableName;
-        if (this._wellKnownValue) {
-            switch (this._wellKnownValue) {
-                case NodeMaterialWellKnownValues.World:
-                case NodeMaterialWellKnownValues.WorldView:
-                case NodeMaterialWellKnownValues.WorldViewProjection:
-                    return;
-                case NodeMaterialWellKnownValues.View:
-                    effect.setMatrix(variableName, scene.getViewMatrix());
-                    break;
-                case NodeMaterialWellKnownValues.Projection:
-                    effect.setMatrix(variableName, scene.getProjectionMatrix());
-                    break;
-                case NodeMaterialWellKnownValues.ViewProjection:
-                    effect.setMatrix(variableName, scene.getTransformMatrix());
-                    break;
-                case NodeMaterialWellKnownValues.CameraPosition:
-                    effect.setVector3(variableName, scene.activeCamera!.globalPosition);
-                    break;
-            }
-            return;
-        }
-
-        let value = this._valueCallback ? this._valueCallback() : this._storedValue;
-
-        if (value === null) {
-            return;
-        }
-
-        switch (this.type) {
-            case NodeMaterialBlockConnectionPointTypes.Float:
-                effect.setFloat(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Int:
-                effect.setInt(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Color3:
-                effect.setColor3(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Color4:
-                effect.setDirectColor4(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Vector2:
-                effect.setVector2(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Vector3:
-                effect.setVector3(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
-                effect.setFloat4(variableName, value.r, value.g, value.b, value.a || 1.0);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Vector4OrColor4:
-            case NodeMaterialBlockConnectionPointTypes.Vector4:
-                effect.setVector4(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Matrix:
-                effect.setMatrix(variableName, value);
-                break;
-            case NodeMaterialBlockConnectionPointTypes.Texture:
-            case NodeMaterialBlockConnectionPointTypes.Texture3D:
-                effect.setTexture(variableName, value);
-                break;
-        }
-    }
 }

+ 6 - 8
src/Materials/Node/nodeMaterialBlockConnectionPointTypes.ts

@@ -18,10 +18,6 @@ export enum NodeMaterialBlockConnectionPointTypes {
     Color4 = 64,
     /** Matrix */
     Matrix = 128,
-    /** Texture */
-    Texture = 256,
-    /** Texture3D */
-    Texture3D = 512,
     /** Vector3 or Color3 */
     Vector3OrColor3 = Vector3 | Color3,
     /** Vector3 or Vector4 */
@@ -30,12 +26,14 @@ export enum NodeMaterialBlockConnectionPointTypes {
     Vector4OrColor4 = Vector4 | Color4,
     /** Color3 or Color4 */
     Color3OrColor4 = Color3 | Color4,
-    /** Vector3 or Color3 */
+    /** Vector2 or Color3 or Color4 */
+    Vector2OrColor3OrColor4 = Vector2 | Color3 | Color4,
+    /** Vector3 or Color3 or Color4 or Vector4 */
     Vector3OrColor3OrVector4OrColor4 = Vector3 | Color3 | Vector4 | Color4,
+    /** Vector2 or Vector3 or Color3 or Color4 or Vector4 */
+    Vector2OrVector3OrColor3OrVector4OrColor4 = Vector2 | Vector3 | Color3 | Vector4 | Color4,
     /** Detect type based on connection */
     AutoDetect = 1024,
     /** Output type that will be defined by input type */
-    BasedOnInput = 2048,
-    /** Light */
-    Light = 4096
+    BasedOnInput = 2048
 }

+ 2 - 0
src/Materials/Node/nodeMaterialBlockTargets.ts

@@ -6,6 +6,8 @@ export enum NodeMaterialBlockTargets {
     Vertex = 1,
     /** Fragment shader */
     Fragment = 2,
+    /** Neutral */
+    Neutral = 4,
     /** Vertex and Fragment */
     VertexAndFragment = Vertex | Fragment
 }

+ 26 - 141
src/Materials/Node/nodeMaterialBuildState.ts

@@ -1,10 +1,7 @@
-import { NodeMaterialConnectionPoint } from './nodeMaterialBlockConnectionPoint';
 import { NodeMaterialBlockConnectionPointTypes } from './nodeMaterialBlockConnectionPointTypes';
-import { NodeMaterialWellKnownValues } from './nodeMaterialWellKnownValues';
 import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
 import { NodeMaterialBuildStateSharedData } from './nodeMaterialBuildStateSharedData';
 import { Effect } from '../effect';
-import { Nullable } from '../../types';
 
 /**
  * Class used to store node based material build state
@@ -49,10 +46,14 @@ export class NodeMaterialBuildState {
     /** @hidden */
     public _vertexState: NodeMaterialBuildState;
 
-    private _attributeDeclaration = "";
-    private _uniformDeclaration = "";
-    private _samplerDeclaration = "";
-    private _varyingTransfer = "";
+    /** @hidden */
+    public _attributeDeclaration = "";
+    /** @hidden */
+    public _uniformDeclaration = "";
+    /** @hidden */
+    public _samplerDeclaration = "";
+    /** @hidden */
+    public _varyingTransfer = "";
 
     private _repeatableContentAnchorIndex = 0;
     /** @hidden */
@@ -159,15 +160,9 @@ export class NodeMaterialBuildState {
             case NodeMaterialBlockConnectionPointTypes.Color4:
             case NodeMaterialBlockConnectionPointTypes.Vector4:
             case NodeMaterialBlockConnectionPointTypes.Vector4OrColor4:
-            case NodeMaterialBlockConnectionPointTypes.Vector3OrVector4:
-            case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
                 return "vec4";
             case NodeMaterialBlockConnectionPointTypes.Matrix:
                 return "mat4";
-            case NodeMaterialBlockConnectionPointTypes.Texture:
-                return "sampler2D";
-            case NodeMaterialBlockConnectionPointTypes.Texture3D:
-                return "sampler3D";
         }
 
         return "";
@@ -278,146 +273,36 @@ export class NodeMaterialBuildState {
     }
 
     /** @hidden */
-    public _emitVaryings(point: NodeMaterialConnectionPoint, define: string = "", force = false, fromFragment = false, replacementName: string = "", type: Nullable<NodeMaterialBlockConnectionPointTypes> = null) {
-        let name = replacementName || point.associatedVariableName;
-        if (point.isVarying || force) {
-            if (this.sharedData.varyings.indexOf(name) !== -1) {
-                return;
-            }
-
-            this.sharedData.varyings.push(name);
+    public _emitVaryingFromString(name: string, type: string, define: string = "", notDefine = false) {
+        if (this.sharedData.varyings.indexOf(name) !== -1) {
+            return;
+        }
 
-            if (define) {
-                this.sharedData.varyingDeclaration += `#ifdef ${define}\r\n`;
-            }
-            this.sharedData.varyingDeclaration += `varying ${this._getGLType(type || point.type)} ${name};\r\n`;
-            if (define) {
-                this.sharedData.varyingDeclaration += `#endif\r\n`;
-            }
+        this.sharedData.varyings.push(name);
 
-            if (this.target === NodeMaterialBlockTargets.Vertex && fromFragment) {
-                if (define) {
-                    this.sharedData.varyingDeclaration += `#ifdef ${define}\r\n`;
-                }
-                this._varyingTransfer += `${name} = ${point.name};\r\n`;
-                if (define) {
-                    this.sharedData.varyingDeclaration += `#endif\r\n`;
-                }
-            }
+        if (define) {
+            this.sharedData.varyingDeclaration += `${notDefine ? "#ifndef" : "#ifdef"} ${define}\r\n`;
         }
-    }
-
-    private _emitDefine(define: string): string {
-        if (define[0] === "!") {
-            return `#ifndef ${define.substring(1)}\r\n`;
+        this.sharedData.varyingDeclaration += `varying ${type} ${name};\r\n`;
+        if (define) {
+            this.sharedData.varyingDeclaration += `#endif\r\n`;
         }
-
-        return `#ifdef ${define}\r\n`;
     }
 
     /** @hidden */
-    public _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string) {
-        define = define || point.define;
-
-        // Lights
-        if (point.type === NodeMaterialBlockConnectionPointTypes.Light) {
-            // Do nothing
+    public _emitUniformFromString(name: string, type: string, define: string = "", notDefine = false) {
+        if (this.uniforms.indexOf(name) !== -1) {
             return;
         }
 
-        // Samplers
-        if (point.type === NodeMaterialBlockConnectionPointTypes.Texture) {
-            point.name = this._getFreeVariableName(point.name);
-            point.associatedVariableName = point.name;
-
-            if (this.samplers.indexOf(point.name) !== -1) {
-                return;
-            }
-
-            this.samplers.push(point.name);
-            if (define) {
-                this._uniformDeclaration += this._emitDefine(define);
-            }
-            this._samplerDeclaration += `uniform ${this._getGLType(point.type)} ${point.name};\r\n`;
-            if (define) {
-                this._uniformDeclaration += `#endif\r\n`;
-            }
-            this.sharedData.uniformConnectionPoints.push(point);
-            return;
-        }
+        this.uniforms.push(name);
 
-        if (!point.isUniform && !point.isAttribute) {
-            return;
+        if (define) {
+            this._uniformDeclaration += `${notDefine ? "#ifndef" : "#ifdef"} ${define}\r\n`;
         }
-
-        // Uniforms
-        if (point.isUniform) {
-            if (!point.associatedVariableName) {
-                point.associatedVariableName = this._getFreeVariableName("u_" + point.name);
-            }
-
-            if (point._forceUniformInVertexShaderOnly && this._vertexState) { // Uniform for fragment need to be carried over by varyings
-                this._vertexState._emitUniformOrAttributes(point);
-                return;
-            }
-
-            if (this.uniforms.indexOf(point.associatedVariableName) !== -1) {
-                return;
-            }
-
-            this.uniforms.push(point.associatedVariableName);
-            if (define) {
-                this._uniformDeclaration += this._emitDefine(define);
-            }
-            this._uniformDeclaration += `uniform ${this._getGLType(point.type)} ${point.associatedVariableName};\r\n`;
-            if (define) {
-                this._uniformDeclaration += `#endif\r\n`;
-            }
-
-            // well known
-            let hints = this.sharedData.hints;
-            if (point._wellKnownValue !== null) {
-                switch (point._wellKnownValue) {
-                    case NodeMaterialWellKnownValues.WorldView:
-                        hints.needWorldViewMatrix = true;
-                        break;
-                    case NodeMaterialWellKnownValues.WorldViewProjection:
-                        hints.needWorldViewProjectionMatrix = true;
-                        break;
-                }
-            }
-
-            this.sharedData.uniformConnectionPoints.push(point);
-
-            return;
-        }
-
-        // Attribute
-        if (point.isAttribute) {
-            point.associatedVariableName = point.name;
-
-            if (this.target === NodeMaterialBlockTargets.Fragment) { // Attribute for fragment need to be carried over by varyings
-                this._vertexState._emitUniformOrAttributes(point);
-
-                if (point._needToEmitVarying) {
-                    this._vertexState._emitVaryings(point, undefined, true, true, "v_" + point.associatedVariableName);
-                    point.associatedVariableName = "v_" + point.associatedVariableName;
-                }
-                return;
-            }
-
-            if (this.attributes.indexOf(point.associatedVariableName) !== -1) {
-                return;
-            }
-
-            this.attributes.push(point.associatedVariableName);
-            if (define) {
-                this._attributeDeclaration += this._emitDefine(define);
-            }
-            this._attributeDeclaration += `attribute ${this._getGLType(point.type)} ${point.associatedVariableName};\r\n`;
-            if (define) {
-                this._attributeDeclaration += `#endif\r\n`;
-            }
+        this._uniformDeclaration += `uniform ${type} ${name};\r\n`;
+        if (define) {
+            this._uniformDeclaration += `#endif\r\n`;
         }
     }
 }

+ 9 - 2
src/Materials/Node/nodeMaterialBuildStateSharedData.ts

@@ -1,5 +1,7 @@
 import { NodeMaterialConnectionPoint } from './nodeMaterialBlockConnectionPoint';
 import { NodeMaterialBlock } from './nodeMaterialBlock';
+import { InputBlock } from './Blocks/Input/inputBlock';
+import { TextureBlock } from './Blocks/Dual/textureBlock';
 
 /**
  * Class used to store shared data between 2 NodeMaterialBuildState
@@ -16,9 +18,14 @@ export class NodeMaterialBuildStateSharedData {
     public varyingDeclaration = "";
 
     /**
-     * Uniform connection points
+     * Input blocks
      */
-    public uniformConnectionPoints = new Array<NodeMaterialConnectionPoint>();
+    public inputBlocks = new Array<InputBlock>();
+
+    /**
+     * Input blocks
+     */
+    public textureBlocks = new Array<TextureBlock>();
 
     /**
      * Bindable blocks (Blocks that need to set data to the effect)

+ 2 - 2
src/Materials/Node/nodeMaterialWellKnownValues.ts

@@ -16,6 +16,6 @@ export enum NodeMaterialWellKnownValues {
     WorldViewProjection = 6,
     /** CameraPosition */
     CameraPosition = 7,
-    /** Will be filled by the block itself */
-    Automatic = 8
+    /** Fog Color */
+    FogColor = 8
 }