feat: export all trees to single json file support
This commit is contained in:
1 parent
f8cefaec6b
commit
637fd4a6f8
2 files changed
+473
-412
No files matched your search
+356
-326
@@ -1,345 +1,375 @@
|
|||||||
import { Menu, app, dialog, BrowserWindow, MenuItem, WebContents, MenuItemConstructorOptions } from 'electron';
|
import {
|
||||||
import * as fs from 'fs';
|
Menu,
|
||||||
import * as Utils from '../common/Utils';
|
app,
|
||||||
import MainEventType from '../common/MainEventType';
|
dialog,
|
||||||
import { MainProcess } from './MainProcess';
|
BrowserWindow,
|
||||||
import Settings from './Settings';
|
MenuItem,
|
||||||
|
WebContents,
|
||||||
|
MenuItemConstructorOptions,
|
||||||
|
} from "electron";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as Utils from "../common/Utils";
|
||||||
|
import MainEventType from "../common/MainEventType";
|
||||||
|
import { MainProcess } from "./MainProcess";
|
||||||
|
import Settings from "./Settings";
|
||||||
|
|
||||||
export default class AppMenu {
|
export default class AppMenu {
|
||||||
private mainProcess: MainProcess;
|
private mainProcess: MainProcess;
|
||||||
private mainWindow: BrowserWindow;
|
private mainWindow: BrowserWindow;
|
||||||
private webContents: WebContents;
|
private webContents: WebContents;
|
||||||
private settings: Settings;
|
private settings: Settings;
|
||||||
|
|
||||||
constructor(mainProcess: MainProcess) {
|
constructor(mainProcess: MainProcess) {
|
||||||
this.mainProcess = mainProcess;
|
this.mainProcess = mainProcess;
|
||||||
this.mainWindow = mainProcess.mainWindow;
|
this.mainWindow = mainProcess.mainWindow;
|
||||||
this.webContents = mainProcess.mainWindow.webContents;
|
this.webContents = mainProcess.mainWindow.webContents;
|
||||||
this.settings = mainProcess.settings;
|
this.settings = mainProcess.settings;
|
||||||
}
|
|
||||||
|
|
||||||
createMenu() {
|
|
||||||
const menu: Menu = new Menu();
|
|
||||||
menu.append(this.createWorkspaceMenu());
|
|
||||||
menu.append(this.createFileMenu());
|
|
||||||
menu.append(this.createNodeMenu());
|
|
||||||
menu.append(this.createToolsMenu());
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
private createFileMenu() {
|
|
||||||
const fileItems: MenuItemConstructorOptions[] = [];
|
|
||||||
for (let path of this.settings.recentFiles) {
|
|
||||||
fileItems.push({
|
|
||||||
label: path,
|
|
||||||
click: () => {
|
|
||||||
console.log("open recent file", path);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createMenu() {
|
||||||
|
const menu: Menu = new Menu();
|
||||||
|
menu.append(this.createWorkspaceMenu());
|
||||||
|
menu.append(this.createFileMenu());
|
||||||
|
menu.append(this.createNodeMenu());
|
||||||
|
menu.append(this.createToolsMenu());
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
return new MenuItem({
|
private createFileMenu() {
|
||||||
label: "行为树",
|
const fileItems: MenuItemConstructorOptions[] = [];
|
||||||
submenu: [
|
for (let path of this.settings.recentFiles) {
|
||||||
{
|
fileItems.push({
|
||||||
label: "新建",
|
label: path,
|
||||||
accelerator: 'ctrl+n',
|
click: () => {
|
||||||
click: () => {
|
console.log("open recent file", path);
|
||||||
(async () => {
|
},
|
||||||
const res = await dialog.showSaveDialog({
|
});
|
||||||
properties: ['showOverwriteConfirmation'],
|
|
||||||
filters: [
|
|
||||||
{ name: "Json", extensions: ['json'] }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
if (!res.canceled) {
|
|
||||||
const path = res.filePath;
|
|
||||||
fs.writeFileSync(path, JSON.stringify(Utils.createNewTree(path), null, 2));
|
|
||||||
this.webContents.send(MainEventType.CREATE_TREE, path);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "打开文件",
|
|
||||||
accelerator: "Ctrl+O",
|
|
||||||
click: () => {
|
|
||||||
(async () => {
|
|
||||||
const res = await dialog.showOpenDialog({
|
|
||||||
properties: ['openFile'],
|
|
||||||
filters: [
|
|
||||||
{ name: "Json", extensions: ['json'] }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
if (res.filePaths.length > 0) {
|
|
||||||
const path = res.filePaths[0];
|
|
||||||
if (this.settings.recentFiles.indexOf(path) < 0) {
|
|
||||||
this.settings.recentFiles.unshift(path);
|
|
||||||
this.settings.save();
|
|
||||||
this.mainProcess.rebuildMenu();
|
|
||||||
}
|
|
||||||
this.webContents.send(MainEventType.OPEN_FILE, path);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: "最近打开",
|
|
||||||
submenu: fileItems,
|
|
||||||
},
|
|
||||||
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: "保存",
|
|
||||||
accelerator: 'ctrl+s',
|
|
||||||
click: () => {
|
|
||||||
this.webContents.send(MainEventType.SAVE);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "全部保存",
|
|
||||||
accelerator: 'ctrl+shift+s',
|
|
||||||
click: () => {
|
|
||||||
this.webContents.send(MainEventType.SAVE_ALL);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: '新建节点',
|
|
||||||
accelerator: 'insert',
|
|
||||||
click: () => {
|
|
||||||
this.webContents.send(MainEventType.CREATE_NODE, 'unknow');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '删除节点',
|
|
||||||
accelerator: 'delete',
|
|
||||||
click: () => {
|
|
||||||
this.webContents.send(MainEventType.DELETE_NODE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: '复制节点',
|
|
||||||
accelerator: 'ctrl+c',
|
|
||||||
role: 'copy',
|
|
||||||
click: () => {
|
|
||||||
this.webContents.send(MainEventType.COPY_NODE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '粘贴节点',
|
|
||||||
accelerator: 'ctrl+v',
|
|
||||||
click: () => {
|
|
||||||
this.webContents.send(MainEventType.PASTE_NODE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private createWorkspaceMenu() {
|
return new MenuItem({
|
||||||
const openWorkspace = (path: string) => {
|
label: "行为树",
|
||||||
const curWorkspace = this.settings.curWorkspace;
|
submenu: [
|
||||||
curWorkspace.setFilepath(path);
|
{
|
||||||
curWorkspace.load();
|
label: "新建",
|
||||||
this.settings.pushRecentWorkspace(path);
|
accelerator: "ctrl+n",
|
||||||
this.mainProcess.rebuildMenu();
|
click: () => {
|
||||||
this.webContents.send(MainEventType.OPEN_DIR, curWorkspace.getWorkdir(), curWorkspace.getFilepath());
|
(async () => {
|
||||||
};
|
const res = await dialog.showSaveDialog({
|
||||||
const saveToNewPath = () => {
|
properties: ["showOverwriteConfirmation"],
|
||||||
(async () => {
|
filters: [{ name: "Json", extensions: ["json"] }],
|
||||||
const res = await dialog.showSaveDialog({
|
});
|
||||||
properties: ['showOverwriteConfirmation'],
|
if (!res.canceled) {
|
||||||
filters: [
|
const path = res.filePath;
|
||||||
{ name: "Json", extensions: ['json'] }
|
fs.writeFileSync(
|
||||||
]
|
path,
|
||||||
|
JSON.stringify(Utils.createNewTree(path), null, 2)
|
||||||
|
);
|
||||||
|
this.webContents.send(MainEventType.CREATE_TREE, path);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "打开文件",
|
||||||
|
accelerator: "Ctrl+O",
|
||||||
|
click: () => {
|
||||||
|
(async () => {
|
||||||
|
const res = await dialog.showOpenDialog({
|
||||||
|
properties: ["openFile"],
|
||||||
|
filters: [{ name: "Json", extensions: ["json"] }],
|
||||||
|
});
|
||||||
|
if (res.filePaths.length > 0) {
|
||||||
|
const path = res.filePaths[0];
|
||||||
|
if (this.settings.recentFiles.indexOf(path) < 0) {
|
||||||
|
this.settings.recentFiles.unshift(path);
|
||||||
|
this.settings.save();
|
||||||
|
this.mainProcess.rebuildMenu();
|
||||||
|
}
|
||||||
|
this.webContents.send(MainEventType.OPEN_FILE, path);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: "最近打开",
|
||||||
|
submenu: fileItems,
|
||||||
|
},
|
||||||
|
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: "保存",
|
||||||
|
accelerator: "ctrl+s",
|
||||||
|
click: () => {
|
||||||
|
this.webContents.send(MainEventType.SAVE);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "全部保存",
|
||||||
|
accelerator: "ctrl+shift+s",
|
||||||
|
click: () => {
|
||||||
|
this.webContents.send(MainEventType.SAVE_ALL);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "合并导出Json",
|
||||||
|
click: () => {
|
||||||
|
(async () => {
|
||||||
|
const res = await dialog.showSaveDialog({
|
||||||
|
properties: ["showOverwriteConfirmation"],
|
||||||
|
filters: [{ name: "Json", extensions: ["json"] }],
|
||||||
|
});
|
||||||
|
if (res.filePath) {
|
||||||
|
const curWorkspace = this.settings.curWorkspace;
|
||||||
|
curWorkspace.writeAllTrees(res.filePath,(err)=>{
|
||||||
|
const msg = err?err:"导出成功";
|
||||||
|
dialog.showMessageBox({
|
||||||
|
type:"info",
|
||||||
|
buttons:["ok"],
|
||||||
|
message:msg
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: "新建节点",
|
||||||
|
accelerator: "insert",
|
||||||
|
click: () => {
|
||||||
|
this.webContents.send(MainEventType.CREATE_NODE, "unknow");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "删除节点",
|
||||||
|
accelerator: "delete",
|
||||||
|
click: () => {
|
||||||
|
this.webContents.send(MainEventType.DELETE_NODE);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: "复制节点",
|
||||||
|
accelerator: "ctrl+c",
|
||||||
|
role: "copy",
|
||||||
|
click: () => {
|
||||||
|
this.webContents.send(MainEventType.COPY_NODE);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "粘贴节点",
|
||||||
|
accelerator: "ctrl+v",
|
||||||
|
click: () => {
|
||||||
|
this.webContents.send(MainEventType.PASTE_NODE);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
if (!res.canceled) {
|
|
||||||
this.settings.curWorkspace.setFilepath(res.filePath);
|
|
||||||
this.settings.curWorkspace.save();
|
|
||||||
openWorkspace(res.filePath);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
const recentItems: MenuItemConstructorOptions[] = [];
|
|
||||||
for (let path of this.settings.recentWorkspaces) {
|
private createWorkspaceMenu() {
|
||||||
recentItems.push({
|
const openWorkspace = (path: string) => {
|
||||||
label: path,
|
const curWorkspace = this.settings.curWorkspace;
|
||||||
click: () => {
|
curWorkspace.setFilepath(path);
|
||||||
console.log("open recent workspace", path);
|
curWorkspace.load();
|
||||||
openWorkspace(path);
|
this.settings.pushRecentWorkspace(path);
|
||||||
}
|
this.mainProcess.rebuildMenu();
|
||||||
})
|
this.webContents.send(
|
||||||
}
|
MainEventType.OPEN_DIR,
|
||||||
return new MenuItem({
|
curWorkspace.getWorkdir(),
|
||||||
label: "工作区",
|
curWorkspace.getFilepath()
|
||||||
submenu: [
|
);
|
||||||
{
|
};
|
||||||
label: "打开",
|
const saveToNewPath = () => {
|
||||||
click: () => {
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const res = await dialog.showOpenDialog({
|
const res = await dialog.showSaveDialog({
|
||||||
properties: ['openFile'],
|
properties: ["showOverwriteConfirmation"],
|
||||||
filters: [
|
filters: [{ name: "Json", extensions: ["json"] }],
|
||||||
{ name: "Json", extensions: ['json'] }
|
});
|
||||||
]
|
if (!res.canceled) {
|
||||||
});
|
this.settings.curWorkspace.setFilepath(res.filePath);
|
||||||
if (res.filePaths.length > 0) {
|
this.settings.curWorkspace.save();
|
||||||
openWorkspace(res.filePaths[0]);
|
openWorkspace(res.filePath);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
};
|
||||||
},
|
const recentItems: MenuItemConstructorOptions[] = [];
|
||||||
{
|
for (let path of this.settings.recentWorkspaces) {
|
||||||
label: "保存",
|
recentItems.push({
|
||||||
click: () => {
|
label: path,
|
||||||
if (this.settings.curWorkspace.getFilepath()) {
|
click: () => {
|
||||||
this.settings.curWorkspace.save();
|
console.log("open recent workspace", path);
|
||||||
|
openWorkspace(path);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new MenuItem({
|
||||||
|
label: "工作区",
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: "打开",
|
||||||
|
click: () => {
|
||||||
|
(async () => {
|
||||||
|
const res = await dialog.showOpenDialog({
|
||||||
|
properties: ["openFile"],
|
||||||
|
filters: [{ name: "Json", extensions: ["json"] }],
|
||||||
|
});
|
||||||
|
if (res.filePaths.length > 0) {
|
||||||
|
openWorkspace(res.filePaths[0]);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "保存",
|
||||||
|
click: () => {
|
||||||
|
if (this.settings.curWorkspace.getFilepath()) {
|
||||||
|
this.settings.curWorkspace.save();
|
||||||
|
} else {
|
||||||
|
saveToNewPath();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "另存为",
|
||||||
|
click: () => {
|
||||||
|
saveToNewPath();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "最近打开",
|
||||||
|
submenu: recentItems,
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: "打开目录",
|
||||||
|
accelerator: "Ctrl+Shift+O",
|
||||||
|
click: () => {
|
||||||
|
if (!this.settings.curWorkspace.getNodeConfPath()) {
|
||||||
|
dialog.showErrorBox("警告", "请先指定节点定义配置!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(async () => {
|
||||||
|
const res = await dialog.showOpenDialog({
|
||||||
|
properties: ["openDirectory"],
|
||||||
|
});
|
||||||
|
if (res.filePaths.length > 0) {
|
||||||
|
const curWorkspace = this.settings.curWorkspace;
|
||||||
|
const path = res.filePaths[0];
|
||||||
|
curWorkspace.setWorkdir(path);
|
||||||
|
curWorkspace.save();
|
||||||
|
this.webContents.send(
|
||||||
|
MainEventType.OPEN_DIR,
|
||||||
|
path,
|
||||||
|
curWorkspace.getFilepath()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "节点定义",
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: "选择文件",
|
||||||
|
click: () => {
|
||||||
|
(async () => {
|
||||||
|
const res = await dialog.showOpenDialog({
|
||||||
|
properties: ["openFile"],
|
||||||
|
filters: [{ name: "Json", extensions: ["json"] }],
|
||||||
|
});
|
||||||
|
if (res.filePaths.length > 0) {
|
||||||
|
const nodeConfigPath = res.filePaths[0];
|
||||||
|
this.settings.curWorkspace.setNodeConfPath(nodeConfigPath);
|
||||||
|
this.mainProcess.rebuildMenu();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{ label: this.settings.nodeConfPath },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: "关闭",
|
||||||
|
click: () => {
|
||||||
|
app.quit();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createToolsMenu() {
|
||||||
|
return new MenuItem({
|
||||||
|
label: "开发工具",
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: "打开控制台",
|
||||||
|
accelerator: "Ctrl+Shift+I",
|
||||||
|
click: (_, browserWindow) => {
|
||||||
|
browserWindow.webContents.toggleDevTools();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "重载",
|
||||||
|
accelerator: "Ctrl+R",
|
||||||
|
click: (_, browserWindow) => {
|
||||||
|
browserWindow.reload();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createNodeMenu() {
|
||||||
|
const classifyItems: MenuItemConstructorOptions[] = [];
|
||||||
|
const map: { [key: string]: MenuItemConstructorOptions } = {};
|
||||||
|
for (let t of this.settings.nodeClassify) {
|
||||||
|
let item: MenuItemConstructorOptions = {
|
||||||
|
id: t.classify,
|
||||||
|
label: `${t.classify}(${t.desc})`,
|
||||||
|
submenu: [],
|
||||||
|
};
|
||||||
|
classifyItems.push(item);
|
||||||
|
map[t.classify] = item;
|
||||||
|
}
|
||||||
|
const other: MenuItemConstructorOptions = {
|
||||||
|
id: "other",
|
||||||
|
label: "其它",
|
||||||
|
submenu: [],
|
||||||
|
};
|
||||||
|
var hasOther = false;
|
||||||
|
|
||||||
|
for (let node of this.settings.nodeConfig) {
|
||||||
|
const item: MenuItemConstructorOptions = {
|
||||||
|
label: `${node.name}(${node.desc})`,
|
||||||
|
click: () => {
|
||||||
|
console.log("create node", node.name);
|
||||||
|
this.webContents.send(MainEventType.CREATE_NODE, node.name);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let typeItem = map[node.type];
|
||||||
|
if (!typeItem) {
|
||||||
|
typeItem = other;
|
||||||
|
hasOther = true;
|
||||||
|
}
|
||||||
|
if (typeItem.submenu instanceof Menu) {
|
||||||
|
console.log("typeItem.submenu error", typeItem);
|
||||||
} else {
|
} else {
|
||||||
saveToNewPath();
|
typeItem.submenu.push(item);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '另存为',
|
|
||||||
click: () => {
|
|
||||||
saveToNewPath();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "最近打开",
|
|
||||||
submenu: recentItems,
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: "打开目录",
|
|
||||||
accelerator: "Ctrl+Shift+O",
|
|
||||||
click: () => {
|
|
||||||
if (!this.settings.curWorkspace.getNodeConfPath()) {
|
|
||||||
dialog.showErrorBox("警告", "请先指定节点定义配置!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(async () => {
|
|
||||||
const res = await dialog.showOpenDialog({
|
|
||||||
properties: ['openDirectory']
|
|
||||||
});
|
|
||||||
if (res.filePaths.length > 0) {
|
|
||||||
const curWorkspace = this.settings.curWorkspace;
|
|
||||||
const path = res.filePaths[0];
|
|
||||||
curWorkspace.setWorkdir(path);
|
|
||||||
curWorkspace.save();
|
|
||||||
this.webContents.send(MainEventType.OPEN_DIR, path, curWorkspace.getFilepath());
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "节点定义",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: "选择文件",
|
|
||||||
click: () => {
|
|
||||||
(async () => {
|
|
||||||
const res = await dialog.showOpenDialog({
|
|
||||||
properties: ['openFile'],
|
|
||||||
filters: [
|
|
||||||
{ name: "Json", extensions: ['json'] }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
if (res.filePaths.length > 0) {
|
|
||||||
const nodeConfigPath = res.filePaths[0];
|
|
||||||
this.settings.curWorkspace.setNodeConfPath(nodeConfigPath);
|
|
||||||
this.mainProcess.rebuildMenu();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{ label: this.settings.nodeConfPath, }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: "关闭",
|
|
||||||
click: () => {
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private createToolsMenu() {
|
if (hasOther) {
|
||||||
return new MenuItem({
|
classifyItems.push(other);
|
||||||
label: "开发工具",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: "打开控制台",
|
|
||||||
accelerator: "Ctrl+Shift+I",
|
|
||||||
click: (_, browserWindow) => {
|
|
||||||
browserWindow.webContents.toggleDevTools();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "重载",
|
|
||||||
accelerator: "Ctrl+R",
|
|
||||||
click: (_, browserWindow) => {
|
|
||||||
browserWindow.reload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private createNodeMenu() {
|
|
||||||
const classifyItems: MenuItemConstructorOptions[] = [];
|
|
||||||
const map: { [key: string]: MenuItemConstructorOptions } = {}
|
|
||||||
for (let t of this.settings.nodeClassify) {
|
|
||||||
let item: MenuItemConstructorOptions = {
|
|
||||||
id: t.classify,
|
|
||||||
label: `${t.classify}(${t.desc})`,
|
|
||||||
submenu: [],
|
|
||||||
};
|
|
||||||
classifyItems.push(item);
|
|
||||||
map[t.classify] = item;
|
|
||||||
}
|
|
||||||
const other: MenuItemConstructorOptions = {
|
|
||||||
id: 'other',
|
|
||||||
label: "其它",
|
|
||||||
submenu: [],
|
|
||||||
};
|
|
||||||
var hasOther = false;
|
|
||||||
|
|
||||||
for (let node of this.settings.nodeConfig) {
|
|
||||||
const item: MenuItemConstructorOptions = {
|
|
||||||
label: `${node.name}(${node.desc})`,
|
|
||||||
click: () => {
|
|
||||||
console.log("create node", node.name);
|
|
||||||
this.webContents.send(MainEventType.CREATE_NODE, node.name);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let typeItem = map[node.type];
|
|
||||||
if (!typeItem) {
|
|
||||||
typeItem = other;
|
|
||||||
hasOther = true;
|
|
||||||
}
|
|
||||||
if (typeItem.submenu instanceof Menu) {
|
|
||||||
console.log("typeItem.submenu error", typeItem);
|
|
||||||
} else {
|
|
||||||
typeItem.submenu.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasOther) {
|
return new MenuItem({
|
||||||
classifyItems.push(other);
|
label: "新建节点",
|
||||||
|
submenu: classifyItems,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new MenuItem({
|
|
||||||
label: "新建节点",
|
|
||||||
submenu: classifyItems
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+117
-86
@@ -1,6 +1,7 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from "fs";
|
||||||
import * as path from 'path';
|
import { BehaviorNodeTypeModel } from "../common/BehaviorTreeModel";
|
||||||
import { BehaviorNodeTypeModel } from '../common/BehaviorTreeModel';
|
import * as glob from "glob";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
export interface WorkspaceModel {
|
export interface WorkspaceModel {
|
||||||
isRelative?: boolean;
|
isRelative?: boolean;
|
||||||
@@ -9,98 +10,128 @@ export interface WorkspaceModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const unknowNodeType: BehaviorNodeTypeModel = {
|
const unknowNodeType: BehaviorNodeTypeModel = {
|
||||||
name: 'unknow',
|
name: "unknow",
|
||||||
desc: '新建节点',
|
desc: "新建节点",
|
||||||
type: 'Action',
|
type: "Action",
|
||||||
}
|
};
|
||||||
|
|
||||||
export default class Workspace {
|
export default class Workspace {
|
||||||
private filepath: string;
|
private filepath: string;
|
||||||
private nodeConfPath: string;
|
private nodeConfPath: string;
|
||||||
private workdir: string;
|
private workdir: string;
|
||||||
|
|
||||||
private name2conf: { [name: string]: BehaviorNodeTypeModel } = {};
|
private name2conf: { [name: string]: BehaviorNodeTypeModel } = {};
|
||||||
private types: BehaviorNodeTypeModel[] = [];
|
private types: BehaviorNodeTypeModel[] = [];
|
||||||
|
|
||||||
constructor(filepath: string) {
|
constructor(filepath: string) {
|
||||||
this.filepath = filepath;
|
this.filepath = filepath;
|
||||||
}
|
|
||||||
|
|
||||||
load() {
|
|
||||||
if (!this.filepath) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const str = fs.readFileSync(this.filepath, 'utf8');
|
|
||||||
const model = JSON.parse(str) as WorkspaceModel;
|
|
||||||
if (model.isRelative) {
|
|
||||||
const root = path.dirname(this.filepath);
|
|
||||||
this.nodeConfPath = root + '/' + model.nodeConfPath;
|
|
||||||
this.workdir = root + '/' + model.workdir;
|
|
||||||
} else {
|
|
||||||
this.nodeConfPath = model.nodeConfPath;
|
|
||||||
this.workdir = model.workdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initNodeConf();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private initNodeConf() {
|
|
||||||
if (!this.nodeConfPath) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const types: BehaviorNodeTypeModel[] = JSON.parse(fs.readFileSync(this.nodeConfPath, 'utf8'));
|
load() {
|
||||||
this.name2conf = {};
|
if (!this.filepath) {
|
||||||
types.forEach(t => {
|
return;
|
||||||
this.name2conf[t.name] = t;
|
}
|
||||||
})
|
try {
|
||||||
this.types = types;
|
const str = fs.readFileSync(this.filepath, 'utf8');
|
||||||
}
|
const model = JSON.parse(str) as WorkspaceModel;
|
||||||
|
if (model.isRelative) {
|
||||||
getNodeConfPath() {
|
const root = path.dirname(this.filepath);
|
||||||
return this.nodeConfPath;
|
this.nodeConfPath = root + '/' + model.nodeConfPath;
|
||||||
}
|
this.workdir = root + '/' + model.workdir;
|
||||||
setNodeConfPath(path: string) {
|
} else {
|
||||||
this.nodeConfPath = path;
|
this.nodeConfPath = model.nodeConfPath;
|
||||||
this.initNodeConf();
|
this.workdir = model.workdir;
|
||||||
}
|
}
|
||||||
getWorkdir() {
|
|
||||||
return this.workdir;
|
this.initNodeConf();
|
||||||
}
|
} catch (error) {
|
||||||
setWorkdir(workdir: string) {
|
console.log(error);
|
||||||
this.workdir = workdir;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
save(filepath?: string) {
|
|
||||||
if (filepath) {
|
|
||||||
this.filepath = filepath;
|
|
||||||
}
|
}
|
||||||
if (!this.filepath) {
|
|
||||||
return;
|
private initNodeConf() {
|
||||||
|
if (!this.nodeConfPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const types: BehaviorNodeTypeModel[] = JSON.parse(fs.readFileSync(this.nodeConfPath, 'utf8'));
|
||||||
|
this.name2conf = {};
|
||||||
|
types.forEach(t => {
|
||||||
|
this.name2conf[t.name] = t;
|
||||||
|
})
|
||||||
|
this.types = types;
|
||||||
}
|
}
|
||||||
fs.writeFileSync(this.filepath, JSON.stringify({
|
|
||||||
nodeConfPath: this.nodeConfPath,
|
|
||||||
workdir: this.workdir,
|
|
||||||
}, null, 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
get nodeConf() {
|
getNodeConfPath() {
|
||||||
return this.types;
|
return this.nodeConfPath;
|
||||||
}
|
}
|
||||||
|
setNodeConfPath(path: string) {
|
||||||
|
this.nodeConfPath = path;
|
||||||
|
this.initNodeConf();
|
||||||
|
}
|
||||||
|
getWorkdir(): string {
|
||||||
|
return this.workdir;
|
||||||
|
}
|
||||||
|
setWorkdir(workdir: string) {
|
||||||
|
this.workdir = workdir;
|
||||||
|
}
|
||||||
|
|
||||||
getFilepath() {
|
writeAllTrees(outFilePath: string, cb?: (err: string) => void) {
|
||||||
return this.filepath;
|
if (!fs.existsSync(this.getWorkdir())) {
|
||||||
}
|
cb && cb("请先打开工作区");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glob.glob(path.join(this.getWorkdir(), "**/*.json"), function (err, files) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
cb && cb(err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setFilepath(filepath: string) {
|
let result = new Array();
|
||||||
this.filepath = filepath;
|
files.forEach((file) => {
|
||||||
}
|
const data = fs.readFileSync(file, "utf8");
|
||||||
|
result.push(JSON.parse(data));
|
||||||
|
});
|
||||||
|
|
||||||
getNodeConf(name: string) {
|
fs.writeFileSync(outFilePath, JSON.stringify(result, null, 2));
|
||||||
return this.name2conf[name] || unknowNodeType;
|
cb && cb(null);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save(filepath?: string) {
|
||||||
|
if (filepath) {
|
||||||
|
this.filepath = filepath;
|
||||||
|
}
|
||||||
|
if (!this.filepath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs.writeFileSync(
|
||||||
|
this.filepath,
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
nodeConfPath: this.nodeConfPath,
|
||||||
|
workdir: this.workdir,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get nodeConf() {
|
||||||
|
return this.types;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilepath() {
|
||||||
|
return this.filepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilepath(filepath: string) {
|
||||||
|
this.filepath = filepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeConf(name: string) {
|
||||||
|
return this.name2conf[name] || unknowNodeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user