support group by type for node def
This commit is contained in:
1 parent
be509bed9e
commit
543c5b09c3
7 files changed
+110
-88
No files matched your search
@@ -1,14 +1,11 @@
|
|||||||
{
|
{
|
||||||
"folders": [
|
"folders": [
|
||||||
{
|
{
|
||||||
"path": "."
|
"path": "."
|
||||||
}
|
|
||||||
],
|
|
||||||
"settings": {
|
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
||||||
"[json]": {
|
|
||||||
"editor.formatOnSave": false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "MoveToPos",
|
"name": "MoveToPos",
|
||||||
"type": "Action",
|
"type": "Action (Client)",
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "x",
|
"name": "x",
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "MoveToTarget",
|
"name": "MoveToTarget",
|
||||||
"type": "Action",
|
"type": "Action (Server)",
|
||||||
"input": [
|
"input": [
|
||||||
"{目标}"
|
"{目标}"
|
||||||
],
|
],
|
||||||
|
|||||||
+64
-35
@@ -1,4 +1,5 @@
|
|||||||
import { FileTreeType, useWorkspace } from "@/contexts/workspace-context";
|
import { FileTreeType, useWorkspace } from "@/contexts/workspace-context";
|
||||||
|
import { NodeDef, getNodeType } from "@/misc/b3type";
|
||||||
import * as b3util from "@/misc/b3util";
|
import * as b3util from "@/misc/b3util";
|
||||||
import { modal } from "@/misc/hooks";
|
import { modal } from "@/misc/hooks";
|
||||||
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
|
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
|
||||||
@@ -31,6 +32,15 @@ type MenuEvent =
|
|||||||
| "move"
|
| "move"
|
||||||
| "duplicate";
|
| "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 => {
|
const findFile = (path: string | undefined, node: FileTreeType): FileTreeType | undefined => {
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return;
|
return;
|
||||||
@@ -112,7 +122,6 @@ export const Explorer: FC = () => {
|
|||||||
editors: useWorkspace((state) => state.editors),
|
editors: useWorkspace((state) => state.editors),
|
||||||
fileTree: useWorkspace((state) => state.fileTree),
|
fileTree: useWorkspace((state) => state.fileTree),
|
||||||
nodeDefs: useWorkspace((state) => state.nodeDefs),
|
nodeDefs: useWorkspace((state) => state.nodeDefs),
|
||||||
nodeTree: useWorkspace((state) => state.nodeTree),
|
|
||||||
workdir: useWorkspace((state) => state.workdir),
|
workdir: useWorkspace((state) => state.workdir),
|
||||||
onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef),
|
onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef),
|
||||||
open: useWorkspace((state) => state.open),
|
open: useWorkspace((state) => state.open),
|
||||||
@@ -134,49 +143,69 @@ export const Explorer: FC = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workspace.nodeTree) {
|
const nodeTree = useMemo(() => {
|
||||||
workspace.nodeTree.title = t("nodeDefinition");
|
const data: NodeTreeType = {
|
||||||
workspace.nodeTree.icon = (
|
title: t("nodeDefinition"),
|
||||||
<Flex justify="center" align="center" style={{ height: "100%" }}>
|
icon: (
|
||||||
<PiTreeStructureFill size={19} />
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
workspace.nodeTree.children?.forEach((catalog) => {
|
|
||||||
catalog.icon = (
|
|
||||||
<Flex justify="center" align="center" style={{ height: "100%" }}>
|
<Flex justify="center" align="center" style={{ height: "100%" }}>
|
||||||
<img
|
<PiTreeStructureFill size={19} />
|
||||||
className="b3-node-icon"
|
|
||||||
style={{ width: "13px", height: "13px", color: "white" }}
|
|
||||||
src={`./icons/${catalog.title}.svg`}
|
|
||||||
/>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
),
|
||||||
catalog.children?.forEach((node) => {
|
children: [],
|
||||||
if (node.def?.icon) {
|
style: {
|
||||||
node.icon = (
|
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%" }}>
|
<Flex justify="center" align="center" style={{ height: "100%" }}>
|
||||||
<img
|
<img
|
||||||
className="b3-node-icon"
|
className="b3-node-icon"
|
||||||
key={catalog.title}
|
|
||||||
style={{ width: "13px", height: "13px", color: "white" }}
|
style={{ width: "13px", height: "13px", color: "white" }}
|
||||||
src={
|
src={`./icons/${type}.svg`}
|
||||||
process.env.VITE_DEV_SERVER_URL && isMacos
|
|
||||||
? `${Path.basename(workspace.workdir)}/${node.def?.icon}`
|
|
||||||
: `${workspace.workdir}/${node.def?.icon}`
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
),
|
||||||
} else {
|
};
|
||||||
node.icon = (
|
data.children?.push(catalog);
|
||||||
<Flex justify="center" align="center" style={{ height: "100%" }}>
|
}
|
||||||
<BsBoxFill style={{ width: "12px", height: "12px", color: "white" }} />{" "}
|
catalog.children?.push({
|
||||||
</Flex>
|
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"
|
||||||
|
key={catalog.title}
|
||||||
|
style={{ width: "13px", height: "13px", color: "white" }}
|
||||||
|
src={
|
||||||
|
process.env.VITE_DEV_SERVER_URL && isMacos
|
||||||
|
? `${Path.basename(workspace.workdir)}/${nodeDef.icon}`
|
||||||
|
: `${workspace.workdir}/${nodeDef.icon}`
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
|
<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(() => {
|
useEffect(() => {
|
||||||
if (workspace.editing) {
|
if (workspace.editing) {
|
||||||
@@ -795,7 +824,7 @@ export const Explorer: FC = () => {
|
|||||||
<DirectoryTree
|
<DirectoryTree
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
fieldNames={{ key: "title" }}
|
fieldNames={{ key: "title" }}
|
||||||
treeData={workspace.nodeTree ? [workspace.nodeTree] : []}
|
treeData={nodeTree ? [nodeTree] : []}
|
||||||
draggable={{ icon: false, nodeDraggable: (node) => !!node.isLeaf }}
|
draggable={{ icon: false, nodeDraggable: (node) => !!node.isLeaf }}
|
||||||
onSelect={(_, info) => {
|
onSelect={(_, info) => {
|
||||||
const node = info.node;
|
const node = info.node;
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ const NodeInspector: FC = () => {
|
|||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.setFieldValue("id", data.id);
|
form.setFieldValue("id", data.id);
|
||||||
form.setFieldValue("name", data.name);
|
form.setFieldValue("name", data.name);
|
||||||
|
form.setFieldValue("type", def.type);
|
||||||
form.setFieldValue("desc", data.desc);
|
form.setFieldValue("desc", data.desc);
|
||||||
form.setFieldValue("debug", data.debug);
|
form.setFieldValue("debug", data.debug);
|
||||||
form.setFieldValue("path", data.path);
|
form.setFieldValue("path", data.path);
|
||||||
@@ -227,6 +228,14 @@ const NodeInspector: FC = () => {
|
|||||||
>
|
>
|
||||||
<Input disabled={true} />
|
<Input disabled={true} />
|
||||||
</Form.Item>
|
</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">
|
<Form.Item label={t("node.name")} name="name">
|
||||||
<AutoComplete
|
<AutoComplete
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useWorkspace } from "@/contexts/workspace-context";
|
import { useWorkspace } from "@/contexts/workspace-context";
|
||||||
import { TreeGraphData } from "@/misc/b3type";
|
import { TreeGraphData, getNodeType } from "@/misc/b3type";
|
||||||
import { checkTreeData, toBreakWord } from "@/misc/b3util";
|
import { checkTreeData, toBreakWord } from "@/misc/b3util";
|
||||||
import i18n from "@/misc/i18n";
|
import i18n from "@/misc/i18n";
|
||||||
|
import { isMacos } from "@/misc/keys";
|
||||||
|
import Path from "@/misc/path";
|
||||||
import G6 from "@antv/g6";
|
import G6 from "@antv/g6";
|
||||||
|
|
||||||
const NODE_COLORS: any = {
|
const NODE_COLORS: any = {
|
||||||
@@ -73,7 +75,7 @@ G6.registerNode(
|
|||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
const workspace = useWorkspace.getState();
|
const workspace = useWorkspace.getState();
|
||||||
const nodeDef = workspace.getNodeDef(cfg.name as string);
|
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"];
|
let color = nodeDef.color || NODE_COLORS[classify] || NODE_COLORS["Other"];
|
||||||
if (
|
if (
|
||||||
!workspace.hasNodeDef(cfg.name as string) ||
|
!workspace.hasNodeDef(cfg.name as string) ||
|
||||||
@@ -176,7 +178,11 @@ G6.registerNode(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// icon
|
// 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", {
|
addShape("image", {
|
||||||
attrs: {
|
attrs: {
|
||||||
x: 5,
|
x: 5,
|
||||||
|
|||||||
@@ -79,15 +79,6 @@ export type FileTreeType = {
|
|||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NodeTreeType = {
|
|
||||||
title: string;
|
|
||||||
def?: NodeDef;
|
|
||||||
icon?: React.ReactNode;
|
|
||||||
isLeaf?: boolean;
|
|
||||||
children?: NodeTreeType[];
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EditNode = {
|
export type EditNode = {
|
||||||
data: NodeModel;
|
data: NodeModel;
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
@@ -112,7 +103,6 @@ export type WorkspaceStore = {
|
|||||||
path: string;
|
path: string;
|
||||||
|
|
||||||
allFiles: string[];
|
allFiles: string[];
|
||||||
nodeTree?: NodeTreeType;
|
|
||||||
fileTree?: FileTreeType;
|
fileTree?: FileTreeType;
|
||||||
editors: EditorStore[];
|
editors: EditorStore[];
|
||||||
editing?: EditorStore;
|
editing?: EditorStore;
|
||||||
@@ -452,36 +442,11 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
|
|||||||
loadNodeDefs: () => {
|
loadNodeDefs: () => {
|
||||||
const workspace = get();
|
const workspace = get();
|
||||||
const nodeDefData = readJson(`${workspace.workdir}/node-config.b3-setting`) as NodeDef[];
|
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();
|
const nodeDefs: Map<string, NodeDef> = new Map();
|
||||||
for (const v of nodeDefData) {
|
for (const v of nodeDefData) {
|
||||||
nodeDefs.set(v.name, v);
|
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));
|
set({ nodeDefs });
|
||||||
nodeTree.children?.forEach((child) =>
|
|
||||||
child.children?.sort((a, b) => a.title.localeCompare(b.title))
|
|
||||||
);
|
|
||||||
set({ nodeDefs, nodeTree });
|
|
||||||
workspace.editing?.dispatch?.("reload");
|
workspace.editing?.dispatch?.("reload");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -1,6 +1,7 @@
|
|||||||
import { TreeGraphData as G6TreeGraphData } from "@antv/g6";
|
import { TreeGraphData as G6TreeGraphData } from "@antv/g6";
|
||||||
|
|
||||||
export type NodeArgType = "string" | "int" | "float" | "boolean" | "enum" | "code";
|
export type NodeArgType = "string" | "int" | "float" | "boolean" | "enum" | "code";
|
||||||
|
export type NodeType = "Action" | "Composite" | "Decorator" | "Condition" | "Other" | "Error";
|
||||||
|
|
||||||
export interface NodeArgOption {
|
export interface NodeArgOption {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -16,7 +17,7 @@ export interface NodeArg {
|
|||||||
}
|
}
|
||||||
export interface NodeDef {
|
export interface NodeDef {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: NodeType;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
args?: NodeArg[];
|
args?: NodeArg[];
|
||||||
input?: string[];
|
input?: string[];
|
||||||
@@ -67,3 +68,18 @@ export const unknownNodeDef: NodeDef = {
|
|||||||
desc: "新建节点",
|
desc: "新建节点",
|
||||||
type: "Action",
|
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";
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in new issue
Block a user