panel_ex.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /*
  2. 面板扩展
  3. 功能: 绑定组件到代码
  4. */
  5. 'use strict';
  6. const path = require('path');
  7. const fs = require('fs');
  8. const md5 = require('md5');
  9. const config = require('../../config');
  10. const tools = require('../../tools/tools');
  11. const prsPath = Editor.Project && Editor.Project.path ? Editor.Project.path : Editor.remote.projectPath;
  12. let is_lock = false;
  13. let ASSETS_TYPE_MAP = {'sprite-atlas':"cc.SpriteAtlas",'sprite-frame':"cc.SpriteFrame",'texture':"cc.SpriteFrame",'prefab':"cc.Prefab",
  14. 'audio-clip':'cc.AudioClip','raw-asset':'cc.RawAsset','dragonbones':'dragonBones.DragonBonesAsset','dragonbones-atlas':'dragonBones.DragonBonesAtlasAsset',
  15. 'spine':'sp.SkeletonData',"particle":"cc.ParticleAsset",'asset':'cc.Asset','material':'cc.Material','mesh':'cc.Mesh','skeleton-animation-clip':'cc.SkeletonAnimationClip'};
  16. let IS_URL_TYPE = ['cc.AudioClip','cc.RawAsset','cc.Asset']
  17. // 拖拽加入组件优先顺序
  18. let QUICK_LOAD_TYPE_ORDER = ['cc.SkinnedMeshRenderer','cc.MeshRenderer','cc.Slider','cc.ProgressBar','cc.Toggle','dragonBones.ArmatureDisplay','sp.Skeleton','cc.Animation','cc.Sprite','cc.Label','cc.EditBox','cc.RichText']
  19. let NEW_VAR_RULE = path.join(path.resolve(__dirname,"./"),"drag_var_rule.js");
  20. let USER_NEW_VAR_RULE = path.join(config.cacheDir,"drag_var_rule.js");
  21. module.exports = {
  22. /** @type import('../../panel/vs-panel/vs-panel-base') */
  23. parent : null,
  24. // 面板初始化
  25. onLoad(parent){
  26. // index.js 对象
  27. this.parent = parent;
  28. this.currSelectInfo = {}
  29. // 首次使用拷贝模板到可写路径
  30. if(!tools.isFileExit(USER_NEW_VAR_RULE)){
  31. tools.createDir(USER_NEW_VAR_RULE)
  32. tools.copyFile(NEW_VAR_RULE,USER_NEW_VAR_RULE)
  33. }
  34. },
  35. // 插入组件入口
  36. insertWidgetAction(isQuick,widgetType,insertUuids)
  37. {
  38. let nodes = insertUuids || Editor.Selection.curSelection('node') || [];
  39. Editor.Scene.callSceneScript('simple-code', 'getNodesInfo',nodes, (err, nodeInfos) =>{
  40. if(!nodeInfos.length) return;
  41. // 生成规则
  42. let rules = [];
  43. // 变量是否定义为数组类型
  44. let isArray = !isQuick && nodeInfos.length>1;
  45. let codeInfo = this.getCurrEditorFileInfo();
  46. // 加载多个变量
  47. for (let i = 0; i < nodeInfos.length; i++) {
  48. // 定义变量类型
  49. const nodeInfo = nodeInfos[i];
  50. let widgetType2 = 'cc.Node';
  51. if(widgetType){
  52. widgetType2 = nodeInfo.compNames.indexOf(widgetType) != -1 ? widgetType : widgetType2;
  53. }else{
  54. let orderList = require(USER_NEW_VAR_RULE).QUICK_LOAD_TYPE_ORDER || QUICK_LOAD_TYPE_ORDER;
  55. for (let i = 0; i < orderList.length; i++)
  56. {
  57. if( nodeInfo.compNames.indexOf(orderList[i]) != -1){
  58. widgetType2 = orderList[i];
  59. break;
  60. }
  61. }
  62. }
  63. rules.push({
  64. symbolName:nodeInfo.name,
  65. widgetType:widgetType2,
  66. nodeUuid:nodeInfo.uuid,
  67. })
  68. }
  69. if(isArray || !isQuick){
  70. // 加载单个变量
  71. let defineName = widgetType.indexOf('.') != -1 ? nodeInfos[0].name : widgetType
  72. this.loadSymbolName((symbolName)=>
  73. {
  74. rules.forEach((v)=>v.symbolName = symbolName);// 修改变量名
  75. this.loadWidgetRules(codeInfo,rules,isArray,false)
  76. },defineName || '',codeInfo.symbols)
  77. }else{
  78. this.loadWidgetRules(codeInfo,rules,isArray,true)
  79. }
  80. })
  81. },
  82. // 插入资源入口
  83. insertAssets(isQuick,insertUuids)
  84. {
  85. insertUuids = insertUuids || Editor.Selection.curSelection('asset');
  86. //1.读取选中的资源
  87. //2.解析资源类型 == cc.SpriteFrame ? || xxxx
  88. //3.接下来流程和加载组件一样
  89. if(insertUuids == null || insertUuids.length == 0){
  90. Editor.info("生成失败,由于Creator API限制,请点击一下需要拖动的资源然后再拖入")
  91. return
  92. }
  93. // 生成规则
  94. let rules = [];
  95. // 变量是否定义为数组类型
  96. let isArray = insertUuids.length > 1;
  97. let index = 0;
  98. // 读取默认规则配置
  99. for (let i = 0; i < insertUuids.length; i++) {
  100. Editor.assetdb.queryInfoByUuid(insertUuids[i],(_,fileInfo)=>
  101. {
  102. if(!fileInfo){
  103. return;
  104. }
  105. let widgetType = ASSETS_TYPE_MAP[fileInfo.type];
  106. if(widgetType==null){
  107. Editor.info('不支持插入的资源类型:',fileInfo.type,fileInfo)
  108. return;
  109. }
  110. let file_ = this.parent.fileMgr.getUriInfo(fileInfo.url);
  111. let symbolName = file_.name;
  112. if(file_.extname != ''){
  113. symbolName = symbolName.substr(0,symbolName.lastIndexOf('.'));
  114. }
  115. rules.push({
  116. symbolName:symbolName,
  117. widgetType:widgetType,
  118. assetUuid:insertUuids[i],
  119. })
  120. // 资源信息读取完再执行下面
  121. index++;
  122. if(index != insertUuids.length){
  123. return;
  124. }
  125. let codeInfo = this.getCurrEditorFileInfo();
  126. if(codeInfo == null){
  127. return;
  128. }
  129. if(isQuick){
  130. this.loadWidgetRules(codeInfo,rules,isArray,true)
  131. }else{
  132. this.loadSymbolName((symbolName)=>
  133. {
  134. rules.forEach((v)=>v.symbolName = symbolName);// 修改变量名
  135. this.loadWidgetRules(codeInfo,rules,isArray,false)
  136. },symbolName,codeInfo.symbols);
  137. }
  138. });
  139. }
  140. },
  141. // 加载自定义的组件
  142. loadCustomWidgetsToCode(codeInfo){
  143. if(this.parent.file_info == null || this.parent.file_info.uuid != codeInfo.editInfo.uuid ){
  144. return;
  145. }
  146. let info = Editor.Selection.curGlobalActivate();
  147. let rootNodeUuid = info.type == 'node' && info.id ? info.id : null;
  148. //1.获得生成组件规则
  149. Editor.Scene.callSceneScript('simple-code', 'getCustomWidgetRule',{rootNodeUuid,fileUuid: codeInfo.editInfo.uuid,url: codeInfo.editInfo.url}, (err, args) => {
  150. let rules = args.rules;
  151. this.loadWidgetRules(codeInfo,rules,false,true)
  152. });
  153. },
  154. /**
  155. * 读取规则
  156. 1.获得当前打开的脚本是否该场景内节点绑定的
  157. 2.获得与当前脚本绑定的Nodes
  158. 3.往脚本添加组件类型字段
  159. 4.往脚本的类型字段写入当前选中的组件或资源
  160. */
  161. loadWidgetRules(codeInfo,rules,isArray,isQuick){
  162. if(codeInfo == null || rules == null){
  163. return;
  164. }
  165. // 1.获得生成组件规则配置
  166. Editor.Scene.callSceneScript('simple-code', 'loadWidgetRules',{ rules:rules, isArray:isArray, scriptUuid:codeInfo.editInfo.uuid, isQuick:isQuick}, (err, args) => {
  167. // rules = [{symbolName:'',widgetType:'',nodeUuid:'',assetUuid:''}]
  168. rules = args.rules;
  169. isArray = args.isArray;
  170. if(this.parent.file_info.uuid != codeInfo.editInfo.uuid || !rules || rules.length == 0) {
  171. return;
  172. }
  173. if(!args.bindNodeList || args.bindNodeList.length == 0){
  174. alert("生成拖拽组件失败,当前场景Nodes没有绑定当前编辑中的脚本")
  175. return;
  176. }
  177. // 提供撤销
  178. codeInfo.editInfo.vs_model.pushStackElement();
  179. let oldCodeText = codeInfo.editInfo.vs_model.getValue();
  180. let isAssets = rules[0].assetUuid != null;
  181. if(isArray){
  182. // 数组类型成员变量
  183. let insertUuids = []; // 绑定到数组变量的组件们
  184. rules.forEach((v)=>{ insertUuids.push(v.nodeUuid || v.assetUuid) })
  185. this.newTextAndBindWidget(codeInfo,args.bindNodeList,rules[0],insertUuids,isArray,isAssets)
  186. }else{
  187. // 普通类型成员变量
  188. for (let i = 0; i < rules.length; i++) {
  189. let rule = rules[i];
  190. let isAssets = rule.assetUuid != null;
  191. let insertUuids = [rule.nodeUuid || rule.assetUuid]
  192. this.newTextAndBindWidget(codeInfo,args.bindNodeList,rule,insertUuids,isArray,isAssets)
  193. }
  194. }
  195. // 3.保存刷新creator生成变量拖拽组件
  196. this.saveFile(codeInfo.editInfo.vs_model,oldCodeText,rules);
  197. });
  198. },
  199. // 创建脚本的成员变量并绑定组件到成员变量
  200. newTextAndBindWidget(codeInfo,bindNodeList,rule,insertUuids,isArray,isAssets){
  201. let widgetType = rule.widgetType;
  202. let symbolName = rule.symbolName;
  203. if(!rule.disableGenerated)
  204. {
  205. if(symbolName.match(/[a-zA-Z_$][\w$]*/) == null){
  206. Editor.info('生成拖拽组件:变量命名不符合规范:',symbolName);
  207. return;
  208. }
  209. // 2.插入成员变量文本
  210. symbolName = this.insertTextToModel(widgetType,symbolName,codeInfo,isArray,rule);
  211. rule.symbolName = symbolName;
  212. }
  213. setTimeout(()=>{
  214. // 4.给成员变量赋值引用对象
  215. this.insertWidgetInfo(bindNodeList,widgetType,symbolName,isArray,insertUuids,isAssets,rule);
  216. },100);
  217. },
  218. // 变量名是否正常
  219. isNormalSymbolName(symbolName){
  220. if(symbolName.match(/[a-zA-Z_$][\w$]*/) == null || symbolName.match(/[\[\]\`\!\#\%\^\&\*\(\)\+\=\{\}\?\<\>\-]+/)){
  221. return false
  222. }
  223. return true;
  224. },
  225. insertWidgetInfo(bindNodeList,widgetType,symbolName,isArray,insertUuids,isAssets,rule){
  226. let args = {bindNodeList,widgetType,symbolName,isArray,insertUuids,isAssets,rule}
  227. Editor.Scene.callSceneScript('simple-code', 'insertWidgetInfo',args, (err, isEnd) => {
  228. // console.log('生成完成.',isEnd)
  229. });
  230. },
  231. getCurrEditorFileBindNodes(uuid,calback){
  232. let args = {code_uuid:uuid}
  233. Editor.Scene.callSceneScript('simple-code', 'getCurrEditorFileBindNodes',args, (err, bindNodeList) => {
  234. calback(bindNodeList);
  235. });
  236. },
  237. saveFile(model,oldCodeText,rules){
  238. // 加工代码块
  239. let codeText = model.getValue();
  240. Editor.Scene.callSceneScript('simple-code', 'saveWidgetCodeFile',{codeText:codeText, dbUrl:model.dbUrl, rules:rules}, (err, newCodeText) =>
  241. {
  242. model.setValue(newCodeText);
  243. // 1.保存刷新creator生成变量拖拽组件
  244. if(oldCodeText === null || oldCodeText != newCodeText){
  245. this.parent.saveFile(true,true);
  246. // 标记场景切换时需要保存*号
  247. Editor.Scene.callSceneScript('simple-code', 'scene-need-save')
  248. }
  249. });
  250. },
  251. // 面板销毁
  252. onDestroy(){
  253. },
  254. //3.往脚本添加组件类型字段
  255. insertTextToModel(widgetType,symbolName,codeInfo,isArray,rule)
  256. {
  257. // 1.获得脚本变量插入text位置
  258. // 2.获得插入组件文本内容
  259. // 3.向脚本指定位置插入获刚得到的文本,并保存文件
  260. let vs_model = codeInfo.editInfo.vs_model;
  261. let text = vs_model.getValue()
  262. let reg = codeInfo.isTs ? /class [a-zA-Z_$][\w$]* extends.*[\n]{0,5}[ ]{0,15}[ ]{0,5}{/ : /properties[ ]{0,5}:[ ]{0,5}[\n]{0,5}[ ]{0,15}{[ ]{0,5}/
  263. let findObj = text.match(reg);
  264. if(findObj)
  265. {
  266. // 变量名去掉不符合规则的符号
  267. symbolName = symbolName[0].toLowerCase() + symbolName.substr(1);
  268. symbolName = symbolName.replace(/( |\.|\-|\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\=|\+|\`|\<|\>|\?)/g,'');
  269. // 1.获得插入文本内容
  270. let startPos = findObj.index + findObj[0].length;
  271. let symbols = this.upSymbolInfoByName(text,codeInfo);
  272. let symbolInfo = this.getSymbolInfoByName(symbols,symbolName);
  273. let isUrl = IS_URL_TYPE.indexOf(widgetType) != -1;
  274. if(symbolInfo && symbolInfo.symbolName == symbolName && symbolInfo.widgetType == widgetType && !isArray == !symbolInfo.isArray){
  275. // 代码内已存在同名同类型变量,不再覆盖
  276. return symbolName;
  277. }
  278. try {
  279. let oldText = symbolInfo && symbolInfo.text;
  280. let insertText = require(USER_NEW_VAR_RULE).getInsertText(widgetType,symbolName,oldText,rule,isArray,codeInfo.isTs,isUrl);
  281. // 2.检测变量是否已经存在,若存在则需要替换旧的变量字符串
  282. if(symbolInfo){
  283. text = text.substr(0,symbolInfo.startPos)+insertText+text.substr(symbolInfo.endPos)
  284. }else{
  285. text = text.substr(0,startPos)+insertText+text.substr(startPos)
  286. }
  287. text = this.getInsertScriptImportPath(text,vs_model.dbUrl,widgetType,codeInfo.isTs);
  288. vs_model.setValue(text);
  289. } catch (error) {
  290. Editor.error('生成自定义绑定规则配置出错: ',error)
  291. }
  292. }
  293. return symbolName;
  294. },
  295. // 插入自定义脚本的import路径
  296. getInsertScriptImportPath(text,currPath,widgetType,isTs){
  297. if(!text || !currPath || widgetType.indexOf('.') != -1) {
  298. return text;
  299. }
  300. // 1.搜索脚本
  301. // 2.转换相对路径
  302. // 3.检测是路径否已存在
  303. // 4.搜索插入位置
  304. // 5.覆盖文本
  305. let reg = /(.js|.ts)/;
  306. let subReg = new RegExp(`(${widgetType}.js|${widgetType}.ts)`,'i');
  307. let fileUrl
  308. for (let i = 0; i < this.parent.file_list_buffer.length; i++) {
  309. const fileItem = this.parent.file_list_buffer[i];
  310. if(fileItem.extname.match(reg) && fileItem.value.match(subReg)){
  311. fileUrl = fileItem.meta;
  312. break;
  313. }
  314. }
  315. if(!fileUrl){
  316. return text;
  317. }
  318. let importPath = tools.fsPathToRelativePath(currPath,fileUrl)
  319. importPath = importPath.substr(0,importPath.length-3) // '.ts'.length == 3
  320. if(text.match(importPath)){
  321. return text; // import路径已存在
  322. }
  323. // 找出import的最后一行,将代码插入这一行下面
  324. let importText = isTs ? `import ${widgetType} from "${importPath}";` : `\nlet ${widgetType} = require("${importPath}");`
  325. let regImport = /import .+?from.+[\r\n]/g
  326. let temp
  327. let lastImort
  328. while(temp = regImport.exec(text)){
  329. lastImort = temp;
  330. }
  331. let insertPos = 0;
  332. if(lastImort){
  333. insertPos = lastImort.index + lastImort[0].length;
  334. importText = '\n' + importText
  335. }else{
  336. importText = importText + '\n'
  337. }
  338. text = text.substr(0,insertPos) + importText + text.substr(insertPos);
  339. return text;
  340. },
  341. upSymbolInfoByName(text,codeInfo){
  342. // 重新解析过成员变量文本的范围,
  343. return codeInfo.symbols = this.parseSctSymbolInfo(text,codeInfo.isTs);
  344. },
  345. getSymbolInfoByName(symbols,symbolName){
  346. for (let i = 0; i < symbols.length; i++) {
  347. const item = symbols[i];
  348. if(item.symbolName == symbolName){
  349. return item;
  350. }
  351. }
  352. },
  353. // 获得插入的代码文字
  354. // getInsertText(widgetType,symbolName,isArray,isReplaceMode,isTs,isUrl){
  355. // let text = ''
  356. // if(isTs){
  357. // let intext = isReplaceMode ? '' : '\n\n ';
  358. // if(isArray){
  359. // text = intext+
  360. // `@property({ type: ['${widgetType}'] }' )`+'\n'+
  361. // ` ${symbolName}: ${widgetType} [] = [];`
  362. // }else{
  363. // text = intext+
  364. // `@property({ type: ${widgetType} })`+'\n'+
  365. // ` ${symbolName}: ${widgetType} = null;`
  366. // }
  367. // }else
  368. // {
  369. // let key = isUrl ? "url: " : 'type: '
  370. // let intext = isReplaceMode ? '' : '\n ';
  371. // text = intext +
  372. // symbolName+':{\n'+
  373. // ' default: '+(isArray? "[]":"null")+',\n'+
  374. // ' '+key+widgetType+',\n'+
  375. // ' },';
  376. // }
  377. // return text;
  378. // },
  379. // 获得当前编辑文件的信息
  380. getCurrEditorFileInfo()
  381. {
  382. if(!this.parent.file_info){
  383. return;
  384. }
  385. let file_url = this.parent.file_info.path;
  386. let vs_model = this.parent.file_info.vs_model;
  387. let text = vs_model.getValue()
  388. let file_ = this.parent.fileMgr.getUriInfo(file_url);
  389. let isTs = file_.extname != '.js';
  390. let symbols = this.parseSctSymbolInfo(text,isTs);
  391. return {
  392. text,
  393. isTs,
  394. name:file_.name,
  395. extname:file_.extname,
  396. editInfo:this.parent.file_info,
  397. symbols, // 获得当前编辑文件的成员变量信息
  398. };
  399. },
  400. // 解析变量符号
  401. parseSctSymbolInfo(text,isTs){
  402. let symbols = [];
  403. if(isTs)
  404. {
  405. let parseTs = (code_text, start_ind = 0)=>
  406. {
  407. let findObj = code_text.substr(start_ind).match(/@property\(.+\)[\s]{0,35}([\w$]+)[\s]{0,10}:[\s]{0,10}([\w$.]+)[\s]{0,5}[=]{0,1}.+/)
  408. if (findObj)
  409. {
  410. let startPos = findObj.index + start_ind;
  411. let endPos = startPos + findObj[0].length;
  412. let symbolName = findObj[1]
  413. let widgetType = findObj[2]
  414. let isArray = findObj[0].match(/\[[\s\S]*?\]/) != null;
  415. let symbolInfo = { startPos, endPos, symbolName, widgetType, value: symbolName, meta: widgetType,text:findObj[0], isArray }
  416. symbols.push(symbolInfo);
  417. parseTs(code_text, endPos)
  418. }
  419. }
  420. parseTs(text)
  421. }else
  422. {
  423. // JS 解析代码格式是否正常的,
  424. let esprima = Editor.require('packages://simple-code/node_modules/esprima/esprima')
  425. try {
  426. esprima.parse(text)
  427. } catch (error) {
  428. return [];
  429. }
  430. // 变量 properties 对象位置
  431. let findObj = text.match(/properties[ ]{0,5}:[ ]{0,5}[\n]{0,5}[ ]{0,15}{/)
  432. if(!findObj){
  433. Editor.info('JS脚本缺少 properties:{}, 对象,无法自动拖拽组件')
  434. return;
  435. }
  436. let start_ind = findObj.index + findObj[0].length;
  437. let getBracketEndPos = (s_ind) => {
  438. if (text[s_ind] != '{') return -1;
  439. for (let i = s_ind + 1; i < text.length; i++) {
  440. if (text[i] == '{') {
  441. i = getBracketEndPos(i);
  442. if (i == -1) return -1;
  443. } else if (text[i] == '}') {
  444. return i;
  445. }
  446. }
  447. return -1;
  448. };
  449. // properties对象的结尾位置
  450. let end_ind = getBracketEndPos(start_ind - 1)
  451. if(end_ind != -1)
  452. {
  453. // 读取对象成员信息
  454. let code = text.substr(start_ind, end_ind - start_ind)
  455. let parseJs = (code_text, start_ind = 0) =>
  456. {
  457. let findObjDefind = code_text.substr(start_ind).match(/([\w$_][\w$._0-9]*)[\s]{0,}:[\s]{0,}\{[\s\S]{0,}?type[\s\:]{0,}([\w$_][\w$._0-9]*)[\s\S]{0,}?,{0,1}[\s]{0,}?\}[\s]{0,}?,{0,1}/)
  458. let findOjbMini = code_text.substr(start_ind).match(/([\w$_][\w$._0-9]*)[\s]{0,}:[\s]{0,}[\s\[]{0,}([\w$_][\w$._0-9]+).*[\s]{0,},/); // 简写 value : [ cc.Node ],
  459. let findObj = findObjDefind
  460. if(findObjDefind){
  461. if(findOjbMini && !findOjbMini.input.substr(0,findOjbMini.index).match(/[\{\}]/)){
  462. if(findOjbMini.index < findObjDefind.index){
  463. findObj = findOjbMini;
  464. }
  465. }
  466. }else if(findOjbMini && !findOjbMini.input.substr(0,findOjbMini.index).match(/[\{\}]/)){
  467. findObj = findOjbMini
  468. }
  469. if (findObj)
  470. {
  471. let startPos = findObj.index + start_ind;
  472. let endPos = startPos + findObj[0].length;
  473. let symbolName = findObj[1]
  474. let widgetType = findObj[2]
  475. let isArray = findObj[0].match(/\[[\s\S]*?\]/) != null;
  476. let symbolInfo = { startPos, endPos, symbolName, widgetType, value: symbolName, meta: widgetType, text:findObj[0],isArray }
  477. symbols.push(symbolInfo);
  478. parseJs(code_text, endPos)
  479. }
  480. }
  481. parseJs(code,0);
  482. for (let i = 0; i < symbols.length; i++) {
  483. const symbolInfo = symbols[i];
  484. symbolInfo.startPos +=start_ind;
  485. symbolInfo.endPos +=start_ind;
  486. }
  487. }
  488. }
  489. return symbols;
  490. },
  491. loadSymbolName(callback,defineName='',result=[])
  492. {
  493. // 要求输入变量名
  494. let ps = {value:tools.translateZhAndEn('请确认变量名','Please confirm the variable name'),meta:'',score:0};
  495. result.unshift(ps)
  496. // 下拉框选中后操作事件
  497. let onSearchAccept = (data,cmdLine)=>
  498. {
  499. let name = cmdLine.getValue();
  500. if(ps.value != data.item.value){
  501. name = data.item.value
  502. }else{
  503. name = defineName;
  504. }
  505. if(name && name != ps.value){
  506. callback(name);
  507. }
  508. }
  509. // 修改搜索框时,通过该函数读取显示的实时显示下拉列表内容, cmdLine为输入文本框对象
  510. let onCompletionsFunc = (cmdLine)=>{
  511. defineName = cmdLine.getValue()
  512. return result;
  513. }
  514. this.parent.ace.openSearchBox(defineName,[],(data,cmdLine)=>onSearchAccept(data,cmdLine),(cmdLine)=>onCompletionsFunc(cmdLine))
  515. this.parent.ace.setMiniSearchBoxToTouchPos();
  516. },
  517. onDrag(e,dragArgs){
  518. let panel = Editor.Panel.getFocusedPanel()
  519. if(!panel) return;
  520. // 获得拖拽的组件资源uuid
  521. let uuids;
  522. if(dragArgs.items){
  523. uuids = []
  524. for (let i = 0; i < dragArgs.items.length; i++) {
  525. const item = dragArgs.items[i];
  526. uuids.push(item.id);
  527. }
  528. }
  529. let type = dragArgs.type || panel.id
  530. if(type == 'asset' || type == 'assets'){
  531. this.insertAssets(this.parent.cfg.isQuickDrag,uuids)
  532. }if(type == 'node' || type == 'hierarchy'){
  533. this.insertWidgetAction(this.parent.cfg.isQuickDrag,null,uuids);
  534. }
  535. },
  536. /** 需要刷新creator右键菜单
  537. * @param type = node | asset
  538. * */
  539. onRefreshCreatorMenu(type,uuid){
  540. this.updateMenu(type,uuid)
  541. },
  542. updateMenu(type,uuid){
  543. // 当前选中的对象
  544. this.currSelectInfo.type = type;
  545. this.currSelectInfo.uuid = uuid;
  546. this.getCurrEditorFileBindNodes(this.parent.file_info && this.parent.file_info.uuid, (bindNodeList)=>
  547. {
  548. if(type == 'asset'){
  549. // 资源菜单
  550. if(!uuid || !bindNodeList){
  551. Editor.Ipc.sendToMain('simple-code:setMenuConfig',{id:"cc-widget-assets-to-code",menuCfg:undefined})
  552. }else{
  553. let menuCfg = {
  554. assetMenu : [
  555. { type: 'separator' },
  556. { label : tools.translate('quickly-drop-asset'), enabled:true, cmd: "quickInsertAssets"}, // 快速生成拖拽资源
  557. { label : tools.translate('drop-asset'), enabled:true, cmd: "insertAssets"},// 生成拖拽资源
  558. ],
  559. }
  560. Editor.Ipc.sendToMain('simple-code:setMenuConfig',{id:"cc-widget-assets-to-code",menuCfg:menuCfg})
  561. }
  562. }else if(type == 'node'){
  563. // nodeTree菜单
  564. if(!uuid || !bindNodeList){
  565. // 清除菜单
  566. Editor.Ipc.sendToMain('simple-code:setMenuConfig',{id:"cc-widget-comp-to-code",menuCfg:undefined})
  567. }else
  568. {
  569. Editor.Scene.callSceneScript('simple-code', 'getNodeCompNames',uuid, (err, compNames) => {
  570. let submenu = [{ label: 'cc.Node', enabled: true, cmd:'insertWidgetByName'},];
  571. for (let i = 0; i < compNames.length; i++) {
  572. const name = compNames[i];
  573. let item = { label: name, enabled: true, cmd: "insertWidgetByName"};
  574. submenu.push(item);
  575. }
  576. let menuCfg = {
  577. layerMenu : [
  578. { type: 'separator' },
  579. { label : tools.translate('quickly-drop-component'), enabled:true, cmd: "quickInsertWidget", }, // 快速生成拖拽组件
  580. { label : tools.translate('drop-component'), enabled:true, submenu:submenu, }, // 生成拖拽组件
  581. ],
  582. }
  583. Editor.Ipc.sendToMain('simple-code:setMenuConfig',{id:"cc-widget-comp-to-code",menuCfg:menuCfg})
  584. });
  585. }
  586. }
  587. })
  588. },
  589. getSelections(type){
  590. if(this.currSelectInfo.type != type || !this.currSelectInfo.uuid){
  591. return [];
  592. }
  593. // 判断当前选中资源中有无当前鼠标所在位置的资源
  594. let uuids = Editor.Selection.curSelection(type) || [];
  595. if(uuids.indexOf(this.currSelectInfo.uuid) != -1){
  596. return uuids;
  597. }else{
  598. return [this.currSelectInfo.uuid];
  599. }
  600. },
  601. messages:{
  602. // 加载自定义组件绑定规则
  603. 'loadCustomWidgetsToCode'(){
  604. let codeInfo = this.getCurrEditorFileInfo();
  605. if(codeInfo == null){
  606. return;
  607. }
  608. this.loadCustomWidgetsToCode(codeInfo)
  609. },
  610. // 打开生成规则配置
  611. 'openDragVarRuleFile'()
  612. {
  613. this.parent.openOutSideFile(USER_NEW_VAR_RULE,true);
  614. },
  615. // 添加组件
  616. 'insertWidgetByName'(e,args)
  617. {
  618. if(this.parent == null) return;
  619. let uuids = this.getSelections('node');
  620. this.insertWidgetAction(false,args.label,uuids);
  621. },
  622. // 快速添加组件
  623. 'quickInsertWidget'(e,args)
  624. {
  625. if(this.parent == null) return;
  626. let uuids = this.getSelections('node');
  627. this.insertWidgetAction(true,null,uuids);
  628. },
  629. // 添加资源
  630. 'insertAssets'(e,args){
  631. if(this.parent == null) return;
  632. let uuids = this.getSelections('asset');
  633. this.insertAssets(false,uuids)
  634. },
  635. // 快速添加资源
  636. 'quickInsertAssets'(e,args){
  637. if(this.parent == null) return;
  638. let uuids = this.getSelections('asset');
  639. this.insertAssets(true,uuids)
  640. },
  641. 'selection:activated'(){
  642. if(this.parent == null) return;
  643. },
  644. },
  645. // 拖动文件到inspector面板
  646. // getCodePanet(){
  647. // console.log('开始查找')
  648. // let inspector = document.getElementById('inspector');
  649. // if(!inspector){
  650. // return
  651. // }
  652. // inspector = inspector.shadowRoot.getElementById('view')
  653. // if(!inspector) return
  654. // let props = inspector.getElementsByClassName('props')[0];
  655. // if(!props) return;
  656. // let prop,assertName,uuid;
  657. // for (let i = 0; i < props.children.length; i++) {
  658. // let div = props.children[i];
  659. // let assetNode = div.getElementsByTagName('ui-asset')[0];
  660. // if(!assetNode || assetNode._type != "script") continue;
  661. // // 资源拖拽接收器
  662. // prop = div;
  663. // uuid = assetNode._value;
  664. // assertName = assetNode._name;
  665. // break;
  666. // }
  667. // if(!prop) return;
  668. // prop = prop.children[0]
  669. // console.log(prop)
  670. // // 读取拖入的文件
  671. // prop.addEventListener('drag',(e)=>{
  672. // // if(e.dataTransfer.files[0]){
  673. // e.preventDefault();
  674. // e.stopPropagation();
  675. // // }
  676. // },true)
  677. // prop.addEventListener('dragover',(e)=>{
  678. // // if(e.dataTransfer.files[0]){
  679. // e.preventDefault();
  680. // e.stopPropagation();
  681. // // }
  682. // },true)
  683. // // 读取拖入的文件
  684. // prop.addEventListener('drop',(e)=>{
  685. // e.preventDefault();
  686. // console.log('解析:',e)
  687. // },true)
  688. // console.log('找到面板:',assertName,uuid)
  689. // },
  690. };