Browse Source

Associated with #6012: load / save done

David Catuhe 6 years ago
parent
commit
4861718152

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

@@ -17,7 +17,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps>
             Vertex: ["BonesBlock", "InstancesBlock", "MorphTargetsBlock"],
             Fragment: ["AlphaTestBlock", "ImageProcessingBlock", "RGBAMergerBlock", "RGBASplitterBlock", "TextureBlock", "LightBlock", "FogBlock"],
             Outputs: ["VertexOutputBlock", "FragmentOutputBlock"],
-            Math: ["AddBlock", "ClampBlock", "CrossBlock", "DotBlock", "MultiplyBlock", "VectorTransformBlock"],
+            Math: ["AddBlock", "ClampBlock", "CrossBlock", "DotBlock", "MultiplyBlock", "TransformBlock"],
             Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "Matrix"],
         }
 

+ 2 - 0
nodeEditor/src/components/propertyTab/propertyTab.scss

@@ -230,6 +230,7 @@
         display: grid;
         align-items: center;
         justify-items: stretch;
+        padding-bottom: 5px;
 
         input[type="file"] {
             display: none;
@@ -241,6 +242,7 @@
             margin: 5px 10px;
             color:white;
             padding: 4px 5px;
+            padding-top: 0px;
             opacity: 0.9;
             cursor: pointer;
             text-align: center;

+ 19 - 1
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -6,6 +6,8 @@ import { DefaultNodeModel } from '../../components/diagram/defaultNodeModel';
 import { ButtonLineComponent } from '../../sharedComponents/buttonLineComponent';
 import { LineContainerComponent } from '../../sharedComponents/lineContainerComponent';
 import { StringTools } from '../../stringTools';
+import { FileButtonLineComponent } from '../../sharedComponents/fileButtonLineComponent';
+import { Tools } from 'babylonjs/Misc/tools';
 require("./propertyTab.scss");
 
 interface IPropertyTabComponentProps {
@@ -26,6 +28,17 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
         });
     }
 
+    load(file: File) {
+        Tools.ReadFile(file, (data) => {
+            let decoder = new TextDecoder("utf-8");
+            let serializationObject = JSON.parse(decoder.decode(data));
+
+            this.props.globalState.nodeMaterial!.loadFromSerialization(serializationObject, "");
+            
+            this.props.globalState.onResetRequiredObservable.notifyObservers();
+        }, undefined, true);
+    }
+
     render() {
         if (this.state.currentNode) {
             return (
@@ -66,7 +79,12 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                             this.props.globalState.onReOrganizedRequiredObservable.notifyObservers();
                         }} />
                     </LineContainerComponent>
-                    <LineContainerComponent title="FILE">
+                    <LineContainerComponent title="FILE">                        
+                        <FileButtonLineComponent label="Load" onClick={(file) => this.load(file)} accept=".json" />
+                        <ButtonLineComponent label="Save" onClick={() => {
+                            let json = JSON.stringify(this.props.globalState.nodeMaterial!.serialize());
+                            StringTools.DownloadAsFile(json, "nodeMaterial.json");
+                        }} />
                         <ButtonLineComponent label="Export shaders" onClick={() => {
                             StringTools.DownloadAsFile(this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
                         }} />

+ 13 - 7
nodeEditor/src/graphEditor.tsx

@@ -46,7 +46,7 @@ import { ClampBlock } from 'babylonjs/Materials/Node/Blocks/clampBlock';
 import { CrossBlock } from 'babylonjs/Materials/Node/Blocks/crossBlock';
 import { DotBlock } from 'babylonjs/Materials/Node/Blocks/dotBlock';
 import { MultiplyBlock } from 'babylonjs/Materials/Node/Blocks/multiplyBlock';
-import { VectorTransformBlock } from 'babylonjs/Materials/Node/Blocks/vectorTransformBlock';
+import { TransformBlock } from 'babylonjs/Materials/Node/Blocks/transformBlock';
 
 require("storm-react-diagrams/dist/style.min.css");
 require("./main.scss");
@@ -180,7 +180,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             this.reOrganize();
         })
 
-        this.build();
+        this.build(true);
     }
 
     distributeGraph() {
@@ -251,7 +251,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
         }
     }
 
