cocos2d-cli 1.2.1 → 1.4.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 → cocos2d-cli.js} +17 -12
- package/package.json +3 -3
- package/src/commands/add-component.js +23 -54
- package/src/commands/add.js +31 -114
- package/src/commands/build.js +1 -1
- package/src/commands/create-scene.js +93 -467
- package/src/commands/get.js +5 -154
- package/src/commands/prefab-create.js +107 -379
- package/src/commands/remove.js +123 -59
- package/src/commands/set.js +12 -245
- package/src/commands/tree.js +4 -3
- package/src/lib/components/button.js +137 -0
- package/src/lib/components/camera.js +107 -0
- package/src/lib/components/canvas.js +89 -0
- package/src/lib/components/index.js +157 -0
- package/src/lib/components/label.js +120 -0
- package/src/lib/components/layout.js +110 -0
- package/src/lib/components/particle-system.js +160 -0
- package/src/lib/components/sprite.js +98 -0
- package/src/lib/components/widget.js +122 -0
- package/src/lib/fire-utils.js +58 -392
- package/src/lib/node-utils.js +359 -0
- package/src/lib/templates.js +212 -0
- package/src/lib/utils.js +139 -0
- package/src/commands/delete.js +0 -74
- package/src/commands/remove-component.js +0 -63
- package/src/lib/components.js +0 -404
package/src/commands/remove.js
CHANGED
|
@@ -1,97 +1,161 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* remove 命令 -
|
|
2
|
+
* remove 命令 - 统一的删除命令
|
|
3
|
+
* 支持删除节点和组件
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
|
-
const { loadScene, saveScene,
|
|
6
|
+
const { loadScene, saveScene, rebuildReferences, refreshEditor, loadScriptMap } = require('../lib/fire-utils');
|
|
7
|
+
const { outputError, outputSuccess } = require('../lib/utils');
|
|
8
|
+
const { buildTree, collectNodeAndChildren, detectItemType } = require('../lib/node-utils');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 删除组件
|
|
12
|
+
*/
|
|
13
|
+
function removeComponent(data, compIndex) {
|
|
14
|
+
const compData = data[compIndex];
|
|
15
|
+
if (!compData) {
|
|
16
|
+
return { error: `组件索引 ${compIndex} 不存在` };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const compType = compData.__type__;
|
|
20
|
+
const nodeId = compData.node?.__id__;
|
|
21
|
+
|
|
22
|
+
if (nodeId === undefined) {
|
|
23
|
+
return { error: `索引 ${compIndex} 不是组件` };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const node = data[nodeId];
|
|
27
|
+
if (!node) {
|
|
28
|
+
return { error: `组件关联的节点 ${nodeId} 不存在` };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const nodeName = node._name || '(unnamed)';
|
|
32
|
+
|
|
33
|
+
// 从节点的 _components 中移除引用
|
|
34
|
+
if (node._components) {
|
|
35
|
+
node._components = node._components.filter(c => c.__id__ !== compIndex);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 重建引用并删除组件
|
|
39
|
+
const indicesToDelete = new Set([compIndex]);
|
|
40
|
+
rebuildReferences(data, indicesToDelete);
|
|
41
|
+
data.splice(compIndex, 1);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
success: true,
|
|
45
|
+
type: 'component',
|
|
46
|
+
componentType: compType,
|
|
47
|
+
componentIndex: compIndex,
|
|
48
|
+
nodeName,
|
|
49
|
+
nodeIndex: nodeId
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 删除节点
|
|
55
|
+
*/
|
|
56
|
+
function removeNode(data, nodeIndex) {
|
|
57
|
+
const node = data[nodeIndex];
|
|
58
|
+
if (!node) {
|
|
59
|
+
return { error: `节点索引 ${nodeIndex} 不存在` };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (nodeIndex <= 1) {
|
|
63
|
+
return { error: '不能删除根节点' };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const nodeName = node._name || '(unnamed)';
|
|
67
|
+
|
|
68
|
+
// 收集所有需要删除的索引
|
|
69
|
+
const indicesToDelete = collectNodeAndChildren(data, nodeIndex);
|
|
70
|
+
|
|
71
|
+
// 从父节点的 _children 中移除引用
|
|
72
|
+
if (node._parent) {
|
|
73
|
+
const parentIndex = node._parent.__id__;
|
|
74
|
+
const parent = data[parentIndex];
|
|
75
|
+
if (parent && parent._children) {
|
|
76
|
+
parent._children = parent._children.filter(c => c.__id__ !== nodeIndex);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 重建引用
|
|
81
|
+
rebuildReferences(data, indicesToDelete);
|
|
82
|
+
|
|
83
|
+
// 删除元素
|
|
84
|
+
const sortedIndices = Array.from(indicesToDelete).sort((a, b) => b - a);
|
|
85
|
+
for (const idx of sortedIndices) {
|
|
86
|
+
data.splice(idx, 1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
type: 'node',
|
|
92
|
+
nodeName,
|
|
93
|
+
nodeIndex,
|
|
94
|
+
deletedCount: sortedIndices.length
|
|
95
|
+
};
|
|
96
|
+
}
|
|
6
97
|
|
|
7
98
|
function run(args) {
|
|
8
99
|
if (args.length < 2) {
|
|
9
|
-
|
|
100
|
+
outputError('用法: cocos2d-cli remove <场景文件路径> <索引> [--component|--node]');
|
|
10
101
|
return;
|
|
11
102
|
}
|
|
12
103
|
|
|
13
104
|
const scenePath = args[0];
|
|
14
105
|
|
|
15
|
-
// 索引必须是数字
|
|
16
106
|
if (!/^\d+$/.test(args[1])) {
|
|
17
|
-
|
|
107
|
+
outputError('索引必须是数字,请先用 tree 命令查看节点索引');
|
|
18
108
|
return;
|
|
19
109
|
}
|
|
20
110
|
|
|
21
111
|
const index = parseInt(args[1]);
|
|
112
|
+
const forceComponent = args.includes('--component');
|
|
113
|
+
const forceNode = args.includes('--node');
|
|
114
|
+
|
|
115
|
+
if (forceComponent && forceNode) {
|
|
116
|
+
outputError('不能同时指定 --component 和 --node');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
22
119
|
|
|
23
120
|
try {
|
|
24
121
|
let data = loadScene(scenePath);
|
|
25
|
-
const scriptMap = loadScriptMap(scenePath);
|
|
26
122
|
|
|
27
|
-
// 检查索引是否存在
|
|
28
123
|
if (!data[index]) {
|
|
29
|
-
|
|
124
|
+
outputError(`索引 ${index} 不存在`);
|
|
30
125
|
return;
|
|
31
126
|
}
|
|
32
127
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
console.log(JSON.stringify({ error: '不能删除根节点' }));
|
|
42
|
-
return;
|
|
128
|
+
// 确定删除类型
|
|
129
|
+
let deleteType;
|
|
130
|
+
if (forceComponent) {
|
|
131
|
+
deleteType = 'component';
|
|
132
|
+
} else if (forceNode) {
|
|
133
|
+
deleteType = 'node';
|
|
134
|
+
} else {
|
|
135
|
+
deleteType = detectItemType(data, index);
|
|
43
136
|
}
|
|
44
137
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
138
|
+
// 执行删除
|
|
139
|
+
let result;
|
|
140
|
+
if (deleteType === 'component') {
|
|
141
|
+
result = removeComponent(data, index);
|
|
59
142
|
} else {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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);
|
|
80
|
-
}
|
|
143
|
+
result = removeNode(data, index);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (result.error) {
|
|
147
|
+
outputError(result.error);
|
|
148
|
+
return;
|
|
81
149
|
}
|
|
82
150
|
|
|
83
151
|
// 保存场景
|
|
84
152
|
saveScene(scenePath, data);
|
|
85
|
-
|
|
86
|
-
// 触发编辑器刷新
|
|
87
153
|
refreshEditor(scenePath);
|
|
88
154
|
|
|
89
|
-
|
|
90
|
-
data = loadScene(scenePath);
|
|
91
|
-
console.log(buildTree(data, scriptMap, 1));
|
|
155
|
+
outputSuccess(result);
|
|
92
156
|
|
|
93
157
|
} catch (err) {
|
|
94
|
-
|
|
158
|
+
outputError(err.message);
|
|
95
159
|
}
|
|
96
160
|
}
|
|
97
161
|
|
package/src/commands/set.js
CHANGED
|
@@ -1,271 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* set 命令 - 修改节点属性
|
|
3
|
-
* 修改成功后返回节点最终状态(与 get 命令格式一致)
|
|
2
|
+
* set 命令 - 修改节点属性
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
const { loadScene, saveScene, buildMaps, findNodeIndex, refreshEditor } = require('../lib/fire-utils');
|
|
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
|
-
|
|
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;
|
|
136
|
-
}
|
|
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
|
-
}
|
|
6
|
+
const { parseOptions, outputError, outputJson } = require('../lib/utils');
|
|
7
|
+
const { setNodeProperties, getNodeState } = require('../lib/node-utils');
|
|
164
8
|
|
|
165
9
|
function run(args) {
|
|
166
10
|
if (args.length < 2) {
|
|
167
|
-
|
|
11
|
+
outputError('用法: cocos2d-cli set <场景.fire | 预制体.prefab> <节点索引|名称> [选项]');
|
|
168
12
|
return;
|
|
169
13
|
}
|
|
170
14
|
|
|
171
15
|
const scenePath = args[0];
|
|
172
16
|
const nodeRef = args[1];
|
|
173
|
-
|
|
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
|
-
});
|
|
17
|
+
const options = parseOptions(args, 2);
|
|
182
18
|
|
|
183
19
|
try {
|
|
184
20
|
const data = loadScene(scenePath);
|
|
185
21
|
const { indexMap } = buildMaps(data);
|
|
186
22
|
|
|
187
|
-
// 查找节点
|
|
188
23
|
const nodeIndex = findNodeIndex(data, indexMap, nodeRef);
|
|
189
24
|
|
|
190
25
|
if (nodeIndex === null || !data[nodeIndex]) {
|
|
191
|
-
|
|
26
|
+
outputError(`找不到节点: ${nodeRef}`);
|
|
192
27
|
return;
|
|
193
28
|
}
|
|
194
29
|
|
|
195
30
|
const node = data[nodeIndex];
|
|
196
31
|
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
node._name = options.name;
|
|
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
|
-
}
|
|
32
|
+
// 设置节点属性
|
|
33
|
+
setNodeProperties(node, options);
|
|
233
34
|
|
|
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);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// 修改缩放
|
|
256
|
-
if (options.scaleX !== undefined || options.scaleY !== undefined) {
|
|
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
|
-
}
|
|
263
|
-
|
|
264
|
-
// 修改 Label 文字内容及字体属性
|
|
35
|
+
// 修改 Label 文字属性
|
|
265
36
|
if (options.string !== undefined || options.fontSize !== undefined || options.lineHeight !== undefined) {
|
|
266
37
|
const labelComp = (node._components || []).map(ref => data[ref.__id__]).find(c => c && c.__type__ === 'cc.Label');
|
|
267
38
|
if (!labelComp) {
|
|
268
|
-
|
|
39
|
+
outputError(`节点 ${node._name} 没有 cc.Label 组件,无法设置文字属性`);
|
|
269
40
|
return;
|
|
270
41
|
}
|
|
271
42
|
if (options.string !== undefined) {
|
|
@@ -280,16 +51,12 @@ function run(args) {
|
|
|
280
51
|
}
|
|
281
52
|
}
|
|
282
53
|
|
|
283
|
-
// 保存场景
|
|
284
54
|
saveScene(scenePath, data);
|
|
285
|
-
|
|
286
|
-
// 触发编辑器刷新
|
|
287
55
|
refreshEditor(scenePath);
|
|
288
56
|
|
|
289
|
-
|
|
290
|
-
console.log(JSON.stringify(getNodeState(data, node, nodeIndex)));
|
|
57
|
+
outputJson(getNodeState(data, node, nodeIndex));
|
|
291
58
|
} catch (err) {
|
|
292
|
-
|
|
59
|
+
outputError(err.message);
|
|
293
60
|
}
|
|
294
61
|
}
|
|
295
62
|
|
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
|
|
|
@@ -30,4 +31,4 @@ function run(args) {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
module.exports = { run };
|
|
34
|
+
module.exports = { run };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cc.Button 组件
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { generateId } = require('../utils');
|
|
6
|
+
|
|
7
|
+
const BUTTON_NORMAL_SPRITE = { "__uuid__": "f0048c10-f03e-4c97-b9d3-3506e1d58952" };
|
|
8
|
+
const BUTTON_PRESSED_SPRITE = { "__uuid__": "e9ec654c-97a2-4787-9325-e6a10375219a" };
|
|
9
|
+
const BUTTON_DISABLED_SPRITE = { "__uuid__": "29158224-f8dd-4661-a796-1ffab537140e" };
|
|
10
|
+
|
|
11
|
+
// 属性映射
|
|
12
|
+
const PROP_MAP = {
|
|
13
|
+
'interactable': '_N$interactable',
|
|
14
|
+
'transition': '_N$transition',
|
|
15
|
+
'zoomScale': 'zoomScale',
|
|
16
|
+
'duration': 'duration',
|
|
17
|
+
'target': '_N$target'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// 枚举值
|
|
21
|
+
const ENUMS = {
|
|
22
|
+
transition: ['NONE', 'COLOR', 'SPRITE', 'SCALE']
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 创建 Button 组件
|
|
27
|
+
* @param {number} nodeId - 节点索引
|
|
28
|
+
* @returns {object} 组件数据
|
|
29
|
+
*/
|
|
30
|
+
function create(nodeId) {
|
|
31
|
+
return {
|
|
32
|
+
"__type__": "cc.Button",
|
|
33
|
+
"_name": "",
|
|
34
|
+
"_objFlags": 0,
|
|
35
|
+
"node": { "__id__": nodeId },
|
|
36
|
+
"_enabled": true,
|
|
37
|
+
"_normalMaterial": null,
|
|
38
|
+
"_grayMaterial": null,
|
|
39
|
+
"duration": 0.1,
|
|
40
|
+
"zoomScale": 1.2,
|
|
41
|
+
"clickEvents": [],
|
|
42
|
+
"_N$interactable": true,
|
|
43
|
+
"_N$enableAutoGrayEffect": false,
|
|
44
|
+
"_N$transition": 3,
|
|
45
|
+
"transition": 3,
|
|
46
|
+
"_N$normalColor": {
|
|
47
|
+
"__type__": "cc.Color",
|
|
48
|
+
"r": 255,
|
|
49
|
+
"g": 255,
|
|
50
|
+
"b": 255,
|
|
51
|
+
"a": 255
|
|
52
|
+
},
|
|
53
|
+
"_N$pressedColor": {
|
|
54
|
+
"__type__": "cc.Color",
|
|
55
|
+
"r": 200,
|
|
56
|
+
"g": 200,
|
|
57
|
+
"b": 200,
|
|
58
|
+
"a": 255
|
|
59
|
+
},
|
|
60
|
+
"pressedColor": {
|
|
61
|
+
"__type__": "cc.Color",
|
|
62
|
+
"r": 200,
|
|
63
|
+
"g": 200,
|
|
64
|
+
"b": 200,
|
|
65
|
+
"a": 255
|
|
66
|
+
},
|
|
67
|
+
"_N$hoverColor": {
|
|
68
|
+
"__type__": "cc.Color",
|
|
69
|
+
"r": 255,
|
|
70
|
+
"g": 255,
|
|
71
|
+
"b": 255,
|
|
72
|
+
"a": 255
|
|
73
|
+
},
|
|
74
|
+
"hoverColor": {
|
|
75
|
+
"__type__": "cc.Color",
|
|
76
|
+
"r": 255,
|
|
77
|
+
"g": 255,
|
|
78
|
+
"b": 255,
|
|
79
|
+
"a": 255
|
|
80
|
+
},
|
|
81
|
+
"_N$disabledColor": {
|
|
82
|
+
"__type__": "cc.Color",
|
|
83
|
+
"r": 120,
|
|
84
|
+
"g": 120,
|
|
85
|
+
"b": 120,
|
|
86
|
+
"a": 200
|
|
87
|
+
},
|
|
88
|
+
"_N$normalSprite": BUTTON_NORMAL_SPRITE,
|
|
89
|
+
"_N$pressedSprite": BUTTON_PRESSED_SPRITE,
|
|
90
|
+
"pressedSprite": BUTTON_PRESSED_SPRITE,
|
|
91
|
+
"_N$hoverSprite": BUTTON_NORMAL_SPRITE,
|
|
92
|
+
"hoverSprite": BUTTON_NORMAL_SPRITE,
|
|
93
|
+
"_N$disabledSprite": BUTTON_DISABLED_SPRITE,
|
|
94
|
+
"_N$target": null,
|
|
95
|
+
"_id": generateId()
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 应用属性
|
|
101
|
+
* @param {object} comp - 组件对象
|
|
102
|
+
* @param {object} props - 属性对象
|
|
103
|
+
*/
|
|
104
|
+
function applyProps(comp, props) {
|
|
105
|
+
if (!props) return;
|
|
106
|
+
|
|
107
|
+
for (const [key, value] of Object.entries(props)) {
|
|
108
|
+
const compKey = PROP_MAP[key];
|
|
109
|
+
if (compKey) {
|
|
110
|
+
comp[compKey] = value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 提取属性(用于显示)
|
|
117
|
+
* @param {object} comp - 组件对象
|
|
118
|
+
* @returns {object} 提取的属性
|
|
119
|
+
*/
|
|
120
|
+
function extractProps(comp) {
|
|
121
|
+
return {
|
|
122
|
+
interactable: comp._N$interactable,
|
|
123
|
+
transition: ENUMS.transition[comp._N$transition] || comp._N$transition,
|
|
124
|
+
zoomScale: comp.zoomScale,
|
|
125
|
+
duration: comp.duration
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
module.exports = {
|
|
130
|
+
type: 'button',
|
|
131
|
+
ccType: 'cc.Button',
|
|
132
|
+
create,
|
|
133
|
+
applyProps,
|
|
134
|
+
extractProps,
|
|
135
|
+
PROP_MAP,
|
|
136
|
+
ENUMS
|
|
137
|
+
};
|