cocos2d-cli 1.2.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +142 -0
  2. package/bin/{cocos-cli.js → cocos2d-cli.js} +36 -22
  3. package/package.json +3 -3
  4. package/src/commands/add-component.js +75 -114
  5. package/src/commands/add.js +115 -294
  6. package/src/commands/build.js +1 -1
  7. package/src/commands/create-scene.js +133 -488
  8. package/src/commands/get.js +104 -158
  9. package/src/commands/prefab-create.js +57 -425
  10. package/src/commands/remove-component.js +81 -33
  11. package/src/commands/remove.js +66 -65
  12. package/src/commands/set.js +105 -253
  13. package/src/commands/tree.js +7 -11
  14. package/src/lib/cc/CCButton.js +122 -0
  15. package/src/lib/cc/CCCamera.js +93 -0
  16. package/src/lib/cc/CCCanvas.js +64 -0
  17. package/src/lib/cc/CCColor.js +32 -0
  18. package/src/lib/cc/CCComponent.js +60 -0
  19. package/src/lib/cc/CCLabel.js +109 -0
  20. package/src/lib/cc/CCNode.js +242 -0
  21. package/src/lib/cc/CCObject.js +23 -0
  22. package/src/lib/cc/CCPrefab.js +242 -0
  23. package/src/lib/cc/CCRect.js +32 -0
  24. package/src/lib/cc/CCScene.js +42 -0
  25. package/src/lib/cc/CCSceneAsset.js +271 -0
  26. package/src/lib/cc/CCSize.js +26 -0
  27. package/src/lib/cc/CCSprite.js +82 -0
  28. package/src/lib/cc/CCTrs.js +74 -0
  29. package/src/lib/cc/CCVec2.js +26 -0
  30. package/src/lib/cc/CCVec3.js +29 -0
  31. package/src/lib/cc/CCWidget.js +98 -0
  32. package/src/lib/cc/index.js +40 -0
  33. package/src/lib/fire-utils.js +58 -392
  34. package/src/lib/json-parser.js +166 -0
  35. package/src/lib/node-utils.js +395 -0
  36. package/src/lib/templates.js +49 -0
  37. package/src/lib/utils.js +202 -0
  38. package/src/commands/delete.js +0 -74
  39. package/src/lib/components.js +0 -404
@@ -1,190 +1,136 @@
1
1
  /**
2
- * get 命令 - 获取节点信息
3
- * 返回与编辑器 Inspector 面板一致的所有属性
2
+ * get 命令 - 获取节点或组件属性
4
3
  */
5
4
 
6
- const { loadScene, buildMaps, findNodeIndex } = require('../lib/fire-utils');
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+ const { CCSceneAsset, CCPrefab } = require('../lib/cc');
7
8
 
8
9
  /**
9
- * 将 _color 对象转为 #RRGGBB 字符串
10
+ * 查找节点
10
11
  */
