add Workspace

This commit is contained in:
zhandouxiaojiji committed 2020-11-04 20:16:14 +08:00
1 parent c4eb53ac68
commit 70cc4dca87
6 files changed
+220 -83

No files matched your search

+1
View File
@@ -1,5 +1,6 @@
export default {
OPEN_FILE: "OPEN_FILE",
OPEN_DIR: "OPEN_DIR",
OPEN_WORKSPACE: "OPEN_WORKSPACE",
CREATE_NODE: 'CREATE_NODE',
SAVE: 'SAVE',
+99 -49
View File
@@ -18,9 +18,9 @@ export default class AppMenu {
createMenu() {
const menu: Menu = new Menu();
menu.append(this.createWorkspaceMenu());
menu.append(this.createFileMenu());
menu.append(this.createNodeMenu());
menu.append(this.createSettingsMenu());
menu.append(this.createToolsMenu());
return menu;
}
@@ -35,15 +35,7 @@ export default class AppMenu {
}
})
}
const workspaceItems: MenuItemConstructorOptions[] = [];
for (let path of this.settings.recentWorkspaces) {
workspaceItems.push({
label: path,
click: () => {
console.log("open recent workspace", path);
}
})
}
return new MenuItem({
label: "行为树",
@@ -71,35 +63,12 @@ export default class AppMenu {
})();
}
},
{
label: "打开目录",
accelerator: "Ctrl+Shift+O",
click: () => {
(async () => {
const res = await dialog.showOpenDialog({
properties: ['openDirectory']
});
if (res.filePaths.length > 0) {
const path = res.filePaths[0];
if (this.settings.recentWorkspaces.indexOf(path) < 0) {
this.settings.recentWorkspaces.unshift(path);
this.settings.save();
this.mainProcess.rebuildMenu();
}
this.webContents.send(MainEventType.OPEN_WORKSPACE, path);
}
})();
}
},
{ type: 'separator' },
{
label: "最近打开",
submenu: fileItems,
},
{
label: "最近目录",
submenu: workspaceItems,
},
{ type: 'separator' },
{
label: "保存",
@@ -113,21 +82,95 @@ export default class AppMenu {
this.webContents.send(MainEventType.SAVE_ALL);
},
},
{ type: 'separator' },
{
label: "关闭",
click: () => {
app.quit();
}
}
]
});
}
private createSettingsMenu() {
private createWorkspaceMenu() {
const openWorkspace = (path: string) => {
this.settings.curWorkspace.setFilepath(path);
this.settings.curWorkspace.load();
this.settings.pushRecentWorkspace(path);
this.mainProcess.rebuildMenu();
this.webContents.send(MainEventType.OPEN_DIR, this.settings.curWorkspace.getWorkdir());
};
const recentItems: MenuItemConstructorOptions[] = [];
for (let path of this.settings.recentWorkspaces) {
recentItems.push({
label: path,
click: () => {
console.log("open recent workspace", path);
openWorkspace(path);
}
})
}
return new MenuItem({
label: "设置",
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 {
(async () => {
const res = await dialog.showSaveDialog({
properties: ['showOverwriteConfirmation'],
filters: [
{ name: "Json", extensions: ['json'] }
]
});
if (!res.canceled) {
this.settings.curWorkspace.setFilepath(res.filePath);
this.settings.curWorkspace.save();
}
})();
}
}
},
{
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 path = res.filePaths[0];
this.settings.curWorkspace.setWorkdir(path);
this.settings.curWorkspace.save();
this.webContents.send(MainEventType.OPEN_DIR, path);
}
})();
}
},
{
label: "节点定义",
submenu: [
@@ -143,15 +186,22 @@ export default class AppMenu {
});
if (res.filePaths.length > 0) {
const nodeConfigPath = res.filePaths[0];
this.settings.set({ nodeConfigPath });
this.settings.curWorkspace.setNodeConfPath(nodeConfigPath);
this.mainProcess.rebuildMenu();
}
})();
}
},
{ type: 'separator' },
{ label: this.settings.nodeConfigPath, }
{ label: this.settings.nodeConfPath, }
]
},
{ type: 'separator' },
{
label: "关闭",
click: () => {
app.quit();
}
}
]
});
@@ -207,7 +257,7 @@ export default class AppMenu {
}
}
let typeItem = map[node.type];
if(!typeItem) {
if (!typeItem) {
typeItem = other;
hasOther = true;
}
@@ -218,7 +268,7 @@ export default class AppMenu {
}
}
if(hasOther) {
if (hasOther) {
classifyItems.push(other);
}
@@ -227,9 +277,9 @@ export default class AppMenu {
click: () => {
this.webContents.send(MainEventType.CREATE_NODE, 'unknow');
}
}
}
classifyItems.push(unknonwItem);
return new MenuItem({
label: "新建节点",
submenu: classifyItems
+17 -18
View File
@@ -1,5 +1,6 @@
import * as fs from 'fs';
import { BehaviorNodeTypeModel } from '../common/BehaviorTreeModel';
import Workspace from './Workspace';
export interface BehaviorNodeClassify {
classify: string;
@@ -9,7 +10,6 @@ export interface BehaviorNodeClassify {
export interface SettingsModel {
recentWorkspaces?: string[];
recentFiles?: string[];
nodeConfigPath?: string; // 节点配置路径
nodeClassify?: BehaviorNodeClassify[];
}
@@ -22,21 +22,18 @@ const sampleNodeClassify: BehaviorNodeClassify[] = [
{ classify: "Action", desc: "行为节点" },
]
const unknowNodeType: BehaviorNodeTypeModel = {
name: 'unknow',
desc: '新建节点',
type: 'Action',
}
export default class Settings {
private settings: SettingsModel;
private name2conf: { [name: string]: BehaviorNodeTypeModel } = {};
curWorkspace?: Workspace;
constructor() {
this.load();
}
get nodeConfigPath() {
return this.settings.nodeConfigPath;
get nodeConfPath() {
return this.curWorkspace.getNodeConfPath();
}
get recentWorkspaces() {
return this.settings.recentWorkspaces;
@@ -45,13 +42,7 @@ export default class Settings {
return this.settings.recentFiles;
}
get nodeConfig() {
const str = fs.readFileSync(this.nodeConfigPath, 'utf8');
const types: BehaviorNodeTypeModel[] = JSON.parse(str);
this.name2conf = {};
types.forEach(t => {
this.name2conf[t.name] = t;
})
return types;
return this.curWorkspace.nodeConf;
}
get nodeClassify() {
return this.settings.nodeClassify;
@@ -73,11 +64,12 @@ export default class Settings {
this.settings = {
recentWorkspaces: [],
recentFiles: [],
nodeConfigPath: sampleNodeConfig,
nodeClassify: sampleNodeClassify,
};
this.save();
}
this.curWorkspace = new Workspace(this.settings.recentWorkspaces[0]);
this.curWorkspace.load();
}
save() {
@@ -85,6 +77,13 @@ export default class Settings {
}
getNodeConf(name: string) {
return this.name2conf[name] || unknowNodeType;
return this.curWorkspace.getNodeConf(name);
}
pushRecentWorkspace(path: string) {
if (this.settings.recentWorkspaces.indexOf(path) < 0) {
this.settings.recentWorkspaces.unshift(path);
}
this.save();
}
}
+90
View File
@@ -0,0 +1,90 @@
import * as fs from 'fs';
import { BehaviorNodeTypeModel } from '../common/BehaviorTreeModel';
const unknowNodeType: BehaviorNodeTypeModel = {
name: 'unknow',
desc: '新建节点',
type: 'Action',
}
export default class Workspace {
private filepath: string;
private nodeConfPath: string;
private workdir: string;
private name2conf: { [name: string]: BehaviorNodeTypeModel } = {};
private types: BehaviorNodeTypeModel[] = [];
constructor(filepath: string) {
this.filepath = filepath;
}
load() {
if(!this.filepath) {
return;
}
const str = fs.readFileSync(this.filepath, 'utf8');
const data = JSON.parse(str);
this.nodeConfPath = data.nodeConfPath;
this.workdir = data.workdir;
this.initNodeConf();
}
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;
}
getNodeConfPath() {
return this.nodeConfPath;
}
setNodeConfPath(path: string) {
this.nodeConfPath = path;
this.initNodeConf();
}
getWorkdir() {
return this.workdir;
}
setWorkdir(workdir: string) {
this.workdir = workdir;
}
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;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "behavior3editor",
"version": "0.0.3",
"version": "0.1.0",
"description": "行为树编辑器",
"main": "./dist/main.js",
"scripts": {
+12 -15
View File
@@ -23,12 +23,12 @@ const { TabPane } = Tabs;
interface MainState {
workspace: string;
workdir: string;
}
export default class Main extends Component {
state: MainState = {
workspace: '',
workdir: '',
}
settings: Settings;
@@ -44,17 +44,14 @@ export default class Main extends Component {
this.setState({ curPath: path });
});
ipcRenderer.on(MainEventType.OPEN_WORKSPACE, (event: any, workspace: any) => {
console.log("on open workspace", workspace);
document.title = workspace;
this.setState({ workspace });
ipcRenderer.on(MainEventType.OPEN_DIR, (event: any, workdir: any) => {
console.log("on open workspace", workdir);
document.title = workdir;
this.setState({ workdir });
});
this.setState({ workspace: this.getLastWorkspace() });
}
getLastWorkspace() {
return this.settings.recentWorkspaces[0];
console.log("workdir", this.settings.curWorkspace.getWorkdir());
this.setState({ workdir: this.settings.curWorkspace.getWorkdir() });
}
updateSettings() {
@@ -63,13 +60,13 @@ export default class Main extends Component {
render() {
console.log("render main");
const { workspace } = this.state;
document.title = `行为树编辑器 - ${workspace}`;
const { workdir } = this.state;
document.title = `行为树编辑器 - ${workdir}`;
return (
<Layout className="body">
<Sider className="sider" width={250}>
<Properties
workspace={this.state.workspace}
workspace={this.state.workdir}
onOpenTree={(path) => {
this.tabs.openFile(path);
}}
@@ -77,7 +74,7 @@ export default class Main extends Component {
</Sider>
<Content className="content">
<TreeTabs
ref = {ref => {
ref={ref => {
this.tabs = ref;
}}
/>