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
|
@@ -1,518 +1,145 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* create-scene 命令 - 从 JSON 结构创建场景文件
|
|
3
|
-
*
|
|
4
|
-
* JSON 格式示例:
|
|
5
|
-
* {
|
|
6
|
-
* "name": "Panel",
|
|
7
|
-
* "width": 400,
|
|
8
|
-
* "height": 300,
|
|
9
|
-
* "color": "#ffffff",
|
|
10
|
-
* "components": [
|
|
11
|
-
* { "type": "sprite", "sizeMode": 1 },
|
|
12
|
-
* { "type": "widget", "top": 0, "bottom": 0 }
|
|
13
|
-
* ],
|
|
14
|
-
* "children": [...]
|
|
15
|
-
* }
|
|
16
|
-
*
|
|
17
|
-
* 节点属性:name, width, height, x, y, color, opacity, anchorX, anchorY, rotation, scaleX, scaleY, active
|
|
18
|
-
* 组件属性:type + 各组件特有属性
|
|
19
|
-
*
|
|
20
|
-
* 场景会自动包含 Canvas 和 Main Camera 节点
|
|
21
3
|
*/
|
|
22
4
|
|
|
23
5
|
const fs = require('fs');
|
|
24
6
|
const path = require('path');
|
|
25
|
-
const {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
'sprite': 'sprite',
|
|
30
|
-
'label': 'label',
|
|
31
|
-
'button': 'button',
|
|
32
|
-
'layout': 'layout',
|
|
33
|
-
'widget': 'widget',
|
|
34
|
-
'camera': 'camera',
|
|
35
|
-
'canvas': 'canvas',
|
|
36
|
-
'particle': 'particleSystem',
|
|
37
|
-
'particlesystem': 'particleSystem'
|
|
38
|
-
};
|
|
7
|
+
const { outputError, outputSuccess } = require('../lib/utils');
|
|
8
|
+
const { createNodeData } = require('../lib/node-utils');
|
|
9
|
+
const { parseComponent, createComponent, applyComponentProps } = require('../lib/components');
|
|
10
|
+
const { createScene } = require('../lib/templates');
|
|
39
11
|
|
|
40
12
|
/**
|
|
41
|
-
*
|
|
13
|
+
* 从 JSON 定义创建场景数据
|
|
42
14
|
*/
|
|
43
|
-
function
|
|
44
|
-
|
|
15
|
+
function createSceneData(nodeDefs, sceneName) {
|
|
16
|
+
const data = createScene(sceneName);
|
|
45
17
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
r: parseInt(hex.substring(0, 2), 16),
|
|
50
|
-
g: parseInt(hex.substring(2, 4), 16),
|
|
51
|
-
b: parseInt(hex.substring(4, 6), 16),
|
|
52
|
-
a: 255
|
|
53
|
-
};
|
|
54
|
-
} else if (hex.length === 8) {
|
|
55
|
-
return {
|
|
56
|
-
r: parseInt(hex.substring(0, 2), 16),
|
|
57
|
-
g: parseInt(hex.substring(2, 4), 16),
|
|
58
|
-
b: parseInt(hex.substring(4, 6), 16),
|
|
59
|
-
a: parseInt(hex.substring(6, 8), 16)
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 生成 UUID
|
|
67
|
-
*/
|
|
68
|
-
function generateUUID() {
|
|
69
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
70
|
-
const r = Math.random() * 16 | 0;
|
|
71
|
-
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
72
|
-
return v.toString(16);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
18
|
+
// Canvas 节点索引
|
|
19
|
+
const canvasIndex = 2;
|
|
75
20
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
*/
|
|
79
|
-
function parseComponent(compDef) {
|
|
80
|
-
if (typeof compDef === 'string') {
|
|
81
|
-
const type = COMPONENT_TYPES[compDef.toLowerCase()];
|
|
82
|
-
return type ? { type, props: {} } : null;
|
|
83
|
-
}
|
|
21
|
+
// 支持数组或单个节点
|
|
22
|
+
const nodes = Array.isArray(nodeDefs) ? nodeDefs : [nodeDefs];
|
|
84
23
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const props = { ...compDef };
|
|
90
|
-
delete props.type;
|
|
91
|
-
return { type, props };
|
|
24
|
+
// 添加用户节点到 Canvas
|
|
25
|
+
for (const nodeDef of nodes) {
|
|
26
|
+
addUserNode(data, nodeDef, canvasIndex);
|
|
92
27
|
}
|
|
93
|
-
|
|
94
|
-
return
|
|
28
|
+
|
|
29
|
+
return data;
|
|
95
30
|
}
|
|
96
31
|
|
|
97
32
|
/**
|
|
98
|
-
*
|
|
99
|
-
* @param comp 组件对象
|
|
100
|
-
* @param props 属性对象
|
|
101
|
-
* @param node 节点对象(可选,用于 label 的 color 设置到节点)
|
|
33
|
+
* 添加用户节点
|
|
102
34
|
*/
|
|
103
|
-
function
|
|
104
|
-
|
|
35
|
+
function addUserNode(data, def, parentIndex) {
|
|
36
|
+
const nodeIndex = data.length;
|
|
37
|
+
const node = createNodeData(def.name || 'Node', parentIndex, def);
|
|
105
38
|
|
|
106
|
-
|
|
39
|
+
data.push(node);
|
|
107
40
|
|
|
108
|
-
//
|
|
109
|
-
if (
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (type === 'cc.Widget') {
|
|
119
|
-
const ALIGN = {
|
|
120
|
-
top: 1,
|
|
121
|
-
verticalCenter: 2,
|
|
122
|
-
bottom: 4,
|
|
123
|
-
left: 8,
|
|
124
|
-
horizontalCenter: 16,
|
|
125
|
-
right: 32
|
|
126
|
-
};
|
|
127
|
-
let alignFlags = 0;
|
|
128
|
-
|
|
129
|
-
for (const dir of ['top', 'bottom', 'left', 'right', 'horizontalCenter', 'verticalCenter']) {
|
|
130
|
-
if (props[dir] !== undefined && props[dir] !== null) {
|
|
131
|
-
alignFlags |= ALIGN[dir];
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (alignFlags > 0) {
|
|
136
|
-
comp._alignFlags = alignFlags;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// 通用属性映射
|
|
141
|
-
const propMap = {
|
|
142
|
-
'sizeMode': '_sizeMode',
|
|
143
|
-
'fillType': '_fillType',
|
|
144
|
-
'fillCenter': '_fillCenter',
|
|
145
|
-
'fillStart': '_fillStart',
|
|
146
|
-
'fillRange': '_fillRange',
|
|
147
|
-
'trim': '_isTrimmedMode',
|
|
148
|
-
'string': '_string',
|
|
149
|
-
'fontSize': '_fontSize',
|
|
150
|
-
'lineHeight': '_lineHeight',
|
|
151
|
-
'horizontalAlign': '_N$horizontalAlign',
|
|
152
|
-
'verticalAlign': '_N$verticalAlign',
|
|
153
|
-
'overflow': '_N$overflow',
|
|
154
|
-
'fontFamily': '_N$fontFamily',
|
|
155
|
-
'wrap': '_enableWrapText',
|
|
156
|
-
'alignFlags': '_alignFlags',
|
|
157
|
-
'left': '_left',
|
|
158
|
-
'right': '_right',
|
|
159
|
-
'top': '_top',
|
|
160
|
-
'bottom': '_bottom',
|
|
161
|
-
'horizontalCenter': '_horizontalCenter',
|
|
162
|
-
'verticalCenter': '_verticalCenter',
|
|
163
|
-
'isAbsLeft': '_isAbsLeft',
|
|
164
|
-
'isAbsRight': '_isAbsRight',
|
|
165
|
-
'isAbsTop': '_isAbsTop',
|
|
166
|
-
'isAbsBottom': '_isAbsBottom',
|
|
167
|
-
'interactable': '_N$interactable',
|
|
168
|
-
'transition': '_N$transition',
|
|
169
|
-
'zoomScale': 'zoomScale',
|
|
170
|
-
'duration': 'duration',
|
|
171
|
-
'layoutType': '_N$layoutType',
|
|
172
|
-
'cellSize': '_N$cellSize',
|
|
173
|
-
'startAxis': '_N$startAxis',
|
|
174
|
-
'paddingLeft': '_N$paddingLeft',
|
|
175
|
-
'paddingRight': '_N$paddingRight',
|
|
176
|
-
'paddingTop': '_N$paddingTop',
|
|
177
|
-
'paddingBottom': '_N$paddingBottom',
|
|
178
|
-
'spacingX': '_N$spacingX',
|
|
179
|
-
'spacingY': '_N$spacingY',
|
|
180
|
-
'resize': '_resize',
|
|
181
|
-
'designResolution': '_designResolution',
|
|
182
|
-
'fitWidth': '_fitWidth',
|
|
183
|
-
'fitHeight': '_fitHeight',
|
|
184
|
-
'orthoSize': '_orthoSize',
|
|
185
|
-
'backgroundColor': '_backgroundColor',
|
|
186
|
-
'cullingMask': '_cullingMask',
|
|
187
|
-
'zoomRatio': '_zoomRatio'
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
if (type === 'cc.Label' && props.string !== undefined) {
|
|
191
|
-
comp._N$string = props.string;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
for (const [key, value] of Object.entries(props)) {
|
|
195
|
-
const compKey = propMap[key];
|
|
196
|
-
if (compKey) {
|
|
197
|
-
if (key === 'fillCenter' && Array.isArray(value)) {
|
|
198
|
-
comp[compKey] = { "__type__": "cc.Vec2", "x": value[0], "y": value[1] };
|
|
199
|
-
} else if (key === 'cellSize' && Array.isArray(value)) {
|
|
200
|
-
comp[compKey] = { "__type__": "cc.Size", "width": value[0], "height": value[1] };
|
|
201
|
-
} else if (key === 'designResolution' && Array.isArray(value)) {
|
|
202
|
-
comp[compKey] = { "__type__": "cc.Size", "width": value[0], "height": value[1] };
|
|
203
|
-
} else if ((key === 'backgroundColor' || key === 'color') && typeof value === 'string') {
|
|
204
|
-
const color = parseColor(value);
|
|
205
|
-
if (color) {
|
|
206
|
-
comp[compKey] = { "__type__": "cc.Color", ...color };
|
|
41
|
+
// 添加组件
|
|
42
|
+
if (def.components) {
|
|
43
|
+
for (const compDef of def.components) {
|
|
44
|
+
const parsed = parseComponent(compDef);
|
|
45
|
+
if (parsed) {
|
|
46
|
+
const comp = createComponent(parsed.type, nodeIndex);
|
|
47
|
+
if (comp) {
|
|
48
|
+
applyComponentProps(comp, parsed.props, node);
|
|
49
|
+
data.push(comp);
|
|
50
|
+
node._components.push({ "__id__": data.length - 1 });
|
|
207
51
|
}
|
|
208
|
-
} else {
|
|
209
|
-
comp[compKey] = value;
|
|
210
52
|
}
|
|
211
53
|
}
|
|
212
54
|
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* 创建场景数据结构
|
|
217
|
-
*/
|
|
218
|
-
function createSceneData(nodeDefs, sceneName) {
|
|
219
|
-
const data = [];
|
|
220
|
-
|
|
221
|
-
// 场景 UUID
|
|
222
|
-
const sceneUUID = generateUUID();
|
|
223
|
-
const canvasUUID = generateUUID();
|
|
224
|
-
const cameraUUID = generateUUID();
|
|
225
|
-
|
|
226
|
-
// 索引 0: cc.SceneAsset
|
|
227
|
-
data.push({
|
|
228
|
-
"__type__": "cc.SceneAsset",
|
|
229
|
-
"_name": sceneName || "NewScene",
|
|
230
|
-
"_objFlags": 0,
|
|
231
|
-
"_native": "",
|
|
232
|
-
"scene": { "__id__": 1 }
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
// 索引 1: cc.Scene
|
|
236
|
-
data.push({
|
|
237
|
-
"__type__": "cc.Scene",
|
|
238
|
-
"_name": sceneName || "NewScene",
|
|
239
|
-
"_objFlags": 0,
|
|
240
|
-
"_parent": null,
|
|
241
|
-
"_children": [{ "__id__": 2 }],
|
|
242
|
-
"_active": true,
|
|
243
|
-
"_components": [],
|
|
244
|
-
"_prefab": null,
|
|
245
|
-
"_opacity": 255,
|
|
246
|
-
"_color": { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 },
|
|
247
|
-
"_contentSize": { "__type__": "cc.Size", "width": 0, "height": 0 },
|
|
248
|
-
"_anchorPoint": { "__type__": "cc.Vec2", "x": 0, "y": 0 },
|
|
249
|
-
"_trs": { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] },
|
|
250
|
-
"_is3DNode": true,
|
|
251
|
-
"_groupIndex": 0,
|
|
252
|
-
"groupIndex": 0,
|
|
253
|
-
"autoReleaseAssets": false,
|
|
254
|
-
"_id": sceneUUID
|
|
255
|
-
});
|
|
256
55
|
|
|
257
|
-
//
|
|
258
|
-
data.push({
|
|
259
|
-
"__type__": "cc.Node",
|
|
260
|
-
"_name": "Canvas",
|
|
261
|
-
"_objFlags": 0,
|
|
262
|
-
"_parent": { "__id__": 1 },
|
|
263
|
-
"_children": [{ "__id__": 3 }], // Main Camera
|
|
264
|
-
"_active": true,
|
|
265
|
-
"_components": [{ "__id__": 5 }, { "__id__": 6 }], // Canvas, Widget
|
|
266
|
-
"_prefab": null,
|
|
267
|
-
"_opacity": 255,
|
|
268
|
-
"_color": { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 },
|
|
269
|
-
"_contentSize": { "__type__": "cc.Size", "width": 960, "height": 640 },
|
|
270
|
-
"_anchorPoint": { "__type__": "cc.Vec2", "x": 0.5, "y": 0.5 },
|
|
271
|
-
"_trs": { "__type__": "TypedArray", "ctor": "Float64Array", "array": [480, 320, 0, 0, 0, 0, 1, 1, 1, 1] },
|
|
272
|
-
"_eulerAngles": { "__type__": "cc.Vec3", "x": 0, "y": 0, "z": 0 },
|
|
273
|
-
"_skewX": 0,
|
|
274
|
-
"_skewY": 0,
|
|
275
|
-
"_is3DNode": false,
|
|
276
|
-
"_groupIndex": 0,
|
|
277
|
-
"groupIndex": 0,
|
|
278
|
-
"_id": canvasUUID
|
|
279
|
-
});
|
|
56
|
+
// 更新父节点的 _children
|
|
57
|
+
data[parentIndex]._children.push({ "__id__": nodeIndex });
|
|
280
58
|
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
"_objFlags": 0,
|
|
286
|
-
"_parent": { "__id__": 2 },
|
|
287
|
-
"_children": [],
|
|
288
|
-
"_active": true,
|
|
289
|
-
"_components": [{ "__id__": 4 }], // Camera
|
|
290
|
-
"_prefab": null,
|
|
291
|
-
"_opacity": 255,
|
|
292
|
-
"_color": { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 },
|
|
293
|
-
"_contentSize": { "__type__": "cc.Size", "width": 0, "height": 0 },
|
|
294
|
-
"_anchorPoint": { "__type__": "cc.Vec2", "x": 0.5, "y": 0.5 },
|
|
295
|
-
"_trs": { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] },
|
|
296
|
-
"_eulerAngles": { "__type__": "cc.Vec3", "x": 0, "y": 0, "z": 0 },
|
|
297
|
-
"_skewX": 0,
|
|
298
|
-
"_skewY": 0,
|
|
299
|
-
"_is3DNode": false,
|
|
300
|
-
"_groupIndex": 0,
|
|
301
|
-
"groupIndex": 0,
|
|
302
|
-
"_id": cameraUUID
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
// 索引 4: Camera 组件
|
|
306
|
-
data.push({
|
|
307
|
-
"__type__": "cc.Camera",
|
|
308
|
-
"_name": "",
|
|
309
|
-
"_objFlags": 0,
|
|
310
|
-
"node": { "__id__": 3 },
|
|
311
|
-
"_enabled": true,
|
|
312
|
-
"_cullingMask": 4294967295,
|
|
313
|
-
"_clearFlags": 7,
|
|
314
|
-
"_backgroundColor": { "__type__": "cc.Color", "r": 0, "g": 0, "b": 0, "a": 255 },
|
|
315
|
-
"_depth": -1,
|
|
316
|
-
"_zoomRatio": 1,
|
|
317
|
-
"_targetTexture": null,
|
|
318
|
-
"_fov": 60,
|
|
319
|
-
"_orthoSize": 10,
|
|
320
|
-
"_nearClip": 1,
|
|
321
|
-
"_farClip": 4096,
|
|
322
|
-
"_ortho": true,
|
|
323
|
-
"_rect": { "__type__": "cc.Rect", "x": 0, "y": 0, "width": 1, "height": 1 },
|
|
324
|
-
"_renderStages": 1,
|
|
325
|
-
"_alignWithScreen": true,
|
|
326
|
-
"_id": generateId()
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
// 索引 5: Canvas 组件
|
|
330
|
-
data.push({
|
|
331
|
-
"__type__": "cc.Canvas",
|
|
332
|
-
"_name": "",
|
|
333
|
-
"_objFlags": 0,
|
|
334
|
-
"node": { "__id__": 2 },
|
|
335
|
-
"_enabled": true,
|
|
336
|
-
"_designResolution": { "__type__": "cc.Size", "width": 960, "height": 640 },
|
|
337
|
-
"_fitWidth": false,
|
|
338
|
-
"_fitHeight": true,
|
|
339
|
-
"_id": generateId()
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// 索引 6: Widget 组件 (Canvas)
|
|
343
|
-
data.push({
|
|
344
|
-
"__type__": "cc.Widget",
|
|
345
|
-
"_name": "",
|
|
346
|
-
"_objFlags": 0,
|
|
347
|
-
"node": { "__id__": 2 },
|
|
348
|
-
"_enabled": true,
|
|
349
|
-
"alignMode": 1,
|
|
350
|
-
"_target": null,
|
|
351
|
-
"_alignFlags": 45,
|
|
352
|
-
"_left": 0,
|
|
353
|
-
"_right": 0,
|
|
354
|
-
"_top": 0,
|
|
355
|
-
"_bottom": 0,
|
|
356
|
-
"_verticalCenter": 0,
|
|
357
|
-
"_horizontalCenter": 0,
|
|
358
|
-
"_isAbsLeft": true,
|
|
359
|
-
"_isAbsRight": true,
|
|
360
|
-
"_isAbsTop": true,
|
|
361
|
-
"_isAbsBottom": true,
|
|
362
|
-
"_isAbsHorizontalCenter": true,
|
|
363
|
-
"_isAbsVerticalCenter": true,
|
|
364
|
-
"_originalWidth": 0,
|
|
365
|
-
"_originalHeight": 0,
|
|
366
|
-
"_id": generateId()
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
// Canvas 节点索引
|
|
370
|
-
const canvasIndex = 2;
|
|
371
|
-
|
|
372
|
-
// 递归添加用户节点
|
|
373
|
-
function addNode(def, parentIndex) {
|
|
374
|
-
const nodeIndex = data.length;
|
|
375
|
-
const uuid = generateUUID();
|
|
376
|
-
|
|
377
|
-
// 解析组件
|
|
378
|
-
const compList = (def.components || [])
|
|
379
|
-
.map(parseComponent)
|
|
380
|
-
.filter(Boolean);
|
|
381
|
-
|
|
382
|
-
// 解析颜色
|
|
383
|
-
let color = { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 };
|
|
384
|
-
if (def.color) {
|
|
385
|
-
const parsed = parseColor(def.color);
|
|
386
|
-
if (parsed) {
|
|
387
|
-
color = { "__type__": "cc.Color", ...parsed };
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// 解析尺寸和位置
|
|
392
|
-
const width = def.width || 0;
|
|
393
|
-
const height = def.height || 0;
|
|
394
|
-
const anchorX = def.anchorX !== undefined ? def.anchorX : 0.5;
|
|
395
|
-
const anchorY = def.anchorY !== undefined ? def.anchorY : 0.5;
|
|
396
|
-
const rotation = def.rotation || 0;
|
|
397
|
-
const scaleX = def.scaleX !== undefined ? def.scaleX : 1;
|
|
398
|
-
const scaleY = def.scaleY !== undefined ? def.scaleY : 1;
|
|
399
|
-
|
|
400
|
-
// 创建节点
|
|
401
|
-
const node = {
|
|
402
|
-
"__type__": "cc.Node",
|
|
403
|
-
"_name": def.name || 'Node',
|
|
404
|
-
"_objFlags": 0,
|
|
405
|
-
"_parent": { "__id__": parentIndex },
|
|
406
|
-
"_children": [],
|
|
407
|
-
"_active": def.active !== false,
|
|
408
|
-
"_components": [],
|
|
409
|
-
"_prefab": null,
|
|
410
|
-
"_opacity": def.opacity !== undefined ? def.opacity : 255,
|
|
411
|
-
"_color": color,
|
|
412
|
-
"_contentSize": { "__type__": "cc.Size", width, height },
|
|
413
|
-
"_anchorPoint": { "__type__": "cc.Vec2", "x": anchorX, "y": anchorY },
|
|
414
|
-
"_trs": {
|
|
415
|
-
"__type__": "TypedArray",
|
|
416
|
-
"ctor": "Float64Array",
|
|
417
|
-
"array": [
|
|
418
|
-
def.x || 0,
|
|
419
|
-
def.y || 0,
|
|
420
|
-
0, 0, 0,
|
|
421
|
-
rotation * Math.PI / 180,
|
|
422
|
-
1, scaleX, scaleY, 1
|
|
423
|
-
]
|
|
424
|
-
},
|
|
425
|
-
"_eulerAngles": { "__type__": "cc.Vec3", "x": 0, "y": 0, "z": rotation },
|
|
426
|
-
"_skewX": 0,
|
|
427
|
-
"_skewY": 0,
|
|
428
|
-
"_is3DNode": false,
|
|
429
|
-
"_groupIndex": 0,
|
|
430
|
-
"groupIndex": 0,
|
|
431
|
-
"_id": uuid
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
data.push(node);
|
|
435
|
-
|
|
436
|
-
// 添加组件
|
|
437
|
-
for (const { type, props } of compList) {
|
|
438
|
-
if (Components[type]) {
|
|
439
|
-
const comp = Components[type](nodeIndex);
|
|
440
|
-
applyComponentProps(comp, props, node);
|
|
441
|
-
const compIndex = data.length;
|
|
442
|
-
data.push(comp);
|
|
443
|
-
node._components.push({ "__id__": compIndex });
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// 更新父节点的 _children
|
|
448
|
-
data[parentIndex]._children.push({ "__id__": nodeIndex });
|
|
449
|
-
|
|
450
|
-
// 递归处理子节点
|
|
451
|
-
if (def.children && def.children.length > 0) {
|
|
452
|
-
for (const child of def.children) {
|
|
453
|
-
addNode(child, nodeIndex);
|
|
454
|
-
}
|
|
59
|
+
// 递归处理子节点
|
|
60
|
+
if (def.children && def.children.length > 0) {
|
|
61
|
+
for (const childDef of def.children) {
|
|
62
|
+
addUserNode(data, childDef, nodeIndex);
|
|
455
63
|
}
|
|
456
|
-
|
|
457
|
-
return nodeIndex;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// 支持数组或单个节点
|
|
461
|
-
const nodes = Array.isArray(nodeDefs) ? nodeDefs : [nodeDefs];
|
|
462
|
-
|
|
463
|
-
// 添加用户节点到 Canvas
|
|
464
|
-
for (const nodeDef of nodes) {
|
|
465
|
-
addNode(nodeDef, canvasIndex);
|
|
466
64
|
}
|
|
467
|
-
|
|
468
|
-
return data;
|
|
469
65
|
}
|
|
470
66
|
|
|
471
67
|
function run(args) {
|
|
472
68
|
if (args.length < 1) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
hint: '
|
|
476
|
-
|
|
477
|
-
}));
|
|
69
|
+
outputError({
|
|
70
|
+
message: '用法: cocos2d-cli create-scene [JSON文件路径] <输出路径.fire>',
|
|
71
|
+
hint: '不传 JSON 则创建默认场景'
|
|
72
|
+
});
|
|
478
73
|
return;
|
|
479
74
|
}
|
|
480
75
|
|
|
481
|
-
|
|
76
|
+
let jsonPath = null;
|
|
77
|
+
let outputPath;
|
|
78
|
+
|
|
79
|
+
if (args.length === 1) {
|
|
80
|
+
outputPath = args[0];
|
|
81
|
+
} else {
|
|
82
|
+
jsonPath = args[0];
|
|
83
|
+
outputPath = args[1];
|
|
84
|
+
}
|
|
85
|
+
|
|
482
86
|
const sceneName = path.basename(outputPath, '.fire');
|
|
483
87
|
|
|
484
|
-
//
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
88
|
+
// 没有传 JSON,创建默认场景
|
|
89
|
+
if (!jsonPath) {
|
|
90
|
+
try {
|
|
91
|
+
if (fs.existsSync(outputPath)) {
|
|
92
|
+
outputError(`文件已存在: ${outputPath}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const dir = path.dirname(outputPath);
|
|
97
|
+
if (!fs.existsSync(dir)) {
|
|
98
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const data = createScene(sceneName);
|
|
102
|
+
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
|
|
103
|
+
|
|
104
|
+
let nodeCount = 0, compCount = 0;
|
|
105
|
+
for (const item of data) {
|
|
106
|
+
if (item.__type__ === 'cc.Node') nodeCount++;
|
|
107
|
+
else if (item.__type__?.startsWith('cc.') && !['cc.Scene', 'cc.SceneAsset'].includes(item.__type__)) {
|
|
108
|
+
compCount++;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
outputSuccess({
|
|
113
|
+
path: outputPath,
|
|
114
|
+
nodes: nodeCount,
|
|
115
|
+
components: compCount
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
} catch (err) {
|
|
119
|
+
outputError(err.message);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
489
122
|
}
|
|
490
123
|
|
|
491
|
-
if (!
|
|
492
|
-
|
|
493
|
-
error: '请通过 stdin 提供 JSON 结构'
|
|
494
|
-
}));
|
|
124
|
+
if (!fs.existsSync(jsonPath)) {
|
|
125
|
+
outputError(`JSON 文件不存在: ${jsonPath}`);
|
|
495
126
|
return;
|
|
496
127
|
}
|
|
497
128
|
|
|
498
129
|
try {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const nodeDef = JSON.parse(
|
|
130
|
+
const input = fs.readFileSync(jsonPath, 'utf8');
|
|
131
|
+
const cleanInput = input.replace(/^\uFEFF/, '').trim();
|
|
132
|
+
const nodeDef = JSON.parse(cleanInput);
|
|
502
133
|
|
|
503
|
-
// 生成场景数据
|
|
504
134
|
const sceneData = createSceneData(nodeDef, sceneName);
|
|
505
135
|
|
|
506
|
-
// 确保输出目录存在
|
|
507
136
|
const outputDir = path.dirname(outputPath);
|
|
508
137
|
if (!fs.existsSync(outputDir)) {
|
|
509
138
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
510
139
|
}
|
|
511
140
|
|
|
512
|
-
// 保存文件
|
|
513
141
|
fs.writeFileSync(outputPath, JSON.stringify(sceneData, null, 2), 'utf8');
|
|
514
142
|
|
|
515
|
-
// 统计信息
|
|
516
143
|
let nodeCount = 0, compCount = 0;
|
|
517
144
|
for (const item of sceneData) {
|
|
518
145
|
if (item.__type__ === 'cc.Node') nodeCount++;
|
|
@@ -521,15 +148,14 @@ function run(args) {
|
|
|
521
148
|
}
|
|
522
149
|
}
|
|
523
150
|
|
|
524
|
-
|
|
525
|
-
success: true,
|
|
151
|
+
outputSuccess({
|
|
526
152
|
path: outputPath,
|
|
527
153
|
nodes: nodeCount,
|
|
528
154
|
components: compCount
|
|
529
|
-
})
|
|
155
|
+
});
|
|
530
156
|
|
|
531
157
|
} catch (err) {
|
|
532
|
-
|
|
158
|
+
outputError(err.message);
|
|
533
159
|
}
|
|
534
160
|
}
|
|
535
161
|
|