123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658 |
- const path = require("path")
- /** 包名 */
- const PACKAGE_NAME = require('../package.json').name;
- const scriptTemplate = require('../package.json').scriptTemplate;
- const StringUtil = require("./../src/utils/string-util")
- const fs = require("fs");
- let wait = ms => new Promise(async resolve => setTimeout(resolve, ms));
- let old = cc._decorator.ccclass;
- const TOOL_CACHE_KEY = '__TOOL_CACHE_KEY__';
- const CACHE_KEY = '__ccclassCache__';
- if (!cc._decorator.ccclass["isnew"]) {
- cc._decorator.ccclass = function (ctor, name) {
- let s = ctor[CACHE_KEY];
- ctor[TOOL_CACHE_KEY] = ctor[CACHE_KEY];
- let wu = ctor[TOOL_CACHE_KEY];
- let ret = old.call(this, ctor, name);
- return ret;
- };
- }
- cc._decorator.ccclass["isnew"] = true;
-
- let HeadMenu = {
- "node": "cc.Node",
- "list": "cc.ScrollView",
- "lb": "cc.Label",
- "spr": "cc.Sprite",
- "rich": "cc.RichText",
- "btn": "cc.Button",
- "bar": "cc.ProgressBar",
- "edit": "cc.EditBox",
- "video": "cc.VideoPlayer",
- "bone": "dragonBones.ArmatureDisplay",
- "spine": "sp.Skeleton"
- };
- let replace = '\n\
- /*自动生成*/\n\
- @property({type:{type}, displayName:""})\n\
- private {name}:{type} = null;\n\
- ';
- const PattStart = '===========================自动绑定组件开始===========================';
- const PattEnd = '===========================自动绑定组件结束===========================';
- const PattStart_BTN = '===========================自动生成按钮事件开始==========================';
- const PattEnd_BTN = '===========================自动生成按钮事件结束==========================';
- //缓存全部需要绑定的节点
- let caches = {};
- let oldCodeMap = {}
- let oldCodeFunction = {}
- module.exports = {
- // 新建ts模板路径
- getTsTemplatePath(){
- return Editor.url(`packages://${PACKAGE_NAME}/${scriptTemplate}`, 'utf8')
- },
-
-
- print:function(nodes){
- for (const key in nodes) {
- const node = nodes[key];
- Editor.log(key,node);
- }
- },
-
- /**
- * 等待3次检查 要检查绑定了才刷新
- */
- async bindRef(data){
- await wait(1000);
- this.bindSciprt(data);
- await wait(1000);
- this.bindSciprt(data);
- //刷新脚本
- Editor.assetdb.refresh(data.jsPath,(err, results)=>{
- if(err){
- data.event.reply(null,"刷新失败"+err);
- }else{
- data.event.reply("刷新成功",results);
- }
- });
-
- Editor.Scene.callSceneScript(PACKAGE_NAME, 'add-script',function(error,obj){
- if(obj){
- return Editor.log(obj);
- }
- //执行回来的操作
- });
- },
- /**
- * 绑定脚本到Node上
- */
- bindSciprt(data){
- let node = this.findNode(data.uuid)
- let comp = node.getComponent(data.jsFileName);
- if(!comp){
- try {
- comp = cc.require(data.jsFileName)
- } catch(t) {}
- // 添加组件
- if (comp){
- node.addComponent(data.jsFileName);
- }
- }
- },
- async createTs(node,event){
- let self = this;
- let uuid = node.uuid;
- let file_type = ".ts";
- let jsFileName = node.name;
- jsFileName = StringUtil.firstLowerCase(jsFileName);
- let templateTs = fs.readFileSync(this.getTsTemplatePath(),'utf-8');
- //获取当前节点的路径
- let obj = await this.getCurrSceneUrl();
- let url = this.getNewFileSavePath(obj.url);
- //创建文件夹
- this.createDir(Editor.url(url));
- templateTs = templateTs.replace(/ScriptTemplate/g, jsFileName);
- let jsPath = `${url}${jsFileName}${file_type}`;
- //Editor.log("创建脚本位置",jsPath)
- Editor.assetdb.createOrSave( jsPath, templateTs, ( err, results )=>
- {
- if(err) return event.reply(null,"创建脚本失败");
- self.bindRef({
- uuid:uuid,
- node:node,
- jsFileName:jsFileName,
- jsPath:jsPath,
- event:event
- });
- });
- },
-
- /**
- * 添加脚本
- * @param {*} event
- * @param {{ uuids: string[], name: string }} data 数据
- */
- 'add-script':async function(event) {
- oldCodeMap = {}
- let obj = await this.getCurrSceneUrl();
- if(!obj) return event.reply("当前没有选中任何节点");
- let self = this;
-
- // 发消息给主进程进行关键词匹配
- let file_type = localStorage.getItem("newFileType")|| ".ts"
- //当前选中的Node
- let head_node = Editor.Selection.curSelection('node')[0];
- //当前选中Node之下的全部节点
- let nodes = this.findNode(head_node);
- //只挂载脚本
- let jsFile = this.isHasJsFile(nodes);
- if (jsFile)
- {
- let node_uids = Editor.Selection.curSelection("node");
- //Editor.log(node_uids, node_uids.length);
- for (let i = 0; i < node_uids.length; i++) {
- let id = node_uids[i];
- Editor.Scene.callSceneScript(PACKAGE_NAME, "auto_code_binder", id);
- }
- }else
- {
- //创建挂载脚本
- this.createTs(nodes,event);
-
- }
- },
- /**
- * 生成代码属性
- *
- * 属性 写入文件
- */
- "auto_code_binder":function(event,uuid){
- caches = {};
- let node = cc.engine.getInstanceById(uuid);
- if (!node) {
- Editor.log("没有找到需要的节点");
- return;
- }
- //开始整个文件查找节点
- this.findChildren(node);
- //获取组件脚本绑定
- let coms = node.getComponents(cc.Component);
- if(coms && coms.length <= 0){
- Editor.warn("该节点下没有脚本组件");
- return;
- }
- for (let com of coms) {
- let name = cc.js.getClassName(com);
- let btns = {};
- //排除系统组件
- if (!name.startsWith("cc.") && !name.startsWith("sp.")) {
- // Editor.warn("自定义脚本",name);
- let comUuid = com.__scriptUuid;
- let path = Editor.remote.assetdb.uuidToFspath(comUuid);
- let tsScriptData = fs.readFileSync(path, "utf-8");
- let patt = new RegExp(`${PattStart}[\\s\\S]*${PattEnd}\*`, "gm");
- let res = tsScriptData.match(patt);
- let data = res === null || res === void 0 ? void 0 : res.toString();
- // Editor.warn("代码内容",data);
- //结束
- if (!res) {
- Editor.log("=====脚本中没有发现替代注释 请在需要添加组件的地方复制粘贴以下注释======");
- Editor.log(`/*${PattStart}*/`);
- Editor.log(`/*${PattEnd}*/`);
- return;
- }
- this.parseText(data);
- let str = `${PattStart}*/`;
- let seq = 0;
- let funcSeq = 0;
- for (const key in caches) {
- const node = caches[key];
- if(node){
- let n = this.getHeadString(key);
- let type = HeadMenu[n];
- if(type == "cc.Button"){
- btns[key] = key;
- }
- if(!type){
- Editor.warn("发现不知道的类型",key);
- continue;
- }
- let old = oldCodeMap[key];
- if (old) {
- if(seq == 0){str += "\n"}
- str += "\t" + old.content + "\n";
- seq +=1;
- }else{
- let txmp = replace;
- if (type) {
- txmp = txmp.replace(new RegExp(/({type})/g,"gm"),type)
- txmp = txmp.replace("{name}", key);
- }
- str += txmp;
- }
- }
- }
- str += "\n\t/*" + PattEnd + "";
- tsScriptData = tsScriptData.replace(res.toString(), str);
-
- //生成按钮方法属性
- let patt_btn = new RegExp(`${PattStart_BTN}[\\s\\S]*${PattEnd_BTN}\*`, "gm");
- let result = tsScriptData.match(patt_btn);
- let btnFuncs = result === null || result === void 0 ? void 0 : result.toString();
- //结束
- if (!btnFuncs) {
- //Editor.log("=====脚本中没有发现替代注释 请在需要添加组件的地方复制粘贴以下注释======");
- //Editor.log(`/*${PattStart}*/`);
- //Editor.log(`/*${PattEnd}*/`);
- return;
- }
- oldCodeFunction = {};
- this.parseFunction(btnFuncs);
- let newStr = `${PattStart_BTN}*/\n`;
- for (const key in btns) {
- const name = btns[key];
- let funcName = `on${this.getFunctionString(name)}TouchEnd`;
- let old = oldCodeFunction[funcName];
- if (old) {
- if(funcSeq == 0){newStr += "\n"}
- newStr += "\t" + old + "\n";
- funcSeq +=1;
- }else{
- let str = `\t${funcName}(){}\n\n`
- newStr += str ;
- }
- }
- newStr += "\n\t/*" + PattEnd_BTN;
- tsScriptData = tsScriptData.replace(result.toString(), newStr);
- fs.writeFileSync(path, tsScriptData);
- this.waitRefreshScript(comUuid,node);
- }
- }
- },
- parseFunction(data){
- if (!data) {
- return;
- }
- let reg = data.match(/on*([\s\S]*?)}/g);
- if (!reg) {
- return;
- }
- for (let i = 0; i < (reg === null || reg === void 0 ? void 0 : reg.length); i++) {
- let str = reg[i];
- let type = str.match(/on([\s\S]*?)TouchEnd/)[0];
- if (!type) {
- continue;
- }
- oldCodeFunction[type] = str;
- }
- },
-
- parseText(data){
- if (!data) {
- return;
- }
- let reg = data.match(/\/\*自动生成\*\/([\s\S]*?);/g);
- if (!reg) {
- //Editor.log("没有匹配");
- return;
- }
- for (let i = 0; i < (reg === null || reg === void 0 ? void 0 : reg.length); i++) {
- let str = reg[i];
- let type = str.match(/type:([\s\S]*?),/)[0];
- if (!type) {
- continue;
- }
- type = type === null || type === void 0 ? void 0 : type.replace("type:", "");
- type = type === null || type === void 0 ? void 0 : type.replace(",", "");
- type = type.trim();
- let name = str.match(/(private|public)([\s\S]*?):/)[0];
- if (!name) {
- continue;
- }
- name = name === null || name === void 0 ? void 0 : name.replace(/(private|public)/, "");
- name = name === null || name === void 0 ? void 0 : name.replace(":", "");
- name = name.trim();
- let old = {};
- old.content = str;
- old.name = name;
- old.type = type;
- oldCodeMap[name] = old;
- }
- },
- //执行刷新
- async waitRefreshScript(comUuid,node){
- let obj = await this.getCurrSceneUrl();
- let assetPath = Editor.remote.assetdb.uuidToUrl(comUuid);
- Editor.assetdb.refresh(assetPath);
- Editor.assetdb.refresh(obj.url);
- //wait(2000)
- //Editor.Scene.callSceneScript(PACKAGE_NAME, "bind_Code_ByNode");
- },
- //生成属性到脚本
- "generate_attribute":function(){
-
- let head_node = Editor.Selection.curSelection('node')[0];
- if(!head_node) return Editor.log("没有选中节点");
- //当前选中Node之下的全部节点
- let nodes = this.findNode(head_node);
- //只挂载脚本
- let jsFile = this.isHasJsFile(nodes);
- if (jsFile)
- {
- //Editor.log("当前有脚本",jsFile.__classname__)
- let node_uids = Editor.Selection.curSelection("node");
- Editor.log(node_uids, node_uids.length);
- for (let i = 0; i < node_uids.length; i++) {
- let id = node_uids[i];
- Editor.Scene.callSceneScript(PACKAGE_NAME, "auto_code_binder", id);
- }
- }else
- {
- //创建挂载脚本
- Editor.log("当前节点没有挂载节点")
- }
- },
- /**
- * 绑定节点到代码
- */
- "bind_Code_ByNode":async function(event){
- let uuid = Editor.Selection.curSelection('node');
- let node = cc.engine.getInstanceById(uuid);
- caches = {};
- if (!node) {
- Editor.log("没有找到需要的节点");
- return;
- }
- //开始整个文件查找节点
- this.findChildren(node);
- this.bindCodeByNode();
- },
- //开始关联
- bindCodeByNode(){
- let uuid = Editor.Selection.curSelection('node');
- let node = cc.engine.getInstanceById(uuid);
- if(!node)return Editor.warn("====请选择一个节========"); ;
- //记录绑定信息
- let coms = node.getComponents(cc.Component);
- for (let com of coms) {
- let name = cc.js.getClassName(com);
- //过滤
- if (name.startsWith("cc.") || name.startsWith("sp.")) { continue };
- let comUuid = com.__scriptUuid;
- let cache = com.constructor[TOOL_CACHE_KEY];
- if(!cache){
- return;
- }
- for (let key in com) {
- if (caches[key]) {
- if(key == "constructor") continue;
- let data = cache.proto.properties[key];
- let children = caches[key];
- if (children) {
- let nodes = children.filter(node => {
- if (data.type == cc.Node) {
- return node;
- }
- return node.getComponent(data.type);
- });
- if (nodes && nodes.length) {
- let first = nodes[0];
- let needCom = null;
- if (data.type == cc.Node) {
- needCom = first;
- } else {
- needCom = first.getComponent(data.type);
- }
- com[key] = needCom;
- //按钮统一格式
- if(cc.Button == data.type){
- let clickEvents = needCom.clickEvents;
- //查找是否已经绑定过了
- let funcName = `on${this.getFunctionString(key)}TouchEnd`
- let isBind = false;
- //查找是否绑定了规定函数
- for (let index = 0; index < clickEvents.length; index++) {
- const clickEvent = clickEvents[index];
- if(clickEvent.handler == funcName){
- isBind = true;
- }
- }
- //绑定自动生成的函数
- if(!isBind){
- var clickEventHandler = new cc.Component.EventHandler();
- //这个 node 节点是你的事件处理代码组件所属的节点
- clickEventHandler.target = node;
- clickEventHandler.component = name;//这个是代码文件名
- clickEventHandler.handler = funcName; //回调函数
- needCom.clickEvents.push(clickEventHandler);
- }
- //设置默认的按钮样式
- // needCom
- needCom.transition = cc.Button.Transition.SCALE;
- needCom.duration = 0.1;
- needCom.zoomScale = 1.2;
- }
- continue;
- }
- }
- }
- }
- let assetPath = Editor.remote.assetdb.uuidToUrl(comUuid);
- Editor.assetdb.refresh(assetPath);
- //Editor.Ipc.sendToMain('assets:open-text-file', comUuid);
- }
-
- Editor.log("=======绑定结束========");
- },
-
- getHeadString:function(str, fortmat = "_") {
- if (!str) {
- return str;
- }
- let res = str.split(fortmat);
- return res[1];
- },
- getFunctionString:function(str, fortmat = "_") {
- if (!str) {
- return str;
- }
- let res = str.split(fortmat);
- let name = res[0]
- if(name.indexOf("$") > -1){
- name = name.substring(name.indexOf("$")+1,name.length);
- return StringUtil.firstUpperCase(name);
- }
- return StringUtil.firstUpperCase(name);
- },
-
- findChildren:function(node) {
- let children = node.children;
- for (let i = 0; i < children.length; i++) {
- let child = children[i];
- if(child.name.indexOf("@") > -1) continue;
- let idx = child.name.indexOf("$");
- if(idx > -1){
- if(caches[child.name] == null){
- caches[child.name] = [];
- }
- caches[child.name].push(child);
- }
- if(child.childrenCount > 0){
- this.findChildren(child)
- }
- }
- },
-
- dump(obj){
- let str = ""
- let i = 0
- for(let name in obj) {
- try{
- str += name + ": " + obj[name] + "\n"
- }catch(err){
- str += name + ": " + typeof obj[name] + "\n"
- }
- i ++;
- if (i>100){
- str+="...more"
- break;
- }
- }
- Editor.log("dump:"+obj,str)
- },
-
- // 保存新建脚本路径
- getNewFileSavePath(node_url){
- // 如果是预制体 脚本就生成到Sciprt下
- if(node_url.lastIndexOf(".prefab") > -1){
- let str = node_url.substr(0,node_url.lastIndexOf("/"))
- return str.replace("prefab","Script") + "/";
- }else{
- return node_url.substr(0,node_url.lastIndexOf("/")) + '/'; //保存到预制节点的同级目录
- }
- // return node_url.substr(0,node_url.lastIndexOf("/")) + '/';
- },
- // 创建目录,绝对路径
- createDir(dirPath){
- if ( fs.existsSync(dirPath) ) return;
- let paths = dirPath.split(path.sep);//分割路径
- let path_ = "";
- for (let n = 0; n < paths.length; n++) {
- path_ += paths[n] + path.sep;
- if(!fs.existsSync(path_)){
- fs.mkdirSync(path_);
- }
- }
- },
- // 获得当前打开的场景文件路径
- async getCurrSceneUrl(callFunc){
- return new Promise((resolve)=>{
- let obj = {};
- let scene = cc.director.getScene();
- if(scene){
- let url = Editor.remote.assetdb.uuidToUrl(scene.uuid);
- if (url){
- obj.url = url
- obj.isScene = true
- obj.uuid = scene.uuid;
- return resolve(obj);
- }else{
- // 当前打开的预制节点路径
- Editor.Ipc.sendToMain(`${PACKAGE_NAME}:getPrefabUuid`,{}, function (error, answer)
- {
- if (answer != null){
- obj.url = Editor.remote.assetdb.uuidToUrl(answer)
- obj.isScene = false
- obj.uuid = answer;
- return resolve(obj);
- }else{
- resolve(null);
- }
- });
- }
- }else{
- // 当前打开的预制节点路径
- Editor.Ipc.sendToMain(`${PACKAGE_NAME}:getPrefabUuid`,{}, function (error, answer)
- {
- if (answer != null){
- obj.url = Editor.remote.assetdb.uuidToUrl(answer)
- obj.isScene = false
- obj.uuid = answer;
- return resolve(obj);
- }else{
- resolve(null);
- }
- });
- }
- })
- },
- // 检测场景是否存在该子节点并返回相关信息
- findNode(select_uuid)
- {
- var canvas = cc.director.getScene();
- var ret_node
- if (canvas && select_uuid) {
- this.getNodeChildren(canvas,(node)=>{
- if (node.uuid == select_uuid){
- ret_node = node;
- return ret_node;
- }
- })
- }
- return ret_node;
- },
- // 遍历所有深层子节点
- getNodeChildren(node,callFunc)
- {
- if (!node) return;
- let nodes = node.getChildren();
- nodes.forEach((v)=>{
- v._path_str = (node._path_str || node.name)+"/" + v.name;
- this.getNodeChildren(v,callFunc)
- });
- callFunc(node)
- },
- getNodeReChildren(node,callFunc)
- {
- if (!node) return;
- let nodes = node.getChildren();
- callFunc(node)
- nodes.forEach((v)=>{
- v._path_str = (node._path_str || node.name)+"/" + v.name;
- this.getNodeReChildren(v,callFunc)
- });
- },
- isHasJsFile(node){
- if(!node) {return false};
- return this.getJsFileList(node)[0];
- },
- getJsFileList(node){
- if(!node) {return []};
- let list = [];
- node.getComponents(cc.Component).forEach((v)=>{
- if(v.__classname__ && v.__classname__.indexOf(".") == -1) list.push(v); //js脚本
- });
- return list;
- },
- }
|