Explorar o código

Added snippet support in nme

David Catuhe %!s(int64=5) %!d(string=hai) anos
pai
achega
005063f9db

+ 4 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/particleSystems/particleSystemPropertyGridComponent.tsx

@@ -221,7 +221,7 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
 
 
                     let windowAsAny = window as any;
                     let windowAsAny = window as any;
 
 
-                    if (windowAsAny.Playground) {
+                    if (windowAsAny.Playground && oldId) {
                         windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
                         windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
                             regex: new RegExp(oldId, "g"),
                             regex: new RegExp(oldId, "g"),
                             replace: system.snippetId
                             replace: system.snippetId
@@ -315,13 +315,15 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
                 <LineContainerComponent globalState={this.props.globalState} title="FILE">
                 <LineContainerComponent globalState={this.props.globalState} title="FILE">
                 <FileButtonLineComponent label="Load" onClick={(file) => this.loadFromFile(file)} accept=".json" />
                 <FileButtonLineComponent label="Load" onClick={(file) => this.loadFromFile(file)} accept=".json" />
                     <ButtonLineComponent label="Save" onClick={() => this.saveToFile()} />
                     <ButtonLineComponent label="Save" onClick={() => this.saveToFile()} />
+                </LineContainerComponent>
+                <LineContainerComponent globalState={this.props.globalState} title="SNIPPET">
                     {
                     {
                         system.snippetId &&
                         system.snippetId &&
                         <TextLineComponent label="Snippet ID" value={system.snippetId} />
                         <TextLineComponent label="Snippet ID" value={system.snippetId} />
                     }
                     }
                     <ButtonLineComponent label="Load from snippet server" onClick={() => this.loadFromSnippet()} />
                     <ButtonLineComponent label="Load from snippet server" onClick={() => this.loadFromSnippet()} />
                     <ButtonLineComponent label="Save to snippet server" onClick={() => this.saveToSnippet()} />
                     <ButtonLineComponent label="Save to snippet server" onClick={() => this.saveToSnippet()} />
-                </LineContainerComponent>
+                </LineContainerComponent>                
                 <LineContainerComponent globalState={this.props.globalState} title="EMITTER">
                 <LineContainerComponent globalState={this.props.globalState} title="EMITTER">
                 <OptionsLineComponent 
                 <OptionsLineComponent 
                         label="Emitter" 
                         label="Emitter" 

+ 96 - 7
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -27,6 +27,7 @@ import { Vector3LineComponent } from '../../sharedComponents/vector3LineComponen
 import { Vector4LineComponent } from '../../sharedComponents/vector4LineComponent';
 import { Vector4LineComponent } from '../../sharedComponents/vector4LineComponent';
 import { Observer } from 'babylonjs/Misc/observable';
 import { Observer } from 'babylonjs/Misc/observable';
 import { NodePort } from '../../diagram/nodePort';
 import { NodePort } from '../../diagram/nodePort';
+import { NodeMaterial } from 'babylonjs/Materials/Node/nodeMaterial';
 require("./propertyTab.scss");
 require("./propertyTab.scss");
 
 
 interface IPropertyTabComponentProps {
 interface IPropertyTabComponentProps {
@@ -154,6 +155,80 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
         });
         });
     }
     }
 
 