11
- function colorToHex(color) {
12
- if (!color) return '#ffffff';
13
- const r = (color.r || 0).toString(16).padStart(2, '0');
14
- const g = (color.g || 0).toString(16).padStart(2, '0');
15
- const b = (color.b || 0).toString(16).padStart(2, '0');
16
- return `#${r}${g}${b}`;
12
+ function findNode(root, path) {
13
+ if (!path) return root;
14
+
15
+ const parts = path.split('/').filter(p => p);
16
+ if (parts.length === 0) return root;
17
+
18
+ let current = root;
19
+
20
+ if (parts[0] === root._name) {
21
+ parts.shift();
22
+ }
23
+
24
+ for (const part of parts) {
25
+ if (!current._children || current._children.length === 0) return null;
26
+ const found = current._children.find(c => c._name === part);
27
+ if (!found) return null;
28
+ current = found;
29
+ }
30
+
31
+ return current;
17
32
  }
18
33
 
19
34
  /**
20
- * 提取组件的关键属性(对应 Inspector 面板显示)
35
+ * 查找组件
21
36
  */
22
- function extractComponentProps(comp) {
23
- if (!comp) return null;
24
- const type = comp.__type__;
25
-
26
- // 只在 disabled 时才输出 enabled 字段
27
- const base = comp._enabled ? { type } : { type, enabled: false };
28
-
29
- // 清理对象中的 __type__ 字段
30
- const clean = (obj) => {
31
- if (!obj || typeof obj !== 'object') return obj;
32
- if (Array.isArray(obj)) return obj.map(clean);
33
- const result = {};
34
- for (const [k, v] of Object.entries(obj)) {
35
- if (k === '__type__') continue;
36
- result[k] = typeof v === 'object' ? clean(v) : v;
37
- }
38
- return result;
39
- };
37
+ function findComponent(node, compType) {
38
+ if (!node._components) return null;
39
+
40
+ const type = compType.toLowerCase();
41
+ const typeName = 'cc.' + type.charAt(0).toUpperCase() + type.slice(1);
42
+
43
+ return node._components.find(c => c.__type__ === typeName);
44
+ }
40
45
 
41
- switch (type) {
42
- case 'cc.Sprite':
43
- return {
44
- ...base,
45
- spriteFrame: comp._spriteFrame?.__uuid__ || null,
46
- sizeMode: ['CUSTOM', 'TRIMMED', 'RAW'][comp._sizeMode] || comp._sizeMode,
47
- spriteType: ['SIMPLE', 'SLICED', 'TILED', 'FILLED', 'MESH'][comp._type] || comp._type,
48
- trim: comp._isTrimmedMode
49
- };
50
- case 'cc.Label':
51
- return {
52
- ...base,
53
- string: comp._string,
54
- fontSize: comp._fontSize,
55
- lineHeight: comp._lineHeight,
56
- horizontalAlign: ['LEFT', 'CENTER', 'RIGHT'][comp._N$horizontalAlign] || comp._N$horizontalAlign,
57
- verticalAlign: ['TOP', 'CENTER', 'BOTTOM'][comp._N$verticalAlign] || comp._N$verticalAlign,
58
- overflow: ['NONE', 'CLAMP', 'SHRINK', 'RESIZE_HEIGHT'][comp._N$overflow] || comp._N$overflow,
59
- fontFamily: comp._N$fontFamily,
60
- enableWrapText: comp._enableWrapText
61
- };
62
- case 'cc.Button':
63
- return {
64
- ...base,
65
- interactable: comp._N$interactable,
66
- transition: ['NONE', 'COLOR', 'SPRITE', 'SCALE'][comp._N$transition] || comp._N$transition,
67
- zoomScale: comp.zoomScale,
68
- duration: comp.duration
69
- };
70
- case 'cc.Widget':
71
- return {
72
- ...base,
73
- alignMode: ['ONCE', 'ON_WINDOW_RESIZE', 'ALWAYS'][comp.alignMode] || comp.alignMode,
74
- left: comp._left,
75
- right: comp._right,
76
- top: comp._top,
77
- bottom: comp._bottom
78
- };
79
- case 'cc.Layout':
80
- return {
81
- ...base,
82
- layoutType: ['NONE', 'HORIZONTAL', 'VERTICAL', 'GRID'][comp._N$layoutType] || comp._N$layoutType,
83
- spacingX: comp._N$spacingX,
84
- spacingY: comp._N$spacingY,
85
- paddingLeft: comp._N$paddingLeft,
86
- paddingRight: comp._N$paddingRight,
87
- paddingTop: comp._N$paddingTop,
88
- paddingBottom: comp._N$paddingBottom
89
- };
90
- case 'cc.Canvas':
91
- return {
92
- ...base,
93
- designResolution: clean(comp._designResolution),
94
- fitWidth: comp._fitWidth,
95
- fitHeight: comp._fitHeight
96
- };
97
- case 'cc.Camera':
98
- return {
99
- ...base,
100
- depth: comp._depth,
101
- zoomRatio: comp._zoomRatio,
102
- ortho: comp._ortho,
103
- cullingMask: comp._cullingMask
104
- };
105
- case 'cc.ParticleSystem':
106
- return {
107
- ...base,
108
- playOnLoad: comp.playOnLoad,
109
- totalParticles: comp.totalParticles,
110
- duration: comp.duration
111
- };
112
- default:
113
- // 未知组件:返回去掉内部字段的原始属性
114
- const result = { ...base };
115
- for (const key of Object.keys(comp)) {
116
- if (!key.startsWith('_') && key !== '__type__') {
117
- result[key] = comp[key];
118
- }
119
- }
120
- return result;
46
+ /**
47
+ * 获取节点属性值
48
+ */
49
+ function getNodeProp(node, prop) {
50
+ switch (prop.toLowerCase()) {
51
+ case 'name': return node._name;
52
+ case 'active': return node._active;
53
+ case 'x': return node._trs.array[0];
54
+ case 'y': return node._trs.array[1];
55
+ case 'width': return node._contentSize.width;
56
+ case 'height': return node._contentSize.height;
57
+ case 'scalex': return node._trs.array[7];
58
+ case 'scaley': return node._trs.array[8];
59
+ case 'rotation': return node._eulerAngles.z;
60
+ case 'anchorx': return node._anchorPoint.x;
61
+ case 'anchory': return node._anchorPoint.y;
62
+ case 'opacity': return node._opacity;
63
+ case 'color': return node._color;
64
+ default: return undefined;
121
65
  }
122
66
  }
123
67
 
124
68
  function run(args) {
125
- if (args.length < 2) {
126
- console.log(JSON.stringify({ error: '用法: cocos2.4 get <场景.fire | 预制体.prefab> <节点索引|名称>' }));
69
+ if (args.length < 3) {
70
+ console.log(JSON.stringify({ error: '用法: cocos2d-cli get <场景.fire|预制体.prefab> <节点路径> <属性名|组件.属性>' }));
127
71
  return;
128
72
  }
129
73
 
130
- const scenePath = args[0];
131
- const nodeRef = args[1];
74
+ const filePath = args[0];
75
+ const nodePath = args[1];
76
+ const propPath = args[2];
77
+
78
+ const ext = path.extname(filePath).toLowerCase();
132
79
 
133
80
  try {
134
- const data = loadScene(scenePath);
135
- const { indexMap } = buildMaps(data);
81
+ let root;
82
+ const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
136
83
 
137
- // 查找节点
138
- const idx = findNodeIndex(data, indexMap, nodeRef);
139
-
140
- if (idx === null || idx < 0 || idx >= data.length) {
141
- console.log(JSON.stringify({ error: `无效的节点索引: ${nodeRef}` }));
84
+ if (ext === '.fire') {
85
+ const asset = CCSceneAsset.fromJSON(json);
86
+ root = asset._scene;
87
+ } else if (ext === '.prefab') {
88
+ const asset = CCPrefab.fromJSON(json);
89
+ root = asset._root;
90
+ } else {
91
+ console.log(JSON.stringify({ error: '不支持的文件类型,仅支持 .fire 和 .prefab' }));
142
92
  return;
143
93
  }
144
94
 
145
- const node = data[idx];
95
+ const node = findNode(root, nodePath);
96
+
146
97
  if (!node) {
147
- console.log(JSON.stringify({ error: `节点不存在: ${nodeRef}` }));
98
+ console.log(JSON.stringify({ error: `节点不存在: ${nodePath}` }));
148
99
  return;
149
100
  }
150
-
151
- // _trs 数组解析变换属性
152
- // 格式: [x, y, z, qx, qy, qz, qw, scaleX, scaleY, scaleZ]
153
- const trs = node._trs?.array || [0,0,0, 0,0,0,1, 1,1,1];
154
-
155
- // 组件详细信息
156
- const components = (node._components || []).map(ref => {
157
- const comp = data[ref.__id__];
158
- return extractComponentProps(comp);
159
- });
160
-
161
- // 子节点名称
162
- const children = (node._children || []).map(ref => data[ref.__id__]?._name || '(unknown)');
163
-
164
- const info = indexMap[idx] || {};
165
-
166
- // 精简 JSON 输出
167
- const result = {
168
- name: info.name,
169
- active: node._active,
170
- position: { x: trs[0], y: trs[1] },
171
- rotation: node._eulerAngles?.z ?? 0,
172
- scale: { x: trs[7], y: trs[8] },
173
- anchor: { x: node._anchorPoint?.x ?? 0.5, y: node._anchorPoint?.y ?? 0.5 },
174
- size: { w: node._contentSize?.width ?? 0, h: node._contentSize?.height ?? 0 },
175
- color: colorToHex(node._color),
176
- opacity: node._opacity ?? 255,
177
- group: node._groupIndex ?? 0
178
- };
179
-
180
- if (children.length > 0) result.children = children;
181
- if (components.length > 0) result.components = components;
182
-
183
- console.log(JSON.stringify(result));
184
-
101
+
102
+ // 检查是否是组件属性(格式: 组件.属性)
103
+ const parts = propPath.split('.');
104
+
105
+ if (parts.length === 2) {
106
+ // 组件属性
107
+ const comp = findComponent(node, parts[0]);
108
+ if (!comp) {
109
+ console.log(JSON.stringify({ error: `组件不存在: ${parts[0]}` }));
110
+ return;
111
+ }
112
+
113
+ const value = comp[parts[1]];
114
+ if (value === undefined) {
115
+ console.log(JSON.stringify({ error: `属性不存在: ${parts[1]}` }));
116
+ return;
117
+ }
118
+
119
+ console.log(JSON.stringify({ value }));
120
+ } else {
121
+ // 节点属性
122
+ const value = getNodeProp(node, propPath);
123
+ if (value === undefined) {
124
+ console.log(JSON.stringify({ error: `属性不存在: ${propPath}` }));
125
+ return;
126
+ }
127
+
128
+ console.log(JSON.stringify({ value }));
129
+ }
130
+
185
131
  } catch (err) {
186
132
  console.log(JSON.stringify({ error: err.message }));
187
133
  }
188
134
  }
189
135
 
190
- module.exports = { run };
136
+ module.exports = { run };