Ver código fonte

【修改】 移动代码位置.添加预制体路径导出

Hua 1 ano atrás
pai
commit
adf6634db8
41 arquivos alterados com 1288 adições e 281 exclusões
  1. 427 277
      assets/edt_scene/scene_main.fire
  2. 63 0
      assets/script/app/view/UIInfo.js
  3. 9 0
      assets/script/app/view/UIInfo.js.meta
  4. 0 0
      assets/script/app/view/battle.meta
  5. 0 0
      assets/script/app/view/battle/BattleRoomPlayer.js
  6. 0 0
      assets/script/app/view/battle/BattleRoomPlayer.js.meta
  7. 0 0
      assets/script/app/view/box_contains.meta
  8. 0 0
      assets/script/app/view/box_contains/BoxChanceItem.js
  9. 0 0
      assets/script/app/view/box_contains/BoxChanceItem.js.meta
  10. 0 0
      assets/script/app/view/box_contains/BoxItem.js
  11. 0 0
      assets/script/app/view/box_contains/BoxItem.js.meta
  12. 0 0
      assets/script/app/view/common.meta
  13. 0 0
      assets/script/app/view/common/ButtonSelect1.js
  14. 0 0
      assets/script/app/view/common/ButtonSelect1.js.meta
  15. 0 0
      assets/script/app/view/common/HeadIcon.js
  16. 0 0
      assets/script/app/view/common/HeadIcon.js.meta
  17. 0 0
      assets/script/app/view/common/ItemIcon.js
  18. 0 0
      assets/script/app/view/common/ItemIcon.js.meta
  19. 0 0
      assets/script/app/view/drop.meta
  20. 0 0
      assets/script/app/view/drop/DropPercentageItem.js
  21. 0 0
      assets/script/app/view/drop/DropPercentageItem.js.meta
  22. 0 0
      assets/script/app/view/drop/DropWastageItem.js
  23. 0 0
      assets/script/app/view/drop/DropWastageItem.js.meta
  24. 10 4
      assets/script/app/view/login/LoginPanel.js
  25. 0 0
      assets/script/app/view/navigation.meta
  26. 0 0
      assets/script/app/view/navigation/NavigationMain.js
  27. 0 0
      assets/script/app/view/navigation/NavigationMain.js.meta
  28. 44 0
      packages/CCSceneMenu/README.md
  29. 10 0
      packages/CCSceneMenu/default-config.json
  30. 21 0
      packages/CCSceneMenu/i18n/en.js
  31. 21 0
      packages/CCSceneMenu/i18n/zh.js
  32. BIN
      packages/CCSceneMenu/img/command.png
  33. BIN
      packages/CCSceneMenu/img/create_node.gif
  34. BIN
      packages/CCSceneMenu/img/new_item.gif
  35. 262 0
      packages/CCSceneMenu/main.js
  36. 20 0
      packages/CCSceneMenu/package.json
  37. 281 0
      packages/CCSceneMenu/panel/index.js
  38. 13 0
      packages/CCSceneMenu/scene-accessor.ts
  39. 18 0
      packages/LuaExport/main.js
  40. 8 0
      packages/LuaExport/package.json
  41. 81 0
      packages/LuaExport/scene-walker.js

Diferenças do arquivo suprimidas por serem muito extensas
+ 427 - 277
assets/edt_scene/scene_main.fire


+ 63 - 0
assets/script/app/view/UIInfo.js

