From 543c5b09c35fa528e175a5a2c9542bc63307e542 Mon Sep 17 00:00:00 2001 From: codetypes Date: Wed, 24 Apr 2024 22:33:57 +0800 Subject: [PATCH] support group by type for node def --- behavior3editor.code-workspace | 19 +++--- sample/node-config.b3-setting | 4 +- src/components/explorer.tsx | 99 ++++++++++++++++++++----------- src/components/inspector.tsx | 9 +++ src/components/register-node.ts | 12 +++- src/contexts/workspace-context.ts | 37 +----------- src/misc/b3type.ts | 18 +++++- 7 files changed, 110 insertions(+), 88 deletions(-) diff --git a/behavior3editor.code-workspace b/behavior3editor.code-workspace index 5c6e990..38d027f 100644 --- a/behavior3editor.code-workspace +++ b/behavior3editor.code-workspace @@ -1,14 +1,11 @@ { - "folders": [ - { - "path": "." - } - ], - "settings": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "[json]": { - "editor.formatOnSave": false - } + "folders": [ + { + "path": "." } + ], + "settings": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/sample/node-config.b3-setting b/sample/node-config.b3-setting index ce58d1f..cab684b 100644 --- a/sample/node-config.b3-setting +++ b/sample/node-config.b3-setting @@ -124,7 +124,7 @@ }, { "name": "MoveToPos", - "type": "Action", + "type": "Action (Client)", "args": [ { "name": "x", @@ -141,7 +141,7 @@ }, { "name": "MoveToTarget", - "type": "Action", + "type": "Action (Server)", "input": [ "{目标}" ], diff --git a/src/components/explorer.tsx b/src/components/explorer.tsx index e73d3c8..1c0ea54 100644 --- a/src/components/explorer.tsx +++ b/src/components/explorer.tsx @@ -1,4 +1,5 @@ import { FileTreeType, useWorkspace } from "@/contexts/workspace-context"; +import { NodeDef, getNodeType } from "@/misc/b3type"; import * as b3util from "@/misc/b3util"; import { modal } from "@/misc/hooks"; import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys"; @@ -31,6 +32,15 @@ type MenuEvent = | "move" | "duplicate"; +export type NodeTreeType = { + title: string; + def?: NodeDef; + icon?: React.ReactNode; + isLeaf?: boolean; + children?: NodeTreeType[]; + style?: React.CSSProperties; +}; + const findFile = (path: string | undefined, node: FileTreeType): FileTreeType | undefined => { if (!path) { return; @@ -112,7 +122,6 @@ export const Explorer: FC = () => { editors: useWorkspace((state) => state.editors), fileTree: useWorkspace((state) => state.fileTree), nodeDefs: useWorkspace((state) => state.nodeDefs), - nodeTree: useWorkspace((state) => state.nodeTree), workdir: useWorkspace((state) => state.workdir), onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef), open: useWorkspace((state) => state.open), @@ -134,49 +143,69 @@ export const Explorer: FC = () => { ); } - if (workspace.nodeTree) { - workspace.nodeTree.title = t("nodeDefinition"); - workspace.nodeTree.icon = ( - - - - ); - workspace.nodeTree.children?.forEach((catalog) => { - catalog.icon = ( + const nodeTree = useMemo(() => { + const data: NodeTreeType = { + title: t("nodeDefinition"), + icon: ( - + - ); - catalog.children?.forEach((node) => { - if (node.def?.icon) { - node.icon = ( + ), + children: [], + style: { + fontWeight: "bold", + fontSize: "13px", + }, + }; + workspace.nodeDefs.forEach((nodeDef) => { + let catalog = data.children?.find((nt) => nt.title === nodeDef.type); + if (!catalog) { + const type = getNodeType(nodeDef); + catalog = { + title: nodeDef.type, + children: [], + icon: ( - ); - } else { - node.icon = ( - - {" "} - - ); - } + ), + }; + data.children?.push(catalog); + } + catalog.children?.push({ + title: `${nodeDef.name}(${nodeDef.desc})`, + isLeaf: true, + def: nodeDef, + icon: nodeDef.icon ? ( + + + + ) : ( + + {" "} + + ), }); }); - } + data.children?.sort((a, b) => a.title.localeCompare(b.title)); + data.children?.forEach((child) => + child.children?.sort((a, b) => a.title.localeCompare(b.title)) + ); + return data; + }, [t, workspace.nodeDefs]); useEffect(() => { if (workspace.editing) { @@ -795,7 +824,7 @@ export const Explorer: FC = () => { !!node.isLeaf }} onSelect={(_, info) => { const node = info.node; diff --git a/src/components/inspector.tsx b/src/components/inspector.tsx index d8d5818..d3c0257 100644 --- a/src/components/inspector.tsx +++ b/src/components/inspector.tsx @@ -80,6 +80,7 @@ const NodeInspector: FC = () => { form.resetFields(); form.setFieldValue("id", data.id); form.setFieldValue("name", data.name); + form.setFieldValue("type", def.type); form.setFieldValue("desc", data.desc); form.setFieldValue("debug", data.debug); form.setFieldValue("path", data.path); @@ -227,6 +228,14 @@ const NodeInspector: FC = () => { > + {t("node.type")} + } + > + + ((set, get) => ({ loadNodeDefs: () => { const workspace = get(); const nodeDefData = readJson(`${workspace.workdir}/node-config.b3-setting`) as NodeDef[]; - const nodeTree: NodeTreeType = { - title: i18n.t("nodeDefinition"), - children: [], - style: { - fontWeight: "bold", - fontSize: "13px", - }, - }; const nodeDefs: Map = new Map(); for (const v of nodeDefData) { nodeDefs.set(v.name, v); - let catalog = nodeTree.children?.find((nt) => nt.title === v.type); - if (!catalog) { - catalog = { - title: v.type, - children: [], - }; - nodeTree.children?.push(catalog); - } - catalog.children?.push({ - title: `${v.name}(${v.desc})`, - isLeaf: true, - def: v, - }); } - nodeTree.children?.sort((a, b) => a.title.localeCompare(b.title)); - nodeTree.children?.forEach((child) => - child.children?.sort((a, b) => a.title.localeCompare(b.title)) - ); - set({ nodeDefs, nodeTree }); + set({ nodeDefs }); workspace.editing?.dispatch?.("reload"); }, diff --git a/src/misc/b3type.ts b/src/misc/b3type.ts index 3b0cc82..749724b 100644 --- a/src/misc/b3type.ts +++ b/src/misc/b3type.ts @@ -1,6 +1,7 @@ import { TreeGraphData as G6TreeGraphData } from "@antv/g6"; export type NodeArgType = "string" | "int" | "float" | "boolean" | "enum" | "code"; +export type NodeType = "Action" | "Composite" | "Decorator" | "Condition" | "Other" | "Error"; export interface NodeArgOption { name: string; @@ -16,7 +17,7 @@ export interface NodeArg { } export interface NodeDef { name: string; - type: string; + type: NodeType; desc?: string; args?: NodeArg[]; input?: string[]; @@ -67,3 +68,18 @@ export const unknownNodeDef: NodeDef = { desc: "新建节点", type: "Action", }; + +export const getNodeType = (def: NodeDef): NodeType => { + const type = def.type.toLocaleLowerCase().toString(); + if (type.startsWith("action")) { + return "Action"; + } else if (type.startsWith("composite")) { + return "Composite"; + } else if (type.startsWith("decorator")) { + return "Decorator"; + } else if (type.startsWith("condition")) { + return "Condition"; + } else { + return "Other"; + } +};