drag_var_rule.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /**
  2. * 生成拖拽变量代码块规则
  3. * 修改后重启Creator生效
  4. * 该脚本可通过开发者工具断点调试
  5. * Generate drag and drop variable code block rules
  6. * Restart Creator after modification takes effect
  7. */
  8. module.exports = {
  9. // 快速绑定组件优先顺序,不填默认为 cc.Node
  10. 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'],
  11. /**
  12. * 第4阶段
  13. * @description 最后给脚本组件成员变量赋值
  14. * @param {cc.Component} scriptComp - 当前编辑中的脚本组件对象, scriptComp.onLoad
  15. * @param {string} widgetType - 要修改的成员变量类型,widgetType = cc.Node
  16. * @param {string} symbolName - 要修改的成员变量,symbolName = 'name'
  17. * @param {boolean} isArray - 数据是否数组类型
  18. * @param {Array} insertUuids - 插入的uuid, isAssets是节点情况下该值为节点的uuids,否则为资源文件的uuids; insertUuids = ['xxxx-xxx-xx']
  19. * @param {boolean} isAssets - 是资源费否则是节点
  20. * @param {object} rule - 第1阶段解析的参数, rule = {symbolName:'',widgetType:'',nodeUuid:'',assetUuid:'',args:['@','Sprite','name']} || null
  21. * @returns
  22. */
  23. setComponentVar(scriptComp,widgetType,symbolName,isArray,insertUuids,isAssets,rule){
  24. // 是资源 || 是数组类型 || 选中的资源不存在 || 脚本里不存在该变量
  25. if(isAssets || isArray || !insertUuids || !scriptComp.hasOwnProperty(symbolName)){
  26. return
  27. }
  28. /** 案例3: 获取node上的Button组件对象,并生成click函数与绑定 */
  29. // if(rule.widgetType == 'cc.Button'){
  30. // // 生成click函数文本
  31. // let node = cc.engine.getInstanceById(rule.nodeUuid); // 通过uuid从场景中获取节点对象
  32. // if(node){
  33. // // 按钮绑定脚本click函数
  34. // let btnComp = node.getComponent('cc.Button');
  35. // btnComp.transition = cc.Button.Transition.SCALE;
  36. // var eventHandler = new cc.Component.EventHandler();
  37. // eventHandler.target = scriptComp.node;
  38. // eventHandler.component = scriptComp.__classname__; // 这个是代码文件名
  39. // eventHandler.handler = rule.symbolName+'Btn'; // click函数
  40. // eventHandler.customEventData = symbolName;
  41. // btnComp.clickEvents = [eventHandler];
  42. // }
  43. // }
  44. },
  45. /**
  46. * 第3阶段
  47. * @description 代码文本加工处理, 比如添加按钮回调函数之类的, 这里靠你想象了
  48. * @param {string} codeText - 代码的内容
  49. * @param {string} fileUrl - 当前脚本路径, fileUrl = 'db://assets/scene/file.js'
  50. * @param {Array} rules - 生成代码规则列表,rules = [ {symbolName:'',widgetType:'',nodeUuid:'',assetUuid:'',args:['@','Sprite','name']} ]
  51. * @param {ITextModel} model - monaco 编辑器当前页面控制器,可以不使用
  52. * @param {Array<cc.Node>} nodes - 需要加工处理的nodes
  53. * @returns {string} - 返回加工完成的代码文本
  54. */
  55. processCode(codeText,fileUrl,rules,model,nodes){
  56. /** 案例3: 获取node上的Button组件对象,并生成click函数并绑定(测试使用的是ts脚本) */
  57. // for (let i = 0; i < rules.length; i++) {
  58. // const rule = rules[i];
  59. // if(rule.widgetType == 'cc.Button'){
  60. // // 生成click函数文本
  61. // let funcText = `\n ${rule.symbolName}Btn(){}\n`;
  62. // let ind = codeText.lastIndexOf('}')
  63. // codeText = codeText.substring(0,ind) + funcText + codeText.substring(ind)
  64. // }
  65. // }
  66. return codeText;
  67. },
  68. /**
  69. * 第2阶段
  70. * @description 获得插入的代码文本,用生成员变量的文本
  71. * @param {string} widgetType - 组件类型,widgetType = cc.Node
  72. * @param {string} symbolName - 变量名,symbolName = 'name'
  73. * @param {string} replaceText - 被替代的旧文本, replaceText = 'property({ type: cc.Node .....'
  74. * @param {Array} rules - 生成代码规则列表,rules = [ {symbolName:'',widgetType:'',nodeUuid:'',assetUuid:'',args:['@','Sprite','name']} ]
  75. * @param {boolean} isArray - 是否数组变量
  76. * @param {boolean} isTs - 是否TS脚本
  77. * @param {boolean} isUrl - 资源类型是否为路径类
  78. * @returns - 返回插入的代码块 = 'property({ type: cc.Node .....'
  79. */
  80. getInsertText(widgetType,symbolName,replaceText,rules,isArray,isTs,isUrl)
  81. {
  82. let text = ''
  83. if(isTs)
  84. {
  85. // TS 变量生成规则
  86. let intext = replaceText != null ? '' : '\n\n ';
  87. if(isArray){
  88. text = intext+
  89. `@property({ type: [${widgetType}], displayName:''})\n` +
  90. ` ${symbolName}: ${widgetType}[] = [];`
  91. }else{
  92. text = intext+
  93. `@property({ type: ${widgetType}, displayName:'' })\n` +
  94. ` ${symbolName}: ${widgetType} = null;`
  95. }
  96. }else
  97. {
  98. // JS 变量生成规则
  99. let key = isUrl ? "url: " : 'type: '
  100. let intext = replaceText != null ? '' : '\n ';
  101. text = intext +
  102. symbolName+':{\n'+
  103. ' default: '+(isArray? "[]":"null")+',\n'+
  104. ' '+key+widgetType+',\n'+
  105. ' },';
  106. }
  107. return text;
  108. },
  109. /**
  110. * 第1阶段,鼠标拖拽node或asset触发事件
  111. * @description 修改 rules 内容实现自定义
  112. * @param {Array} rules - 生成脚本成员变量规则 , rules = [ {symbolName:'',widgetType:'',nodeUuid:'',assetUuid:'',args:['@','Sprite','name']} ](可写)
  113. * @param {boolean} isArray - 是否生成数组类型变量(可写)
  114. * @param {boolean} isQuick - 是否快速绑定模式(只读)
  115. * @returns {object} 返回生成 成员变量规则参数
  116. */
  117. dragWidgetStart(rules,isArray,isQuick){
  118. /** 案例1: 强制成员变量为数组类型 */
  119. // isArray = true;
  120. /** 案例2: 强制变量名为test,组件类型为cc.Node */
  121. // for (let i = 0; i < rules.length; i++) {
  122. // const rule = rules[i];
  123. // if(rule.nodeUuid){
  124. // rule.symbolName = 'test'
  125. // rule.widgetType = 'cc.Node'
  126. // rule.args = '自定义参数'
  127. // }
  128. // }
  129. /** 案例3: 获取node上的Button组件对象,并生成click函数并绑定 */
  130. // for (let i = 0; i < rules.length; i++) {
  131. // const rule = rules[i];
  132. // if(rule.nodeUuid){
  133. // let node = cc.engine.getInstanceById(rule.nodeUuid); // 通过uuid从场景中获取节点对象
  134. // if(node){
  135. // let btnComp = node.getComponent('cc.Button');
  136. // if(btnComp){
  137. // rule.widgetType = 'cc.Button' // 成员变量类型强制改为Button
  138. // rule.args = {act:"bindFunction"}
  139. // }
  140. // }
  141. // }
  142. // }
  143. /** 案例4: 将拖拽node的子节点也一起绑定脚本中 */
  144. // for (let i = 0; i < rules.length; i++) {
  145. // const rule = rules[i];
  146. // if(rule.nodeUuid){
  147. // let node = cc.engine.getInstanceById(rule.nodeUuid); // 通过uuid从场景中获取节点对象
  148. // if(node){
  149. // let childNode = node.children[0]
  150. // if(childNode){
  151. // // 新增生成规则
  152. // rules.push({
  153. // symbolName:rule.symbolName+"Child", // 变量名
  154. // widgetType:'cc.Node', // 变量类型
  155. // nodeUuid:childNode.uuid,
  156. // })
  157. // }
  158. // }
  159. // }
  160. // }
  161. return {rules,isArray} // 只能返回纯数据,不允许传cc.xx对象
  162. },
  163. /**
  164. * 第1阶段,解析规则(Clrl+Shift+E 时才调用这里 ,直接拖拽生成变量不会走这里)
  165. * @description 生成自定义绑定规则,根据 node.name 解析组件的绑定规则
  166. * @param {cc.Node} node - 场景上的 node
  167. * @returns {Array} 返回生成 成员变量规则 = {symbolName:'',widgetType:'',nodeUuid:'',args:['@','Sprite','name']}
  168. */
  169. getNodeWidgetRule(node){
  170. // 1. 通过名字解析规则, name = '@-Sprite-name'
  171. let name = node.name;
  172. // splitSymbol = ['@','Sprite','name']
  173. let splitSymbol = name.split('-')
  174. // 2.解析头缀是否正确 @
  175. if(splitSymbol.length < 3 || splitSymbol[0] != '@'){
  176. return;
  177. }
  178. // 3.解析变量名 symbolName = 'name'
  179. let symbolName = splitSymbol[2];
  180. // 4.解析组件类型 widgetType = 'Sprite'
  181. let widgetType = splitSymbol[1];
  182. if(cc[widgetType]){
  183. widgetType = 'cc.'+widgetType;
  184. }
  185. // 5.获得组件, comp as cc.Sprite
  186. let comp = widgetType == 'cc.Node' ? node : node.getComponent(widgetType);
  187. if(!comp){
  188. // Editor.log("找不到组件: ",name,widgetType)
  189. return;
  190. }
  191. /* 6.返回生成 成员变量规则
  192. * 使用示例:
  193. * @property({ type: widgetType, displayName:'' })
  194. * symbolName: widgetType = null;
  195. */
  196. return {
  197. // 变量名
  198. symbolName:symbolName,
  199. // 组件类型名字
  200. widgetType:widgetType,
  201. // 组件所在节点的uuid
  202. nodeUuid:node.uuid,
  203. // 记录解析配置信息, 在生成代码阶段可以做更多操作,比如生成按钮绑定文本块之类的
  204. args:splitSymbol,
  205. // 禁止生成拖拽变量, 在按钮只绑定函数不生成组件时使用;
  206. disableGenerated:false,
  207. }
  208. },
  209. /**
  210. *
  211. * @description 获取绑定组件与代码的规则 (一般这里不需要修改)
  212. * @param {string} fileUrl - 当前脚本的文件路径 db://assets/scene/file.js
  213. * @param {array} bindNodeList - 与当前脚本绑定的Node们
  214. * @param {cc.Node} rootNode - 当前选中的Node或场景 Root Node
  215. * @returns {Array} - 返回生成变量规则 rules = [{symbolName:'',widgetType:'',nodeUuid:'',args:['@','Sprite','name']}]
  216. */
  217. getCustomWidgetRule(fileUrl,bindNodeList,rootNode){
  218. // 遍历整个场景的 node
  219. let rules = []
  220. getNodeChildren(rootNode,(node)=>
  221. {
  222. let compRule = this.getNodeWidgetRule(node);
  223. if(compRule){
  224. rules.push(compRule);
  225. }
  226. })
  227. //
  228. return rules;
  229. },
  230. };
  231. /**
  232. * @description 遍历所有深层子节点
  233. * @param {cc.Node} node
  234. * @param {function} callFunc
  235. * @returns
  236. */
  237. function getNodeChildren(node,callFunc)
  238. {
  239. if (!node) return;
  240. let nodes = node.getChildren();
  241. nodes.forEach((v)=>{
  242. getNodeChildren(v,callFunc)
  243. });
  244. callFunc(node)
  245. }