@@ -0,0 +1,63 @@
1
+// 当前文件为手动导出文件.请勿修改.在预制体编辑界面点击右键导出即可.
2
+ window.JMC.UIEnum = {
3
+		BagMain:0,
4
+		BattleJoinRoomTip:1,
5
+		BattleMain:2,
6
+		BattleRoom:3,
7
+		BattleRoomPlayer:4,
8
+		BattleRoomPlayerIcon:5,
9
+		BattleRoomPreviweCell:6,
10
+		BoxChanceItem:7,
11
+		BoxContainsMain:8,
12
+		BoxItem:9,
13
+		ButtonSelect1:10,
14
+		DreamBrilliant:11,
15
+		DreamBrilliantCell:12,
16
+		DreamMain:13,
17
+		DreamPopular:14,
18
+		DreamStatistics:15,
19
+		DreamStatisticsCell:16,
20
+		DreamStatisticsFilter:17,
21
+		DropPercentageItem:18,
22
+		DropRecordMain:19,
23
+		DropWastageItem:20,
24
+		FilterMain:21,
25
+		HeadIcon:22,
26
+		ItemIcon:23,
27
+		NavigationMain:24,
28
+		prefab_alert_ctrl:25,
29
+		prefab_loading_ctrl:26,
30
+		prefab_toast_ctrl:27
31
+
32
+}
33
+window.JMC.UIPath = {
34
+		[window.JMC.UIEnum.BagMain] : "Bag/BagMain.prefab",
35
+		[window.JMC.UIEnum.BattleJoinRoomTip] : "Battle/BattleJoinRoomTip.prefab",
36
+		[window.JMC.UIEnum.BattleMain] : "Battle/BattleMain.prefab",
37
+		[window.JMC.UIEnum.BattleRoom] : "Battle/BattleRoom.prefab",
38
+		[window.JMC.UIEnum.BattleRoomPlayer] : "Battle/BattleRoomPlayer.prefab",
39
+		[window.JMC.UIEnum.BattleRoomPlayerIcon] : "Battle/BattleRoomPlayerIcon.prefab",
40
+		[window.JMC.UIEnum.BattleRoomPreviweCell] : "Battle/BattleRoomPreviweCell.prefab",
41
+		[window.JMC.UIEnum.BoxChanceItem] : "BoxContains/BoxChanceItem.prefab",
42
+		[window.JMC.UIEnum.BoxContainsMain] : "BoxContains/BoxContainsMain.prefab",
43
+		[window.JMC.UIEnum.BoxItem] : "BoxContains/BoxItem.prefab",
44
+		[window.JMC.UIEnum.ButtonSelect1] : "Common/ButtonSelect1.prefab",
45
+		[window.JMC.UIEnum.DreamBrilliant] : "Dream/DreamBrilliant.prefab",
46
+		[window.JMC.UIEnum.DreamBrilliantCell] : "Dream/DreamBrilliantCell.prefab",
47
+		[window.JMC.UIEnum.DreamMain] : "Dream/DreamMain.prefab",
48
+		[window.JMC.UIEnum.DreamPopular] : "Dream/DreamPopular.prefab",
49
+		[window.JMC.UIEnum.DreamStatistics] : "Dream/DreamStatistics.prefab",
50
+		[window.JMC.UIEnum.DreamStatisticsCell] : "Dream/DreamStatisticsCell.prefab",
51
+		[window.JMC.UIEnum.DreamStatisticsFilter] : "Dream/DreamStatisticsFilter.prefab",
52
+		[window.JMC.UIEnum.DropPercentageItem] : "Drop/DropPercentageItem.prefab",
53
+		[window.JMC.UIEnum.DropRecordMain] : "Drop/DropRecordMain.prefab",
54
+		[window.JMC.UIEnum.DropWastageItem] : "Drop/DropWastageItem.prefab",
55
+		[window.JMC.UIEnum.FilterMain] : "Filter/FilterMain.prefab",
56
+		[window.JMC.UIEnum.HeadIcon] : "Common/HeadIcon.prefab",
57
+		[window.JMC.UIEnum.ItemIcon] : "Common/ItemIcon.prefab",
58
+		[window.JMC.UIEnum.NavigationMain] : "Navigation/NavigationMain.prefab",
59
+		[window.JMC.UIEnum.prefab_alert_ctrl] : "prefab_alert_ctrl.prefab",
60
+		[window.JMC.UIEnum.prefab_loading_ctrl] : "prefab_loading_ctrl.prefab",
61
+		[window.JMC.UIEnum.prefab_toast_ctrl] : "prefab_toast_ctrl.prefab"
62
+
63
+}

+ 9 - 0
assets/script/app/view/UIInfo.js.meta

@@ -0,0 +1,9 @@
1
+{
2
+  "ver": "1.0.8",
3
+  "uuid": "ebc75aac-d637-48db-89ad-550b1f9b9a89",
4
+  "isPlugin": false,
5
+  "loadPluginInWeb": true,
6
+  "loadPluginInNative": true,
7
+  "loadPluginInEditor": false,
8
+  "subMetas": {}
9
+}

assets/script/app/ctrl/battle.meta → assets/script/app/view/battle.meta


assets/script/app/ctrl/battle/BattleRoomPlayer.js → assets/script/app/view/battle/BattleRoomPlayer.js


assets/script/app/ctrl/battle/BattleRoomPlayer.js.meta → assets/script/app/view/battle/BattleRoomPlayer.js.meta


assets/script/app/ctrl/box_contains.meta → assets/script/app/view/box_contains.meta


assets/script/app/ctrl/box_contains/BoxChanceItem.js → assets/script/app/view/box_contains/BoxChanceItem.js


assets/script/app/ctrl/box_contains/BoxChanceItem.js.meta → assets/script/app/view/box_contains/BoxChanceItem.js.meta


assets/script/app/ctrl/box_contains/BoxItem.js → assets/script/app/view/box_contains/BoxItem.js


assets/script/app/ctrl/box_contains/BoxItem.js.meta → assets/script/app/view/box_contains/BoxItem.js.meta


assets/script/app/ctrl/common.meta → assets/script/app/view/common.meta


assets/script/app/ctrl/common/ButtonSelect1.js → assets/script/app/view/common/ButtonSelect1.js


assets/script/app/ctrl/common/ButtonSelect1.js.meta → assets/script/app/view/common/ButtonSelect1.js.meta


assets/script/app/ctrl/common/HeadIcon.js → assets/script/app/view/common/HeadIcon.js


assets/script/app/ctrl/common/HeadIcon.js.meta → assets/script/app/view/common/HeadIcon.js.meta


assets/script/app/ctrl/common/ItemIcon.js → assets/script/app/view/common/ItemIcon.js


assets/script/app/ctrl/common/ItemIcon.js.meta → assets/script/app/view/common/ItemIcon.js.meta


assets/script/app/ctrl/drop.meta → assets/script/app/view/drop.meta


assets/script/app/ctrl/drop/DropPercentageItem.js → assets/script/app/view/drop/DropPercentageItem.js


assets/script/app/ctrl/drop/DropPercentageItem.js.meta → assets/script/app/view/drop/DropPercentageItem.js.meta


assets/script/app/ctrl/drop/DropWastageItem.js → assets/script/app/view/drop/DropWastageItem.js


assets/script/app/ctrl/drop/DropWastageItem.js.meta → assets/script/app/view/drop/DropWastageItem.js.meta


+ 10 - 4
assets/script/app/view/login/LoginPanel.js

