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.
- package/README.md +142 -0
- package/bin/{cocos-cli.js → cocos2d-cli.js} +36 -22
- package/package.json +3 -3
- package/src/commands/add-component.js +75 -114
- package/src/commands/add.js +115 -294
- package/src/commands/build.js +1 -1
- package/src/commands/create-scene.js +133 -488
- package/src/commands/get.js +104 -158
- package/src/commands/prefab-create.js +57 -425
- package/src/commands/remove-component.js +81 -33
- package/src/commands/remove.js +66 -65
- package/src/commands/set.js +105 -253
- package/src/commands/tree.js +7 -11
- package/src/lib/cc/CCButton.js +122 -0
- package/src/lib/cc/CCCamera.js +93 -0
- package/src/lib/cc/CCCanvas.js +64 -0
- package/src/lib/cc/CCColor.js +32 -0
- package/src/lib/cc/CCComponent.js +60 -0
- package/src/lib/cc/CCLabel.js +109 -0
- package/src/lib/cc/CCNode.js +242 -0
- package/src/lib/cc/CCObject.js +23 -0
- package/src/lib/cc/CCPrefab.js +242 -0
- package/src/lib/cc/CCRect.js +32 -0
- package/src/lib/cc/CCScene.js +42 -0
- package/src/lib/cc/CCSceneAsset.js +271 -0
- package/src/lib/cc/CCSize.js +26 -0
- package/src/lib/cc/CCSprite.js +82 -0
- package/src/lib/cc/CCTrs.js +74 -0
- package/src/lib/cc/CCVec2.js +26 -0
- package/src/lib/cc/CCVec3.js +29 -0
- package/src/lib/cc/CCWidget.js +98 -0
- package/src/lib/cc/index.js +40 -0
- package/src/lib/fire-utils.js +58 -392
- package/src/lib/json-parser.js +166 -0
- package/src/lib/node-utils.js +395 -0
- package/src/lib/templates.js +49 -0
- package/src/lib/utils.js +202 -0
- package/src/commands/delete.js +0 -74
- package/src/lib/components.js +0 -404
package/src/commands/remove.js
CHANGED
|
@@ -1,94 +1,95 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* remove 命令 -
|
|
2
|
+
* remove 命令 - 删除节点
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const { CCSceneAsset, CCPrefab } = require('../lib/cc');
|
|
8
|
+
const { buildTree } = require('../lib/node-utils');
|
|
9
|
+
const { loadScriptMap, isPrefab } = require('../lib/fire-utils');
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* 查找节点
|
|
13
|
+
*/
|
|
14
|
+
function findNode(root, path) {
|
|
15
|
+
if (!path) return root;
|
|
16
|
+
|
|
17
|
+
const parts = path.split('/').filter(p => p);
|
|
18
|
+
if (parts.length === 0) return root;
|
|
19
|
+
|
|
20
|
+
let current = root;
|
|
21
|
+
|
|
22
|
+
if (parts[0] === root._name) {
|
|
23
|
+
parts.shift();
|
|
11
24
|
}
|
|
12
25
|
|
|
13
|
-
const
|
|
26
|
+
for (const part of parts) {
|
|
27
|
+
if (!current._children || current._children.length === 0) return null;
|
|
28
|
+
const found = current._children.find(c => c._name === part);
|
|
29
|
+
if (!found) return null;
|
|
30
|
+
current = found;
|
|
31
|
+
}
|
|
14
32
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
33
|
+
return current;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function run(args) {
|
|
37
|
+
if (args.length < 2) {
|
|
38
|
+
console.log(JSON.stringify({ error: '用法: cocos2d-cli remove <场景.fire|预制体.prefab> <节点路径>' }));
|
|
18
39
|
return;
|
|
19
40
|
}
|
|
20
41
|
|
|
21
|
-
const
|
|
42
|
+
const filePath = args[0];
|
|
43
|
+
const nodePath = args[1];
|
|
44
|
+
|
|
45
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
22
46
|
|
|
23
47
|
try {
|
|
24
|
-
let
|
|
25
|
-
|
|
48
|
+
let root;
|
|
49
|
+
let asset;
|
|
50
|
+
const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
26
51
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
52
|
+
if (ext === '.fire') {
|
|
53
|
+
asset = CCSceneAsset.fromJSON(json);
|
|
54
|
+
root = asset._scene;
|
|
55
|
+
} else if (ext === '.prefab') {
|
|
56
|
+
asset = CCPrefab.fromJSON(json);
|
|
57
|
+
root = asset._root;
|
|
58
|
+
} else {
|
|
59
|
+
console.log(JSON.stringify({ error: '不支持的文件类型,仅支持 .fire 和 .prefab' }));
|
|
30
60
|
return;
|
|
31
61
|
}
|
|
32
62
|
|
|
33
|
-
const
|
|
34
|
-
const itemType = item.__type__;
|
|
63
|
+
const node = findNode(root, nodePath);
|
|
35
64
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
65
|
+
if (!node) {
|
|
66
|
+
console.log(JSON.stringify({ error: `节点不存在: ${nodePath}` }));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
39
69
|
|
|
40
|
-
|
|
70
|
+
// 不能删除根节点
|
|
71
|
+
if (node === root) {
|
|
41
72
|
console.log(JSON.stringify({ error: '不能删除根节点' }));
|
|
42
73
|
return;
|
|
43
74
|
}
|
|
44
75
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (node && node._components) {
|
|
51
|
-
node._components = node._components.filter(c => c.__id__ !== index);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// 真正从数组中删除组件并重建引用
|
|
55
|
-
const indicesToDelete = new Set([index]);
|
|
56
|
-
rebuildReferences(data, indicesToDelete);
|
|
57
|
-
data.splice(index, 1);
|
|
58
|
-
|
|
59
|
-
} else {
|
|
60
|
-
// 删除节点
|
|
61
|
-
// 收集所有需要删除的索引
|
|
62
|
-
const indicesToDelete = collectNodeAndChildren(data, index);
|
|
63
|
-
|
|
64
|
-
// 从父节点的 _children 中移除引用
|
|
65
|
-
if (item._parent) {
|
|
66
|
-
const parentIndex = item._parent.__id__;
|
|
67
|
-
const parent = data[parentIndex];
|
|
68
|
-
if (parent && parent._children) {
|
|
69
|
-
parent._children = parent._children.filter(c => c.__id__ !== index);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 重建引用
|
|
74
|
-
rebuildReferences(data, indicesToDelete);
|
|
75
|
-
|
|
76
|
-
// 删除元素
|
|
77
|
-
const sortedIndices = Array.from(indicesToDelete).sort((a, b) => b - a);
|
|
78
|
-
for (const idx of sortedIndices) {
|
|
79
|
-
data.splice(idx, 1);
|
|
76
|
+
// 从父节点移除
|
|
77
|
+
if (node._parent) {
|
|
78
|
+
const idx = node._parent._children.indexOf(node);
|
|
79
|
+
if (idx > -1) {
|
|
80
|
+
node._parent._children.splice(idx, 1);
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// 触发编辑器刷新
|
|
87
|
-
refreshEditor(scenePath);
|
|
84
|
+
// 保存
|
|
85
|
+
const data = asset.toJSON();
|
|
86
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
|
|
88
87
|
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
// 输出节点树
|
|
89
|
+
const scriptMap = loadScriptMap(filePath);
|
|
90
|
+
const prefab = isPrefab(data);
|
|
91
|
+
const startIndex = prefab ? 0 : 1;
|
|
92
|
+
console.log(buildTree(data, scriptMap, startIndex).trim());
|
|
92
93
|
|
|
93
94
|
} catch (err) {
|
|
94
95
|
console.log(JSON.stringify({ error: err.message }));
|
package/src/commands/set.js
CHANGED
|
@@ -1,296 +1,148 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* set 命令 -
|
|
3
|
-
* 修改成功后返回节点最终状态(与 get 命令格式一致)
|
|
2
|
+
* set 命令 - 设置节点或组件属性
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
|
-
const
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const { CCSceneAsset, CCPrefab } = require('../lib/cc');
|
|
8
|
+
const { buildTree } = require('../lib/node-utils');
|
|
9
|
+
const { loadScriptMap, isPrefab } = require('../lib/fire-utils');
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
|
-
*
|
|
12
|
+
* 查找节点
|
|
10
13
|
*/
|
|
11
|
-
function
|
|
12
|
-
if (!
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
function findNode(root, path) {
|
|
15
|
+
if (!path) return root;
|
|
16
|
+
|
|
17
|
+
const parts = path.split('/').filter(p => p);
|
|
18
|
+
if (parts.length === 0) return root;
|
|
19
|
+
|
|
20
|
+
let current = root;
|
|
21
|
+
|
|
22
|
+
if (parts[0] === root._name) {
|
|
23
|
+
parts.shift();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
for (const part of parts) {
|
|
27
|
+
if (!current._children || current._children.length === 0) return null;
|
|
28
|
+
const found = current._children.find(c => c._name === part);
|
|
29
|
+
if (!found) return null;
|
|
30
|
+
current = found;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return current;
|
|
17
34
|
}
|
|
18
35
|
|
|
19
36
|
/**
|
|
20
|
-
*
|
|
37
|
+
* 查找组件
|
|
21
38
|
*/
|
|
22
|
-
function
|
|
23
|
-
if (!
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (Array.isArray(obj)) return obj.map(clean);
|
|
30
|
-
const result = {};
|
|
31
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
32
|
-
if (k === '__type__') continue;
|
|
33
|
-
result[k] = typeof v === 'object' ? clean(v) : v;
|
|
34
|
-
}
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
switch (type) {
|
|
39
|
-
case 'cc.Sprite':
|
|
40
|
-
return {
|
|
41
|
-
...base,
|
|
42
|
-
spriteFrame: comp._spriteFrame?.__uuid__ || null,
|
|
43
|
-
sizeMode: ['CUSTOM', 'TRIMMED', 'RAW'][comp._sizeMode] || comp._sizeMode,
|
|
44
|
-
spriteType: ['SIMPLE', 'SLICED', 'TILED', 'FILLED', 'MESH'][comp._type] || comp._type,
|
|
45
|
-
trim: comp._isTrimmedMode
|
|
46
|
-
};
|
|
47
|
-
case 'cc.Label':
|
|
48
|
-
return {
|
|
49
|
-
...base,
|
|
50
|
-
string: comp._string,
|
|
51
|
-
fontSize: comp._fontSize,
|
|
52
|
-
lineHeight: comp._lineHeight,
|
|
53
|
-
horizontalAlign: ['LEFT', 'CENTER', 'RIGHT'][comp._N$horizontalAlign] || comp._N$horizontalAlign,
|
|
54
|
-
verticalAlign: ['TOP', 'CENTER', 'BOTTOM'][comp._N$verticalAlign] || comp._N$verticalAlign,
|
|
55
|
-
overflow: ['NONE', 'CLAMP', 'SHRINK', 'RESIZE_HEIGHT'][comp._N$overflow] || comp._N$overflow,
|
|
56
|
-
fontFamily: comp._N$fontFamily,
|
|
57
|
-
enableWrapText: comp._enableWrapText
|
|
58
|
-
};
|
|
59
|
-
case 'cc.Button':
|
|
60
|
-
return {
|
|
61
|
-
...base,
|
|
62
|
-
interactable: comp._N$interactable,
|
|
63
|
-
transition: ['NONE', 'COLOR', 'SPRITE', 'SCALE'][comp._N$transition] || comp._N$transition,
|
|
64
|
-
zoomScale: comp.zoomScale,
|
|
65
|
-
duration: comp.duration
|
|
66
|
-
};
|
|
67
|
-
case 'cc.Widget':
|
|
68
|
-
return {
|
|
69
|
-
...base,
|
|
70
|
-
alignMode: ['ONCE', 'ON_WINDOW_RESIZE', 'ALWAYS'][comp.alignMode] || comp.alignMode,
|
|
71
|
-
left: comp._left,
|
|
72
|
-
right: comp._right,
|
|
73
|
-
top: comp._top,
|
|
74
|
-
bottom: comp._bottom
|
|
75
|
-
};
|
|
76
|
-
case 'cc.Layout':
|
|
77
|
-
return {
|
|
78
|
-
...base,
|
|
79
|
-
layoutType: ['NONE', 'HORIZONTAL', 'VERTICAL', 'GRID'][comp._N$layoutType] || comp._N$layoutType,
|
|
80
|
-
spacingX: comp._N$spacingX,
|
|
81
|
-
spacingY: comp._N$spacingY,
|
|
82
|
-
paddingLeft: comp._N$paddingLeft,
|
|
83
|
-
paddingRight: comp._N$paddingRight,
|
|
84
|
-
paddingTop: comp._N$paddingTop,
|
|
85
|
-
paddingBottom: comp._N$paddingBottom
|
|
86
|
-
};
|
|
87
|
-
case 'cc.Canvas':
|
|
88
|
-
return {
|
|
89
|
-
...base,
|
|
90
|
-
designResolution: clean(comp._designResolution),
|
|
91
|
-
fitWidth: comp._fitWidth,
|
|
92
|
-
fitHeight: comp._fitHeight
|
|
93
|
-
};
|
|
94
|
-
case 'cc.Camera':
|
|
95
|
-
return {
|
|
96
|
-
...base,
|
|
97
|
-
depth: comp._depth,
|
|
98
|
-
zoomRatio: comp._zoomRatio,
|
|
99
|
-
ortho: comp._ortho,
|
|
100
|
-
cullingMask: comp._cullingMask
|
|
101
|
-
};
|
|
102
|
-
case 'cc.ParticleSystem':
|
|
103
|
-
return {
|
|
104
|
-
...base,
|
|
105
|
-
playOnLoad: comp.playOnLoad,
|
|
106
|
-
totalParticles: comp.totalParticles,
|
|
107
|
-
duration: comp.duration
|
|
108
|
-
};
|
|
109
|
-
default:
|
|
110
|
-
const result = { ...base };
|
|
111
|
-
for (const key of Object.keys(comp)) {
|
|
112
|
-
if (!key.startsWith('_') && key !== '__type__') {
|
|
113
|
-
result[key] = comp[key];
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return result;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 解析颜色
|
|
121
|
-
function parseColor(colorStr) {
|
|
122
|
-
if (!colorStr) return null;
|
|
123
|
-
let color = colorStr;
|
|
124
|
-
if (typeof color === 'string') {
|
|
125
|
-
if (color.startsWith('#')) color = color.slice(1);
|
|
126
|
-
if (color.length === 6) {
|
|
127
|
-
const r = parseInt(color.slice(0, 2), 16);
|
|
128
|
-
const g = parseInt(color.slice(2, 4), 16);
|
|
129
|
-
const b = parseInt(color.slice(4, 6), 16);
|
|
130
|
-
if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
|
|
131
|
-
return { "__type__": "cc.Color", r, g, b, a: 255 };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
39
|
+
function findComponent(node, compType) {
|
|
40
|
+
if (!node._components) return null;
|
|
41
|
+
|
|
42
|
+
const type = compType.toLowerCase();
|
|
43
|
+
const typeName = 'cc.' + type.charAt(0).toUpperCase() + type.slice(1);
|
|
44
|
+
|
|
45
|
+
return node._components.find(c => c.__type__ === typeName);
|
|
136
46
|
}
|
|
137
47
|
|
|
138
48
|
/**
|
|
139
|
-
*
|
|
49
|
+
* 设置节点属性值
|
|
140
50
|
*/
|
|
141
|
-
function
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (components.length > 0) result.components = components;
|
|
161
|
-
|
|
162
|
-
return result;
|
|
51
|
+
function setNodeProp(node, prop, value) {
|
|
52
|
+
switch (prop.toLowerCase()) {
|
|
53
|
+
case 'name': node._name = value; return true;
|
|
54
|
+
case 'active': node._active = value === 'true' || value === true; return true;
|
|
55
|
+
case 'x': node._trs.array[0] = parseFloat(value); return true;
|
|
56
|
+
case 'y': node._trs.array[1] = parseFloat(value); return true;
|
|
57
|
+
case 'width': node._contentSize.width = parseFloat(value); return true;
|
|
58
|
+
case 'height': node._contentSize.height = parseFloat(value); return true;
|
|
59
|
+
case 'scalex': node._trs.array[7] = parseFloat(value); return true;
|
|
60
|
+
case 'scaley': node._trs.array[8] = parseFloat(value); return true;
|
|
61
|
+
case 'rotation':
|
|
62
|
+
node._trs.array[5] = parseFloat(value) * Math.PI / 180;
|
|
63
|
+
node._eulerAngles.z = parseFloat(value);
|
|
64
|
+
return true;
|
|
65
|
+
case 'anchorx': node._anchorPoint.x = parseFloat(value); return true;
|
|
66
|
+
case 'anchory': node._anchorPoint.y = parseFloat(value); return true;
|
|
67
|
+
case 'opacity': node._opacity = parseInt(value); return true;
|
|
68
|
+
default: return false;
|
|
69
|
+
}
|
|
163
70
|
}
|
|
164
71
|
|
|
165
72
|
function run(args) {
|
|
166
|
-
if (args.length <
|
|
167
|
-
console.log(JSON.stringify({ error: '用法:
|
|
73
|
+
if (args.length < 4) {
|
|
74
|
+
console.log(JSON.stringify({ error: '用法: cocos2d-cli set <场景.fire|预制体.prefab> <节点路径> <属性名|组件.属性> <值>' }));
|
|
168
75
|
return;
|
|
169
76
|
}
|
|
170
77
|
|
|
171
|
-
const
|
|
172
|
-
const
|
|
78
|
+
const filePath = args[0];
|
|
79
|
+
const nodePath = args[1];
|
|
80
|
+
const propPath = args[2];
|
|
81
|
+
const value = args[3];
|
|
173
82
|
|
|
174
|
-
|
|
175
|
-
const options = {};
|
|
176
|
-
args.slice(2).forEach(arg => {
|
|
177
|
-
if (arg.startsWith('--')) {
|
|
178
|
-
const [key, value] = arg.substring(2).split('=');
|
|
179
|
-
options[key] = value;
|
|
180
|
-
}
|
|
181
|
-
});
|
|
83
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
182
84
|
|
|
183
85
|
try {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
86
|
+
let root;
|
|
87
|
+
let asset;
|
|
88
|
+
const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
89
|
+
|
|
90
|
+
if (ext === '.fire') {
|
|
91
|
+
asset = CCSceneAsset.fromJSON(json);
|
|
92
|
+
root = asset._scene;
|
|
93
|
+
} else if (ext === '.prefab') {
|
|
94
|
+
asset = CCPrefab.fromJSON(json);
|
|
95
|
+
root = asset._root;
|
|
96
|
+
} else {
|
|
97
|
+
console.log(JSON.stringify({ error: '不支持的文件类型,仅支持 .fire 和 .prefab' }));
|
|
192
98
|
return;
|
|
193
99
|
}
|
|
194
100
|
|
|
195
|
-
const node =
|
|
101
|
+
const node = findNode(root, nodePath);
|
|
196
102
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// 修改激活状态
|
|
203
|
-
if (options.active !== undefined) {
|
|
204
|
-
node._active = options.active !== 'false';
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// 修改位置
|
|
208
|
-
if (options.x !== undefined || options.y !== undefined) {
|
|
209
|
-
if (!node._trs) {
|
|
210
|
-
node._trs = { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] };
|
|
211
|
-
}
|
|
212
|
-
if (options.x !== undefined) node._trs.array[0] = parseFloat(options.x);
|
|
213
|
-
if (options.y !== undefined) node._trs.array[1] = parseFloat(options.y);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 修改大小
|
|
217
|
-
if (options.width !== undefined || options.height !== undefined) {
|
|
218
|
-
if (!node._contentSize) {
|
|
219
|
-
node._contentSize = { "__type__": "cc.Size", width: 0, height: 0 };
|
|
220
|
-
}
|
|
221
|
-
if (options.width !== undefined) node._contentSize.width = parseFloat(options.width);
|
|
222
|
-
if (options.height !== undefined) node._contentSize.height = parseFloat(options.height);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// 修改锚点
|
|
226
|
-
if (options.anchorX !== undefined || options.anchorY !== undefined) {
|
|
227
|
-
if (!node._anchorPoint) {
|
|
228
|
-
node._anchorPoint = { "__type__": "cc.Vec2", x: 0.5, y: 0.5 };
|
|
229
|
-
}
|
|
230
|
-
if (options.anchorX !== undefined) node._anchorPoint.x = parseFloat(options.anchorX);
|
|
231
|
-
if (options.anchorY !== undefined) node._anchorPoint.y = parseFloat(options.anchorY);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// 修改透明度
|
|
235
|
-
if (options.opacity !== undefined) {
|
|
236
|
-
node._opacity = Math.max(0, Math.min(255, parseInt(options.opacity)));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// 修改颜色
|
|
240
|
-
if (options.color !== undefined) {
|
|
241
|
-
const color = parseColor(options.color);
|
|
242
|
-
if (color) {
|
|
243
|
-
node._color = color;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// 修改旋转角度
|
|
248
|
-
if (options.rotation !== undefined) {
|
|
249
|
-
if (!node._eulerAngles) {
|
|
250
|
-
node._eulerAngles = { "__type__": "cc.Vec3", x: 0, y: 0, z: 0 };
|
|
251
|
-
}
|
|
252
|
-
node._eulerAngles.z = parseFloat(options.rotation);
|
|
103
|
+
if (!node) {
|
|
104
|
+
console.log(JSON.stringify({ error: `节点不存在: ${nodePath}` }));
|
|
105
|
+
return;
|
|
253
106
|
}
|
|
254
107
|
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
if (!node._trs) {
|
|
258
|
-
node._trs = { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] };
|
|
259
|
-
}
|
|
260
|
-
if (options.scaleX !== undefined) node._trs.array[7] = parseFloat(options.scaleX);
|
|
261
|
-
if (options.scaleY !== undefined) node._trs.array[8] = parseFloat(options.scaleY);
|
|
262
|
-
}
|
|
108
|
+
// 检查是否是组件属性(格式: 组件.属性)
|
|
109
|
+
const parts = propPath.split('.');
|
|
263
110
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
if (!
|
|
268
|
-
console.log(JSON.stringify({ error:
|
|
111
|
+
if (parts.length === 2) {
|
|
112
|
+
// 组件属性
|
|
113
|
+
const comp = findComponent(node, parts[0]);
|
|
114
|
+
if (!comp) {
|
|
115
|
+
console.log(JSON.stringify({ error: `组件不存在: ${parts[0]}` }));
|
|
269
116
|
return;
|
|
270
117
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (options.fontSize !== undefined) {
|
|
276
|
-
labelComp._fontSize = parseInt(options.fontSize);
|
|
118
|
+
|
|
119
|
+
if (comp[parts[1]] === undefined) {
|
|
120
|
+
console.log(JSON.stringify({ error: `属性不存在: ${parts[1]}` }));
|
|
121
|
+
return;
|
|
277
122
|
}
|
|
278
|
-
|
|
279
|
-
|
|
123
|
+
|
|
124
|
+
comp[parts[1]] = value;
|
|
125
|
+
} else {
|
|
126
|
+
// 节点属性
|
|
127
|
+
if (!setNodeProp(node, propPath, value)) {
|
|
128
|
+
console.log(JSON.stringify({ error: `属性不存在: ${propPath}` }));
|
|
129
|
+
return;
|
|
280
130
|
}
|
|
281
131
|
}
|
|
282
132
|
|
|
283
|
-
//
|
|
284
|
-
|
|
133
|
+
// 保存
|
|
134
|
+
const data = asset.toJSON();
|
|
135
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
|
|
285
136
|
|
|
286
|
-
//
|
|
287
|
-
|
|
137
|
+
// 输出节点树
|
|
138
|
+
const scriptMap = loadScriptMap(filePath);
|
|
139
|
+
const prefab = isPrefab(data);
|
|
140
|
+
const startIndex = prefab ? 0 : 1;
|
|
141
|
+
console.log(buildTree(data, scriptMap, startIndex).trim());
|
|
288
142
|
|
|
289
|
-
// 返回节点最终状态(与 get 命令格式一致)
|
|
290
|
-
console.log(JSON.stringify(getNodeState(data, node, nodeIndex)));
|
|
291
143
|
} catch (err) {
|
|
292
144
|
console.log(JSON.stringify({ error: err.message }));
|
|
293
145
|
}
|
|
294
146
|
}
|
|
295
147
|
|
|
296
|
-
module.exports = { run };
|
|
148
|
+
module.exports = { run };
|
package/src/commands/tree.js
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
* tree 命令 - 查看节点树(支持场景和预制体)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const { loadScene, loadScriptMap,
|
|
5
|
+
const { loadScene, loadScriptMap, isPrefab } = require('../lib/fire-utils');
|
|
6
|
+
const { buildTree } = require('../lib/node-utils');
|
|
6
7
|
|
|
7
8
|
function run(args) {
|
|
8
9
|
const filePath = args[0];
|
|
9
10
|
|
|
10
11
|
if (!filePath) {
|
|
11
|
-
console.log(JSON.stringify({ error: '用法:
|
|
12
|
+
console.log(JSON.stringify({ error: '用法: cocos2d-cli tree <场景.fire | 预制体.prefab>' }));
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -17,17 +18,12 @@ function run(args) {
|
|
|
17
18
|
const scriptMap = loadScriptMap(filePath);
|
|
18
19
|
const prefab = isPrefab(data);
|
|
19
20
|
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} else {
|
|
24
|
-
console.log(`[Scene]\n`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
console.log(buildTree(data, scriptMap, 1));
|
|
21
|
+
// Prefab 从索引 0 开始,Scene 从索引 1 开始
|
|
22
|
+
const startIndex = prefab ? 0 : 1;
|
|
23
|
+
console.log(buildTree(data, scriptMap, startIndex).trim());
|
|
28
24
|
} catch (err) {
|
|
29
25
|
console.log(JSON.stringify({ error: err.message }));
|
|
30
26
|
}
|
|
31
27
|
}
|
|
32
28
|
|
|
33
|
-
module.exports = { run };
|
|
29
|
+
module.exports = { run };
|