Merge branch 'dev'

This commit is contained in:
codetypes committed 2024-08-09 13:12:39 +08:00
commit bd8f4b4ead
6 files changed
+834 -760

No files matched your search

+744 -702
View File
File diff suppressed because it is too large. Load diff
+27 -27
View File
@@ -1,6 +1,6 @@
{
"name": "behavior3editor",
"version": "1.5.0",
"version": "1.6.0",
"main": "dist-electron/main/index.js",
"description": "行为树编辑器",
"author": "zhandouxiaojiji & codetypes",
@@ -26,49 +26,49 @@
},
"homepage": "https://github.com/zhandouxiaojiji/behavior3editor#readme",
"devDependencies": {
"@stylistic/eslint-plugin-js": "^1.7.0",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"@stylistic/eslint-plugin-js": "^1.8.1",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-react": "^3.1.0",
"copy-files-from-to": "^3.9.1",
"electron": "^30.0.0",
"copy-files-from-to": "^3.11.0",
"electron": "^30.3.1",
"electron-builder": "^24.13.3",
"eslint": "^8.57.0",
"eslint-plugin-react-refresh": "^0.4.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"sass": "^1.60.0",
"typescript": "^5.5.3",
"vite": "^4.1.4",
"eslint-plugin-react-refresh": "^0.4.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.77.8",
"typescript": "^5.5.4",
"vite": "^4.5.3",
"vite-electron-plugin": "^0.8.3",
"vite-plugin-electron": "^0.28.4",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
},
"dependencies": {
"@ant-design/icons": "^5.3.3",
"@ant-design/icons": "^5.4.0",
"@antv/g6": "^4.8.24",
"@electron/remote": "github:electron/remote",
"@types/electron-localshortcut": "^3.1.3",
"@types/node": "^20.11.27",
"ahooks": "^3.7.10",
"antd": "^5.16.0",
"@types/node": "^20.14.14",
"ahooks": "^3.8.0",
"antd": "^5.20.0",
"electron-localshortcut": "^3.2.1",
"electron-updater": "^6.3.0",
"i18next": "^23.10.1",
"i18next-browser-languagedetector": "^7.2.0",
"i18next-http-backend": "^2.5.0",
"electron-updater": "^6.3.2",
"i18next": "^23.12.2",
"i18next-browser-languagedetector": "^7.2.1",
"i18next-http-backend": "^2.5.2",
"json-stable-stringify": "^1.1.1",
"react-hotkeys-hook": "^4.5.0",
"react-i18next": "^14.1.0",
"react-icons": "^5.0.1",
"react-i18next": "^14.1.3",
"react-icons": "^5.2.1",
"react-markdown": "^9.0.1",
"react-merge-refs": "^2.1.1",
"ts-key-enum": "^2.0.12",
"use-force-update": "^1.0.11",
"usehooks-ts": "^3.0.1",
"zustand": "^4.5.2"
"usehooks-ts": "^3.1.0",
"zustand": "^4.5.4"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
+1 -1
View File
@@ -7,7 +7,7 @@ import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
import Path from "@/misc/path";
import { DownOutlined } from "@ant-design/icons";
import { Button, Dropdown, Flex, FlexProps, Input, MenuProps, Space, Tree } from "antd";
import { ItemType } from "antd/es/menu/hooks/useItems";
import { ItemType } from "antd/es/menu/interface";
import { ipcRenderer, shell } from "electron";
import * as fs from "fs";
import React, { FC, useEffect, useMemo, useState } from "react";
+1 -1
View File
@@ -6,7 +6,7 @@ import { Hotkey, isMacos, sendInputEvent } from "@/misc/keys";
import { CheckOutlined } from "@ant-design/icons";
import { Menu as AppMenu, BrowserWindow, app, dialog } from "@electron/remote";
import { Button, DropDownProps, Dropdown, Flex, FlexProps, LayoutProps, Space } from "antd";
import { ItemType } from "antd/es/menu/hooks/useItems";
import { ItemType } from "antd/es/menu/interface";
import { ipcRenderer } from "electron";
import { MenuItemConstructorOptions } from "electron/renderer";
import * as fs from "fs";
+8 -7
View File
@@ -2,8 +2,6 @@ import { useWorkspace } from "@/contexts/workspace-context";
import { TreeGraphData, getNodeType } from "@/misc/b3type";
import { checkTreeData, cutWordTo, 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 = {
@@ -250,7 +248,7 @@ G6.registerNode(
let desc = (cfg.desc || nodeDef.desc) as string;
if (desc) {
desc = i18n.t("regnode.mark") + desc;
desc = cutWordTo(desc, 33);
desc = cutWordTo(desc, w - 15);
addShape("text", {
attrs: {
textBaseline: "top",
@@ -267,7 +265,7 @@ G6.registerNode(
const args: any = cfg.args;
if (nodeDef.args && args && Object.keys(args).length > 0) {
const { str, line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(args)}`, 36);
const { str, line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(args)}`, 200);
addShape("text", {
attrs: {
textBaseline: "top",
@@ -285,7 +283,10 @@ G6.registerNode(
const input: [] = cfg.input ? (cfg.input as []) : [];
if (nodeDef.input && input.length > 0) {
const { str, line } = toBreakWord(`${i18n.t("regnode.input")}${JSON.stringify(input)}`, 35);
const { str, line } = toBreakWord(
`${i18n.t("regnode.input")}${JSON.stringify(input)}`,
200
);
if (cfg.highlightInput) {
addShape("rect", {
attrs: {
@@ -322,7 +323,7 @@ G6.registerNode(
if (nodeDef.output && output.length > 0) {
const { str, line } = toBreakWord(
`${i18n.t("regnode.output")}${JSON.stringify(output)}`,
35
200
);
if (cfg.highlightOutput) {
addShape("rect", {
@@ -358,7 +359,7 @@ G6.registerNode(
if (cfg.path) {
let path = (i18n.t("regnode.subtree") + cfg.path) as string;
path = cutWordTo(path, 35);
path = cutWordTo(path, w - 15);
addShape("text", {
attrs: {
textBaseline: "top",
+53 -22
View File
@@ -4,6 +4,45 @@ import * as fs from "fs";
import { message } from "./hooks";
import Path from "./path";
import { zhNodeDef } from "./template";
import i18n from "@/misc/i18n";
import { isMacos } from "./keys";
let ctx: CanvasRenderingContext2D | null = null;
let defaultFontSize = "";
const textWidthMap = new Map<string, number>();
const isAsciiChar = (c: number) => {
return (c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f);
};
const calcTextWith = (text: string, fontSize?: string) => {
fontSize = fontSize ?? defaultFontSize;
let b3Workspace: HTMLDivElement | null;
let css: CSSStyleDeclaration | null;
if (!fontSize) {
b3Workspace = document.querySelector(".b3-workspace");
if (b3Workspace) {
css = getComputedStyle(b3Workspace);
defaultFontSize = css.fontSize || "13px";
fontSize = defaultFontSize;
}
}
const key = `${text}-${fontSize}`;
let width = textWidthMap.get(key);
if (!width) {
b3Workspace ||= document.querySelector(".b3-workspace");
if (b3Workspace) {
css ||= getComputedStyle(b3Workspace);
ctx = ctx || document.createElement("canvas").getContext("2d")!;
ctx.font = `${fontSize} ${css.fontFamily}`;
const metrics = ctx.measureText(text);
width = metrics.width;
width = width - (isMacos ? 1.6 : 0.8);
textWidthMap.set(key, width);
}
}
return width ?? 13;
};
export const isSubtreeRoot = (data: TreeGraphData) => {
return data.path && data.id.toString() !== "1";
@@ -395,8 +434,8 @@ export const refreshTreeDataId = (data: TreeGraphData, id?: number) => {
export const calcTreeDataSize = (data: TreeGraphData) => {
let height = 50 + 2;
const updateHeight = (obj: any) => {
if (Array.isArray(obj) || (obj && Object.keys(obj).length > 0)) {
const { str, line } = toBreakWord(`参数:${JSON.stringify(obj)}`, 35);
if ((Array.isArray(obj) && obj.length) || (obj && Object.keys(obj).length > 0)) {
const { line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(obj)}`, 200);
height += 20 * line;
}
};
@@ -563,24 +602,16 @@ export const isTreeFile = (path: string) => {
return path.toLocaleLowerCase().endsWith(".json");
};
const isAsciiChar = (c: number) => {
return (c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f);
};
const isUppercase = (c: number) => {
return c >= 0x0041 && c <= 0x005a;
};
export const toBreakWord = (str: string, maxlen: number) => {
export const toBreakWord = (str: string, maxWidth: number, fontSize?: string) => {
const chars: string[] = [];
let line = 1;
let len = 0;
let line = str.length > 0 ? 1 : 0;
let width = maxWidth;
for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
len += isAsciiChar(c) ? (isUppercase(c) ? 1.5 : 1) : 2;
chars.push(String.fromCharCode(c));
if (len >= maxlen && i < str.length - 1) {
len = 0;
width -= calcTextWith(str.charAt(i), fontSize);
if (width > 0) {
chars.push(str.charAt(i));
} else {
width = maxWidth;
line++;
chars.push("\n");
}
@@ -591,12 +622,12 @@ export const toBreakWord = (str: string, maxlen: number) => {
};
};
export const cutWordTo = (str: string, maxlen: number) => {
export const cutWordTo = (str: string, maxWidth: number, fontSize?: string) => {
let i = 0;
for (; i < str.length; i++) {
const c = str.charCodeAt(i);
maxlen -= isAsciiChar(c) ? (isUppercase(c) ? 1.5 : 1) : 2;
if (maxlen <= 0) {
maxWidth -= calcTextWith(str.charAt(i), fontSize);
if (maxWidth < 0) {
i--;
break;
}
}