mirror of
https://gitee.com/sli97/behavior-eden-coco-plugin.git
synced 2025-10-09 08:36:25 +00:00
version:1.0.1
This commit is contained in:
14
dist/contributions/inspector/behavior-editor.js
vendored
14
dist/contributions/inspector/behavior-editor.js
vendored
@@ -3,8 +3,8 @@
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ready = exports.update = exports.$ = exports.template = void 0;
|
||||
exports.template = `
|
||||
<div style="display:flex;justify-content:center;align-items:center;margin-top:10px;padding-right:8px;">
|
||||
<ui-button class="editor" style="height:24px;padding:0 16px;">Edit Tree</ui-prop>
|
||||
<div style="display:flex;justify-content:center;align-items:center;margin-top:10px;">
|
||||
<ui-button class="editor" style="height:24px;padding:0 16px;">Create / Edit</ui-prop>
|
||||
</div>
|
||||
|
||||
`;
|
||||
@@ -64,15 +64,17 @@ function ready() {
|
||||
});
|
||||
if (success) {
|
||||
console.log(`JSON文件挂载成功`);
|
||||
Editor.Message.request("behavior-eden", "open-panel");
|
||||
}
|
||||
else {
|
||||
console.warn("JSON文件挂载失败");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 打开插件面板
|
||||
Editor.Message.request("behavior-eden", "open-panel");
|
||||
// 打开插件面板
|
||||
const success = await Editor.Message.request("behavior-eden", "open-panel");
|
||||
// success为false,可能是已经打开了,通知面板刷新
|
||||
if (!success) {
|
||||
await Editor.Message.request("behavior-eden", "refresh-panel");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
9
dist/main.js
vendored
9
dist/main.js
vendored
@@ -11,8 +11,13 @@ const package_json_1 = __importDefault(require("../package.json"));
|
||||
* @zh 为扩展的主进程的注册方法
|
||||
*/
|
||||
exports.methods = {
|
||||
openPanel() {
|
||||
Editor.Panel.open(package_json_1.default.name);
|
||||
async openPanel() {
|
||||
return await Editor.Panel.openBeside("scene", package_json_1.default.name);
|
||||
},
|
||||
async refreshPanel() {
|
||||
await Editor.Panel.close(package_json_1.default.name);
|
||||
await new Promise((rs) => setTimeout(rs, 300));
|
||||
await Editor.Panel.openBeside("scene", package_json_1.default.name);
|
||||
},
|
||||
};
|
||||
/**
|
||||
|
327
dist/panels/default/index.js
vendored
327
dist/panels/default/index.js
vendored
@@ -10,8 +10,8 @@ const node_1 = require("../../runtime/node");
|
||||
const decorator_1 = require("../../runtime/core/decorator");
|
||||
const utils_1 = require("../../runtime/core/utils");
|
||||
// 画布宽高
|
||||
const CANVAS_WIDTH = 2400;
|
||||
const CANVAS_HEIGHT = 1600;
|
||||
const CANVAS_WIDTH = 2000;
|
||||
const CANVAS_HEIGHT = 1400;
|
||||
// 节点box属性
|
||||
const BOX_WIDTH = 100;
|
||||
// const BOX_HEIGHT = 64; //height通过getBoxHeight方法动态计算
|
||||
@@ -141,6 +141,21 @@ const ParentNodes = [...decorator_1.nodeClsMap.values()]
|
||||
return false;
|
||||
})
|
||||
.map((cls) => cls.name);
|
||||
/***
|
||||
* 获取所有Composite类型的节点
|
||||
*/
|
||||
const CompositeNodes = [...decorator_1.nodeClsMap.values()]
|
||||
.filter((cls) => {
|
||||
let parentCls = getParentCls(cls);
|
||||
while (parentCls) {
|
||||
if (parentCls.name === node_1.Composite.name) {
|
||||
return true;
|
||||
}
|
||||
parentCls = getParentCls(parentCls);
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map((cls) => cls.name);
|
||||
const activeCursor = () => {
|
||||
stage && (stage.container().style.cursor = "pointer");
|
||||
};
|
||||
@@ -151,7 +166,7 @@ const component = lib_1.Vue.extend({
|
||||
template: lib_1.fs.readFileSync(path_1.default.join(__dirname, "../../../src/panels/static/template/vue/app.html"), "utf-8"),
|
||||
$: {
|
||||
tree: "#tree",
|
||||
left: "#left",
|
||||
scroll: "#scroll",
|
||||
},
|
||||
filters: {
|
||||
toUpperCase(value) {
|
||||
@@ -189,6 +204,7 @@ const component = lib_1.Vue.extend({
|
||||
*/
|
||||
nodeCompMethodInfo: {},
|
||||
logs: [],
|
||||
maskText: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -253,12 +269,143 @@ const component = lib_1.Vue.extend({
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.initCanvas();
|
||||
await this.getAssets();
|
||||
await this.selectCurrentAsset();
|
||||
this.$refs.left.scroll((CANVAS_WIDTH - this.$refs.left.getBoundingClientRect().width) / 2, ROOT_Y - 50);
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
/***
|
||||
* 初始化相关
|
||||
*/
|
||||
async init() {
|
||||
// 初始化画布
|
||||
this.initCanvas();
|
||||
// 根据当前选中节点初始化行为树
|
||||
await this.initSelection();
|
||||
this.backRoot();
|
||||
},
|
||||
initCanvas() {
|
||||
// 初始化舞台
|
||||
stage = new lib_1.Konva.Stage({
|
||||
container: this.$refs.tree,
|
||||
width: CANVAS_WIDTH,
|
||||
height: CANVAS_HEIGHT,
|
||||
});
|
||||
// 基础层,目前只有一层,每层都会生成一个canvas
|
||||
baseLayer = new lib_1.Konva.Layer();
|
||||
// 背景组
|
||||
bgGroup = this.generateBg();
|
||||
baseLayer.add(bgGroup);
|
||||
// 静态箭头层
|
||||
staticArrowGroup = new lib_1.Konva.Group();
|
||||
baseLayer.add(staticArrowGroup);
|
||||
// 动态箭头层(用户手动拉出来的箭头)
|
||||
dynamicArrowGroup = this.generateDynamicArrowGroup();
|
||||
baseLayer.add(dynamicArrowGroup);
|
||||
// Root组
|
||||
rootGroup = this.generateRoot();
|
||||
baseLayer.add(rootGroup);
|
||||
// 节点层
|
||||
nodeGroup = new lib_1.Konva.Group();
|
||||
baseLayer.add(nodeGroup);
|
||||
// 框选层
|
||||
selectionGroup = this.generatesSelectionGroup();
|
||||
baseLayer.add(selectionGroup);
|
||||
// 层添加到舞台
|
||||
stage.add(baseLayer);
|
||||
},
|
||||
// 获取json文件
|
||||
async initAssets() {
|
||||
const behaviorTreeComponentUuids = [];
|
||||
const dfs = (node) => {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
for (const comp of node.components) {
|
||||
if (comp.type === BTreeCompName) {
|
||||
behaviorTreeComponentUuids.push(comp.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const item of node.children) {
|
||||
dfs(item);
|
||||
}
|
||||
};
|
||||
// 获取场景节点树
|
||||
const sceneNode = await Editor.Message.request("scene", "query-node-tree");
|
||||
// 收集场景上所有BehaviorTree组件uuid
|
||||
dfs(sceneNode);
|
||||
// 收集BehaviorTree组件上的json路径
|
||||
const rawUrls = await Promise.all(behaviorTreeComponentUuids.map((uuid) => Editor.Message.request("scene", "execute-component-method", {
|
||||
uuid: uuid,
|
||||
name: "getAssetUrl",
|
||||
})));
|
||||
// 过滤空的并去重
|
||||
const urls = [...new Set(rawUrls.filter(Boolean))];
|
||||
// 根据url获取所有json文件信息
|
||||
const assets = await Promise.all(urls.map((url) => Editor.Message.request("asset-db", "query-asset-info", url)));
|
||||
this.assets = assets.map(({ name, source, file }) => ({ name, url: source, file: file, content: "" }));
|
||||
},
|
||||
async initSelection() {
|
||||
// 找到当前选中的节点
|
||||
const node = await Editor.Message.request("scene", "query-node", Editor.Selection.getSelected("node"));
|
||||
// 未选中节点或者选中的是场景节点(场景节点不能添加组件)
|
||||
if (!(node === null || node === void 0 ? void 0 : node.__comps__)) {
|
||||
this.maskText = "请选中一个非场景根节点非空名称节点来开始行为树制作";
|
||||
return;
|
||||
}
|
||||
// 找到BehaviorTree组件
|
||||
const index = node.__comps__.findIndex((v) => v.type === BTreeCompName);
|
||||
if (index === -1) {
|
||||
this.maskText = "要制作行为树,需要先为当前节点添加行为树组件";
|
||||
return;
|
||||
}
|
||||
const comp = node.__comps__[index];
|
||||
// 调用BehaviorTree组件上的方法
|
||||
const url = await Editor.Message.request("scene", "execute-component-method", {
|
||||
uuid: comp.value.uuid.value,
|
||||
name: "getAssetUrl",
|
||||
});
|
||||
// JSON文件不存在
|
||||
if (!url) {
|
||||
this.maskText = "当前行为树组件缺少JSON资源,点击BehaviorEditor组件按钮即可创建";
|
||||
return;
|
||||
}
|
||||
this.maskText = "";
|
||||
// 选中此文件,设置好currentAsset才能把组件nodes数据同步到JSON
|
||||
this.handleSelectAsset(url);
|
||||
},
|
||||
async handleSelectAsset(url) {
|
||||
var _a;
|
||||
// 实时获取当前场景所有behaviorTree组件上的json文件
|
||||
await this.initAssets();
|
||||
const json = this.assets.find((e) => e.url === url);
|
||||
if (!json) {
|
||||
this.showWarn("JSON文件不存在");
|
||||
return;
|
||||
}
|
||||
if (((_a = this.currentAsset) === null || _a === void 0 ? void 0 : _a.url) === (json === null || json === void 0 ? void 0 : json.url)) {
|
||||
return;
|
||||
}
|
||||
this.currentAsset = json;
|
||||
try {
|
||||
const content = await lib_1.fs.readJSONSync(json.file);
|
||||
this.currentAsset.content = content;
|
||||
this.render();
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
// JSON文件语法异常的情况下,初始化内容
|
||||
this.showWarn("JSON文件内容初始化成功");
|
||||
const content = { nodes: [] };
|
||||
await lib_1.fs.writeJSONSync(json.file, content);
|
||||
this.currentAsset.content = content;
|
||||
this.render();
|
||||
}
|
||||
else {
|
||||
// 输出其他异常
|
||||
this.showWarn(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
handlePanelChange(value) {
|
||||
this.currentPanel = value;
|
||||
},
|
||||
@@ -275,7 +422,7 @@ const component = lib_1.Vue.extend({
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
async handleEventNodeChange(lifeCycle, uuid = "") {
|
||||
async handleEventNodeChange(lifeCycle, uuid = "", shouldSave = true) {
|
||||
if (!this.currentNode) {
|
||||
this.showWarn("当前节点不存在");
|
||||
return;
|
||||
@@ -287,9 +434,13 @@ const component = lib_1.Vue.extend({
|
||||
else {
|
||||
this.currentNode.event[lifeCycle].comp = "";
|
||||
this.currentNode.event[lifeCycle].method = "";
|
||||
this.currentNode.event[lifeCycle].data = "";
|
||||
// 事件参数就不手动清空了
|
||||
// this.currentNode.event[lifeCycle].data = "";
|
||||
}
|
||||
// 点击canvas某个节点的时候,会触发handleEventNodeChange获取场景节点数据,此时不保存数据
|
||||
if (shouldSave) {
|
||||
await this.saveAsset();
|
||||
}
|
||||
await this.saveAsset();
|
||||
},
|
||||
async getNodeCompMethods(lifeCycle, uuid) {
|
||||
const [nodeInfo, compMethodInfo] = await Promise.all([
|
||||
@@ -331,132 +482,16 @@ const component = lib_1.Vue.extend({
|
||||
this.currentNode.event[lifeCycle].data = data;
|
||||
await this.saveAsset();
|
||||
},
|
||||
async selectCurrentAsset() {
|
||||
// 找到点击组件的节点
|
||||
const node = await Editor.Message.request("scene", "query-node", Editor.Selection.getSelected("node"));
|
||||
if (!node) {
|
||||
this.showWarn(`未选中节点`);
|
||||
return;
|
||||
}
|
||||
// 找到BehaviorTree组件
|
||||
const index = node.__comps__.findIndex((v) => v.type === BTreeCompName);
|
||||
if (index === -1) {
|
||||
this.showWarn(`节点未挂载【${BTreeCompName}】组件`);
|
||||
return;
|
||||
}
|
||||
const comp = node.__comps__[index];
|
||||
// 调用BehaviorTree组件上的方法
|
||||
const url = await Editor.Message.request("scene", "execute-component-method", {
|
||||
uuid: comp.value.uuid.value,
|
||||
name: "getAssetUrl",
|
||||
});
|
||||
// JSON文件不存在
|
||||
if (!url) {
|
||||
this.showWarn(`【${BTreeCompName}】组件未指定JSON文件`);
|
||||
return;
|
||||
}
|
||||
// 选中此文件,设置好currentAsset才能把组件nodes数据同步到JSON
|
||||
this.handleSelectAsset(url);
|
||||
},
|
||||
async handleSelectAsset(url) {
|
||||
const json = this.assets.find((e) => e.url === url);
|
||||
if (!json) {
|
||||
this.showWarn("JSON文件不存在");
|
||||
return;
|
||||
}
|
||||
this.currentAsset = json;
|
||||
try {
|
||||
const content = await lib_1.fs.readJSONSync(json.file);
|
||||
this.currentAsset.content = content;
|
||||
this.render();
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
// JSON文件语法异常的情况下,初始化内容
|
||||
this.showWarn("JSON文件内容初始化成功");
|
||||
const content = { nodes: [] };
|
||||
await lib_1.fs.writeJSONSync(json.file, content);
|
||||
this.currentAsset.content = content;
|
||||
this.render();
|
||||
}
|
||||
else {
|
||||
// 输出其他异常
|
||||
this.showWarn(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
// 全部所有behaviorTree组件上使用到的json文件
|
||||
async getAssets() {
|
||||
const behaviorTreeComponentUuids = [];
|
||||
const dfs = (node) => {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
for (const comp of node.components) {
|
||||
if (comp.type === BTreeCompName) {
|
||||
behaviorTreeComponentUuids.push(comp.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const item of node.children) {
|
||||
dfs(item);
|
||||
}
|
||||
};
|
||||
// 获取场景节点树
|
||||
const sceneNode = await Editor.Message.request("scene", "query-node-tree");
|
||||
// 收集场景上所有BehaviorTree组件uuid
|
||||
dfs(sceneNode);
|
||||
// 收集BehaviorTree组件上的json路径
|
||||
const rawUrls = await Promise.all(behaviorTreeComponentUuids.map((uuid) => Editor.Message.request("scene", "execute-component-method", {
|
||||
uuid: uuid,
|
||||
name: "getAssetUrl",
|
||||
})));
|
||||
// 过滤空的并去重
|
||||
const urls = [...new Set(rawUrls.filter(Boolean))];
|
||||
// 根据url获取所有json文件信息
|
||||
const assets = await Promise.all(urls.map((url) => Editor.Message.request("asset-db", "query-asset-info", url)));
|
||||
this.assets = assets.map(({ name, source, file }) => ({ name, url: source, file: file, content: "" }));
|
||||
},
|
||||
async saveAsset() {
|
||||
var _a;
|
||||
const url = (_a = this.currentAsset) === null || _a === void 0 ? void 0 : _a.url;
|
||||
if (!url) {
|
||||
const file = (_a = this.currentAsset) === null || _a === void 0 ? void 0 : _a.file;
|
||||
if (!file) {
|
||||
this.showWarn("数据存储失败,未指定JSON");
|
||||
return;
|
||||
}
|
||||
const content = JSON.stringify(this.currentAsset.content, null, 2);
|
||||
const content = this.currentAsset.content;
|
||||
// 修改json文件
|
||||
await Editor.Message.request("asset-db", "save-asset", url, content);
|
||||
},
|
||||
initCanvas() {
|
||||
// 初始化舞台
|
||||
stage = new lib_1.Konva.Stage({
|
||||
container: this.$refs.tree,
|
||||
width: CANVAS_WIDTH,
|
||||
height: CANVAS_HEIGHT,
|
||||
});
|
||||
// 基础层,目前只有一层,每层都会生成一个canvas
|
||||
baseLayer = new lib_1.Konva.Layer();
|
||||
// 背景组
|
||||
bgGroup = this.generateBg();
|
||||
baseLayer.add(bgGroup);
|
||||
// 静态箭头层
|
||||
staticArrowGroup = new lib_1.Konva.Group();
|
||||
baseLayer.add(staticArrowGroup);
|
||||
// 动态箭头层(用户手动拉出来的箭头)
|
||||
dynamicArrowGroup = this.generateDynamicArrowGroup();
|
||||
baseLayer.add(dynamicArrowGroup);
|
||||
// Root组
|
||||
rootGroup = this.generateRoot();
|
||||
baseLayer.add(rootGroup);
|
||||
// 节点层
|
||||
nodeGroup = new lib_1.Konva.Group();
|
||||
baseLayer.add(nodeGroup);
|
||||
// 框选层
|
||||
selectionGroup = this.generatesSelectionGroup();
|
||||
baseLayer.add(selectionGroup);
|
||||
// 层添加到舞台
|
||||
stage.add(baseLayer);
|
||||
lib_1.fs.writeJSONSync(file, content);
|
||||
},
|
||||
/***
|
||||
* 渲染画布
|
||||
@@ -568,7 +603,7 @@ const component = lib_1.Vue.extend({
|
||||
type,
|
||||
abortType: this.AbortType.None,
|
||||
x: (CANVAS_WIDTH - BOX_WIDTH) / 2,
|
||||
y: CANVAS_HEIGHT / 4,
|
||||
y: ROOT_Y + 100,
|
||||
isRoot: false,
|
||||
children: [],
|
||||
event: {
|
||||
@@ -828,7 +863,7 @@ const component = lib_1.Vue.extend({
|
||||
if (e.evt.buttons === 4) {
|
||||
const movementX = e.evt.movementX;
|
||||
const movementY = e.evt.movementY;
|
||||
this.$refs.left.scrollBy(-movementX, -movementY);
|
||||
this.$refs.scroll.scrollBy(-movementX, -movementY);
|
||||
return;
|
||||
}
|
||||
if (!selection.visible()) {
|
||||
@@ -981,11 +1016,11 @@ const component = lib_1.Vue.extend({
|
||||
selectedBoxes = [];
|
||||
this.currentNode = node;
|
||||
this.handlePanelChange(1);
|
||||
this.render();
|
||||
// 获取节点事件相关信息
|
||||
this.handleEventNodeChange(this.onStart, this.currentNode.event[this.onStart].node);
|
||||
this.handleEventNodeChange(this.onUpdate, this.currentNode.event[this.onUpdate].node);
|
||||
this.handleEventNodeChange(this.onEnd, this.currentNode.event[this.onEnd].node);
|
||||
this.handleEventNodeChange(this.onStart, this.currentNode.event[this.onStart].node, false);
|
||||
this.handleEventNodeChange(this.onUpdate, this.currentNode.event[this.onUpdate].node, false);
|
||||
this.handleEventNodeChange(this.onEnd, this.currentNode.event[this.onEnd].node, false);
|
||||
this.render();
|
||||
});
|
||||
return wrapper;
|
||||
},
|
||||
@@ -1247,6 +1282,12 @@ const component = lib_1.Vue.extend({
|
||||
}
|
||||
return BOX_HEIGHT;
|
||||
},
|
||||
isComposite(node) {
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
return CompositeNodes.includes(node.type);
|
||||
},
|
||||
showWarn(text) {
|
||||
let time = getTime();
|
||||
const content = `${time}:${text}`;
|
||||
@@ -1256,6 +1297,11 @@ const component = lib_1.Vue.extend({
|
||||
this.logs.push({ id: uuid(), content });
|
||||
console.warn(content);
|
||||
},
|
||||
// 视角回到root节点
|
||||
backRoot() {
|
||||
var _a, _b;
|
||||
(_b = (_a = this.$refs) === null || _a === void 0 ? void 0 : _a.scroll) === null || _b === void 0 ? void 0 : _b.scroll((CANVAS_WIDTH - this.$refs.scroll.getBoundingClientRect().width) / 2, ROOT_Y - 50);
|
||||
},
|
||||
},
|
||||
});
|
||||
const panelDataMap = new WeakMap();
|
||||
@@ -1281,7 +1327,14 @@ module.exports = Editor.Panel.define({
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {},
|
||||
methods: {
|
||||
initSelection() {
|
||||
const vm = panelDataMap.get(this);
|
||||
if (vm) {
|
||||
vm.initSelection();
|
||||
}
|
||||
},
|
||||
},
|
||||
ready() {
|
||||
if (this.$.app) {
|
||||
const vm = new component();
|
||||
|
2
dist/runtime/core/Blackboard.js
vendored
2
dist/runtime/core/Blackboard.js
vendored
@@ -22,5 +22,5 @@ class Blackboard {
|
||||
this.map.clear();
|
||||
}
|
||||
}
|
||||
exports.Blackboard = Blackboard;
|
||||
Blackboard.map = new Map();
|
||||
exports.Blackboard = Blackboard;
|
||||
|
Reference in New Issue
Block a user