David Catuhe 6 years ago
parent
commit
b451e4266e

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

@@ -175,22 +175,28 @@ export class PreviewManager {
         }
     }
 
+    private _forceCompilationAsync(material: NodeMaterial, mesh: AbstractMesh): Promise<void> {
+        return material.forceCompilationAsync(mesh);
+
+    }
+
     private _updatePreview(serializationObject: any) {
-        let tempMaterial = NodeMaterial.Parse(serializationObject, this._scene);
         try {
-            tempMaterial.build();
+            let tempMaterial = NodeMaterial.Parse(serializationObject, this._scene);
 
             if (this._meshes.length) {
-                tempMaterial.forceCompilation(this._meshes[0], () => {
+                let tasks = this._meshes.map(m => this._forceCompilationAsync(tempMaterial, m));
+
+                Promise.all(tasks).then(() => {
                     for (var mesh of this._meshes) {
                         mesh.material = tempMaterial;
                     }
-        
+
                     if (this._material) {
                         this._material.dispose();
                     }      
         
-                    this._material = tempMaterial;    
+                    this._material = tempMaterial;  
                 });
             } else {
                 this._material = tempMaterial;    

+ 5 - 1
nodeEditor/src/graphEditor.tsx

@@ -167,6 +167,10 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
 
             this._previewManager = new PreviewManager(this.props.globalState.hostDocument.getElementById("preview-canvas") as HTMLCanvasElement, this.props.globalState);
         }
+
+        if (navigator.userAgent.indexOf("Mobile") !== -1) {
+            ((this.props.globalState.hostDocument || document).querySelector(".blocker") as HTMLElement).style.visibility = "visible";
+        }
     }
 
     componentWillUnmount() {
@@ -686,7 +690,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                 </div>                
                 <MessageDialogComponent globalState={this.props.globalState} />
                 <div className="blocker">
-                    Node Material Editor requires a screen with a minimal resolution of 1000px
+                    Node Material Editor runs only on desktop
                 </div>
             </Portal>
         );

+ 0 - 6
nodeEditor/src/main.scss

@@ -223,10 +223,4 @@
             }
         }
     }
-}
-
-@media (max-width:1000px) {
-    .blocker {
-        visibility: visible;
-    }
 }

+ 2 - 2
nodeEditor/src/serializationTools.ts

@@ -6,11 +6,11 @@ import { DataStorage } from './dataStorage';
 
 export class SerializationTools {
     public static Serialize(material: NodeMaterial, globalState: GlobalState) {
-        let serializationObject = material.serialize();
-
         let bufferSerializationState = Texture.SerializeBuffers;
         Texture.SerializeBuffers = DataStorage.ReadBoolean("EmbedTextures", true);
 
+        let serializationObject = material.serialize();
+
         // Store node locations
         for (var block of material.attachedBlocks) {
             let node = globalState.onGetNodeFromBlock(block);

+ 74 - 2
nodeEditor/src/stringTools.ts

@@ -1,7 +1,79 @@
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
-import { saveAs } from 'file-saver';
 
 export class StringTools {
+    /*
+     * Based on FileSaver.js
+     * A saveAs() FileSaver implementation.
+     *
+     * By Eli Grey, http://eligrey.com
+     *
+     * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
+     * source  : http://purl.eligrey.com/github/FileSaver.js
+     */
+    private static _SaveAs(blob: Blob, name: string, document: HTMLDocument) {
+        if ('download' in HTMLAnchorElement.prototype) {
+            var URL = window.URL || window.webkitURL;
+            var a = document.createElement('a');
+        
+            a.download = name;
+            a.rel = 'noopener'; // tabnabbing
+
+            a.href = URL.createObjectURL(blob)
+            setTimeout(() => { URL.revokeObjectURL(a.href) }, 4E4) // 40s
+            setTimeout(() => { this._Click(a, document) }, 0);
+            return;
+        }
+
+        // Open a popup immediately do go around popup blocker
+        // Mostly only available on user interaction and the fileReader is async so...
+        var popup = open('', '_blank');
+        if (popup) {
+            popup.document.title = popup.document.body.innerText = 'downloading...';
+        }
+
+        var force = blob.type === 'application/octet-stream';
+        var isSafari = /constructor/i.test((window as any).HTMLElement) || (window as any).safari;
+        var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
+
+        if ((isChromeIOS || (force && isSafari)) && typeof FileReader !== 'undefined') {
+            // Safari doesn't allow downloading of blob URLs
+            var reader = new FileReader();
+            reader.onloadend = () => {
+                var url:any = reader.result;
+                url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
+                if (popup) {
+                    popup.location.href = url;
+                }
+                else {
+                    location = url;
+                }
+                popup = null;
+            }
+            reader.readAsDataURL(blob);
+        } else {
+            var URL = window.URL || window.webkitURL
+            var url = URL.createObjectURL(blob)
+            if (popup) {
+                popup.location.href = url;
+            }
+            else {
+                location.href = url;
+            }
+            popup = null;
+            setTimeout(function () { URL.revokeObjectURL(url) }, 4E4);
+        }
+    }
+
+    private static _Click(node: HTMLElement, document: HTMLDocument) {
+        try {
+            node.dispatchEvent(new MouseEvent('click'))
+        } catch (e) {
+            var evt = document.createEvent('MouseEvents');
+            evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
+            node.dispatchEvent(evt);
+        }
+    }
+
     /**
      * Gets the base math type of node material block connection point.
      * @param type Type to parse.
@@ -20,6 +92,6 @@ export class StringTools {
                 type: "application/octet-stream"
             });
 
-        saveAs(blob, filename);        
+        this._SaveAs(blob, filename, document);        
     }
 }

+ 1 - 3
package.json

@@ -47,7 +47,6 @@
         "@types/react": "~16.7.3",
         "@types/react-dom": "~16.0.9",
         "@types/sinon": "^4.1.3",
-        "@types/file-saver": "~2.0.1",
         "ajv": "^6.9.1",
         "awesome-typescript-loader": "^5.2.1",
         "base64-font-loader": "0.0.4",
@@ -106,7 +105,6 @@
         "webpack-dev-server": "^3.1.14",
         "webpack-stream": "5.0.0",
         "xhr2": "^0.1.4",
-        "xmlbuilder": "8.2.2",
-        "file-saver": "~2.0.2"
+        "xmlbuilder": "8.2.2"
     }
 }

+ 10 - 0
src/Materials/Textures/texture.ts

@@ -13,6 +13,7 @@ import { Engine } from '../../Engines/engine';
 import { TimingTools } from '../../Misc/timingTools';
 import { InstantiationTools } from '../../Misc/instantiationTools';
 import { Plane } from '../../Maths/math.plane';
+import { StringTools } from '../../Misc/stringTools';
 
 declare type CubeTexture = import("../../Materials/Textures/cubeTexture").CubeTexture;
 declare type MirrorTexture = import("../../Materials/Textures/mirrorTexture").MirrorTexture;
@@ -585,6 +586,13 @@ export class Texture extends BaseTexture {
      * @returns The JSON representation of the texture
      */
     public serialize(): any {
+        let savedName = this.name;
+        if (!Texture.SerializeBuffers) {
+            if (StringTools.StartsWith(this.name, "data:")) {
+                this.name = "";
+            }
+        }
+
         var serializationObject = super.serialize();
 
         if (!serializationObject) {
@@ -601,6 +609,8 @@ export class Texture extends BaseTexture {
         serializationObject.invertY = this._invertY;
         serializationObject.samplingMode = this.samplingMode;
 
+        this.name = savedName;
+
         return serializationObject;
     }