|
@@ -6,6 +6,11 @@ import { DraggableLineComponent } from '../../sharedComponents/draggableLineComp
|
|
|
import { NodeMaterialModes } from 'babylonjs/Materials/Node/Enums/nodeMaterialModes';
|
|
|
import { Observer } from 'babylonjs/Misc/observable';
|
|
|
import { Nullable } from 'babylonjs/types';
|
|
|
+import { DraggableLineWithButtonComponent } from '../../sharedComponents/draggableLineWithButtonComponent';
|
|
|
+import { LineWithFileButtonComponent } from '../../sharedComponents/lineWithFileButtonComponent';
|
|
|
+import { Tools } from 'babylonjs/Misc/tools';
|
|
|
+const addButton = require("../../../imgs/add.svg");
|
|
|
+const deleteButton = require('../../../imgs/delete.svg');
|
|
|
|
|
|
require("./nodeList.scss");
|
|
|
|
|
@@ -144,12 +149,19 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
|
|
|
"FragCoordBlock": "The gl_FragCoord predefined variable that contains the window relative coordinate (x, y, z, 1/w)",
|
|
|
"ScreenSizeBlock": "The size (in pixels) of the screen window",
|
|
|
};
|
|
|
+
|
|
|
+ private _customFrameList: {[key: string]: string};
|
|
|
|
|
|
constructor(props: INodeListComponentProps) {
|
|
|
super(props);
|
|
|
|
|
|
this.state = { filter: "" };
|
|
|
|
|
|
+ let frameJson = localStorage.getItem("Custom-Frame-List");
|
|
|
+ if(frameJson) {
|
|
|
+ this._customFrameList = JSON.parse(frameJson);
|
|
|
+ }
|
|
|
+
|
|
|
this._onResetRequiredObserver = this.props.globalState.onResetRequiredObservable.add(() => {
|
|
|
this.forceUpdate();
|
|
|
});
|
|
@@ -163,10 +175,56 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
|
|
|
this.setState({ filter: filter });
|
|
|
}
|
|
|
|
|
|
+ loadCustomFrame(file: File) {
|
|
|
+ Tools.ReadFile(file, async (data) => {
|
|
|
+ // get Frame Data from file
|
|
|
+ let decoder = new TextDecoder("utf-8");
|
|
|
+ const frameData = JSON.parse(decoder.decode(data));
|
|
|
+ let frameName = frameData.editorData.frames[0].name + "Custom";
|
|
|
+ let frameToolTip = frameData.editorData.frames[0].comments || "";
|
|
|
+
|
|
|
+ try {
|
|
|
+ localStorage.setItem(frameName, JSON.stringify(frameData));
|
|
|
+ } catch (error) {
|
|
|
+ this.props.globalState.onErrorMessageDialogRequiredObservable.notifyObservers("Error Saving Frame");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let frameJson = localStorage.getItem("Custom-Frame-List");
|
|
|
+ let frameList: {[key: string]: string} = {};
|
|
|
+ if(frameJson) {
|
|
|
+ frameList = JSON.parse(frameJson);
|
|
|
+ }
|
|
|
+ frameList[frameName] = frameToolTip;
|
|
|
+ localStorage.setItem("Custom-Frame-List", JSON.stringify(frameList));
|
|
|
+ this._customFrameList = frameList;
|
|
|
+ this.forceUpdate();
|
|
|
+
|
|
|
+ }, undefined, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ removeItem(value : string) : void {
|
|
|
+ let frameJson = localStorage.getItem("Custom-Frame-List");
|
|
|
+ if(frameJson) {
|
|
|
+ let frameList = JSON.parse(frameJson);
|
|
|
+ delete frameList[value];
|
|
|
+ localStorage.removeItem(value);
|
|
|
+ localStorage.setItem("Custom-Frame-List", JSON.stringify(frameList));
|
|
|
+ this._customFrameList = frameList;
|
|
|
+ this.forceUpdate();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
render() {
|
|
|
+
|
|
|
+ let customFrameNames: string[] = [];
|
|
|
+ for(let frame in this._customFrameList){
|
|
|
+ customFrameNames.push(frame);
|
|
|
+ }
|
|
|
+
|
|
|
// Block types used to create the menu from
|
|
|
const allBlocks = {
|
|
|
-
|
|
|
+ Custom_Frames: customFrameNames,
|
|
|
Animation: ["BonesBlock", "MorphTargetsBlock"],
|
|
|
Color_Management: ["ReplaceColorBlock", "PosterizeBlock", "GradientBlock", "DesaturateBlock"],
|
|
|
Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
|
|
@@ -211,18 +269,28 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
|
|
|
var blockList = (allBlocks as any)[key].filter((b: string) => !this.state.filter || b.toLowerCase().indexOf(this.state.filter.toLowerCase()) !== -1)
|
|
|
.sort((a: string, b: string) => a.localeCompare(b))
|
|
|
.map((block: any, i: number) => {
|
|
|
- let tooltip = NodeListComponent._Tooltips[block] || "";
|
|
|
+ if(key === "Custom_Frames") {
|
|
|
+ return <DraggableLineWithButtonComponent key={block} data={block} tooltip={this._customFrameList[block] || ""} iconImage={deleteButton} iconTitle="Delete"
|
|
|
+ onIconClick={ value => this.removeItem(value)}/>;
|
|
|
+ }
|
|
|
+ return <DraggableLineComponent key={block} data={block} tooltip={ NodeListComponent._Tooltips[block] || ""}/>;
|
|
|
|
|
|
- return <DraggableLineComponent key={block} data={block} tooltip={tooltip}/>;
|
|
|
});
|
|
|
|
|
|
- if (blockList.length) {
|
|
|
+ if(key === "Custom_Frames") {
|
|
|
+ let line = <LineWithFileButtonComponent title={"Add Custom Frame"} closed={false}
|
|
|
+ label="Add..." uploadName={'custom-frame-upload'} iconImage={addButton} accept=".json" onIconClick={(file) => {
|
|
|
+ this.loadCustomFrame(file);
|
|
|
+ }}/>;
|
|
|
+ blockList.push(line);
|
|
|
+ }
|
|
|
+ if(blockList.length) {
|
|
|
blockMenu.push(
|
|
|
<LineContainerComponent key={key + " blocks"} title={key.replace("__", ": ").replace("_", " ")} closed={false}>
|
|
|
{blockList}
|
|
|
</LineContainerComponent>
|
|
|
);
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return (
|
|
@@ -244,6 +312,5 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|
|
|
-
|
|
|
}
|
|
|
}
|