-    build() {
+    build(needToWait = false) {
         // setup the diagram model
         this._model = new DiagramModel();
 
@@ -306,7 +306,13 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                                     }
                                 }
 
-                                link.output.connection.connectTo(link.input.connection);
+                                try {
+                                    link.output.connection.connectTo(link.input.connection);
+                                }        
+                                catch (err) {
+                                    link.output.remove();
+                                    this.props.globalState.onLogRequiredObservable.notifyObservers(new LogEntry(err, true));
+                                }
 
                                 this.forceUpdate();
                             }
@@ -341,7 +347,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             this.forceUpdate();
 
             this.reOrganize();
-        }, 500);
+        }, needToWait ? 500 : 1);
     }
 
     reOrganize() {
@@ -492,8 +498,8 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                 case "MultiplyBlock":
                     block = new MultiplyBlock("Multiply");
                     break;
-                case "VectorTransformBlock":
-                    block = new VectorTransformBlock("VectorTransform");
+                case "TransformBlock":
+                    block = new TransformBlock("Transform");
                     break;
             }
 

+ 11 - 3
src/Materials/Node/Blocks/Input/inputBlock.ts

@@ -4,12 +4,13 @@ import { NodeMaterialBlockConnectionPointMode } from '../../NodeMaterialBlockCon
 import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
 import { Nullable } from '../../../../types';
 import { Effect } from '../../../../Materials/effect';
-import { Matrix, Vector2, Vector3 } from '../../../../Maths/math.vector';
+import { Matrix, Vector2, Vector3, Vector4 } from '../../../../Maths/math.vector';
 import { Scene } from '../../../../scene';
 import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
 import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
 import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
 import { _TypeStore } from '../../../../Misc/typeStore';
+import { Color3, Color4 } from '../../../../Maths/math';
 
 /**
  * Block used to expose an input value
@@ -255,10 +256,17 @@ export class InputBlock extends NodeMaterialBlock {
                 this.value = Vector2.Zero();
                 break;
             case NodeMaterialBlockConnectionPointTypes.Vector3:
-            case NodeMaterialBlockConnectionPointTypes.Color3:
-            case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3:
                 this.value = Vector3.Zero();
                 break;
+            case NodeMaterialBlockConnectionPointTypes.Vector4:
+                this.value = Vector4.Zero();
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Color3:
+                this.value = Color3.White();
+                break;
+            case NodeMaterialBlockConnectionPointTypes.Color4:
+                this.value = new Color4(1, 1, 1, 1);
+                break;                
             case NodeMaterialBlockConnectionPointTypes.Matrix:
                 this.value = Matrix.Identity();
                 break;

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

@@ -7,4 +7,4 @@ export * from "./addBlock";
 export * from "./clampBlock";
 export * from "./crossBlock";
 export * from "./dotBlock";
-export * from "./vectorTransformBlock";
+export * from "./transformBlock";

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

@@ -16,10 +16,11 @@ export class MultiplyBlock extends NodeMaterialBlock {
         super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("left", NodeMaterialBlockConnectionPointTypes.AutoDetect);
-        this.registerInput("right", NodeMaterialBlockConnectionPointTypes.AutoDetect);
+        this.registerInput("right", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+        this._inputs[1]._typeConnectionSource = this._inputs[0];
     }
 
     /**

+ 4 - 4
src/Materials/Node/Blocks/vectorTransformBlock.ts

@@ -8,7 +8,7 @@ import { _TypeStore } from '../../../Misc/typeStore';
 /**
  * Block used to transform a vector (2, 3 or 4) with a matrix. It will generate a Vector4
  */
