msDestiny14 пре 4 година
родитељ
комит
91cebd5acb

+ 2 - 0
dist/preview release/what's new.md

@@ -57,6 +57,7 @@
 
 - Added GUI Editor project to master. ([msDestiny14](https://github.com/msDestiny14))
 - Moving GUI property tab components into GUIEditor. ([msDestiny14](https://github.com/msDestiny14))
+- Adding basic saving and loading funtionality. ([msDestiny14](https://github.com/msDestiny14))
 
 ### GUI
 
@@ -110,6 +111,7 @@
 - Fix for DualSense gamepads being incorrectly read as DualShock gamepads ([PolygonalSun](https://github.com/PolygonalSun))
 - Fix for warning in chrome about passive wheel events ([#9777](https://github.com/BabylonJS/Babylon.js/pull/9777)) ([kaliatech](https://github.com/kaliatech))
 - Fix crash when cloning material in `AssetContainer.instantiateModelsToScene` when mesh is an instanced mesh ([Popov72](https://github.com/Popov72))
+- Fix issue with NinePatch displaying half pixel gaps between slices on Firefox browsers. ([Pryme8](https://github.com/Pryme8))
 
 ## Breaking changes
 

+ 92 - 105
gui/src/2D/controls/image.ts

@@ -32,12 +32,13 @@ export class Image extends Control {
     private _cellHeight: number = 0;
     private _cellId: number = -1;
 
-    private _populateNinePatchSlicesFromImage = false;
     private _sliceLeft: number;
     private _sliceRight: number;
     private _sliceTop: number;
     private _sliceBottom: number;
 
+    private _populateNinePatchSlicesFromImage = false;
+
     private _detectPointerOnOpaqueOnly: boolean;
 
     private _imageDataCache: {
@@ -63,26 +64,6 @@ export class Image extends Control {
     }
 
     /**
-     * Gets or sets a boolean indicating if nine patch slices (left, top, right, bottom) should be read from image data
-     */
-    @serialize()
-    public get populateNinePatchSlicesFromImage(): boolean {
-        return this._populateNinePatchSlicesFromImage;
-    }
-
-    public set populateNinePatchSlicesFromImage(value: boolean) {
-        if (this._populateNinePatchSlicesFromImage === value) {
-            return;
-        }
-
-        this._populateNinePatchSlicesFromImage = value;
-
-        if (this._populateNinePatchSlicesFromImage && this._loaded) {
-            this._extractNinePatchSliceDataFromImage();
-        }
-    }
-
-    /**
      * Gets or sets a boolean indicating if pointers should only be validated on pixels with alpha > 0.
      * Beware using this as this will comsume more memory as the image has to be stored twice
      */
@@ -243,6 +224,26 @@ export class Image extends Control {
         this._markAsDirty();
     }
 
+    /**
+    * Gets or sets a boolean indicating if nine patch slices (left, top, right, bottom) should be read from image data
+    */
+    @serialize()
+    public get populateNinePatchSlicesFromImage(): boolean {
+        return this._populateNinePatchSlicesFromImage;
+    }
+
+    public set populateNinePatchSlicesFromImage(value: boolean) {
+        if (this._populateNinePatchSlicesFromImage === value) {
+            return;
+        }
+
+        this._populateNinePatchSlicesFromImage = value;
+
+        if (this._populateNinePatchSlicesFromImage && this._loaded) {
+            this._extractNinePatchSliceDataFromImage();
+        }
+    }
+
     /** Indicates if the format of the image is SVG */
     public get isSVG(): boolean {
         return this._isSVG;
@@ -375,46 +376,6 @@ export class Image extends Control {
         dstImage.sourceHeight = dstHeight;
     }
 
-    /**
-     * Gets or sets the internal DOM image used to render the control
-     */
-    public set domImage(value: HTMLImageElement) {
-        this._domImage = value;
-        this._loaded = false;
-        this._imageDataCache.data = null;
-
-        if (this._domImage.width) {
-            this._onImageLoaded();
-        } else {
-            this._domImage.onload = () => {
-                this._onImageLoaded();
-            };
-        }
-    }
-
-    public get domImage(): HTMLImageElement {
-        return this._domImage;
-    }
-
-    private _onImageLoaded(): void {
-        this._imageDataCache.data = null;
-        this._imageWidth = this._domImage.width;
-        this._imageHeight = this._domImage.height;
-        this._loaded = true;
-
-        if (this._populateNinePatchSlicesFromImage) {
-            this._extractNinePatchSliceDataFromImage();
-        }
-
-        if (this._autoScale) {
-            this.synchronizeSizeWithContent();
-        }
-
-        this.onImageLoadedObservable.notifyObservers(this);
-
-        this._markAsDirty();
-    }
-
     private _extractNinePatchSliceDataFromImage() {
         if (!this._workingCanvas) {
             this._workingCanvas = document.createElement("canvas");
@@ -466,6 +427,46 @@ export class Image extends Control {
     }
 
     /**
+     * Gets or sets the internal DOM image used to render the control
+     */
+    public set domImage(value: HTMLImageElement) {
+        this._domImage = value;
+        this._loaded = false;
+        this._imageDataCache.data = null;
+
+        if (this._domImage.width) {
+            this._onImageLoaded();
+        } else {
+            this._domImage.onload = () => {
+                this._onImageLoaded();
+            };
+        }
+    }
+
+    public get domImage(): HTMLImageElement {
+        return this._domImage;
+    }
+
+    private _onImageLoaded(): void {
+        this._imageDataCache.data = null;
+        this._imageWidth = this._domImage.width;
+        this._imageHeight = this._domImage.height;
+        this._loaded = true;
+
+        if (this._populateNinePatchSlicesFromImage) {
+            this._extractNinePatchSliceDataFromImage();
+        }
+
+        if (this._autoScale) {
+            this.synchronizeSizeWithContent();
+        }
+
+        this.onImageLoadedObservable.notifyObservers(this);
+
+        this._markAsDirty();
+    }
+
+    /**
      * Gets the image source url
      */
     @serialize()
@@ -644,7 +645,6 @@ export class Image extends Control {
      */
     constructor(public name?: string, url: Nullable<string> = null) {
         super(name);
-
         this.source = url;
     }
 
@@ -818,51 +818,38 @@ export class Image extends Control {
         context.restore();
     }
 
-    private _renderCornerPatch(context: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, targetX: number, targetY: number): void {
-        this._drawImage(context, x, y, width, height, this._currentMeasure.left + targetX, this._currentMeasure.top + targetY, width, height);
-    }
-
     private _renderNinePatch(context: CanvasRenderingContext2D): void {
-        let height = this._imageHeight;
-        let leftWidth = this._sliceLeft;
-        let topHeight = this._sliceTop;
-        let bottomHeight = this._imageHeight - this._sliceBottom;
-        let rightWidth = this._imageWidth - this._sliceRight;
-        let left = 0;
-        let top = 0;
-
-        if (this._populateNinePatchSlicesFromImage) {
-            left = 1;
-            top = 1;
-            height -= 2;
-            leftWidth -= 1;
-            topHeight -= 1;
-            bottomHeight -= 1;
-            rightWidth -= 1;
-        }
-
+        const leftWidth = this._sliceLeft;
+        const topHeight = this._sliceTop;
+        const bottomHeight = this._imageHeight - this._sliceBottom;
+        const rightWidth = this._imageWidth - this._sliceRight;
         const centerWidth = this._sliceRight - this._sliceLeft;
-        const targetCenterWidth = this._currentMeasure.width - rightWidth - this.sliceLeft;
-        const targetTopHeight = this._currentMeasure.height - height + this._sliceBottom;
-
-        // Corners
-        this._renderCornerPatch(context, left, top, leftWidth, topHeight, 0, 0);
-        this._renderCornerPatch(context, left, this._sliceBottom, leftWidth, height - this._sliceBottom, 0, targetTopHeight);
-
-        this._renderCornerPatch(context, this._sliceRight, top, rightWidth, topHeight, this._currentMeasure.width - rightWidth, 0);
-        this._renderCornerPatch(context, this._sliceRight, this._sliceBottom, rightWidth, height - this._sliceBottom, this._currentMeasure.width - rightWidth, targetTopHeight);
-
+        const centerHeight = this._sliceBottom - this._sliceTop;
+        const targetCenterWidth = (this._currentMeasure.width - rightWidth - leftWidth) + 2;
+        const targetCenterHeight = (this._currentMeasure.height - bottomHeight - topHeight) + 2;
+        const centerLeftOffset = this._currentMeasure.left + leftWidth - 1;
+        const centerTopOffset = this._currentMeasure.top + topHeight - 1;
+        const rightOffset = this._currentMeasure.left + this._currentMeasure.width - rightWidth;
+        const bottomOffset = this._currentMeasure.top + this._currentMeasure.height - bottomHeight;
+
+        //Top Left
+        this._drawImage(context, 0, 0, leftWidth, topHeight, this._currentMeasure.left, this._currentMeasure.top, leftWidth, topHeight);
+        //Top
+        this._drawImage(context, this._sliceLeft, 0, centerWidth, topHeight, centerLeftOffset, this._currentMeasure.top, targetCenterWidth, topHeight);
+        //Top Right
+        this._drawImage(context, this.sliceRight, 0, rightWidth, topHeight, rightOffset, this._currentMeasure.top, rightWidth, topHeight);
+        //Left
+        this._drawImage(context, 0, this._sliceTop, leftWidth, centerHeight, this._currentMeasure.left, centerTopOffset, leftWidth, targetCenterHeight);
         // Center
-        this._drawImage(context, this._sliceLeft, this._sliceTop, centerWidth, this._sliceBottom - this._sliceTop, this._currentMeasure.left + leftWidth, this._currentMeasure.top + topHeight, targetCenterWidth, targetTopHeight - topHeight);
-
-        // Borders
-        this._drawImage(context, left, this._sliceTop, leftWidth, this._sliceBottom - this._sliceTop, this._currentMeasure.left, this._currentMeasure.top + topHeight, leftWidth, targetTopHeight - topHeight);
-
-        this._drawImage(context, this._sliceRight, this._sliceTop, leftWidth, this._sliceBottom - this._sliceTop, this._currentMeasure.left + this._currentMeasure.width - rightWidth, this._currentMeasure.top + topHeight, leftWidth, targetTopHeight - topHeight);
-
-        this._drawImage(context, this._sliceLeft, top, centerWidth, topHeight, this._currentMeasure.left + leftWidth, this._currentMeasure.top, targetCenterWidth, topHeight);
-
-        this._drawImage(context, this._sliceLeft, this._sliceBottom, centerWidth, bottomHeight, this._currentMeasure.left + leftWidth, this._currentMeasure.top + targetTopHeight, targetCenterWidth, bottomHeight);
+        this._drawImage(context, this._sliceLeft, this._sliceTop, centerWidth, centerHeight, centerLeftOffset, centerTopOffset, targetCenterWidth, targetCenterHeight);
+        //Right
+        this._drawImage(context, this._sliceRight, this._sliceTop, rightWidth, centerHeight, rightOffset, centerTopOffset, rightWidth, targetCenterHeight);
+        //Bottom Left
+        this._drawImage(context, 0, this._sliceBottom, leftWidth, bottomHeight, this._currentMeasure.left, bottomOffset, leftWidth, bottomHeight);
+        //Bottom
+        this._drawImage(context, this.sliceLeft, this._sliceBottom, centerWidth, bottomHeight, centerLeftOffset, bottomOffset, targetCenterWidth, bottomHeight);
+        //Bottom Right
+        this._drawImage(context, this._sliceRight, this._sliceBottom, rightWidth, bottomHeight, rightOffset, bottomOffset, rightWidth, bottomHeight);
     }
 
     public dispose() {
@@ -883,4 +870,4 @@ export class Image extends Control {
     /** NINE_PATCH */
     public static readonly STRETCH_NINE_PATCH = 4;
 }
-_TypeStore.RegisteredTypes["BABYLON.GUI.Image"] = Image;
+_TypeStore.RegisteredTypes["BABYLON.GUI.Image"] = Image;

+ 91 - 154
guiEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -1,17 +1,16 @@
-
 import * as React from "react";
-import { GlobalState } from '../../globalState';
-import { Nullable } from 'babylonjs/types';
-import { ButtonLineComponent } from '../../sharedUiComponents/lines/buttonLineComponent';
-import { LineContainerComponent } from '../../sharedUiComponents/lines/lineContainerComponent';
-import { FileButtonLineComponent } from '../../sharedUiComponents/lines/fileButtonLineComponent';
-import { Tools } from 'babylonjs/Misc/tools';
-import { CheckBoxLineComponent } from '../../sharedUiComponents/lines/checkBoxLineComponent';
-import { DataStorage } from 'babylonjs/Misc/dataStorage';
-import { GUINode } from '../../diagram/guiNode';
-import { Observer } from 'babylonjs/Misc/observable';
+import { GlobalState } from "../../globalState";
+import { Nullable } from "babylonjs/types";
+import { ButtonLineComponent } from "../../sharedUiComponents/lines/buttonLineComponent";
+import { LineContainerComponent } from "../../sharedUiComponents/lines/lineContainerComponent";
+import { FileButtonLineComponent } from "../../sharedUiComponents/lines/fileButtonLineComponent";
+import { Tools } from "babylonjs/Misc/tools";
+import { CheckBoxLineComponent } from "../../sharedUiComponents/lines/checkBoxLineComponent";
+import { DataStorage } from "babylonjs/Misc/dataStorage";
+import { GUINode } from "../../diagram/guiNode";
+import { Observer } from "babylonjs/Misc/observable";
 import { TextLineComponent } from "../../sharedUiComponents/lines/textLineComponent";
-import { SerializationTools } from "../../serializationTools";
+import { StringTools } from "../../sharedUiComponents/stringTools";
 import { Engine } from "babylonjs/Engines/engine";
 import { LockObject } from "../../sharedUiComponents/tabs/propertyGrids/lockObject";
 import { SliderPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent";
@@ -45,6 +44,7 @@ import { EllipsePropertyGridComponent } from "../../sharedUiComponents/tabs/prop
 import { CheckboxPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/checkboxPropertyGridComponent";
 import { Control } from "babylonjs-gui/2D/controls/control";
 import { ControlPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/controlPropertyGridComponent";
+import { AdvancedDynamicTexture } from "babylonjs-gui/2D/advancedDynamicTexture";
 
 require("./propertyTab.scss");
 
@@ -54,7 +54,7 @@ interface IPropertyTabComponentProps {
 
 interface IPropertyTabComponentState {
     currentNode: Nullable<GUINode>;
- }
+}
 
 export class PropertyTabComponent extends React.Component<IPropertyTabComponentProps, IPropertyTabComponentState> {
     private _onBuiltObserver: Nullable<Observer<void>>;
@@ -63,7 +63,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
     constructor(props: IPropertyTabComponentProps) {
         super(props);
 
-        this.state = { currentNode: null};
+        this.state = { currentNode: null };
     }
 
     timerRefresh() {
@@ -76,7 +76,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
         this._timerIntervalId = window.setInterval(() => this.timerRefresh(), 500);
         this.props.globalState.onSelectionChangedObservable.add((selection) => {
             if (selection instanceof GUINode) {
-                this.setState({ currentNode: selection});
+                this.setState({ currentNode: selection });
             } else {
                 this.setState({ currentNode: null });
             }
@@ -92,210 +92,148 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
         this.props.globalState.onBuiltObservable.remove(this._onBuiltObserver);
     }
 
-
     load(file: File) {
-        Tools.ReadFile(file, (data) => {
-            let decoder = new TextDecoder("utf-8");
-            SerializationTools.Deserialize(JSON.parse(decoder.decode(data)), this.props.globalState);
-
-            this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
-        }, undefined, true);
-    }
-
-    loadFrame(file: File) {
-        Tools.ReadFile(file, (data) => {
-            // get Frame Data from file
-            //let decoder = new TextDecoder("utf-8");
-           // const frameData = JSON.parse(decoder.decode(data));
-           // SerializationTools.AddFrameToMaterial(frameData, this.props.globalState, this.props.globalState.nodeMaterial);
-        }, undefined, true);
+        Tools.ReadFile(
+            file,
+            (data) => {
+                const decoder = new TextDecoder("utf-8");
+                this.props.globalState.workbench.loadFromJson(JSON.parse(decoder.decode(data)));
+
+                this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
+            },
+            undefined,
+            true
+        );
     }
 
     save() {
-        //let json = SerializationTools.Serialize(this.props.globalState.nodeMaterial, this.props.globalState);
-        //StringTools.DownloadAsFile(this.props.globalState.hostDocument, json, "nodeMaterial.json");
-    }
-
-    customSave() {
-        /*this.props.globalState.onLogRequiredObservable.notifyObservers({message: "Saving your material to Babylon.js snippet server...", isError: false});
-        this.props.globalState.customSave!.action(SerializationTools.Serialize(this.props.globalState.nodeMaterial, this.props.globalState)).then(() => {
-            this.props.globalState.onLogRequiredObservable.notifyObservers({message: "Material saved successfully", isError: false});
-        }).catch((err) => {
-            this.props.globalState.onLogRequiredObservable.notifyObservers({message: err, isError: true});
-        });*/
+        const json = JSON.stringify(this.props.globalState.guiTexture.serializeContent());
+        StringTools.DownloadAsFile(this.props.globalState.hostDocument, json, "guiTexture.json");
     }
 
     saveToSnippetServer() {
-        /*const material = this.props.globalState.nodeMaterial;
-        const xmlHttp = new XMLHttpRequest();
-
-        let json = SerializationTools.Serialize(material, this.props.globalState);
+        const adt = this.props.globalState.guiTexture;
+        const content = JSON.stringify(adt.serializeContent());
 
+        const xmlHttp = new XMLHttpRequest();
         xmlHttp.onreadystatechange = () => {
             if (xmlHttp.readyState == 4) {
                 if (xmlHttp.status == 200) {
-                    var snippet = JSON.parse(xmlHttp.responseText);
-                    const oldId = material.snippetId;
-                    material.snippetId = snippet.id;
+                    const snippet = JSON.parse(xmlHttp.responseText);
+                    const oldId = adt.snippetId;
+                    adt.snippetId = snippet.id;
                     if (snippet.version && snippet.version != "0") {
-                        material.snippetId += "#" + snippet.version;
+                        adt.snippetId += "#" + snippet.version;
                     }
-
                     this.forceUpdate();
                     if (navigator.clipboard) {
-                        navigator.clipboard.writeText(material.snippetId);
+                        navigator.clipboard.writeText(adt.snippetId);
                     }
 
-                    let windowAsAny = window as any;
+                    const windowAsAny = window as any;
 
                     if (windowAsAny.Playground && oldId) {
                         windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
                             regex: new RegExp(oldId, "g"),
-                            replace: material.snippetId
+                            replace: `parseFromSnippetAsync("${adt.snippetId}`,
                         });
                     }
 
-                    this.props.globalState.hostDocument.defaultView!.alert("NodeMaterial saved with ID: " + material.snippetId + " (please note that the id was also saved to your clipboard)");
-
-                }
-                else {
-                    this.props.globalState.hostDocument.defaultView!.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.`);
+                    alert("GUI saved with ID: " + adt.snippetId + " (please note that the id was also saved to your clipboard)");
+                } else {
+                    alert("Unable to save your GUI");
                 }
             }
         };
 
-        xmlHttp.open("POST", NodeMaterial.SnippetUrl + (material.snippetId ? "/" + material.snippetId : ""), true);
+        xmlHttp.open("POST", AdvancedDynamicTexture.SnippetUrl + (adt.snippetId ? "/" + adt.snippetId : ""), true);
         xmlHttp.setRequestHeader("Content-Type", "application/json");
 
-        var dataToSend = {
-            payload : JSON.stringify({
-                nodeMaterial: json
+        const dataToSend = {
+            payload: JSON.stringify({
+                gui: content,
             }),
             name: "",
             description: "",
-            tags: ""
+            tags: "",
         };
 
-        xmlHttp.send(JSON.stringify(dataToSend));*/
+        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");
+        const 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();
-            if (!this.changeMode(this.props.globalState.nodeMaterial!.mode, true, false)) {
-                this.props.globalState.onResetRequiredObservable.notifyObservers();
-            }
-        }).catch((err) => {
-            this.props.globalState.hostDocument.defaultView!.alert("Unable to load your node material: " + err);
-        });*/
+        this.props.globalState.workbench.loadFromSnippet(snippedID);
     }
 
-    renderProperties()
-    {
-        var className = this.state.currentNode?.guiControl.getClassName();
+    renderProperties() {
+        const className = this.state.currentNode?.guiControl.getClassName();
         switch (className) {
             case "TextBlock": {
                 const textBlock = this.state.currentNode?.guiControl as TextBlock;
-                return (<TextBlockPropertyGridComponent textBlock={textBlock}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <TextBlockPropertyGridComponent textBlock={textBlock} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "InputText": {
                 const inputText = this.state.currentNode?.guiControl as InputText;
-                return (<InputTextPropertyGridComponent inputText={inputText}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <InputTextPropertyGridComponent inputText={inputText} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "ColorPicker": {
                 const colorPicker = this.state.currentNode?.guiControl as ColorPicker;
-                return (<ColorPickerPropertyGridComponent colorPicker={colorPicker}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <ColorPickerPropertyGridComponent colorPicker={colorPicker} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Image": {
                 const image = this.state.currentNode?.guiControl as Image;
-                return (<ImagePropertyGridComponent image={image}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <ImagePropertyGridComponent image={image} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Slider": {
                 const slider = this.state.currentNode?.guiControl as Slider;
-                return (<SliderPropertyGridComponent slider={slider}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <SliderPropertyGridComponent slider={slider} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "ImageBasedSlider": {
                 const imageBasedSlider = this.state.currentNode?.guiControl as ImageBasedSlider;
-                return (<ImageBasedSliderPropertyGridComponent imageBasedSlider={imageBasedSlider}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <ImageBasedSliderPropertyGridComponent imageBasedSlider={imageBasedSlider} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Rectangle": {
                 const rectangle = this.state.currentNode?.guiControl as Rectangle;
-                return (<RectanglePropertyGridComponent rectangle={rectangle}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <RectanglePropertyGridComponent rectangle={rectangle} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "StackPanel": {
                 const stackPanel = this.state.currentNode?.guiControl as StackPanel;
-                return (<StackPanelPropertyGridComponent stackPanel={stackPanel}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <StackPanelPropertyGridComponent stackPanel={stackPanel} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Grid": {
                 const grid = this.state.currentNode?.guiControl as Grid;
-                return (<GridPropertyGridComponent grid={grid}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <GridPropertyGridComponent grid={grid} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "ScrollViewer": {
                 const scrollViewer = this.state.currentNode?.guiControl as ScrollViewer;
-                return (<ScrollViewerPropertyGridComponent scrollViewer={scrollViewer}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <ScrollViewerPropertyGridComponent scrollViewer={scrollViewer} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Ellipse": {
                 const ellipse = this.state.currentNode?.guiControl as Ellipse;
-                return (<EllipsePropertyGridComponent ellipse={ellipse}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <EllipsePropertyGridComponent ellipse={ellipse} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Checkbox": {
                 const checkbox = this.state.currentNode?.guiControl as Checkbox;
-                return (<CheckboxPropertyGridComponent checkbox={checkbox}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <CheckboxPropertyGridComponent checkbox={checkbox} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "RadioButton": {
                 const radioButton = this.state.currentNode?.guiControl as RadioButton;
-                return (<RadioButtonPropertyGridComponent radioButton={radioButton}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <RadioButtonPropertyGridComponent radioButton={radioButton} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
             case "Line": {
                 const line = this.state.currentNode?.guiControl as Line;
-                return (<LinePropertyGridComponent line={line}
-                    lockObject={this._lockObject}
-                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+                return <LinePropertyGridComponent line={line} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
             }
         }
 
         if (className !== "") {
             const control = this.state.currentNode?.guiControl as Control;
-            return (<ControlPropertyGridComponent control={control}
-                lockObject={this._lockObject}
-                onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            return <ControlPropertyGridComponent control={control} lockObject={this._lockObject} onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />;
         }
         return null;
     }
@@ -310,9 +248,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                 }}>
                     <div id="header" >
                         <img id="logo" src="https://www.babylonjs.com/Assets/logo-babylonjs-social-twitter.png" />
-                        <div id="title">
-                            GUI EDITOR
-                        </div>
+                        <div id="title">GUI EDITOR</div>
                     </div>
                     {this.renderProperties()}
                         <ButtonLineComponent label="DELETE GUI" onClick={() => {
@@ -327,20 +263,22 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
             <div id="propertyTab">
                 <div id="header">
                     <img id="logo" src="https://www.babylonjs.com/Assets/logo-babylonjs-social-twitter.png" />
-                    <div id="title">
-                        GUI EDITOR
-                    </div>
+                    <div id="title">GUI EDITOR</div>
                 </div>
                 <div>
                     <LineContainerComponent title="GENERAL">
-                        <TextLineComponent label="Version" value={Engine.Version}/>
-                        <TextLineComponent label="Help" value="doc.babylonjs.com" underline={true} onLink={() => window.open('https://doc.babylonjs.com', '_blank')}/>
-                        <ButtonLineComponent label="Reset to default" onClick={() => {
-                            this.props.globalState.onResetRequiredObservable.notifyObservers();
-                        }} />
+                        <TextLineComponent label="Version" value={Engine.Version} />
+                        <TextLineComponent label="Help" value="doc.babylonjs.com" underline={true} onLink={() => window.open("https://doc.babylonjs.com", "_blank")} />
+                        <ButtonLineComponent
+                            label="Reset to default"
+                            onClick={() => {
+                                this.props.globalState.onResetRequiredObservable.notifyObservers();
+                            }}
+                        />
                     </LineContainerComponent>
                     <LineContainerComponent title="OPTIONS">
-                        <CheckBoxLineComponent label="Show grid"
+                        <CheckBoxLineComponent
+                            label="Show grid"
                             isSelected={() => DataStorage.ReadBoolean("ShowGrid", true)}
                             onSelect={(value: boolean) => {
                                 DataStorage.WriteBoolean("ShowGrid", value);
@@ -349,27 +287,26 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                     </LineContainerComponent>
                     <LineContainerComponent title="FILE">
                         <FileButtonLineComponent label="Load" onClick={(file) => this.load(file)} accept=".json" />
-                        <ButtonLineComponent label="Save" onClick={() => {
-                            this.save();
-                        }} />
-                        {
-                            this.props.globalState.customSave &&
-                            <ButtonLineComponent label={this.props.globalState.customSave!.label} onClick={() => {
-                                this.customSave();
-                            }} />
-                        }
+                        <ButtonLineComponent
+                            label="Save"
+                            onClick={() => {
+                                this.save();
+                            }}
+                        />
                     </LineContainerComponent>
                     {
-                        !this.props.globalState.customSave &&
                         <LineContainerComponent title="SNIPPET">
                             <ButtonLineComponent label="Load from snippet server" onClick={() => this.loadFromSnippet()} />
-                            <ButtonLineComponent label="Save to snippet server" onClick={() => {
-                                this.saveToSnippetServer();
-                            }} />
+                            <ButtonLineComponent
+                                label="Save to snippet server"
+                                onClick={() => {
+                                    this.saveToSnippetServer();
+                                }}
+                            />
                         </LineContainerComponent>
                     }
                 </div>
             </div>
         );
     }
-}
+}

+ 59 - 35
guiEditor/src/diagram/guiNode.ts

@@ -1,25 +1,27 @@
-import { GlobalState } from '../globalState';
-import { Nullable } from 'babylonjs/types';
-import { Observer } from 'babylonjs/Misc/observable';
-import { WorkbenchComponent, FramePortData } from './workbench';
-import { Control } from 'babylonjs-gui/2D/controls/control';
-import { Vector2 } from 'babylonjs/Maths/math.vector';
-
+import { GlobalState } from "../globalState";
+import { Nullable } from "babylonjs/types";
+import { Observer } from "babylonjs/Misc/observable";
+import { WorkbenchComponent, FramePortData } from "./workbench";
+import { Control } from "babylonjs-gui/2D/controls/control";
+import { Vector2 } from "babylonjs/Maths/math.vector";
+import { Container } from "babylonjs-gui/2D/controls/container";
 
 export class GUINode {
     private _x = 0;
     private _y = 0;
     private _gridAlignedX = 0;
-    private _gridAlignedY = 0;    
+    private _gridAlignedY = 0;
     private _globalState: GlobalState;
-    private _onSelectionChangedObserver: Nullable<Observer<Nullable<GUINode | FramePortData>>>;  
-    private _onSelectionBoxMovedObserver: Nullable<Observer<ClientRect | DOMRect>>;   
-    private _onUpdateRequiredObserver: Nullable<Observer<void>>;  
-    private _ownerCanvas: WorkbenchComponent; 
+    private _onSelectionChangedObserver: Nullable<Observer<Nullable<GUINode | FramePortData>>>;
+    private _onSelectionBoxMovedObserver: Nullable<Observer<ClientRect | DOMRect>>;
+    private _onUpdateRequiredObserver: Nullable<Observer<void>>;
+    private _ownerCanvas: WorkbenchComponent;
     private _isSelected: boolean;
     private _isVisible = true;
     private _enclosingFrameId = -1;
 
+    public children: GUINode[] = [];
+
     public get isVisible() {
         return this._isVisible;
     }
@@ -45,7 +47,7 @@ export class GUINode {
             return;
         }
         this._x = value;
-        
+
         this._gridAlignedX = this._ownerCanvas.getGridPosition(value);
     }
 
@@ -95,41 +97,39 @@ export class GUINode {
         this._isSelected = value;
 
         if (value) {
-            this._globalState.onSelectionChangedObservable.notifyObservers(this);  
+            this._globalState.onSelectionChangedObservable.notifyObservers(this);
         }
     }
 
     public constructor(globalState: GlobalState, public guiControl: Control) {
         this._globalState = globalState;
         this._ownerCanvas = this._globalState.workbench;
-        
-        guiControl.onPointerUpObservable.add(evt => {
+        this.x = guiControl.leftInPixels;
+        this.y = guiControl.topInPixels;
+        guiControl.onPointerUpObservable.add((evt) => {
             this.clicked = false;
             console.log("up");
         });
 
-        guiControl.onPointerDownObservable.add( evt => {
+        guiControl.onPointerDownObservable.add((evt) => {
+            if (!this._ownerCanvas.isUp) return;
             this.clicked = true;
             this.isSelected = true;
             console.log("down");
-        }
-        );
+            this._ownerCanvas.isUp = false;
+        });
 
-        guiControl.onPointerEnterObservable.add( evt => {
+        guiControl.onPointerEnterObservable.add((evt) => {
             this._ownerCanvas.isOverGUINode = true;
             console.log("in");
-        }
-        );
+        });
 
-        guiControl.onPointerOutObservable.add( evt => {
+        guiControl.onPointerOutObservable.add((evt) => {
             this._ownerCanvas.isOverGUINode = false;
             console.log("out");
-        }
-        );
-
-        this._onSelectionBoxMovedObserver = this._globalState.onSelectionBoxMoved.add(rect1 => {
         });
 
+        this._onSelectionBoxMovedObserver = this._globalState.onSelectionBoxMoved.add((rect1) => {});
     }
 
     public cleanAccumulation(useCeil = false) {
@@ -138,27 +138,51 @@ export class GUINode {
     }
 
     public clicked: boolean;
-    public _onMove(evt: Vector2, startPos: Vector2) {
-       
-        if(!this.clicked) return false;
+    public _onMove(evt: Vector2, startPos: Vector2, ignorClick: boolean = false) {
+        if (!this.clicked && !ignorClick) return false;
         console.log("moving");
 
         let newX = (evt.x - startPos.x) ;// / this._ownerCanvas.zoom;
         let newY = (evt.y - startPos.y) ;// / this._ownerCanvas.zoom;
 
         this.x += newX;
-        this.y += newY;  
+        this.y += newY;
+
+        this.children.forEach((child) => {
+            child._onMove(evt, startPos, true);
+        });
 
         return true;
         //evt.stopPropagation();
     }
 
-    public updateVisual()
-    {
+    public updateVisual() {
         this.guiControl.leftInPixels = this.x;
         this.guiControl.topInPixels = this.y;
     }
 
+    private _isContainer() {
+        switch (this.guiControl.typeName) {
+            case "Button":
+            case "StackPanel":
+            case "Rectangle":
+            case "Ellipse":
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public addGui(childNode: GUINode) {
+        if (!this._isContainer) return;
+        this.children.push(childNode);
+        (this.guiControl as Container).addControl(childNode.guiControl);
+
+        //adjust the position to be relative
+        //childNode.x = this.x - childNode.x;
+        //childNode.y = this.y - childNode.y;
+    }
+
     public dispose() {
         // notify frame observers that this node is being deleted
         this._globalState.onGuiNodeRemovalObservable.notifyObservers(this);
@@ -175,6 +199,6 @@ export class GUINode {
             this._globalState.onSelectionBoxMoved.remove(this._onSelectionBoxMovedObserver);
         }
 
-        this.guiControl.dispose();   
+        this.guiControl.dispose();
     }
-}
+}

+ 0 - 113
guiEditor/src/diagram/properties/genericNodePropertyComponent.tsx

@@ -1,113 +0,0 @@
-
-import * as React from "react";
-import { LineContainerComponent } from '../../sharedUiComponents/lines/lineContainerComponent';
-import { IPropertyComponentProps } from './propertyComponentProps';
-import { CheckBoxLineComponent } from '../../sharedUiComponents/lines/checkBoxLineComponent';
-import { FloatLineComponent } from '../../sharedComponents/floatLineComponent';
-import { SliderLineComponent } from '../../sharedComponents/sliderLineComponent';
-import { PropertyTypeForEdition, IPropertyDescriptionForEdition } from 'babylonjs/Materials/Node/nodeMaterialDecorator';
-
-export class GenericPropertyComponent extends React.Component<IPropertyComponentProps> {
-    constructor(props: IPropertyComponentProps) {
-        super(props);
-    }
-
-    render() {
-        return (
-            <>
-                <GeneralPropertyTabComponent globalState={this.props.globalState} guiControl={this.props.guiControl}/>
-                <GenericPropertyTabComponent globalState={this.props.globalState} guiControl={this.props.guiControl}/>
-            </>
-        );
-    }
-}
-
-export class GeneralPropertyTabComponent extends React.Component<IPropertyComponentProps> {
-    constructor(props: IPropertyComponentProps) {
-        super(props);
-    }
-
-    render() {
-        return (
-            <>
-                <LineContainerComponent title="GENERAL">
-                </LineContainerComponent>
-            </>
-        );
-    }
-}
-
-export class GenericPropertyTabComponent extends React.Component<IPropertyComponentProps> {
-    constructor(props: IPropertyComponentProps) {
-        super(props);
-    }
-
-    forceRebuild(notifiers?: { "rebuild"?: boolean; "update"?: boolean; }) {
-        if (!notifiers || notifiers.update) {
-            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
-        }
-
-        if (!notifiers || notifiers.rebuild) {
-            this.props.globalState.onRebuildRequiredObservable.notifyObservers();
-        }
-    }
-
-    render() {
-        const block = this.props.guiControl,
-              propStore: IPropertyDescriptionForEdition[] = (block as any)._propStore;
-
-        if (!propStore) {
-            return (
-                <>
-                </>
-            );
-        }
-
-        const componentList: { [groupName: string]: JSX.Element[]} = {},
-              groups: string[] = [];
-
-        for (const { propertyName, displayName, type, groupName, options } of propStore) {
-            let components = componentList[groupName];
-
-            if (!components) {
-                components = [];
-                componentList[groupName] = components;
-                groups.push(groupName);
-            }
-
-            switch (type) {
-                case PropertyTypeForEdition.Boolean: {
-                    components.push(
-                        <CheckBoxLineComponent label={displayName} target={this.props.guiControl} propertyName={propertyName} onValueChanged={() => this.forceRebuild(options.notifiers)} />
-                    );
-                    break;
-                }
-                case PropertyTypeForEdition.Float: {
-                    let cantDisplaySlider = (isNaN(options.min as number) || isNaN(options.max as number) || options.min === options.max);
-                    if (cantDisplaySlider) {
-                        components.push(
-                            <FloatLineComponent globalState={this.props.globalState} label={displayName} propertyName={propertyName} target={this.props.guiControl} onChange={() => this.forceRebuild(options.notifiers)} />
-                        );
-                    } else {
-                        components.push(
-                            <SliderLineComponent label={displayName} target={this.props.guiControl} globalState={this.props.globalState} propertyName={propertyName} step={Math.abs((options.max as number) - (options.min as number)) / 100.0} minimum={Math.min(options.min as number, options.max as number)} maximum={options.max as number} onChange={() => this.forceRebuild(options.notifiers)}/>
-                        );
-                    }
-                    break;
-                }
-            }
-        }
-
-        return (
-            <>
-            {
-                groups.map((group) =>
-                    <LineContainerComponent title={group}>
-                        {componentList[group]}
-                    </LineContainerComponent>
-                )
-            }
-            </>
-        );
-    }
-}

+ 0 - 7
guiEditor/src/diagram/properties/propertyComponentProps.ts

@@ -1,7 +0,0 @@
-import { Control } from "babylonjs-gui/2D/controls/control";
-import { GlobalState } from "../../globalState";
-
-export interface IPropertyComponentProps {
-    globalState: GlobalState;
-    guiControl: Control;
-}

+ 31 - 3
guiEditor/src/diagram/workbench.tsx

@@ -150,7 +150,7 @@ export class WorkbenchComponent extends React.Component<IWorkbenchComponentProps
                 this._selectedGuiNodes = [];
             } 
             else {
-                if (selection instanceof GUINode){
+                if (selection instanceof GUINode ) {
                     if (this._ctrlKeyIsPressed) {
                         if (this._selectedGuiNodes.indexOf(selection) === -1) {
                             this._selectedGuiNodes.push(selection);
@@ -159,6 +159,7 @@ export class WorkbenchComponent extends React.Component<IWorkbenchComponentProps
                     else {              
                         this._selectedGuiNodes = [selection];
                     }
+                    
                 
                 } 
             }
@@ -194,7 +195,7 @@ export class WorkbenchComponent extends React.Component<IWorkbenchComponentProps
         }
 		return gridSize * Math.floor(position / gridSize);
     }
-    
+
     public getGridPositionCeil(position: number) {
         let gridSize = this.gridSize;
 		if (gridSize === 0) {
@@ -203,6 +204,29 @@ export class WorkbenchComponent extends React.Component<IWorkbenchComponentProps
 		return gridSize * Math.ceil(position / gridSize);
 	}
 
+    loadFromJson(serializationObject: any) {
+        this.globalState.onSelectionChangedObservable.notifyObservers(null);
+        this._guiNodes = [];
+        this.globalState.guiTexture.parseContent(serializationObject);
+        this.props.globalState.workbench.loadFromGuiTexture();
+    }
+    
+    async loadFromSnippet(snippedID: string){
+        this.globalState.onSelectionChangedObservable.notifyObservers(null);
+        this._guiNodes = [];
+        await this.globalState.guiTexture.parseFromSnippetAsync(snippedID);
+        this.props.globalState.workbench.loadFromGuiTexture();
+    }
+    
+    loadFromGuiTexture()
+    {
+        var children = this.globalState.guiTexture.getChildren();
+        children[0].children.forEach(guiElement => {
+            var newGuiNode = new GUINode(this.props.globalState, guiElement);
+            this._guiNodes.push(newGuiNode);
+        });
+    }
+
     updateTransform() {
         this._rootContainer.style.transform = `translate(${this._x}px, ${this._y}px) scale(${this._zoom})`;
 
@@ -397,9 +421,11 @@ export class WorkbenchComponent extends React.Component<IWorkbenchComponentProps
         }
         
         this._mouseStartPointX = evt.clientX;
-        this._mouseStartPointY = evt.clientY;        
+        this._mouseStartPointY = evt.clientY;   
+             
     }
 
+    public isUp : boolean = true;
     onUp(evt: React.PointerEvent) {
         this._mouseStartPointX = null;
         this._mouseStartPointY = null;
@@ -418,6 +444,8 @@ export class WorkbenchComponent extends React.Component<IWorkbenchComponentProps
             this._frameCandidate = null;
 
         }
+        this.isUp = true;
+        
     }
 
     onWheel(evt: React.WheelEvent) {

+ 1 - 2
guiEditor/src/guiEditor.ts

@@ -3,7 +3,6 @@ import * as ReactDOM from "react-dom";
 import { GlobalState } from "./globalState";
 import { WorkbenchEditor } from "./workbenchEditor";
 import { Popup } from "./sharedUiComponents/lines/popup";
-import { SerializationTools } from "./serializationTools";
 import { Observable } from "babylonjs/Misc/observable";
 /**
  * Interface used to specify creation options for the gui editor
@@ -57,7 +56,7 @@ export class GUIEditor {
 
         if (options.customLoadObservable) {
             options.customLoadObservable.add((data) => {
-                SerializationTools.Deserialize(data, globalState);
+                //TODO: Add deserilization here.
                 globalState.onResetRequiredObservable.notifyObservers();
                 globalState.onBuiltObservable.notifyObservers();
             });

+ 0 - 8
guiEditor/src/serializationTools.ts

@@ -1,8 +0,0 @@
-import { GlobalState } from './globalState';
-
-export class SerializationTools {
-
-    public static Deserialize(serializationObject: any, globalState: GlobalState) {
-        globalState.onIsLoadingChanged.notifyObservers(true);
-    }
-}

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

@@ -4,7 +4,7 @@ import { GlobalState } from '../../globalState';
 import { Nullable } from 'babylonjs/types';
 import { ButtonLineComponent } from '../../sharedComponents/buttonLineComponent';
 import { LineContainerComponent } from '../../sharedComponents/lineContainerComponent';
-import { StringTools } from '../../stringTools';
+import { StringTools } from '../../sharedUiComponents/stringTools';
 import { FileButtonLineComponent } from '../../sharedComponents/fileButtonLineComponent';
 import { Tools } from 'babylonjs/Misc/tools';
 import { SerializationTools } from '../../serializationTools';

+ 6 - 3
nodeEditor/src/diagram/display/inputDisplayManager.ts

@@ -7,7 +7,6 @@ import { AnimatedInputBlockTypes } from 'babylonjs/Materials/Node/Blocks/Input/a
 import { Vector2, Vector3, Vector4 } from 'babylonjs/Maths/math.vector';
 import { Color3 } from 'babylonjs/Maths/math.color';
 import { BlockTools } from '../../blockTools';
-import { StringTools } from '../../stringTools';
 
 const inputNameToAttributeValue: { [name: string] : string } = {
     "position2d" : "position",
@@ -46,15 +45,19 @@ export class InputDisplayManager implements IDisplayManager {
 
     public getHeaderText(block: NodeMaterialBlock): string {
         let inputBlock = block as InputBlock;
-        let name = `${inputBlock.name} (${StringTools.GetBaseType(inputBlock.output.type)})`;
+        let name = `${inputBlock.name} (${InputDisplayManager.GetBaseType(inputBlock.output.type)})`;
 
         if (inputBlock.isAttribute) {
-            name = StringTools.GetBaseType(inputBlock.output.type);
+            name = InputDisplayManager.GetBaseType(inputBlock.output.type);
         }
 
         return name;
     }
 
+    public static GetBaseType(type: NodeMaterialBlockConnectionPointTypes): string {
+        return NodeMaterialBlockConnectionPointTypes[type];
+    }
+
     public getBackgroundColor(block: NodeMaterialBlock): string {
         let color = "";
         let inputBlock = block as InputBlock;

+ 1 - 1
nodeEditor/src/diagram/graphFrame.ts

@@ -7,7 +7,7 @@ import { IFrameData } from '../nodeLocationInfo';
 import { Color3 } from 'babylonjs/Maths/math.color';
 import { NodePort } from './nodePort';
 import { SerializationTools } from '../serializationTools';
-import { StringTools } from '../stringTools';
+import { StringTools } from '../sharedUiComponents/stringTools';
 import { FrameNodePort } from './frameNodePort';
 
 enum ResizingDirection {

+ 0 - 10
nodeEditor/src/stringTools.ts

@@ -1,5 +1,3 @@
-import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/Enums/nodeMaterialBlockConnectionPointTypes';
-
 export class StringTools {
     /*
      * Based on FileSaver.js
@@ -75,14 +73,6 @@ export class StringTools {
     }
 
     /**
-     * Gets the base math type of node material block connection point.
-     * @param type Type to parse.
-     */
-    public static GetBaseType(type: NodeMaterialBlockConnectionPointTypes): string {
-        return NodeMaterialBlockConnectionPointTypes[type];
-    }
-
-    /**
      * Download a string into a file that will be saved locally by the browser
      * @param content defines the string to download locally as a file
      */