Przeglądaj źródła

Better snippet support #6736

David Catuhe 6 lat temu
rodzic
commit
8dc45a6f8f

+ 33 - 13
nodeEditor/public/index.js

@@ -3,6 +3,9 @@ var currentSnippetToken;
 var previousHash = "";
 var nodeMaterial;
 
+var customLoadObservable = new BABYLON.Observable();
+var editorDisplayed = false;
+
 var cleanHash = function () {
     var splits = decodeURIComponent(location.hash.substr(1)).split("#");
 
@@ -26,7 +29,14 @@ var checkHash = function () {
                     if (xmlHttp.readyState == 4) {
                         if (xmlHttp.status == 200) {
                             var snippet = JSON.parse(JSON.parse(xmlHttp.responseText).jsonPayload);
-                            nodeMaterial.loadFromSerialization(snippet.nodeMaterial);
+
+                            if (editorDisplayed) {
+                                customLoadObservable.notifyObservers(snippet.nodeMaterial);
+                            } else {
+                                nodeMaterial.loadFromSerialization(snippet.nodeMaterial);
+                                nodeMaterial.build(true);
+                                showEditor();
+                            }
                         }
                     }
                 }
@@ -44,24 +54,17 @@ var checkHash = function () {
     setTimeout(checkHash, 200);
 }
 
-// Let's start
-if (BABYLON.Engine.isSupported()) {
-    var canvas = document.createElement("canvas");
-    var engine = new BABYLON.Engine(canvas, false);
-    var scene = new BABYLON.Scene(engine);
-
-    nodeMaterial = new BABYLON.NodeMaterial("node");
-    nodeMaterial.setToDefault();
-    nodeMaterial.build(true);
-
+var showEditor = function() {
+    editorDisplayed = true;
     var hostElement = document.getElementById("host-element");
 
     BABYLON.NodeEditor.Show({
         nodeMaterial: nodeMaterial, 
         hostElement: hostElement,
+        customLoadObservable: customLoadObservable,
         customSave: {
             label: "Save as unique URL",
-            callback: () => {
+            action: (data) => {
                 var xmlHttp = new XMLHttpRequest();
                 xmlHttp.onreadystatechange = function () {
                     if (xmlHttp.readyState == 4) {
@@ -86,7 +89,7 @@ if (BABYLON.Engine.isSupported()) {
     
                 var dataToSend = {
                     payload : JSON.stringify({
-                        nodeMaterial: nodeMaterial.serialize() 
+                        nodeMaterial: data
                     }),
                     name: "",
                     description: "",
@@ -98,6 +101,23 @@ if (BABYLON.Engine.isSupported()) {
         }
     });
 }
+
+// Let's start
+if (BABYLON.Engine.isSupported()) {
+    var canvas = document.createElement("canvas");
+    var engine = new BABYLON.Engine(canvas, false);
+    var scene = new BABYLON.Scene(engine);
+
+    nodeMaterial = new BABYLON.NodeMaterial("node");
+
+    // Set to default
+    if (!location.hash) {
+        nodeMaterial.setToDefault();
+        nodeMaterial.build(true);
+        showEditor();
+    }
+
+}
 else {
     alert('Babylon.js is not supported.')
 }

+ 4 - 4
nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx

@@ -137,6 +137,10 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                     <TextLineComponent label="Type" value={StringTools.GetBaseType(inputBlock.type)} />
                 </LineContainerComponent>
                 <LineContainerComponent title="PROPERTIES">
+                    {
+                        inputBlock.isUniform && !inputBlock.isSystemValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
+                        <CheckBoxLineComponent label="Visible in the Inspector" target={inputBlock} propertyName="visibleInInspector"/>
+                    }                 
                     <OptionsLineComponent label="Mode" options={modeOptions} target={inputBlock} 
                         noDirectUpdate={true}
                         getSelection={(block) => {
@@ -184,10 +188,6 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                     }   
                     {
                         inputBlock.isUniform && !inputBlock.isSystemValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
-                        <CheckBoxLineComponent label="Visible in the Inspector" target={inputBlock} propertyName="visibleInInspector"/>
-                    }                 
-                    {
-                        inputBlock.isUniform && !inputBlock.isSystemValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
                         this.renderValue(this.props.globalState)
                     }
                     {

+ 5 - 2
nodeEditor/src/components/preview/previewManager.ts

@@ -78,10 +78,13 @@ export class PreviewManager {
             case PreviewMeshType.Torus:
                 this._dummy = Mesh.CreateTorus("dummy-torus", 2, 0.5, 32, this._scene);
                 break;
-                case PreviewMeshType.Cylinder:
+            case PreviewMeshType.Cylinder:
                 this._dummy = Mesh.CreateCylinder("dummy-cylinder", 2, 1, 1.2, 32, 1, this._scene);
                 break;                
-        }
+            case PreviewMeshType.Plane:
+                this._dummy = Mesh.CreateGround("dummy-plane", 2, 2, 128, this._scene);
+                break;                
+            }
         this._dummy.material = this._material;
     }
 

+ 4 - 1
nodeEditor/src/components/preview/previewMeshControlComponent.tsx

@@ -2,7 +2,7 @@
 import * as React from "react";
 import { GlobalState } from '../../globalState';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faCircle, faRing, faCube, faHockeyPuck } from '@fortawesome/free-solid-svg-icons';
+import { faCircle, faRing, faCube, faHockeyPuck, faSquareFull } from '@fortawesome/free-solid-svg-icons';
 import { PreviewMeshType } from './previewMeshType';
 import { DataStorage } from '../../dataStorage';
 
@@ -40,6 +40,9 @@ export class PreviewMeshControlComponent extends React.Component<IPreviewMeshCon
                 <div onClick={() => this.changeMeshType(PreviewMeshType.Cylinder)} className={"button" + (this.props.globalState.previewMeshType === PreviewMeshType.Cylinder ? " selected" : "")}>
                     <FontAwesomeIcon icon={faHockeyPuck} />
                 </div>
+                <div onClick={() => this.changeMeshType(PreviewMeshType.Plane)} className={"button" + (this.props.globalState.previewMeshType === PreviewMeshType.Plane ? " selected" : "")}>
+                    <FontAwesomeIcon icon={faSquareFull} />
+                </div>
             </div>
         );
 

+ 2 - 1
nodeEditor/src/components/preview/previewMeshType.ts

@@ -2,5 +2,6 @@ export enum PreviewMeshType {
     Sphere,
     Box, 
     Torus,
-    Cylinder
+    Cylinder,
+    Plane
 }

+ 4 - 35
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -9,6 +9,7 @@ import { StringTools } from '../../stringTools';
 import { FileButtonLineComponent } from '../../sharedComponents/fileButtonLineComponent';
 import { Tools } from 'babylonjs/Misc/tools';
 import { INodeLocationInfo } from '../../nodeLocationInfo';
+import { SerializationTools } from '../../serializationTools';
 require("./propertyTab.scss");
 
 interface IPropertyTabComponentProps {
@@ -32,45 +33,13 @@ 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));
+            SerializationTools.Deserialize(JSON.parse(decoder.decode(data)), this.props.globalState);
 
-            this.props.globalState.nodeMaterial!.loadFromSerialization(serializationObject, "");
-
-            // Check for id mapping
-            if (serializationObject.locations && serializationObject.map) {
-                let map: {[key: number]: number} = serializationObject.map;
-                let locations: INodeLocationInfo[] = serializationObject.locations;
-
-                for (var location of locations) {
-                    location.blockId = map[location.blockId];
-                }
-            }
-            
-            this.props.globalState.onResetRequiredObservable.notifyObservers(serializationObject.locations);
         }, undefined, true);
     }
 
     save() {
-        let material = this.props.globalState.nodeMaterial;
-        let serializationObject = material.serialize();
-
-        // Store node locations
-        for (var block of material.attachedBlocks) {
-            let node = this.props.globalState.onGetNodeFromBlock(block);
-
-            if (!serializationObject.locations) {
-                serializationObject.locations = [];
-            }
-
-            serializationObject.locations.push({
-                blockId: block.uniqueId,
-                x: node ? node.x : 0,
-                y: node ? node.y : 0
-            });
-        }
-
-        // Output
-        let json = JSON.stringify(serializationObject, undefined, 2);
+        let json = SerializationTools.Serialize(this.props.globalState.nodeMaterial, this.props.globalState);
         StringTools.DownloadAsFile(this.props.globalState.hostDocument, json, "nodeMaterial.json");
     }
 
@@ -126,7 +95,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                         {
                             this.props.globalState.customSave && 
                             <ButtonLineComponent label={this.props.globalState.customSave!.label} onClick={() => {
-                                this.props.globalState.customSave!.callback(this.props.globalState.nodeMaterial);
+                                this.props.globalState.customSave!.action(SerializationTools.Serialize(this.props.globalState.nodeMaterial, this.props.globalState));
                             }} />
                         }
                     </LineContainerComponent>

+ 2 - 2
nodeEditor/src/globalState.ts

@@ -25,8 +25,8 @@ export class GlobalState {
     onGetNodeFromBlock: (block: NodeMaterialBlock) => NodeModel;
     previewMeshType: PreviewMeshType;
     blockKeyboardEvents = false;
-
-    customSave?: {label: string, callback: (nodeMaterial: NodeMaterial) => void};
+    
+    customSave?: {label: string, action: (data: string) => void};
 
     public constructor() {
         this.previewMeshType = DataStorage.ReadNumber("PreviewMeshType", PreviewMeshType.Box);

+ 10 - 1
nodeEditor/src/nodeEditor.ts

@@ -4,13 +4,16 @@ import { GlobalState } from './globalState';
 import { GraphEditor } from './graphEditor';
 import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial"
 import { Popup } from "../src/sharedComponents/popup"
+import { Observable } from 'babylonjs';
+import { SerializationTools } from './serializationTools';
 /**
  * Interface used to specify creation options for the node editor
  */
 export interface INodeEditorOptions {
     nodeMaterial: NodeMaterial,
     hostElement?: HTMLElement,
-    customSave?: {label: string, callback: (nodeMaterial: NodeMaterial) => void};
+    customSave?: {label: string, action: (data: string) => void};
+    customLoadObservable?: Observable<any>
 }
 
 /**
@@ -49,6 +52,12 @@ export class NodeEditor {
 
         ReactDOM.render(graphEditor, hostElement);
 
+        if (options.customLoadObservable) {
+            options.customLoadObservable.add(data => {
+                SerializationTools.Deserialize(data, globalState);
+            })
+        }
+
         this._CurrentState = globalState;
 
         // Close the popup window when the page is refreshed or scene is disposed

+ 42 - 0
nodeEditor/src/serializationTools.ts

@@ -0,0 +1,42 @@
+import { NodeMaterial } from 'babylonjs/Materials/Node/nodeMaterial';
+import { GlobalState } from './globalState';
+import { INodeLocationInfo } from './nodeLocationInfo';
+
+export class SerializationTools {
+    public static Serialize(material: NodeMaterial, globalState: GlobalState) {
+        let serializationObject = material.serialize();
+
+        // Store node locations
+        for (var block of material.attachedBlocks) {
+            let node = globalState.onGetNodeFromBlock(block);
+
+            if (!serializationObject.locations) {
+                serializationObject.locations = [];
+            }
+
+            serializationObject.locations.push({
+                blockId: block.uniqueId,
+                x: node ? node.x : 0,
+                y: node ? node.y : 0
+            });
+        }
+
+        return JSON.stringify(serializationObject, undefined, 2);
+    }
+
+    public static Deserialize(serializationObject:any, globalState: GlobalState) {        
+        globalState.nodeMaterial!.loadFromSerialization(serializationObject, "");
+
+        // Check for id mapping
+        if (serializationObject.locations && serializationObject.map) {
+            let map: {[key: number]: number} = serializationObject.map;
+            let locations: INodeLocationInfo[] = serializationObject.locations;
+
+            for (var location of locations) {
+                location.blockId = map[location.blockId];
+            }
+        }
+        
+        globalState.onResetRequiredObservable.notifyObservers(serializationObject.locations);
+    }
+}

+ 6 - 2
nodeEditor/src/sharedComponents/color3LineComponent.tsx

@@ -1,6 +1,6 @@
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
-import { Color3 } from "babylonjs/Maths/math";
+import { Color3, Color4 } from "babylonjs/Maths/math";
 import { PropertyChangedEvent } from "./propertyChangedEvent";
 import { NumericInputComponent } from "./numericInputComponent";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@@ -46,7 +46,11 @@ export class Color3LineComponent extends React.Component<IColor3LineComponentPro
             });
         }
 
-        this.props.target[this.props.propertyName] = newColor;
+        if (this.props.target[this.props.propertyName].getClassName() === "Color4") {
+            this.props.target[this.props.propertyName] = new Color4(newColor.r, newColor.g, newColor.b, 1.0);
+        } else {
+            this.props.target[this.props.propertyName] = newColor;
+        }
 
         this.setState({ color: newColor });