support group by type for node def

This commit is contained in:
codetypes committed 2024-04-24 22:33:57 +08:00
1 parent be509bed9e
commit 543c5b09c3
7 files changed
+90 -68

No files matched your search

+1 -4
View File
@@ -6,9 +6,6 @@
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[json]": {
"editor.formatOnSave": false
}
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
+2 -2
View File
@@ -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": [
"{目标}"
],
+51 -22
View File
@@ -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,26 +143,44 @@ export const Explorer: FC = () => {
);
}
if (workspace.nodeTree) {
workspace.nodeTree.title = t("nodeDefinition");
workspace.nodeTree.icon = (
const nodeTree = useMemo(() => {
const data: NodeTreeType = {
title: t("nodeDefinition"),
icon: (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<PiTreeStructureFill size={19} />
</Flex>
);
workspace.nodeTree.children?.forEach((catalog) => {
catalog.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: (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<img
className="b3-node-icon"
style={{ width: "13px", height: "13px", color: "white" }}
src={`./icons/${catalog.title}.svg`}
src={`./icons/${type}.svg`}
/>
</Flex>
);
catalog.children?.forEach((node) => {
if (node.def?.icon) {
node.icon = (
),
};
data.children?.push(catalog);
}
catalog.children?.push({
title: `${nodeDef.name}(${nodeDef.desc})`,
isLeaf: true,
def: nodeDef,
icon: nodeDef.icon ? (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<img
className="b3-node-icon"
@@ -161,22 +188,24 @@ export const Explorer: FC = () => {
style={{ width: "13px", height: "13px", color: "white" }}
src={
process.env.VITE_DEV_SERVER_URL && isMacos
? `${Path.basename(workspace.workdir)}/${node.def?.icon}`
: `${workspace.workdir}/${node.def?.icon}`
? `${Path.basename(workspace.workdir)}/${nodeDef.icon}`
: `${workspace.workdir}/${nodeDef.icon}`
}
/>
</Flex>
);
} else {
node.icon = (
) : (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<BsBoxFill style={{ width: "12px", height: "12px", color: "white" }} />{" "}
</Flex>
),
});
});
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 = () => {
<DirectoryTree
tabIndex={-1}
fieldNames={{ key: "title" }}
treeData={workspace.nodeTree ? [workspace.nodeTree] : []}
treeData={nodeTree ? [nodeTree] : []}
draggable={{ icon: false, nodeDraggable: (node) => !!node.isLeaf }}
onSelect={(_, info) => {
const node = info.node;
+9
View File
@@ -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 = () => {
>
<Input disabled={true} />
</Form.Item>
<Form.Item
name="type"
label={
<div style={{ minWidth: "80px", justifyContent: "flex-end" }}>{t("node.type")}</div>
}
>
<Input disabled={true} />
</Form.Item>
<Form.Item label={t("node.name")} name="name">
<AutoComplete
disabled={disabled}
+9 -3
View File
@@ -1,7 +1,9 @@
import { useWorkspace } from "@/contexts/workspace-context";
import { TreeGraphData } from "@/misc/b3type";
import { TreeGraphData, getNodeType } from "@/misc/b3type";
import { checkTreeData, toBreakWord } from "@/misc/b3util";
import i18n from "@/misc/i18n";
import { isMacos } from "@/misc/keys";
import Path from "@/misc/path";
import G6 from "@antv/g6";
const NODE_COLORS: any = {
@@ -73,7 +75,7 @@ G6.registerNode(
draw(cfg, group) {
const workspace = useWorkspace.getState();
const nodeDef = workspace.getNodeDef(cfg.name as string);
let classify = nodeDef.type || "Other";
let classify = getNodeType(nodeDef);
let color = nodeDef.color || NODE_COLORS[classify] || NODE_COLORS["Other"];
if (
!workspace.hasNodeDef(cfg.name as string) ||
@@ -176,7 +178,11 @@ G6.registerNode(
});
// icon
const img = nodeDef.icon ? workspace.workdir + "/" + nodeDef.icon : `./icons/${classify}.svg`;
const img = nodeDef.icon
? process.env.VITE_DEV_SERVER_URL && isMacos
? `${Path.basename(workspace.workdir)}/${nodeDef.icon}`
: `${workspace.workdir}/${nodeDef.icon}`
: `./icons/${classify}.svg`;
addShape("image", {
attrs: {
x: 5,
+1 -36
View File
@@ -79,15 +79,6 @@ export type FileTreeType = {
style?: React.CSSProperties;
};
export type NodeTreeType = {
title: string;
def?: NodeDef;
icon?: React.ReactNode;
isLeaf?: boolean;
children?: NodeTreeType[];
style?: React.CSSProperties;
};
export type EditNode = {
data: NodeModel;
editable: boolean;
@@ -112,7 +103,6 @@ export type WorkspaceStore = {
path: string;
allFiles: string[];
nodeTree?: NodeTreeType;
fileTree?: FileTreeType;
editors: EditorStore[];
editing?: EditorStore;
@@ -452,36 +442,11 @@ export const useWorkspace = create<WorkspaceStore>((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<string, NodeDef> = 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");
},
+17 -1
View File
@@ -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";
}
};