@@ -33,7 +33,11 @@ cc.Class({
33 33
     },
34 34
 
35 35
     onLoad () {
36
-       
36
+       let phoneNum = cc.sys.localStorage.getItem("user_phone_num", "")
37
+       let password = cc.sys.localStorage.getItem("user_password", "")
38
+        
39
+       this.phoneEditor.string = phoneNum;
40
+       this.passwordEditor.string = password; 
37 41
     },
38 42
 
39 43
     reloadData (cb) {
@@ -43,9 +47,9 @@ cc.Class({
43 47
     gotoLoginOnClicked () {
44 48
         var phoneNum = this.phoneEditor.string;
45 49
         if (phoneNum.length == 0 && !G.FuncUtils.isMobile(phoneNum)) {
46
-            G.AppUtils.getSceneCtrl().addToast("手机号码格式不正确");
50
+            G.AppUtils.getSceneCtrl().addToast("手机号码格式不正确"); 
47 51
             return;
48
-        }
52
+        }  
49 53
 
50 54
         var password = this.passwordEditor.string;
51 55
         if (password.length == 0) {
@@ -57,8 +61,10 @@ cc.Class({
57 61
             G.AppUtils.getSceneCtrl().addToast("密码过长");
58 62
             return;
59 63
         }
64
+        G.LogiMngr.requestLoginByPhone(phoneNum, password);
60 65
 
61
-        G.LoginMgr.requestLoginByPhone(phoneNum, password);
66
+        cc.sys.localStorage.setItem("user_phone_num", phoneNum)
67
+        cc.sys.localStorage.setItem("user_password", password)
62 68
     },
63 69
 
64 70
     gotoRegisterOnClicked () {

assets/script/app/ctrl/navigation.meta → assets/script/app/view/navigation.meta


assets/script/app/ctrl/navigation/NavigationMain.js → assets/script/app/view/navigation/NavigationMain.js


assets/script/app/ctrl/navigation/NavigationMain.js.meta → assets/script/app/view/navigation/NavigationMain.js.meta


+ 44 - 0
packages/CCSceneMenu/README.md

@@ -0,0 +1,44 @@
1
+# Cocos Creator场景编辑器右键菜单插件
2
+
3
+原帖地址:
4
+https://forum.cocos.org/t/topic/88435
5
+
6
+<a name="LvBEQ"></a>
7
+### 背景
8
+Cocos Creator的场景编辑器没有自带的右键菜单,也不提供右键菜单的扩展方法(截止目前v2.2.2版)。<br />关卡编辑时,如果将常用功能登记到右键菜单内,可以避免在主菜单、层级视图、资源视图、场景编辑器之间来回切换,提升效率。<br />右键菜单创建节点时,可以直接创建到指定位置,提升效率。
9
+
10
+代码:[https://github.com/caogtaa/CCSceneMenu/tree/master](https://github.com/caogtaa/CCSceneMenu/tree/master)<br />演示工程:[https://github.com/caogtaa/CCSceneMenuDemo](https://github.com/caogtaa/CCSceneMenuDemo)
11
+
12
+<a name="5LgTA"></a>
13
+### 功能介绍
14
+
15
+- 支持通过插件UI编辑场景菜单的内容
16
+- 支持登记prefab uuid到右键菜单,通过菜单创建该prefab的实例。(prefab uuid在资源视图里右击可以查到)
17
+- 支持登记自定义命令到右键菜单(填写自己插件的消息和参数),方便开发者扩展
18
+
19
+<a name="Ttx0E"></a>
20
+### 兼容性
21
+
22
+- 插件目前只支持2D场景
23
+- 支持Cocos Creator v2.2.2,Windows/Mac。其他版本未测试。
24
+
25
+<a name="bJ3D5"></a>
26
+### 效果
27
+场景编辑器<br />![image.gif](img/create_node.gif)
28
+
29
+菜单管理<br />![image.gif](img/new_item.gif)<br />![image.png](img/command.png)
30
+
31
+<a name="PCuTN"></a>
32
+### 如何安装
33
+<a name="SGuBV"></a>
34
+#### 方法1,手动安装
35
+将源码解压到项目工程的packages目录下(解压后需要有新目录)
36
+
37
+<a name="u5ROG"></a>
38
+#### 方法2,git项目通过submodule安装
39
+```bash
40
+git submodule add git@github.com:caogtaa/CCSceneMenu.git packages/CCSceneMenu
41
+git submodule init
42
+git submodule update
43
+```
44
+

+ 10 - 0
packages/CCSceneMenu/default-config.json

@@ -0,0 +1,10 @@
1
+[
2
+    {
3
+        "type": "1",
4
+        "name": "注册预制体信息",
5
+        "uuid": "",
6
+        "submenu": [],
7
+        "command": "export-prefab-info:exportInfo",
8
+        "param": ""
9
+    }
10
+]

+ 21 - 0
packages/CCSceneMenu/i18n/en.js

@@ -0,0 +1,21 @@
1
+module.exports = {
2
+  'PKG_scene_menu': 'Scene Editor Menu',
3
+  'PKG_edit': 'Edit Menu',
4
+  'PNL_title': 'Custom Scene Context Menu',
5
+  'PNL_hint': 'Click to edit item, right click to add / remove item',
6
+  'PNL_save': 'Save Menu',
7
+  'PNL_root': 'Context Menu (Root)',
8
+  'PNL_name': 'Name',
9
+  'PNL_type': 'Type',
10
+  'PNL_command': 'Command',
11
+  'PNL_parameter': 'Parameter',
12
+  'PNL_prefab': 'Prefab',
13
+  'PNL_prefab_uuid': 'Prefab uuid',
14
+  'PNL_reddot_prefab': 'RedDotPrefab',
15
+  'PNL_submenu': 'Sub Menu',
16
+  'PNL_name_ph': 'menu display name',
17
+  'PNL_command_ph': 'PluginName:CommandName',
18
+  'PNL_parameter_ph': '(Optional) Command Parameter',
19
+  'PNL_add_child': 'Add Child',
20
+  'PNL_delete': 'Delete',
21
+};

+ 21 - 0
packages/CCSceneMenu/i18n/zh.js

@@ -0,0 +1,21 @@
1
+module.exports = {
2
+  'PKG_scene_menu': '场景编辑器菜单',
3
+  'PKG_edit': '编辑菜单',
4
+  'PNL_title': '定制场景菜单',
5
+  'PNL_hint': '点击菜单项编辑属性,右击添加/删除菜单项',
6
+  'PNL_save': '保存菜单',
7
+  'PNL_root': '(菜单根节点)',
8
+  'PNL_name': '显示名',
9
+  'PNL_type': '类型',
10
+  'PNL_command': '命令',
11
+  'PNL_parameter': '参数',
12
+  'PNL_prefab': 'Prefab',
13
+  'PNL_prefab_uuid': 'Prefab uuid',
14
+  'PNL_reddot_prefab': 'RedDotPrefab',
15
+  'PNL_submenu': '子菜单',
16
+  'PNL_name_ph': '菜单项显示名',
17
+  'PNL_command_ph': '插件名:命令名',
18
+  'PNL_parameter_ph': '(可选)命令参数',
19
+  'PNL_add_child': '添加子菜单项',
20
+  'PNL_delete': '删除',
21
+};

BIN
packages/CCSceneMenu/img/command.png


BIN
packages/CCSceneMenu/img/create_node.gif


BIN
packages/CCSceneMenu/img/new_item.gif


+ 262 - 0
packages/CCSceneMenu/main.js

@@ -0,0 +1,262 @@
1
+/*
2
+ * @Author: CGT (caogtaa@gmail.com) 
3
+ * @Date: 2020-01-16 22:09:08 
4
+ * @Last Modified by: CGT (caogtaa@gmail.com)
5
+ * @Last Modified time: 2020-01-16 23:46:33
6
+ */
7
+
8
+'use strict';
9
+
10
+let _menuTemplateCache = null;
11
+let _paramCache = {};
12
+
13
+function createNode(uuid) {
14
+  let param = { uuid: uuid };
15
+  Object.assign(param, _paramCache);
16
+  Editor.Scene.callSceneScript('cc-ext-scene-menu', 'create-node', param, (err) => {
17
+    if (err)
18
+      Editor.log(err);
19
+  });
20
+}
21
+
22
+function sendCommand(command, param) {
23
+  let p = {};
24
+  Object.assign(p, _paramCache);
25
+  p.customParam = param;
26
+  Editor.Ipc.sendToMain(command, p, null);
27
+}
28
+
29
+function generateMenuTemplate(conf) {
30
+  let result = [];
31
+  for (let c of conf) {
32
+    // https://electronjs.org/docs/api/menu
33
+    let item = {};
34
+    item.label = c.name;
35
+
36
+    // item.click = createNode.bind(c.uuid);
37
+    // the menu item auto unbound my function, why?
38
+    // so I put uuid in closure
39
+    if (c.type == 0) {
40
+      // prefab
41
+      let uuid = c.uuid;
42
+      item.click = () => {
43
+        createNode(uuid);
44
+      };
45
+    } else if (c.type == 1) {
46
+      // command
47
+      item.click = () => {
48
+        sendCommand(c.command, c.param);
49
+      };
50
+    } else if (c.type == 3) {
51
+      let uuid = c.uuid;
52
+      item.click = () => {
53
+        // createRedDotNode(uuid);
54
+      };
55
+    } else if (c.submenu) {
56
+      item.submenu = generateMenuTemplate(c.submenu);
57
+    } else {
58
+      // unexpected
59
+    }
60
+
61
+    result.push(item);
62
+  }
63
+
64
+  return result;
65
+}
66
+
67
+function loadMenu() {
68
+  const fs = require('fs');
69
+  let configPath = Editor.Project.path + '/scene-menu-config.json';
70
+  if (!fs.existsSync(configPath)) {
71
+    // read default config
72
+    configPath = Editor.url('packages://cc-ext-scene-menu/default-config.json');
73
+  }
74
+
75
+  fs.readFile(configPath, function (err, data) {
76
+    if (err) {
77
+      // file not exists
78
+      return;
79
+    }
80
+
81
+    try {
82
+      // Editor.log(`main.js read data: ${data}`);
83
+      let config = JSON.parse(data);
84
+      _menuTemplateCache = generateMenuTemplate(config);
85
+    } catch (err) {
86
+      // if any error occur, old template cache is not replaced
87
+    } finally {
88
+
89
+    }
90
+  });
91
+}
92
+
93
+function injectContextMenu(webContents) {
94
+  if (webContents.__gt_injected) {
95
+    // already injected
96
+    return;
97
+  }
98
+
99
+  if (webContents != Editor.Window.main.nativeWin.webContents) {
100
+    // not cc main app window
101
+    return;
102
+  }
103
+  webContents.__gt_injected = true;
104
+
105
+  let hackCode = `
106
+    (() => {
107
+      function appendListener(node, eventType, fn = null) {
108
+        node.addEventListener(eventType, (e) => {
109
+          if (fn)	fn(e);
110
+        }, true);		
111
+      }
112
+    
113
+      let getLabelRoot = (gridRoot, className) => {
114
+        for (let c of gridRoot.children) {
115
+          if (c.className === className)
116
+            return c;
117
+        }
118
+    
119
+        return null;
120
+      };
121
+    
122
+      let getPixel = (elem) => {
123
+        return parseFloat(elem.style.transform.match(/(-?[0-9\.]+)/g)[0]);
124
+      };
125
+    
126
+      let getWorldPos = (elem) => {
127
+        return parseFloat(elem.innerText.replace(/,/g, ''));
128
+      };
129
+    
130
+      let pixelToWorld = (labelRoot, pixel) => {
131
+        let pmin = getPixel(labelRoot.firstChild);
132
+        let pmax = getPixel(labelRoot.lastChild);
133
+        let wmin = getWorldPos(labelRoot.firstChild);
134
+        let wmax = getWorldPos(labelRoot.lastChild);
135
+        return (pixel - pmin) * (wmax - wmin) / (pmax - pmin) + wmin;
136
+      };
137
+    
138
+      let svgPosToWorld = (x, y) => {
139
+        let gridRoot = document.getElementById('scene').shadowRoot.getElementById('sceneView').shadowRoot.getElementById('grid').shadowRoot;
140
+        let vLabelRoot = getLabelRoot(gridRoot, 'vLabels');
141
+        let hLabelRoot = getLabelRoot(gridRoot, 'hLabels');
142
+        let worldX = pixelToWorld(hLabelRoot, x+4); // horizontal label offset = 4 (move rightward in svg)
143
+        let worldY = pixelToWorld(vLabelRoot, y-15);  // vertical label offset = -15 (move upward in svg)
144
+        return [worldX, worldY];
145
+      };
146
+
147
+      let svgNode = null;
148
+      let downX = 0;
149
+      let downY = 0;
150
+      let isDown = false;
151
+      let postContextMenuMsg = () => {
152
+
153
+        // if (cc.director.getScene().getName() != "reddot") {
154
+        //   return;
155
+        // }
156
+        
157
+        let rect = svgNode.getBoundingClientRect();
158
+        downX -= rect.left;
159
+        downY -= rect.top;
160
+        let worldX = 0;
161
+        let worldY = 0;
162
+        try {
163
+          let arr = svgPosToWorld(downX, downY);
164
+          worldX = arr[0];
165
+          worldY = arr[1];
166
+        } catch(error) {}
167
+
168
+        Editor.Ipc.sendToMain('cc-ext-scene-menu:on-context-menu', 
169
+          {x: downX, y: downY, worldX: worldX, worldY: worldY}, null);
170
+      };
171
+    
172
+      appendListener(document, 'mousedown', (e) => {
173
+        if (e.button != 2)
174
+          return;
175
+
176
+        // check if inside svg view
177
+        if (!svgNode)
178
+          svgNode = document.getElementById('scene').shadowRoot.getElementById('sceneView').shadowRoot.getElementById('gizmosView').shadowRoot.getElementById('SvgjsSvg1000');
179
+        
180
+        if (!svgNode) {
181
+          Editor.log('svg view not ready');
182
+          return;
183
+        }
184
+    
185
+        let rect = svgNode.getBoundingClientRect();
186
+        if (e.pageX >= rect.left && e.pageX < rect.right && e.pageY >= rect.top && e.pageY < rect.bottom) {
187
+          downX = e.pageX;
188
+          downY = e.pageY;
189
+          isDown = true;
190
+        }
191
+      });
192
+    
193
+      appendListener(document, 'mouseup', (e) => {
194
+        if (e.button == 2 && isDown && e.pageX == downX && e.pageY == downY) {
195
+          isDown = false;
196
+          
197
+
198
+          postContextMenuMsg();
199
+        }
200
+      });
201
+    })();
202
+
203
+    1+2+3
204
+  `;
205
+
206
+  webContents.executeJavaScript(hackCode, function (result) {
207
+    // result = 6
208
+  });
209
+}
210
+
211
+module.exports = {
212
+  load() {
213
+    loadMenu();
214
+    try {
215
+      if (Editor.Window.main.nativeWin.webContents.__gt_injected) {
216
+        // in case plugin if reloaded
217
+        return;
218
+      }
219
+    } catch (error) {
220
+      // usually happen when creator is just started and main window is not created
221
+      Editor.log(error);
222
+    }
223
+
224
+    // todo: 如果插件是中途加载的,判断webContents如果就绪了就注入
225
+    const electron = require('electron');
226
+    let injectFn = injectContextMenu;
227
+    electron.app.on('web-contents-created', (sender, webContents) => {
228
+      webContents.on('dom-ready', (e) => {
229
+        injectFn(e.sender);
230
+      });
231
+    });
232
+  },
233
+
234
+  unload() {
235
+    
236
+  },
237
+
238
+  // register your ipc messages here
239
+  messages: {
240
+    'create-node'() {
241
+      Editor.Scene.callSceneScript('cc-ext-scene-menu', 'create-node', null, function (err) {
242
+        // Editor.log('create-node finish');
243
+      });
244
+    },
245
+    'on-context-menu'(event, param) {
246
+      param = param || { x: 0, y: 0, worldX: 0, worldY: 0 };
247
+      _paramCache = param;
248
+      if (_menuTemplateCache) {
249
+        Editor.Window.main.popupMenu(_menuTemplateCache, param.x, param.y);
250
+      }
251
+    },
252
+    'custom-context-menu'() {
253
+      Editor.Panel.open('cc-ext-scene-menu');
254
+    },
255
+    'update-context-menu'() {
256
+      loadMenu();
257
+    },
258
+    'say-hello'(event, param) {
259
+      Editor.log(`Hello! param: {worldX = ${param.worldX}, worldY = ${param.worldY}}, customParam = ${param.customParam}`);
260
+    }
261
+  },
262
+};

+ 20 - 0
packages/CCSceneMenu/package.json

@@ -0,0 +1,20 @@
1
+{
2
+  "name": "cc-ext-scene-menu",
3
+  "version": "0.0.1",
4
+  "description": "Add context menu for Cocos Creator scene editor",
5
+  "author": "caogtaa@gmail.com",
6
+  "main": "main.js",
7
+  "main-menu": {
8
+    "i18n:MAIN_MENU.package.title/i18n:cc-ext-scene-menu.PKG_scene_menu/i18n:cc-ext-scene-menu.PKG_edit": {
9
+      "message": "cc-ext-scene-menu:custom-context-menu"
10
+    }
11
+  },
12
+  "panel": {
13
+    "main": "panel/index.js",
14
+    "type": "dockable",
15
+    "title": "i18n:cc-ext-scene-menu.PNL_title",
16
+    "width": 550,
17
+    "height": 400
18
+  },
19
+  "scene-script": "scene-accessor.ts"
20
+}

+ 281 - 0
packages/CCSceneMenu/panel/index.js

@@ -0,0 +1,281 @@
1
+/*
2
+ * @Author: CGT (caogtaa@gmail.com) 
3
+ * @Date: 2020-01-16 22:09:21 
4
+ * @Last Modified by: CGT (caogtaa@gmail.com)
5
+ * @Last Modified time: 2020-01-17 07:32:06
6
+ */
7
+
8
+'use strict';
9
+
10
+let _config = {};
11
+Editor.Panel.extend({
12
+  // css style for panel
13
+
14
+  style: `
15
+    :host { margin: 5px; }
16
+    :host ui-input { width: 100%; }
17
+    h2 { color: #f90; }
18
+
19
+    ul {
20
+      list-style-type: none;
21
+      padding-inline-start: 20px;
22
+    }
23
+
24
+    ul.root {
25
+      padding-inline-start: 15px;
26
+    }
27
+
28
+    ul li {
29
+      padding: 2px 10px 1px 0;
30
+      text-align: -webkit-match-parent;
31
+      color: #ccc;
32
+      border-bottom: 1px solid #454545;
33
+      box-sizing: border-box;
34
+    }
35
+
36
+    span.selected {
37
+      background: #555;
38
+    }
39
+
40
+    .caret {
41
+      cursor: pointer;
42
+      user-select: none;
43
+      width: 12px;
44
+      display: inline-block;
45
+    }
46
+
47
+    .caret-holder {
48
+      width: 12px;
49
+      display: inline-block;
50
+    }
51
+    
52
+    .caret::before {
53
+      content: "\\25B6";
54
+      color: #ccc;
55
+      display: inline-block;
56
+      margin-right: 6px;
57
+    }
58
+    
59
+    .caret-down::before {
60
+      transform: rotate(90deg);  
61
+    }
62
+    
63
+    .nested {
64
+      display: none;
65
+    }
66
+
67
+    .collapsed {
68
+
69
+    }
70
+    
71
+    .active:not(.collapsed) {
72
+      display: block;
73
+    }
74
+  `,
75
+
76
+  // html template for panel
77
+  template: `
78
+    <h2>${Editor.T('cc-ext-scene-menu.PNL_title')}</h2>
79
+    <hr />
80
+    <p>${Editor.T('cc-ext-scene-menu.PNL_hint')}</p>
81
+    <div v-if="d.loaded">
82
+      <ul class="root">
83
+        <li>
84
+          <span class="caret caret-down" v-on:click="toggleCaret"></span>
85
+          <span v-bind:class="{ selected: d.focus_item==null }" v-on:click="d.focus_item=null;" v-on:contextmenu="onContextMenu($event, true, null)">${Editor.T('cc-ext-scene-menu.PNL_root')}</span>
86
+          <ul class="nested active">
87
+            <li v-for="c in d.config">
88
+              <span v-show="c.type == '2'" class="caret" v-on:click="toggleCaret"></span>
89
+              <span v-show="c.type != '2'" class="caret-holder">&nbsp;</span>
90
+              <span v-bind:class="{ selected: d.focus_item==c }" v-on:click="d.focus_item=c;" v-on:contextmenu="onContextMenu($event, false, c)">{{c.name}}</span>
91
+              <ul class="nested" v-bind:class="{ collapsed: c.type!='2' }">
92
+                <li v-for="subc in c.submenu">
93
+                  <span class="caret-holder">&nbsp;</span>
94
+                  <span v-bind:class="{ selected: d.focus_item==subc }" v-on:click="d.focus_item=subc;" v-on:contextmenu="onContextMenu($event, false, subc, c)">{{subc.name}}</span>
95
+                </li>
96
+              </ul>
97
+            </li>
98
+          </ul>
99
+        </li>
100
+      </ul>
101
+
102
+      <ui-box-container v-if="d.focus_item">
103
+        <ui-prop name="${Editor.T('cc-ext-scene-menu.PNL_name')}">
104
+          <ui-input v-value="d.focus_item.name" placeholder="${Editor.T('cc-ext-scene-menu.PNL_name_ph')}"></ui-input>
105
+        </ui-prop>
106
+        <ui-prop name="${Editor.T('cc-ext-scene-menu.PNL_type')}">
107
+          <ui-select v-value="d.focus_item.type" @change="onTypeChange($event)">
108
+            <option value="0">${Editor.T('cc-ext-scene-menu.PNL_prefab')}</option>
109
+            <option value="1">${Editor.T('cc-ext-scene-menu.PNL_command')}</option>
110
+            <option value="2">${Editor.T('cc-ext-scene-menu.PNL_submenu')}</option>
111
+            <option value="3">${Editor.T('cc-ext-scene-menu.PNL_reddot_prefab')}</option>
112
+          </ui-select>
113
+        </ui-prop>
114
+        <ui-prop name="${Editor.T('cc-ext-scene-menu.PNL_prefab_uuid')}" v-if="d.focus_item.type=='0'">
115
+          <ui-input v-value="d.focus_item.uuid" placeholder="prefab uuid"></ui-input>
116
+        </ui-prop>
117
+        <ui-prop name="${Editor.T('cc-ext-scene-menu.PNL_command')}" v-if="d.focus_item.type=='1'">
118
+          <ui-input v-value="d.focus_item.command" placeholder="${Editor.T('cc-ext-scene-menu.PNL_command_ph')}"></ui-input>
119
+        </ui-prop>
120
+        <ui-prop name="${Editor.T('cc-ext-scene-menu.PNL_parameter')}" v-if="d.focus_item.type=='1'">
121
+          <ui-input v-value="d.focus_item.param" placeholder="${Editor.T('cc-ext-scene-menu.PNL_parameter_ph')}"></ui-input>
122
+        </ui-prop>
123
+        <ui-prop name="${Editor.T('cc-ext-scene-menu.PNL_prefab_uuid')}" v-if="d.focus_item.type=='3'">
124
+          <ui-input v-value="d.focus_item.uuid" placeholder="prefab uuid"></ui-input>
125
+        </ui-prop>
126
+      </ui-box-container>
127
+
128
+      <hr />
129
+      <ui-button id="save" @confirm="onSaveConfirm">${Editor.T('cc-ext-scene-menu.PNL_save')}</ui-button>
130
+    </div>
131
+  `,
132
+
133
+  // element and variable binding
134
+  $: {
135
+  },
136
+
137
+  // method executed when template and styles are successfully loaded and initialized
138
+  ready() {
139
+    const fs = require('fs');
140
+    let configPath = Editor.Project.path + '/scene-menu-config.json';
141
+    // Editor.log(configPath);
142
+    if (!fs.existsSync(configPath)) {
143
+      // read default config
144
+      configPath = Editor.url('packages://cc-ext-scene-menu/default-config.json');
145
+    }
146
+
147
+    let saveConfig = () => {
148
+      let data = JSON.stringify(_config, null, 4);
149
+      fs.writeFile(configPath, data, function (err) {
150
+        if (err) {
151
+          Editor.log(err);
152
+          return;
153
+        }
154
+
155
+        Editor.Ipc.sendToMain('cc-ext-scene-menu:update-context-menu');
156
+      });
157
+    };
158
+
159
+    let initWindow = (config) => {
160
+      _config = config;
161
+      new window.Vue({
162
+        el: this.shadowRoot,
163
+        data: {
164
+          d: {
165
+            config: _config,
166
+            focus_item: null,
167
+            loaded: true,
168
+            command: '',
169
+            param: ''
170
+          }
171
+        },
172
+        methods: {
173
+          onSaveConfirm(e) {
174
+            e.stopPropagation();
175
+            saveConfig();
176
+          },
177
+          toggleCaret(e) {
178
+            e.target.classList.toggle('caret-down');
179
+            e.target.parentElement.querySelector(".nested").classList.toggle("active");
180
+          },
181
+          onContextMenu(e, isRoot, obj = null, parent = null) {
182
+            this.d.focus_item = obj;
183
+            let d = this.d;
184
+            let electron = require("electron");
185
+            let menuTemplate = [];
186
+            let currentTarget = e.currentTarget;
187
+            if (!parent) {
188
+              // max depth is 2
189
+              menuTemplate.push({
190
+                label: Editor.T('cc-ext-scene-menu.PNL_add_child'),
191
+                click() {
192
+                  let newItem = {
193
+                    type: "0",
194
+                    name: "New Item",
195
+                    uuid: "",
196
+                    submenu: [],
197
+                    command: "",
198
+                    param: ""
199
+                  };
200
+
201
+                  if (isRoot) {
202
+                    d.config.push(newItem);
203
+                  } else {
204
+                    if (!obj.submenu) {
205
+                      obj.submenu = [];
206
+                    }
207
+
208
+                    obj.type = 2;
209
+                    obj.submenu.push(newItem);
210
+                    currentTarget.parentElement.querySelector(".nested").classList.add("active");
211
+                    currentTarget.parentElement.querySelector(".nested").classList.remove("collapsed");
212
+                    currentTarget.parentElement.querySelector(".caret").classList.add("caret-down");
213
+                  }
214
+                }
215
+              });
216
+            }
217
+
218
+            if (!isRoot) {
219
+              let d = this.d;
220
+              menuTemplate.push({
221
+                label: Editor.T('cc-ext-scene-menu.PNL_delete'),
222
+                click() {
223
+                  if (obj && parent) {
224
+                    // deep level item
225
+                    const index = parent.submenu.indexOf(obj);
226
+                    if (index > -1) {
227
+                      if (d.focus_item == obj) {
228
+                        d.focus_item = null;
229
+                      }
230
+                      parent.submenu.splice(index, 1);
231
+                    }
232
+                  } else if (obj) {
233
+                    // 1st level item
234
+                    const index = config.indexOf(obj);
235
+                    if (index > -1) {
236
+                      if (d.focus_item == obj) {
237
+                        d.focus_item = null;
238
+                      }
239
+                      config.splice(index, 1);
240
+                    }
241
+                  }
242
+                }
243
+              });
244
+            }
245
+
246
+            let menu = electron.remote.Menu.buildFromTemplate(menuTemplate);
247
+            menu.popup();
248
+            e.preventDefault();
249
+          },
250
+          onTypeChange(e) {
251
+          }
252
+        }
253
+      });
254
+    };
255
+
256
+    fs.readFile(configPath, function (err, data) {
257
+      if (err) {
258
+        // file not exists
259
+        initWindow([]);
260
+        return;
261
+      }
262
+
263
+      let config = [];
264
+      try {
265
+        config = JSON.parse(data);
266
+        // Editor.log(`index.js read data: ${data}`);
267
+      } catch (err) {
268
+
269
+      } finally {
270
+        initWindow(config);
271
+      }
272
+    });
273
+  },
274
+
275
+  // register your ipc messages here
276
+  messages: {
277
+    'cc-ext-scene-menu:demo'(event) {
278
+      Editor.log('this is Demo');
279
+    }
280
+  }
281
+});

+ 13 - 0
packages/CCSceneMenu/scene-accessor.ts

@@ -0,0 +1,13 @@
1
+/*
2
+ * @Author: CGT (caogtaa@gmail.com) 
3
+ * @Date: 2020-01-16 22:08:55 
4
+ * @Last Modified by:   CGT (caogtaa@gmail.com) 
5
+ * @Last Modified time: 2020-01-16 22:08:55 
6
+ */
7
+
8
+// @ts-ignore
9
+module.exports = {
10
+  'create-node': function (event, param) {
11
+    
12
+  }
13
+};

+ 18 - 0
packages/LuaExport/main.js

@@ -0,0 +1,18 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+    load() {
5
+        let func = Editor.Ipc.sendToPanel;
6
+    },
7
+
8
+    unload() {
9
+        // execute when package unloaded
10
+    },
11
+    messages: {
12
+        'exportInfo'() {
13
+            Editor.Scene.callSceneScript('export-prefab-info', 'exportInfo', null, function (err) {
14
+                // Editor.log('create-node finish');
15
+            });
16
+        },
17
+    }
18
+};

+ 8 - 0
packages/LuaExport/package.json

@@ -0,0 +1,8 @@
1
+{
2
+  "name": "export-prefab-info",
3
+  "version": "0.0.1",
4
+  "description": "导出预制体信息",
5
+  "author": "",
6
+  "main": "main.js",
7
+  "scene-script": "scene-walker.js"
8
+}

+ 81 - 0
packages/LuaExport/scene-walker.js

@@ -0,0 +1,81 @@
1
+
2
+let fs = require('fs');
3
+let path = require('path');
4
+
5
+module.exports = {
6
+    'exportInfo': function () {
7
+        cc.log("export info");
8
+
9
+        let rootPath = Editor.url('db://assets/edt_prefab/ctrl', 'utf8')
10
+        let allPrefabs = this.getAllUIPrefab(rootPath);
11
+        let allPrefabInfos = this.getAllPrefabInfo(rootPath, allPrefabs);
12
+        this.writeInfoFile(allPrefabInfos);
13
+        // allPrefabInfos.forEach((info) => {
14
+        //     // cc.log(info.name, info.path);
15
+        // });
16
+    },
17
+
18
+    isPrefab(file) {
19
+        return /\.(prefab)$/.test(file);
20
+    },
21
+
22
+    getAllUIPrefab(folder){
23
+        const files = fs.readdirSync(folder);
24
+        let result = []
25
+        files.forEach((file) => {
26
+            const filePath = path.join(folder, file);
27
+            if (fs.statSync(filePath).isDirectory()) {
28
+                result = result.concat(this.getAllUIPrefab(filePath));
29
+            } else if (this.isPrefab(filePath)) {
30
+                result.push(filePath)
31
+            }
32
+        });
33
+        return result;
34
+    },
35
+
36
+    getAllPrefabInfo(rootPath, allPrefabs) {
37
+        let result = [];
38
+        allPrefabs.forEach((file) => {
39
+            let prefabName = path.basename(file, path.extname(file));
40
+            let prefabPath = file.replace(rootPath, "").substring(1)
41
+            result.push({
42
+                "name":prefabName,
43
+                "path":prefabPath,
44
+            })
45
+        });
46
+
47
+        result.sort(function (a, b) {
48
+            return a.name.localeCompare(b.name); //降序排序
49
+        });
50
+        return result;
51
+    },
52
+
53
+    writeInfoFile(allPrefabInfos) {
54
+        let result = "";
55
+        let enumTemplate = "ENUM_TEMPLATE";
56
+        let pathTemplate = "PATH_TEMPLATE";
57
+        result = "// 当前文件为手动导出文件.请勿修改.在预制体编辑界面点击右键导出即可.\n window.JMC.UIEnum = {\n" + enumTemplate + "\n}\nwindow.JMC.UIPath = {\n" + pathTemplate + "\n}";
58
+
59
+        let enumStr = "";
60
+        for (let index = 0; index < allPrefabInfos.length; index++) {
61
+            enumStr = enumStr + "\t\t" + allPrefabInfos[index].name + ":" + index + (index == allPrefabInfos.length - 1 ? "" : ",")  + "\n";
62
+        }
63
+
64
+        let pathStr = "";
65
+        for (let index = 0; index < allPrefabInfos.length; index++) {
66
+            let endStr = index == allPrefabInfos.length - 1 ? "" : ",";
67
+            pathStr = pathStr + "\t\t[window.JMC.UIEnum." + allPrefabInfos[index].name + "] : \"" + allPrefabInfos[index].path.replace("\\", "/") + "\"" + endStr + "\n";
68
+        }
69
+
70
+        result = result.replace(enumTemplate, enumStr);
71
+        result = result.replace(pathTemplate, pathStr);
72
+        
73
+
74
+        let rootPath = Editor.url('db://assets/script/app/view/UIInfo.js', 'utf8')
75
+        fs.writeFileSync(rootPath, result)
76
+
77
+        //保存后刷新资源
78
+        Editor.assetdb.refresh('db://assets/script/app/view/UIInfo.js', function (err, results) {
79
+        });
80
+    },
81
+};