'use strict'; let reEditing = false; let reSaving = false; let reEditingModelString = null; let reEditingUuid = null; let reEditingName = null; module.exports = { load () { // 当 package 被正确加载的时候执行 //console.log("behaviortree-editor loaded"); }, unload () { // 当 package 被正确卸载的时候执行 //console.log("behaviortree-editor unloaded"); }, messages: { 'test' (e,arg){ Editor.log(arg); Editor.log(Editor.metas); }, 're-open-by-comp' (e,arg) { if(reEditing){ Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "you are locked in re-editing mode.", detail:"leave the re-editing mode and try again. maybe you should save first." },function(){}); return}; reEditing = true; Editor.Panel.open("behaviortree-editor"); //Editor.Ipc.sendToPanel('behaviortree-editor','load-data',); //Editor.log(arg.uuid); Editor.Ipc.sendToMain("asset-db:query-path-by-uuid",arg.uuid,function(e,result){ //Editor.log(e); //Editor.log(result); let fs_handler = require('fs'); fs_handler.readFile(result, "utf-8", function(err, data) { //Editor.log(data); let modelString= data.match(/\/\/#########################################.*#############################################/)[0].replace(/#*/g,"").replace(/^\/\//,""); reEditingModelString = modelString; reEditingUuid = arg.uuid; reEditingName = arg.name; //Editor.log(reEditingName); //Editor.log(modelData); //Editor.Ipc.sendToPanel("behaviortree-editor","re-modify-by-comp",{modelString:modelString,uuid:arg.uuid}); //require('electron').ipcMain.send('behaviortree-editor:re-modify-by-comp',{modelString:modelString,uuid:arg.uuid}); //Editor.log(Editor.Ipc); }); }); }, 'load-data-of-comp' (e,arg){ if(!reEditing){Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "you are not in re-editing mode", detail:"you can enter the re-editing mode from behaviortree-Component." },function(){}); e.reply(null,{error: true}); }else{ if(reSaving){Editor.log(Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "please wait the temp saving", detail:"after saving, you can load from lasteat saved data if in re-editing mode." },function(){}));e.reply(null,{error:true})} else{ e.reply(null,{error: false, reEditingModelString:reEditingModelString, reEditingName: reEditingName}); } } }, 'leave-re-editing-mode' (e){ reEditing = false; Editor.log(Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "you leave re-editing mode", detail:"in new mode the file would saved as default way.and just close the edit-panel would not leave re-editing mode." },function(){}));e.reply(null,{error:true}) e.reply(null,{}); }, 'open' () { Editor.Panel.open("behaviortree-editor"); }, 'receive-json' (e,arg) { let modelAsObj = arg; //console.log(modelAsObj); let nodeDataArray = modelAsObj.nodeDataArray; let getNodeByType = function(type){ for(let node of nodeDataArray){ if(node.type == type){ return node; } } }; let getNodesByParentKey = function(key){ let nodes = []; for(let node of nodeDataArray){ if(node.parent!== undefined && node.parent == key){ nodes.push(node); } } return nodes; }; let orderFromTopToDown = function(a,b){ let ay = a.loc.split(" ")[1]; let by = b.loc.split(" ")[1]; //Editor.log(ay,by,(ay - by) | 0); return (ay - by) | 0; } let rootNode = getNodeByType("Root"); let generateTreeLayerString = function(parentNode,childNodes){ let children = []; for(let childNode of childNodes){ if(childNode.name == childNode.type){ children.push("new b3." + childNode.type + "(" + "##key" + childNode.key +"##" +")"); }else{ children.push("new " + childNode.name + "(" +"##key" + childNode.key +"##"+ ")"); } // if(childNode.parameter){ // console.log(childNode.parameter.replace(/\"/g,"'")); // } } let tempParameter = JSON.parse(parentNode.parameter); let resultObj = {}; resultObj.parameter = parentNode.parameter.replace(/"/g,"'"); switch(parentNode.type){ case 'Limiter': case 'RepeaterUntilFailure': case 'RepeaterUntilSuccess': case 'Repeater':{resultObj.maxLoop = tempParameter.maxLoop; break;} } switch(parentNode.type){ case 'MaxTime': {resultObj.maxTime = rtempParameter.maxTime; break;} } switch(parentNode.type){ case 'Wait': {resultObj.milliseconds = tempParameter.milliseconds; break;} } switch(parentNode.catagory){ case 'Composite': {resultObj.children = children; break;} } switch(parentNode.catagory){ case 'Decorator': {resultObj.child = children[0]; break;} } return JSON.stringify(resultObj); } let nodeQuene = []; nodeQuene.push(rootNode); let finalString = "new b3.Sequence(##key" + rootNode.key +"##)"; while(nodeQuene.length != 0){ let node = nodeQuene.shift(); let childNodes = getNodesByParentKey(node.key); let orderedChildNodes = childNodes.sort(orderFromTopToDown); nodeQuene = nodeQuene.concat(orderedChildNodes); let gString = generateTreeLayerString(node,orderedChildNodes); finalString = finalString.replace("##key"+node.key+"##",gString); } //console.log(finalString); let customNodeString = "let self = this;\n"; let hasGeneratedNodes = []; for(let node of nodeDataArray){ if(hasGeneratedNodes[node.name] != undefined){continue;} if(node.name != node.type || node.type == 'Action' || node.type == 'Condition' || node.type == 'Composite' || node.type == 'Decorator'){ hasGeneratedNodes[node.name] = true; customNodeString += "let "+node.name+" = b3.Class(b3."+node.type+");\n" + node.name+".prototype.name = '"+node.name+"';\n" + node.name+".prototype.__"+node.catagory+"_initialize = "+node.name+".prototype.initialize;\n" + node.name+".prototype.initialize = function(settings){\n" + " settings = settings || {};\n" + " this.__"+node.catagory+"_initialize();\n" + " this.parameter = settings.parameter;\n"; switch(node.type){ case 'Limiter': case 'RepeaterUntilFailure': case 'RepeaterUntilSuccess': case 'Repeater':{customNodeString += "this.maxLoop = settings.maxLoop;\n";break;} } switch(node.type){ case 'MaxTime': {customNodeString += "this.maxTime = settings.maxTime;\n";break;} } switch(node.type){ case 'Wait': {customNodeString += "this.milliseconds = settings.milliseconds;\n";break;} } switch(node.catagory){ case 'Composite': {customNodeString += "this.children = settings.children;\n";break;} } switch(node.catagory){ case 'Decorator': {customNodeString += "this.child = settings.child;\n";break;} } customNodeString += "}\n" + node.name+".prototype.enter = function(tick){\n" + " return self.getComponent('"+node.name+"').enter(tick,b3,this);\n" + "}\n" + node.name+".prototype.open = function(tick) {\n" + " return self.getComponent('"+node.name+"').open(tick,b3,this);\n" + "}\n" + node.name+".prototype.tick = function(tick) {\n" + " return self.getComponent('"+node.name+"').tick(tick,b3,this);\n" + "}\n" + node.name+".prototype.close = function(tick) {\n" + " return self.getComponent('"+node.name+"').close(tick,b3,this);\n" + "}\n" + node.name+".prototype.exit = function(tick) {\n" + " return self.getComponent('"+node.name+"').exit(tick,b3,this);\n" + "}\n"; } } let tipsString = "//Don't modify this if you want to re-modify the behaviortree in the future\n"; let modelString = "//#########################################" + JSON.stringify(modelAsObj) + "#############################################\n"; //添加js脚本 // let mainString = tipsString + // modelString + // "\n" + // "\n" + // "cc.Class({\n" + // "extends: cc.Component,\n" + // "editor: {\n" + // "inspector: 'packages://behaviortree-editor/bt-inspector.js'\n"+ // "},\n" + // "properties: {\n" + // "},\n" + // "onLoad: function () {\n" + // "let b3 = require('b3core.0.1.0module');\n"+ // customNodeString + // "let tree = new b3.BehaviorTree();\n"+ // "tree.root = " + finalString.replace(/"/g,"") + ";\n"+ // "this.tree = tree;\n"+ // "this.blackboard = new b3.Blackboard();\n" + // "this.b3 = b3;\n" + // "},\n" + // "tick: function(target){\n"+ // "let t = {};\n" + // "if(target != undefined){t = target;}\n" + // "this.tree.tick(t,this.blackboard)\n" + // "}" + // "});\n"; // 添加ts脚本 let mainString = tipsString + modelString + "\n" + "\n" + "const {ccclass, property} = cc._decorator;\n" + "export default class newClass extends cc.Component {\n" + "editor: {\n" + "inspector: 'packages://behaviortree-editor/bt-inspector.js'\n"+ "},\n" + // "properties: {\n" + // "},\n" + "onLoad () {\n" + "let b3 = require('b3core.0.1.0module');\n"+ customNodeString + "let tree = new b3.BehaviorTree();\n"+ "tree.root = " + finalString.replace(/"/g,"") + ";\n"+ "this.tree = tree;\n"+ "this.blackboard = new b3.Blackboard();\n" + "this.b3 = b3;\n" + "},\n" + "tick(target){\n"+ "let t = {};\n" + "if(target != undefined){t = target;}\n" + "this.tree.tick(t,this.blackboard)\n" + "}" + "});\n"; + "}\n"; //console.log(mainString); let fs_handler = require("fs"); if(reEditing){ Editor.Ipc.sendToMain("asset-db:query-url-by-uuid",reEditingUuid,function(e,result){ fs_handler.writeFileSync(Editor.url(result),mainString); Editor.Ipc.sendToMain("asset-db:refresh",result,function(err,results){ reSaving = true; fs_handler.readFile(Editor.url(result), "utf-8", function(err, data) { let modelString= data.match(/\/\/#########################################.*#############################################/)[0].replace(/#*/g,"").replace(/^\/\//,""); reEditingModelString = modelString; reSaving = false; Editor.log(Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "file of re-edit saved", detail:"you could see something blink blink in assetdb. take care of the component name." },function(){})); }); }); }); } else{ //生成行为树组件脚本 //添加js脚本 // fs_handler.writeFileSync(Editor.url("db://assets/BehaviorTree.js"),mainString); // Editor.Ipc.sendToMain("asset-db:refresh","db://assets/BehaviorTree.js",function(err,results){ //添加ts脚本 fs_handler.writeFileSync(Editor.url("db://assets/script/behaviorTrees/BehaviorTree.ts"),mainString); Editor.Ipc.sendToMain("asset-db:refresh","db://assets/script/behaviorTrees/BehaviorTree.ts",function(err,results){ Editor.log(Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "file of new saved", detail:"you could see something new(maybe) in assetdb. take care of the component name." },function(){})); }); } }, 'add-lib' () { let fs_handler = require("fs"); fs_handler.writeFileSync(Editor.url("db://assets/script/behaviorTrees/b3core.0.1.0module.js"), fs_handler.readFileSync(Editor.url("packages://behaviortree-editor/b3core.0.1.0module.js"))); Editor.Ipc.sendToMain("asset-db:refresh","db://assets/script/behaviorTrees/b3core.0.1.0module.js",function(err,results){ Editor.log(Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "behaviortree lib added", detail:"even though the lib name is ugly, but don't modify it please." },function(){})); }); }, 'generate-tree-node-template' (){ // 添加js脚本 // let mainString = "cc.Class({\n" + // "extends: cc.Component,\n" + // "\n" + // "properties: {\n" + // "\n" + // "},\n" + // "\n" + // "\n" + // "onLoad: function () {\n" + // "\n" + // "},\n" + // "enter: function(tick,b3,treeNode){\n" + // "\n" + // "},\n"+ // "open: function(tick,b3,treeNode){\n" + // "\n"+ // "},\n" + // "tick: function(tick,b3,treeNode){\n" + // "\n"+ // "},\n" + // "close: function(tick,b3,treeNode){\n" + // "\n" + // "},\n" + // "exit: function(tick,b3,treeNode){\n" + // "\n" + // "},\n" + // "\n" + // "});\n"; // 添加ts脚本 let mainString = "const {ccclass, property} = cc._decorator;\n" + "export default class newClass extends cc.Component {\n" + "\n" + // "properties: {\n" + // "\n" + // "},\n" + "\n" + "\n" + "onLoad () {\n" + "\n" + "},\n" + "enter (tick,b3,treeNode){\n" + "\n" + "},\n"+ "open (tick,b3,treeNode){\n" + "\n"+ "},\n" + "tick (tick,b3,treeNode){\n" + "\n"+ "},\n" + "close (tick,b3,treeNode){\n" + "\n" + "},\n" + "exit (tick,b3,treeNode){\n" + "\n" + "},\n" + "\n" + "});\n"; + "}\n"; let fs_handler = require("fs"); // 添加js脚本 // fs_handler.writeFileSync(Editor.url("db://assets/TreeNodeTemplate.js"), mainString); // Editor.Ipc.sendToMain("asset-db:refresh","db://assets/TreeNodeTemplate.js",function(err,results){ // 添加ts脚本 fs_handler.writeFileSync(Editor.url("db://assets/script/behaviorTrees/TreeNodeTemplate.ts"), mainString); Editor.Ipc.sendToMain("asset-db:refresh","db://assets/script/behaviorTrees/TreeNodeTemplate.ts",function(err,results){ Editor.log(Editor.Dialog.messageBox ({ type:"none", buttons: ["shut up"], title:"tips", message: "treenode code template generated", detail:"look more about the code and the src in behaviortree lib to get more tips" },function(){})); }); }, }, };