+    saveToSnippetServer() {
+        const material = this.props.globalState.nodeMaterial;
+        const xmlHttp = new XMLHttpRequest();
+        
+        let json = SerializationTools.Serialize(material, this.props.globalState);
+
+        xmlHttp.onreadystatechange = () => {
+            if (xmlHttp.readyState == 4) {
+                if (xmlHttp.status == 200) {
+                    var snippet = JSON.parse(xmlHttp.responseText);
+                    const oldId = material.snippetId;
+                    material.snippetId = snippet.id;
+                    if (snippet.version && snippet.version != "0") {
+                        material.snippetId += "#" + snippet.version;
+                    }
+
+                    this.forceUpdate();
+                    if (navigator.clipboard) {
+                        navigator.clipboard.writeText(material.snippetId);
+                    }
+
+                    let windowAsAny = window as any;
+
+                    if (windowAsAny.Playground && oldId) {
+                        windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
+                            regex: new RegExp(oldId, "g"),
+                            replace: material.snippetId
+                        });
+                    }
+
+                    alert("NodeMaterial saved with ID: " + material.snippetId + " (please note that the id was also saved to your clipboard)");
+                               
+                }
+                else {
+                    alert(`Unable to save your node material. It may be too large (${(dataToSend.payload.length / 1024).toFixed(2)} KB) because of embedded textures. Please reduce texture sizes or point to a specific url instead of embedding them and try again.`);
+                }
+            }
+        }
+
+        xmlHttp.open("POST", NodeMaterial.SnippetUrl + (material.snippetId ? "/" + material.snippetId : ""), true);
+        xmlHttp.setRequestHeader("Content-Type", "application/json");
+
+        var dataToSend = {
+            payload : JSON.stringify({
+                nodeMaterial: json
+            }),
+            name: "",
+            description: "",
+            tags: ""
+        };
+
+        xmlHttp.send(JSON.stringify(dataToSend));
+    }
+
+    loadFromSnippet() {
+        const material = this.props.globalState.nodeMaterial;
+        const scene = material.getScene();
+
+        let snippedID = window.prompt("Please enter the snippet ID to use");
+
+        if (!snippedID) {
+            return;
+        }
+        
+        this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
+
+        NodeMaterial.ParseFromSnippetAsync(snippedID, scene, "", material).then(() => {
+            material.build();
+            this.props.globalState.onResetRequiredObservable.notifyObservers();
+        }).catch(err => {
+            alert("Unable to load your node material: " + err);
+        });
+    }    
+
     render() {
     render() {
         if (this.state.currentNode) {
         if (this.state.currentNode) {
             return (
             return (
@@ -237,19 +312,33 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                         <ButtonLineComponent label="Save" onClick={() => {
                         <ButtonLineComponent label="Save" onClick={() => {
                             this.save();
                             this.save();
                         }} />
                         }} />
-                        {
-                            this.props.globalState.customSave && 
-                            <ButtonLineComponent label={this.props.globalState.customSave!.label} onClick={() => {
-                                this.customSave();
-                            }} />
-                        }
                         <ButtonLineComponent label="Generate code" onClick={() => {
                         <ButtonLineComponent label="Generate code" onClick={() => {
                             StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.generateCode(), "code.txt");
                             StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.generateCode(), "code.txt");
                         }} />
                         }} />
                         <ButtonLineComponent label="Export shaders" onClick={() => {
                         <ButtonLineComponent label="Export shaders" onClick={() => {
                             StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
                             StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
                         }} />
                         }} />
-                    </LineContainerComponent>                    
+                        {
+                            this.props.globalState.customSave && 
+                            <ButtonLineComponent label={this.props.globalState.customSave!.label} onClick={() => {
+                                this.customSave();
+                            }} />
+                        }                        
+
+                    </LineContainerComponent>                            
+                    {
+                        !this.props.globalState.customSave &&                           
+                        <LineContainerComponent title="SNIPPET"> 
+                            {
+                                this.props.globalState.nodeMaterial!.snippetId &&
+                                <TextLineComponent label="Snippet ID" value={this.props.globalState.nodeMaterial!.snippetId} />
+                            }                                
+                            <ButtonLineComponent label="Load from snippet server" onClick={() => this.loadFromSnippet()} />
+                            <ButtonLineComponent label="Save to snippet server" onClick={() => {
+                                this.saveToSnippetServer();
+                            }} />
+                        </LineContainerComponent>  
+                    }                
                     <LineContainerComponent title="INPUTS">   
                     <LineContainerComponent title="INPUTS">   
                     {
                     {
                         this.props.globalState.nodeMaterial.getInputBlocks().map(ib => {
                         this.props.globalState.nodeMaterial.getInputBlocks().map(ib => {

+ 12 - 2
src/Materials/Node/nodeMaterial.ts

@@ -143,6 +143,11 @@ export class NodeMaterial extends PushMaterial {
     }
     }
 
 
     /**
     /**
+     * Snippet ID if the material was created from the snippet server
+     */
+    public snippetId: string;
+
+    /**
      * Gets or sets data used by visual editor
      * Gets or sets data used by visual editor
      * @see https://nme.babylonjs.com
      * @see https://nme.babylonjs.com
      */
      */
@@ -1339,7 +1344,7 @@ export class NodeMaterial extends PushMaterial {
      * @param rootUrl defines the root URL to use to load textures and relative dependencies
      * @param rootUrl defines the root URL to use to load textures and relative dependencies
      * @returns a promise that will resolve to the new node material
      * @returns a promise that will resolve to the new node material
      */
      */
-    public static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl: string = ""): Promise<NodeMaterial> {
+    public static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl: string = "", nodeMaterial?: NodeMaterial): Promise<NodeMaterial> {
         return new Promise((resolve, reject) => {
         return new Promise((resolve, reject) => {
             var request = new WebRequest();
             var request = new WebRequest();
             request.addEventListener("readystatechange", () => {
             request.addEventListener("readystatechange", () => {
@@ -1347,9 +1352,14 @@ export class NodeMaterial extends PushMaterial {
                     if (request.status == 200) {
                     if (request.status == 200) {
                         var snippet = JSON.parse(JSON.parse(request.responseText).jsonPayload);
                         var snippet = JSON.parse(JSON.parse(request.responseText).jsonPayload);
                         let serializationObject = JSON.parse(snippet.nodeMaterial);
                         let serializationObject = JSON.parse(snippet.nodeMaterial);
-                        let nodeMaterial = SerializationHelper.Parse(() => new NodeMaterial(snippetId, scene), serializationObject, scene, rootUrl);
+
+                        if (!nodeMaterial) {
+                            nodeMaterial = SerializationHelper.Parse(() => new NodeMaterial(snippetId, scene), serializationObject, scene, rootUrl);
+                        }
 
 
                         nodeMaterial.loadFromSerialization(serializationObject);
                         nodeMaterial.loadFromSerialization(serializationObject);
+                        nodeMaterial.snippetId = snippetId;
+
                         try {
                         try {
                             nodeMaterial.build(true);
                             nodeMaterial.build(true);
                             resolve(nodeMaterial);
                             resolve(nodeMaterial);