cocos2d-cli 1.0.4 → 1.1.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/bin/cocos-cli.js +39 -21
- package/data/prefab-template.json +72 -0
- package/data/scene-template.json +241 -0
- package/package.json +4 -6
- package/src/commands/add.js +230 -101
- package/src/commands/create-scene.js +494 -0
- package/src/commands/delete.js +16 -15
- package/src/commands/get.js +153 -16
- package/src/commands/prefab-create.js +49 -0
- package/src/commands/remove.js +11 -76
- package/src/commands/set.js +145 -31
- package/src/commands/tree.js +15 -74
- package/src/lib/components.js +2 -2
- package/src/lib/fire-utils.js +233 -11
package/src/commands/get.js
CHANGED
|
@@ -1,12 +1,129 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* get 命令 - 获取节点信息
|
|
2
|
+
* get 命令 - 获取节点信息
|
|
3
|
+
* 返回与编辑器 Inspector 面板一致的所有属性
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
const { loadScene, buildMaps, findNodeIndex } = require('../lib/fire-utils');
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* 将 _color 对象转为 #RRGGBB 字符串
|
|
10
|
+
*/
|
|
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}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 提取组件的关键属性(对应 Inspector 面板显示)
|
|
21
|
+
*/
|
|
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
|
+
};
|
|
40
|
+
|
|
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;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
7
124
|
function run(args) {
|
|
8
125
|
if (args.length < 2) {
|
|
9
|
-
console.log(JSON.stringify({ error: '用法: cocos2.4 get
|
|
126
|
+
console.log(JSON.stringify({ error: '用法: cocos2.4 get <场景.fire | 预制体.prefab> <节点索引|名称>' }));
|
|
10
127
|
return;
|
|
11
128
|
}
|
|
12
129
|
|
|
@@ -30,21 +147,41 @@ function run(args) {
|
|
|
30
147
|
console.log(JSON.stringify({ error: `节点不存在: ${nodeRef}` }));
|
|
31
148
|
return;
|
|
32
149
|
}
|
|
33
|
-
|
|
34
|
-
//
|
|
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
|
+
|
|
35
164
|
const info = indexMap[idx] || {};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
+
|
|
48
185
|
} catch (err) {
|
|
49
186
|
console.log(JSON.stringify({ error: err.message }));
|
|
50
187
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prefab-create 命令 - 创建新预制体文件
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { saveScene, createPrefab } = require('../lib/fire-utils');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
function run(args) {
|
|
10
|
+
if (args.length < 2) {
|
|
11
|
+
console.log(JSON.stringify({ error: '用法: cocos2.4 prefab-create <预制体路径> <根节点名称>' }));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const prefabPath = args[0];
|
|
16
|
+
const rootName = args[1] || 'RootNode';
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// 检查文件是否已存在
|
|
20
|
+
if (fs.existsSync(prefabPath)) {
|
|
21
|
+
console.log(JSON.stringify({ error: `文件已存在: ${prefabPath}` }));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 确保目录存在
|
|
26
|
+
const dir = path.dirname(prefabPath);
|
|
27
|
+
if (!fs.existsSync(dir)) {
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 创建预制体数据
|
|
32
|
+
const data = createPrefab(rootName);
|
|
33
|
+
|
|
34
|
+
// 保存文件
|
|
35
|
+
saveScene(prefabPath, data);
|
|
36
|
+
|
|
37
|
+
console.log(JSON.stringify({
|
|
38
|
+
success: true,
|
|
39
|
+
path: prefabPath,
|
|
40
|
+
rootName: rootName,
|
|
41
|
+
message: `预制体创建成功: ${rootName}`
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
} catch (err) {
|
|
45
|
+
console.log(JSON.stringify({ error: err.message }));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { run };
|
package/src/commands/remove.js
CHANGED
|
@@ -2,96 +2,31 @@
|
|
|
2
2
|
* remove 命令 - 删除节点或组件
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const { loadScene, saveScene,
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
// 加载脚本映射
|
|
10
|
-
function loadScriptMap(scenePath) {
|
|
11
|
-
const projectPath = path.dirname(path.dirname(scenePath));
|
|
12
|
-
const mapPath = path.join(projectPath, 'data', 'script_map.json');
|
|
13
|
-
try {
|
|
14
|
-
if (fs.existsSync(mapPath)) {
|
|
15
|
-
return JSON.parse(fs.readFileSync(mapPath, 'utf-8'));
|
|
16
|
-
}
|
|
17
|
-
} catch (e) {}
|
|
18
|
-
return {};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// 构建树形结构
|
|
22
|
-
function buildTree(data, scriptMap, nodeIndex, prefix = '', isLast = true, isRoot = true) {
|
|
23
|
-
const node = data[nodeIndex];
|
|
24
|
-
if (!node) return '';
|
|
25
|
-
|
|
26
|
-
const nodeName = isRoot ? 'Root' : (node._name || '(unnamed)');
|
|
27
|
-
const active = node._active !== false ? '●' : '○';
|
|
28
|
-
const uuidRegex = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
|
|
29
|
-
|
|
30
|
-
let result = prefix + (isRoot ? '' : active + ' ') + nodeName + ' #' + nodeIndex;
|
|
31
|
-
|
|
32
|
-
// 添加组件信息
|
|
33
|
-
if (node._components && node._components.length > 0) {
|
|
34
|
-
const comps = node._components.map(c => {
|
|
35
|
-
const comp = data[c.__id__];
|
|
36
|
-
if (!comp) return `? #${c.__id__}`;
|
|
37
|
-
const typeName = comp.__type__;
|
|
38
|
-
let displayName;
|
|
39
|
-
if (uuidRegex.test(typeName)) {
|
|
40
|
-
const scriptInfo = scriptMap[typeName];
|
|
41
|
-
if (scriptInfo && scriptInfo.name) {
|
|
42
|
-
displayName = scriptInfo.name;
|
|
43
|
-
} else {
|
|
44
|
-
displayName = '⚠️MissingScript';
|
|
45
|
-
}
|
|
46
|
-
} else if (typeName === 'MissingScript') {
|
|
47
|
-
displayName = '⚠️MissingScript';
|
|
48
|
-
} else {
|
|
49
|
-
displayName = typeName.replace('cc.', '');
|
|
50
|
-
}
|
|
51
|
-
return `${displayName} #${c.__id__}`;
|
|
52
|
-
}).join(', ');
|
|
53
|
-
result += ` (${comps})`;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
result += '\n';
|
|
57
|
-
|
|
58
|
-
// 处理子节点
|
|
59
|
-
if (node._children && node._children.length > 0) {
|
|
60
|
-
node._children.forEach((childRef, idx) => {
|
|
61
|
-
const childIsLast = idx === node._children.length - 1;
|
|
62
|
-
const childPrefix = prefix + (isRoot ? '' : (isLast ? ' ' : '│ '));
|
|
63
|
-
result += buildTree(data, scriptMap, childRef.__id__, childPrefix, childIsLast, false);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return result;
|
|
68
|
-
}
|
|
5
|
+
const { loadScene, saveScene, collectNodeAndChildren, rebuildReferences, refreshEditor, loadScriptMap, buildTree } = require('../lib/fire-utils');
|
|
69
6
|
|
|
70
7
|
function run(args) {
|
|
71
8
|
if (args.length < 2) {
|
|
72
|
-
console.log('用法: cocos2.4 remove <场景文件路径> <索引>');
|
|
9
|
+
console.log(JSON.stringify({ error: '用法: cocos2.4 remove <场景文件路径> <索引>' }));
|
|
73
10
|
return;
|
|
74
11
|
}
|
|
75
12
|
|
|
76
13
|
const scenePath = args[0];
|
|
77
14
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const index = parseInt(args[1]);
|
|
82
|
-
|
|
83
|
-
if (isNaN(index)) {
|
|
84
|
-
console.log('错误: 索引必须是数字');
|
|
15
|
+
// 索引必须是数字
|
|
16
|
+
if (!/^\d+$/.test(args[1])) {
|
|
17
|
+
console.log(JSON.stringify({ error: '索引必须是数字,请先用 tree 命令查看节点索引' }));
|
|
85
18
|
return;
|
|
86
19
|
}
|
|
87
20
|
|
|
21
|
+
const index = parseInt(args[1]);
|
|
22
|
+
|
|
88
23
|
try {
|
|
89
24
|
let data = loadScene(scenePath);
|
|
90
25
|
const scriptMap = loadScriptMap(scenePath);
|
|
91
26
|
|
|
92
27
|
// 检查索引是否存在
|
|
93
28
|
if (!data[index]) {
|
|
94
|
-
console.log(
|
|
29
|
+
console.log(JSON.stringify({ error: `索引 ${index} 不存在` }));
|
|
95
30
|
return;
|
|
96
31
|
}
|
|
97
32
|
|
|
@@ -103,7 +38,7 @@ function run(args) {
|
|
|
103
38
|
const isComponent = item.node !== undefined;
|
|
104
39
|
|
|
105
40
|
if (isNode && index <= 1) {
|
|
106
|
-
console.log('
|
|
41
|
+
console.log(JSON.stringify({ error: '不能删除根节点' }));
|
|
107
42
|
return;
|
|
108
43
|
}
|
|
109
44
|
|
|
@@ -156,8 +91,8 @@ function run(args) {
|
|
|
156
91
|
console.log(buildTree(data, scriptMap, 1));
|
|
157
92
|
|
|
158
93
|
} catch (err) {
|
|
159
|
-
console.log(
|
|
94
|
+
console.log(JSON.stringify({ error: err.message }));
|
|
160
95
|
}
|
|
161
96
|
}
|
|
162
97
|
|
|
163
|
-
module.exports = { run };
|
|
98
|
+
module.exports = { run };
|
package/src/commands/set.js
CHANGED
|
@@ -1,9 +1,122 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* set 命令 - 修改节点属性
|
|
2
|
+
* set 命令 - 修改节点属性
|
|
3
|
+
* 修改成功后返回节点最终状态(与 get 命令格式一致)
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
const { loadScene, saveScene, buildMaps, findNodeIndex, refreshEditor } = require('../lib/fire-utils');
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* 将 _color 对象转为 #RRGGBB 字符串
|
|
10
|
+
*/
|
|
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}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 提取组件的关键属性(对应 Inspector 面板显示)
|
|
21
|
+
*/
|
|
22
|
+
function extractComponentProps(comp) {
|
|
23
|
+
if (!comp) return null;
|
|
24
|
+
const type = comp.__type__;
|
|
25
|
+
const base = comp._enabled ? { type } : { type, enabled: false };
|
|
26
|
+
|
|
27
|
+
const clean = (obj) => {
|
|
28
|
+
if (!obj || typeof obj !== 'object') return obj;
|
|
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
|
+
|
|
7
120
|
// 解析颜色
|
|
8
121
|
function parseColor(colorStr) {
|
|
9
122
|
if (!colorStr) return null;
|
|
@@ -22,9 +135,36 @@ function parseColor(colorStr) {
|
|
|
22
135
|
return null;
|
|
23
136
|
}
|
|
24
137
|
|
|
138
|
+
/**
|
|
139
|
+
* 获取节点的完整状态(与 get 命令一致)
|
|
140
|
+
*/
|
|
141
|
+
function getNodeState(data, node, nodeIndex) {
|
|
142
|
+
const trs = node._trs?.array || [0,0,0, 0,0,0,1, 1,1,1];
|
|
143
|
+
const components = (node._components || []).map(ref => extractComponentProps(data[ref.__id__]));
|
|
144
|
+
const children = (node._children || []).map(ref => data[ref.__id__]?._name || '(unknown)');
|
|
145
|
+
|
|
146
|
+
const result = {
|
|
147
|
+
name: node._name,
|
|
148
|
+
active: node._active,
|
|
149
|
+
position: { x: trs[0], y: trs[1] },
|
|
150
|
+
rotation: node._eulerAngles?.z ?? 0,
|
|
151
|
+
scale: { x: trs[7], y: trs[8] },
|
|
152
|
+
anchor: { x: node._anchorPoint?.x ?? 0.5, y: node._anchorPoint?.y ?? 0.5 },
|
|
153
|
+
size: { w: node._contentSize?.width ?? 0, h: node._contentSize?.height ?? 0 },
|
|
154
|
+
color: colorToHex(node._color),
|
|
155
|
+
opacity: node._opacity ?? 255,
|
|
156
|
+
group: node._groupIndex ?? 0
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
if (children.length > 0) result.children = children;
|
|
160
|
+
if (components.length > 0) result.components = components;
|
|
161
|
+
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
|
|
25
165
|
function run(args) {
|
|
26
166
|
if (args.length < 2) {
|
|
27
|
-
console.log(JSON.stringify({ error: '用法: cocos2.4 set
|
|
167
|
+
console.log(JSON.stringify({ error: '用法: cocos2.4 set <场景.fire | 预制体.prefab> <节点索引|名称> [选项]' }));
|
|
28
168
|
return;
|
|
29
169
|
}
|
|
30
170
|
|
|
@@ -53,20 +193,15 @@ function run(args) {
|
|
|
53
193
|
}
|
|
54
194
|
|
|
55
195
|
const node = data[nodeIndex];
|
|
56
|
-
const changes = {};
|
|
57
196
|
|
|
58
197
|
// 修改名称
|
|
59
198
|
if (options.name !== undefined) {
|
|
60
|
-
const oldName = node._name;
|
|
61
199
|
node._name = options.name;
|
|
62
|
-
changes.name = { from: oldName, to: options.name };
|
|
63
200
|
}
|
|
64
201
|
|
|
65
202
|
// 修改激活状态
|
|
66
203
|
if (options.active !== undefined) {
|
|
67
|
-
const oldActive = node._active;
|
|
68
204
|
node._active = options.active !== 'false';
|
|
69
|
-
changes.active = { from: oldActive, to: node._active };
|
|
70
205
|
}
|
|
71
206
|
|
|
72
207
|
// 修改位置
|
|
@@ -74,11 +209,8 @@ function run(args) {
|
|
|
74
209
|
if (!node._trs) {
|
|
75
210
|
node._trs = { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] };
|
|
76
211
|
}
|
|
77
|
-
const oldX = node._trs.array[0];
|
|
78
|
-
const oldY = node._trs.array[1];
|
|
79
212
|
if (options.x !== undefined) node._trs.array[0] = parseFloat(options.x);
|
|
80
213
|
if (options.y !== undefined) node._trs.array[1] = parseFloat(options.y);
|
|
81
|
-
changes.position = { from: [oldX, oldY], to: [node._trs.array[0], node._trs.array[1]] };
|
|
82
214
|
}
|
|
83
215
|
|
|
84
216
|
// 修改大小
|
|
@@ -86,11 +218,8 @@ function run(args) {
|
|
|
86
218
|
if (!node._contentSize) {
|
|
87
219
|
node._contentSize = { "__type__": "cc.Size", width: 0, height: 0 };
|
|
88
220
|
}
|
|
89
|
-
const oldW = node._contentSize.width;
|
|
90
|
-
const oldH = node._contentSize.height;
|
|
91
221
|
if (options.width !== undefined) node._contentSize.width = parseFloat(options.width);
|
|
92
222
|
if (options.height !== undefined) node._contentSize.height = parseFloat(options.height);
|
|
93
|
-
changes.size = { from: { width: oldW, height: oldH }, to: { width: node._contentSize.width, height: node._contentSize.height } };
|
|
94
223
|
}
|
|
95
224
|
|
|
96
225
|
// 修改锚点
|
|
@@ -98,18 +227,13 @@ function run(args) {
|
|
|
98
227
|
if (!node._anchorPoint) {
|
|
99
228
|
node._anchorPoint = { "__type__": "cc.Vec2", x: 0.5, y: 0.5 };
|
|
100
229
|
}
|
|
101
|
-
const oldX = node._anchorPoint.x;
|
|
102
|
-
const oldY = node._anchorPoint.y;
|
|
103
230
|
if (options.anchorX !== undefined) node._anchorPoint.x = parseFloat(options.anchorX);
|
|
104
231
|
if (options.anchorY !== undefined) node._anchorPoint.y = parseFloat(options.anchorY);
|
|
105
|
-
changes.anchor = { from: [oldX, oldY], to: [node._anchorPoint.x, node._anchorPoint.y] };
|
|
106
232
|
}
|
|
107
233
|
|
|
108
234
|
// 修改透明度
|
|
109
235
|
if (options.opacity !== undefined) {
|
|
110
|
-
const oldOpacity = node._opacity;
|
|
111
236
|
node._opacity = Math.max(0, Math.min(255, parseInt(options.opacity)));
|
|
112
|
-
changes.opacity = { from: oldOpacity, to: node._opacity };
|
|
113
237
|
}
|
|
114
238
|
|
|
115
239
|
// 修改颜色
|
|
@@ -117,7 +241,6 @@ function run(args) {
|
|
|
117
241
|
const color = parseColor(options.color);
|
|
118
242
|
if (color) {
|
|
119
243
|
node._color = color;
|
|
120
|
-
changes.color = { to: options.color };
|
|
121
244
|
}
|
|
122
245
|
}
|
|
123
246
|
|
|
@@ -126,9 +249,7 @@ function run(args) {
|
|
|
126
249
|
if (!node._eulerAngles) {
|
|
127
250
|
node._eulerAngles = { "__type__": "cc.Vec3", x: 0, y: 0, z: 0 };
|
|
128
251
|
}
|
|
129
|
-
const oldRotation = node._eulerAngles.z;
|
|
130
252
|
node._eulerAngles.z = parseFloat(options.rotation);
|
|
131
|
-
changes.rotation = { from: oldRotation, to: node._eulerAngles.z };
|
|
132
253
|
}
|
|
133
254
|
|
|
134
255
|
// 修改缩放
|
|
@@ -136,25 +257,18 @@ function run(args) {
|
|
|
136
257
|
if (!node._trs) {
|
|
137
258
|
node._trs = { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] };
|
|
138
259
|
}
|
|
139
|
-
const oldScaleX = node._trs.array[7];
|
|
140
|
-
const oldScaleY = node._trs.array[8];
|
|
141
260
|
if (options.scaleX !== undefined) node._trs.array[7] = parseFloat(options.scaleX);
|
|
142
261
|
if (options.scaleY !== undefined) node._trs.array[8] = parseFloat(options.scaleY);
|
|
143
|
-
changes.scale = { from: [oldScaleX, oldScaleY], to: [node._trs.array[7], node._trs.array[8]] };
|
|
144
262
|
}
|
|
145
263
|
|
|
146
264
|
// 保存场景
|
|
147
265
|
saveScene(scenePath, data);
|
|
148
266
|
|
|
149
|
-
//
|
|
267
|
+
// 触发编辑器刷新
|
|
150
268
|
refreshEditor(scenePath);
|
|
151
269
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
index: nodeIndex,
|
|
155
|
-
name: node._name,
|
|
156
|
-
changes
|
|
157
|
-
}, null, 2));
|
|
270
|
+
// 返回节点最终状态(与 get 命令格式一致)
|
|
271
|
+
console.log(JSON.stringify(getNodeState(data, node, nodeIndex)));
|
|
158
272
|
} catch (err) {
|
|
159
273
|
console.log(JSON.stringify({ error: err.message }));
|
|
160
274
|
}
|