-export class VectorTransformBlock extends NodeMaterialBlock {
+export class TransformBlock extends NodeMaterialBlock {
     /**
      * Defines the value to use to complement W value to transform it to a Vector4
      */
@@ -20,7 +20,7 @@ export class VectorTransformBlock extends NodeMaterialBlock {
     public complementZ = 0;
 
     /**
-     * Creates a new VectorTransformBlock
+     * Creates a new TransformBlock
      * @param name defines the block name
      */
     public constructor(name: string) {
@@ -36,7 +36,7 @@ export class VectorTransformBlock extends NodeMaterialBlock {
      * @returns the class name
      */
     public getClassName() {
-        return "VectorTransformBlock";
+        return "TransformBlock";
     }
 
     /**
@@ -84,4 +84,4 @@ export class VectorTransformBlock extends NodeMaterialBlock {
     }
 }
 
-_TypeStore.RegisteredTypes["BABYLON.VectorTransformBlock"] = VectorTransformBlock;
+_TypeStore.RegisteredTypes["BABYLON.TransformBlock"] = TransformBlock;

+ 21 - 10
src/Materials/Node/nodeMaterial.ts

@@ -19,7 +19,7 @@ import { ImageProcessingConfiguration, IImageProcessingConfigurationDefines } fr
 import { Nullable } from '../../types';
 import { VertexBuffer } from '../../Meshes/buffer';
 import { Tools } from '../../Misc/tools';
-import { VectorTransformBlock } from './Blocks/vectorTransformBlock';
+import { TransformBlock } from './Blocks/transformBlock';
 import { VertexOutputBlock } from './Blocks/Vertex/vertexOutputBlock';
 import { FragmentOutputBlock } from './Blocks/Fragment/fragmentOutputBlock';
 import { InputBlock } from './Blocks/Input/inputBlock';
@@ -847,14 +847,14 @@ export class NodeMaterial extends PushMaterial {
         var worldInput = new InputBlock("world");
         worldInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.World);
 
-        var worldPos = new VectorTransformBlock("worldPos");
+        var worldPos = new TransformBlock("worldPos");
         positionInput.connectTo(worldPos);
         worldInput.connectTo(worldPos);
 
         var viewProjectionInput = new InputBlock("viewProjection");
         viewProjectionInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.ViewProjection);
 
-        var worldPosdMultipliedByViewProjection = new VectorTransformBlock("worldPos * viewProjectionTransform");
+        var worldPosdMultipliedByViewProjection = new TransformBlock("worldPos * viewProjectionTransform");
         worldPos.connectTo(worldPosdMultipliedByViewProjection);
         viewProjectionInput.connectTo(worldPosdMultipliedByViewProjection);
 
@@ -924,14 +924,12 @@ export class NodeMaterial extends PushMaterial {
     }
 
     /**
-     * Creates a node material from parsed material data
+     * Clear the current graph and load a new one from a serialization object
      * @param source defines the JSON representation of the material
-     * @param scene defines the hosting scene
      * @param rootUrl defines the root URL to use to load textures and relative dependencies
-     * @returns a new node material
      */
-    public static Parse(source: any, scene: Scene, rootUrl: string = ""): NodeMaterial {
-        let nodeMaterial = SerializationHelper.Parse(() => new NodeMaterial(source.name, scene), source, scene, rootUrl);
+    public loadFromSerialization(source: any, rootUrl: string = "") {
+        this.clear();
 
         let map: {[key: number]: NodeMaterialBlock} = {};
 
@@ -940,7 +938,7 @@ export class NodeMaterial extends PushMaterial {
             let blockType = _TypeStore.GetClass(parsedBlock.customType);
             if (blockType) {
                 let block: NodeMaterialBlock = new blockType();
-                block._deserialize(parsedBlock, scene, rootUrl);
+                block._deserialize(parsedBlock, this.getScene(), rootUrl);
                 map[parsedBlock.id] = block;
             }
         }
@@ -968,8 +966,21 @@ export class NodeMaterial extends PushMaterial {
 
         // Outputs
         for (var outputNodeId of source.outputNodes) {
-            nodeMaterial.addOutputNode(map[outputNodeId]);
+            this.addOutputNode(map[outputNodeId]);
         }
+    }
+
+    /**
+     * Creates a node material from parsed material data
+     * @param source defines the JSON representation of the material
+     * @param scene defines the hosting scene
+     * @param rootUrl defines the root URL to use to load textures and relative dependencies
+     * @returns a new node material
+     */
+    public static Parse(source: any, scene: Scene, rootUrl: string = ""): NodeMaterial {
+        let nodeMaterial = SerializationHelper.Parse(() => new NodeMaterial(source.name, scene), source, scene, rootUrl);
+
+        nodeMaterial.loadFromSerialization(source, rootUrl);
 
         return nodeMaterial;
     }