cocos2d-cli 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +142 -0
  2. package/bin/cocos2d-cli.js +21 -12
  3. package/package.json +1 -1
  4. package/src/commands/add-component.js +77 -85
  5. package/src/commands/add.js +116 -212
  6. package/src/commands/create-scene.js +133 -109
  7. package/src/commands/get.js +113 -18
  8. package/src/commands/prefab-create.js +49 -139
  9. package/src/commands/remove-component.js +111 -0
  10. package/src/commands/remove.js +59 -122
  11. package/src/commands/set.js +121 -36
  12. package/src/commands/tree.js +3 -8
  13. package/src/lib/cc/CCButton.js +122 -0
  14. package/src/lib/cc/CCCamera.js +93 -0
  15. package/src/lib/cc/CCCanvas.js +64 -0
  16. package/src/lib/cc/CCColor.js +32 -0
  17. package/src/lib/cc/CCComponent.js +60 -0
  18. package/src/lib/cc/CCLabel.js +109 -0
  19. package/src/lib/cc/CCNode.js +242 -0
  20. package/src/lib/cc/CCObject.js +23 -0
  21. package/src/lib/cc/CCPrefab.js +242 -0
  22. package/src/lib/cc/CCRect.js +32 -0
  23. package/src/lib/cc/CCScene.js +42 -0
  24. package/src/lib/cc/CCSceneAsset.js +271 -0
  25. package/src/lib/cc/CCSize.js +26 -0
  26. package/src/lib/cc/CCSprite.js +82 -0
  27. package/src/lib/cc/CCTrs.js +74 -0
  28. package/src/lib/cc/CCVec2.js +26 -0
  29. package/src/lib/cc/CCVec3.js +29 -0
  30. package/src/lib/cc/CCWidget.js +98 -0
  31. package/src/lib/cc/index.js +40 -0
  32. package/src/lib/fire-utils.js +75 -1
  33. package/src/lib/json-parser.js +166 -0
  34. package/src/lib/node-utils.js +64 -28
  35. package/src/lib/templates.js +31 -194
  36. package/src/lib/utils.js +63 -0
  37. package/data/prefab-template.json +0 -72
  38. package/data/scene-template.json +0 -241
  39. package/src/lib/components/button.js +0 -137
  40. package/src/lib/components/camera.js +0 -107
  41. package/src/lib/components/canvas.js +0 -89
  42. package/src/lib/components/index.js +0 -157
  43. package/src/lib/components/label.js +0 -120
  44. package/src/lib/components/layout.js +0 -110
  45. package/src/lib/components/particle-system.js +0 -160
  46. package/src/lib/components/sprite.js +0 -98
  47. package/src/lib/components/widget.js +0 -122
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Cocos Creator 变换数据类 (TRS = Translation, Rotation, Scale)
3
+ * array: [posX, posY, posZ, rotX, rotY, rotZ, rotW, scaleX, scaleY, scaleZ]
4
+ */
5
+ class CCTrs {
6
+ constructor() {
7
+ this.__type__ = 'TypedArray';
8
+ this.ctor = 'Float64Array';
9
+ this.array = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1];
10
+ }
11
+
12
+ // Position
13
+ get x() { return this.array[0]; }
14
+ set x(v) { this.array[0] = v; }
15
+
16
+ get y() { return this.array[1]; }
17
+ set y(v) { this.array[1] = v; }
18
+
19
+ get z() { return this.array[2]; }
20
+ set z(v) { this.array[2] = v; }
21
+
22
+ // Scale
23
+ get scaleX() { return this.array[7]; }
24
+ set scaleX(v) { this.array[7] = v; }
25
+
26
+ get scaleY() { return this.array[8]; }
27
+ set scaleY(v) { this.array[8] = v; }
28
+
29
+ get scaleZ() { return this.array[9]; }
30
+ set scaleZ(v) { this.array[9] = v; }
31
+
32
+ // Rotation (四元数)
33
+ get rotX() { return this.array[3]; }
34
+ set rotX(v) { this.array[3] = v; }
35
+
36
+ get rotY() { return this.array[4]; }
37
+ set rotY(v) { this.array[4] = v; }
38
+
39
+ get rotZ() { return this.array[5]; }
40
+ set rotZ(v) { this.array[5] = v; }
41
+
42
+ get rotW() { return this.array[6]; }
43
+ set rotW(v) { this.array[6] = v; }
44
+
45
+ /**
46
+ * 设置位置
47
+ */
48
+ setPosition(x, y, z = 0) {
49
+ this.array[0] = x;
50
+ this.array[1] = y;
51
+ this.array[2] = z;
52
+ return this;
53
+ }
54
+
55
+ /**
56
+ * 设置缩放
57
+ */
58
+ setScale(x, y = x, z = 1) {
59
+ this.array[7] = x;
60
+ this.array[8] = y;
61
+ this.array[9] = z;
62
+ return this;
63
+ }
64
+
65
+ toJSON() {
66
+ return {
67
+ __type__: this.__type__,
68
+ ctor: this.ctor,
69
+ array: [...this.array]
70
+ };
71
+ }
72
+ }
73
+
74
+ module.exports = CCTrs;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Cocos Creator 二维向量类
3
+ */
4
+ class CCVec2 {
5
+ constructor(x = 0, y = 0) {
6
+ this.__type__ = 'cc.Vec2';
7
+ this.x = x;
8
+ this.y = y;
9
+ }
10
+
11
+ set(x, y) {
12
+ this.x = x;
13
+ this.y = y;
14
+ return this;
15
+ }
16
+
17
+ toJSON() {
18
+ return {
19
+ __type__: this.__type__,
20
+ x: this.x,
21
+ y: this.y
22
+ };
23
+ }
24
+ }
25
+
26
+ module.exports = CCVec2;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Cocos Creator 三维向量类
3
+ */
4
+ class CCVec3 {
5
+ constructor(x = 0, y = 0, z = 0) {
6
+ this.__type__ = 'cc.Vec3';
7
+ this.x = x;
8
+ this.y = y;
9
+ this.z = z;
10
+ }
11
+
12
+ set(x, y, z = 0) {
13
+ this.x = x;
14
+ this.y = y;
15
+ this.z = z;
16
+ return this;
17
+ }
18
+
19
+ toJSON() {
20
+ return {
21
+ __type__: this.__type__,
22
+ x: this.x,
23
+ y: this.y,
24
+ z: this.z
25
+ };
26
+ }
27
+ }
28
+
29
+ module.exports = CCVec3;
@@ -0,0 +1,98 @@
1
+ const CCComponent = require('./CCComponent');
2
+
3
+ /**
4
+ * Cocos Creator Widget 组件
5
+ */
6
+ class CCWidget extends CCComponent {
7
+ constructor() {
8
+ super();
9
+ this.__type__ = 'cc.Widget';
10
+
11
+ this.alignMode = 1;
12
+ this._target = null;
13
+ this._alignFlags = 45;
14
+ this._left = 0;
15
+ this._right = 0;
16
+ this._top = 0;
17
+ this._bottom = 0;
18
+ this._verticalCenter = 0;
19
+ this._horizontalCenter = 0;
20
+ this._isAbsLeft = true;
21
+ this._isAbsRight = true;
22
+ this._isAbsTop = true;
23
+ this._isAbsBottom = true;
24
+ this._isAbsHorizontalCenter = true;
25
+ this._isAbsVerticalCenter = true;
26
+ this._originalWidth = 0;
27
+ this._originalHeight = 0;
28
+ }
29
+
30
+ /**
31
+ * 设置对齐标志
32
+ * 45 = 左 + 右 + 上 + 下 (全对齐)
33
+ */
34
+ setAlignFlags(flags) {
35
+ this._alignFlags = flags;
36
+ return this;
37
+ }
38
+
39
+ /**
40
+ * 设置边距
41
+ */
42
+ setMargins(left, right, top, bottom) {
43
+ this._left = left;
44
+ this._right = right;
45
+ this._top = top;
46
+ this._bottom = bottom;
47
+ return this;
48
+ }
49
+
50
+ /**
51
+ * 转换为属性面板显示格式
52
+ */
53
+ toPanelJSON() {
54
+ return {
55
+ ...super.toPanelJSON(),
56
+ top: this._top,
57
+ bottom: this._bottom,
58
+ left: this._left,
59
+ right: this._right,
60
+ horizontalCenter: this._horizontalCenter,
61
+ verticalCenter: this._verticalCenter,
62
+ isAbsLeft: this._isAbsLeft,
63
+ isAbsRight: this._isAbsRight,
64
+ isAbsTop: this._isAbsTop,
65
+ isAbsBottom: this._isAbsBottom
66
+ };
67
+ }
68
+
69
+ toJSON() {
70
+ return {
71
+ __type__: this.__type__,
72
+ _name: this._name,
73
+ _objFlags: this._objFlags,
74
+ node: this.node,
75
+ _enabled: this._enabled,
76
+ alignMode: this.alignMode,
77
+ _target: this._target,
78
+ _alignFlags: this._alignFlags,
79
+ _left: this._left,
80
+ _right: this._right,
81
+ _top: this._top,
82
+ _bottom: this._bottom,
83
+ _verticalCenter: this._verticalCenter,
84
+ _horizontalCenter: this._horizontalCenter,
85
+ _isAbsLeft: this._isAbsLeft,
86
+ _isAbsRight: this._isAbsRight,
87
+ _isAbsTop: this._isAbsTop,
88
+ _isAbsBottom: this._isAbsBottom,
89
+ _isAbsHorizontalCenter: this._isAbsHorizontalCenter,
90
+ _isAbsVerticalCenter: this._isAbsVerticalCenter,
91
+ _originalWidth: this._originalWidth,
92
+ _originalHeight: this._originalHeight,
93
+ _id: this._id
94
+ };
95
+ }
96
+ }
97
+
98
+ module.exports = CCWidget;
@@ -0,0 +1,40 @@
1
+ const CCObject = require('./CCObject');
2
+ const CCNode = require('./CCNode');
3
+ const CCScene = require('./CCScene');
4
+ const CCSceneAsset = require('./CCSceneAsset');
5
+ const { CCPrefab, CCPrefabInfo } = require('./CCPrefab');
6
+ const CCColor = require('./CCColor');
7
+ const CCSize = require('./CCSize');
8
+ const CCVec2 = require('./CCVec2');
9
+ const CCVec3 = require('./CCVec3');
10
+ const CCTrs = require('./CCTrs');
11
+ const CCRect = require('./CCRect');
12
+ const CCComponent = require('./CCComponent');
13
+ const CCCanvas = require('./CCCanvas');
14
+ const CCWidget = require('./CCWidget');
15
+ const CCCamera = require('./CCCamera');
16
+ const CCSprite = require('./CCSprite');
17
+ const CCLabel = require('./CCLabel');
18
+ const CCButton = require('./CCButton');
19
+
20
+ module.exports = {
21
+ CCObject,
22
+ CCNode,
23
+ CCScene,
24
+ CCSceneAsset,
25
+ CCPrefab,
26
+ CCPrefabInfo,
27
+ CCColor,
28
+ CCSize,
29
+ CCVec2,
30
+ CCVec3,
31
+ CCTrs,
32
+ CCRect,
33
+ CCComponent,
34
+ CCCanvas,
35
+ CCWidget,
36
+ CCCamera,
37
+ CCSprite,
38
+ CCLabel,
39
+ CCButton
40
+ };
@@ -5,6 +5,7 @@
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
+ const crypto = require('crypto');
8
9
 
9
10
  /**
10
11
  * 检测是否为预制体文件
@@ -232,7 +233,7 @@ function installPlugin(scenePath) {
232
233
  fs.mkdirSync(packagesPath, { recursive: true });
233
234
  }
234
235
 
235
- const cliPluginPath = path.join(__dirname, '..', '..', 'editor-plugin', 'cocos2d-cli-helper');
236
+ const cliPluginPath = path.join(__dirname, '..', '..', 'editor-plugin');
236
237
 
237
238
  if (!fs.existsSync(cliPluginPath)) return false;
238
239
 
@@ -277,6 +278,72 @@ function getPrefabRootIndex(data) {
277
278
  return 1;
278
279
  }
279
280
 
281
+ /**
282
+ * 生成 UUID
283
+ */
284
+ function generateUUID() {
285
+ return crypto.randomUUID();
286
+ }
287
+
288
+ /**
289
+ * 生成预制体的 meta 对象
290
+ * @param {string} uuid - 可选的 UUID,不传则自动生成
291
+ * @returns {object}
292
+ */
293
+ function createPrefabMeta(uuid) {
294
+ return {
295
+ ver: '1.3.2',
296
+ uuid: uuid || generateUUID(),
297
+ importer: 'prefab',
298
+ optimizationPolicy: 'AUTO',
299
+ asyncLoadAssets: false,
300
+ readonly: false,
301
+ subMetas: {}
302
+ };
303
+ }
304
+
305
+ /**
306
+ * 生成场景的 meta 对象
307
+ * @param {string} uuid - 可选的 UUID,不传则自动生成
308
+ * @returns {object}
309
+ */
310
+ function createSceneMeta(uuid) {
311
+ return {
312
+ ver: '1.3.2',
313
+ uuid: uuid || generateUUID(),
314
+ importer: 'scene',
315
+ asyncLoadAssets: false,
316
+ autoReleaseAssets: false,
317
+ subMetas: {}
318
+ };
319
+ }
320
+
321
+ /**
322
+ * 保存 meta 文件
323
+ * @param {string} filePath - 资源文件路径(.prefab 或 .fire)
324
+ * @param {object} meta - meta 对象
325
+ */
326
+ function saveMetaFile(filePath, meta) {
327
+ const metaPath = filePath + '.meta';
328
+ fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf8');
329
+ return metaPath;
330
+ }
331
+
332
+ /**
333
+ * 加载 meta 文件
334
+ * @param {string} filePath - 资源文件路径
335
+ * @returns {object|null}
336
+ */
337
+ function loadMetaFile(filePath) {
338
+ const metaPath = filePath + '.meta';
339
+ try {
340
+ if (fs.existsSync(metaPath)) {
341
+ return JSON.parse(fs.readFileSync(metaPath, 'utf8'));
342
+ }
343
+ } catch (e) {}
344
+ return null;
345
+ }
346
+
280
347
  module.exports = {
281
348
  // 文件操作
282
349
  loadScene,
@@ -293,6 +360,13 @@ module.exports = {
293
360
  installPlugin,
294
361
  checkPluginStatus,
295
362
 
363
+ // Meta 文件管理
364
+ generateUUID,
365
+ createPrefabMeta,
366
+ createSceneMeta,
367
+ saveMetaFile,
368
+ loadMetaFile,
369
+
296
370
  // 工具函数
297
371
  loadScriptMap,
298
372
  generateFileId,
@@ -0,0 +1,166 @@
1
+ /**
2
+ * JSON 解析器
3
+ * 将简化JSON转换为CCNode对象树
4
+ */
5
+
6
+ const { CCNode, CCCanvas, CCWidget, CCSprite, CCLabel, CCButton, CCCamera } = require('./cc');
7
+ const { parseColor } = require('./utils');
8
+
9
+ /**
10
+ * 创建组件实例
11
+ */
12
+ function createComponent(type) {
13
+ switch (type.toLowerCase()) {
14
+ case 'canvas': return new CCCanvas();
15
+ case 'widget': return new CCWidget();
16
+ case 'sprite': return new CCSprite();
17
+ case 'label': return new CCLabel();
18
+ case 'button': return new CCButton();
19
+ case 'camera': return new CCCamera();
20
+ default: return null;
21
+ }
22
+ }
23
+
24
+ /**
25
+ * 解析组件定义
26
+ */
27
+ function parseComponent(compDef) {
28
+ if (typeof compDef === 'string') {
29
+ return { type: compDef, props: {} };
30
+ }
31
+ if (typeof compDef === 'object' && compDef.type) {
32
+ const props = { ...compDef };
33
+ delete props.type;
34
+ return { type: compDef.type, props };
35
+ }
36
+ return null;
37
+ }
38
+
39
+ /**
40
+ * 应用组件属性
41
+ */
42
+ function applyComponentProps(comp, props, node) {
43
+ if (!props) return;
44
+
45
+ for (const [key, value] of Object.entries(props)) {
46
+ switch (key) {
47
+ case 'string':
48
+ if (comp._string !== undefined) {
49
+ comp._string = value;
50
+ if (comp._N$string !== undefined) comp._N$string = value;
51
+ }
52
+ break;
53
+ case 'fontSize':
54
+ if (comp._fontSize !== undefined) comp._fontSize = value;
55
+ break;
56
+ case 'lineHeight':
57
+ if (comp._lineHeight !== undefined) comp._lineHeight = value;
58
+ break;
59
+ case 'sizeMode':
60
+ if (comp._sizeMode !== undefined) comp._sizeMode = value;
61
+ break;
62
+ case 'color':
63
+ if (node) {
64
+ const parsed = parseColor(value);
65
+ if (parsed && node._color) {
66
+ node._color.r = parsed.r;
67
+ node._color.g = parsed.g;
68
+ node._color.b = parsed.b;
69
+ node._color.a = parsed.a;
70
+ }
71
+ }
72
+ break;
73
+ default:
74
+ if (comp[key] !== undefined) {
75
+ comp[key] = value;
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * 应用属性到节点
83
+ */
84
+ function applyNodeProps(node, def) {
85
+ if (def.name) node._name = def.name;
86
+ if (def.active !== undefined) node._active = def.active;
87
+ if (def.opacity !== undefined) node._opacity = def.opacity;
88
+ if (def.width !== undefined) node._contentSize.width = def.width;
89
+ if (def.height !== undefined) node._contentSize.height = def.height;
90
+ if (def.x !== undefined) node._trs.array[0] = def.x;
91
+ if (def.y !== undefined) node._trs.array[1] = def.y;
92
+ if (def.rotation !== undefined) {
93
+ node._trs.array[5] = def.rotation * Math.PI / 180;
94
+ node._eulerAngles.z = def.rotation;
95
+ }
96
+ if (def.scaleX !== undefined) node._trs.array[7] = def.scaleX;
97
+ if (def.scaleY !== undefined) node._trs.array[8] = def.scaleY;
98
+ if (def.anchorX !== undefined) node._anchorPoint.x = def.anchorX;
99
+ if (def.anchorY !== undefined) node._anchorPoint.y = def.anchorY;
100
+ if (def.color) {
101
+ const parsed = parseColor(def.color);
102
+ if (parsed) {
103
+ node._color.set(parsed.r, parsed.g, parsed.b, parsed.a);
104
+ }
105
+ }
106
+ }
107
+
108
+ /**
109
+ * 解析节点定义(递归)
110
+ * @param {Object} def - 节点定义
111
+ * @returns {CCNode}
112
+ */
113
+ function parseNode(def) {
114
+ const node = new CCNode(def.name || 'Node');
115
+
116
+ // 应用属性
117
+ applyNodeProps(node, def);
118
+
119
+ // 添加组件
120
+ if (def.components && def.components.length > 0) {
121
+ node._components = [];
122
+ for (const compDef of def.components) {
123
+ const parsed = parseComponent(compDef);
124
+ if (parsed) {
125
+ const comp = createComponent(parsed.type);
126
+ if (comp) {
127
+ applyComponentProps(comp, parsed.props, node);
128
+ comp.node = node;
129
+ node._components.push(comp);
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ // 递归处理子节点
136
+ if (def.children && def.children.length > 0) {
137
+ node._children = [];
138
+ for (const childDef of def.children) {
139
+ const child = parseNode(childDef);
140
+ child._parent = node;
141
+ node._children.push(child);
142
+ }
143
+ }
144
+
145
+ return node;
146
+ }
147
+
148
+ /**
149
+ * 从简化JSON解析为CCNode树
150
+ * @param {Object|string} json - JSON对象或字符串
151
+ * @returns {CCNode}
152
+ */
153
+ function fromJSON(json) {
154
+ if (typeof json === 'string') {
155
+ json = JSON.parse(json.replace(/^\uFEFF/, '').trim());
156
+ }
157
+
158
+ const rootDef = Array.isArray(json) ? json[0] : json;
159
+ return parseNode(rootDef);
160
+ }
161
+
162
+ module.exports = {
163
+ fromJSON,
164
+ parseNode,
165
+ applyNodeProps
166
+ };
@@ -147,9 +147,20 @@ function setNodeProperties(node, options) {
147
147
  * @returns {object} 节点状态
148
148
  */
149
149
  function getNodeState(data, node, nodeIndex) {
150
- const { extractComponentProps } = require('./components');
151
150
  const trs = node._trs?.array || [0, 0, 0, 0, 0, 0, 1, 1, 1, 1];
152
- const components = (node._components || []).map(ref => extractComponentProps(data[ref.__id__]));
151
+
152
+ // 组件使用 toPanelJSON
153
+ const components = {};
154
+ if (node._components && node._components.length > 0) {
155
+ node._components.forEach(ref => {
156
+ const comp = data[ref.__id__];
157
+ if (comp && comp.toPanelJSON) {
158
+ const typeName = comp.__type__.replace('cc.', '');
159
+ components[typeName] = comp.toPanelJSON();
160
+ }
161
+ });
162
+ }
163
+
153
164
  const children = (node._children || []).map(ref => data[ref.__id__]?._name || '(unknown)');
154
165
 
155
166
  const result = {
@@ -166,7 +177,7 @@ function getNodeState(data, node, nodeIndex) {
166
177
  };
167
178
 
168
179
  if (children.length > 0) result.children = children;
169
- if (components.length > 0) result.components = components;
180
+ if (Object.keys(components).length > 0) result.components = components;
170
181
 
171
182
  return result;
172
183
  }
@@ -261,6 +272,31 @@ function deleteNode(data, nodeIndex, rebuildReferences) {
261
272
  };
262
273
  }
263
274
 
275
+ /**
276
+ * 构建组件信息字符串
277
+ */
278
+ function buildComponentInfo(data, node, scriptMap, uuidRegex) {
279
+ if (!node._components || node._components.length === 0) return '';
280
+
281
+ const comps = node._components.map(c => {
282
+ const comp = data[c.__id__];
283
+ if (!comp) return '?';
284
+ const typeName = comp.__type__;
285
+ let displayName;
286
+ if (uuidRegex.test(typeName)) {
287
+ const scriptInfo = scriptMap[typeName];
288
+ displayName = (scriptInfo && scriptInfo.name) ? scriptInfo.name : '[MissingScript]';
289
+ } else if (typeName === 'MissingScript') {
290
+ displayName = '[MissingScript]';
291
+ } else {
292
+ displayName = typeName.replace('cc.', '');
293
+ }
294
+ return displayName;
295
+ }).join(', ');
296
+
297
+ return ` (${comps})`;
298
+ }
299
+
264
300
  /**
265
301
  * 构建节点树输出
266
302
  * @param {Array} data - 场景数据
@@ -276,46 +312,46 @@ function buildTree(data, scriptMap, nodeIndex, prefix = '', isLast = true, isRoo
276
312
  if (!node) return '';
277
313
 
278
314
  const isSceneRoot = node.__type__ === 'cc.Scene';
279
- const nodeName = isRoot ? 'Root' : (node._name || '(unnamed)');
315
+ const isPrefabRoot = node.__type__ === 'cc.Prefab';
316
+ const nodeName = node._name || '(unnamed)';
280
317
  const active = node._active !== false ? '●' : '○';
281
318
  const uuidRegex = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
282
319
 
283
320
  let result = '';
284
321
 
285
322
  if (isSceneRoot) {
286
- result = prefix + '[Scene]\n';
287
- } else {
288
- result = prefix + (isRoot ? '' : active + ' ') + nodeName + ' #' + nodeIndex;
323
+ result = '[Scene]\n';
324
+ } else if (isPrefabRoot) {
325
+ // 预制体直接显示根节点
326
+ const prefabNode = data[1];
327
+ if (!prefabNode) return '';
289
328
 
290
- // 添加组件信息
291
- if (node._components && node._components.length > 0) {
292
- const comps = node._components.map(c => {
293
- const comp = data[c.__id__];
294
- if (!comp) return `? #${c.__id__}`;
295
- const typeName = comp.__type__;
296
- let displayName;
297
- if (uuidRegex.test(typeName)) {
298
- const scriptInfo = scriptMap[typeName];
299
- displayName = (scriptInfo && scriptInfo.name) ? scriptInfo.name : '[MissingScript]';
300
- } else if (typeName === 'MissingScript') {
301
- displayName = '[MissingScript]';
302
- } else {
303
- displayName = typeName.replace('cc.', '');
304
- }
305
- return `${displayName} #${c.__id__}`;
306
- }).join(', ');
307
- result += ` (${comps})`;
308
- }
329
+ const prefabActive = prefabNode._active !== false ? '●' : '○';
330
+ result = prefabActive + ' ' + (prefabNode._name || 'Root');
331
+ result += buildComponentInfo(data, prefabNode, scriptMap, uuidRegex);
332
+ result += '\n';
309
333
 
334
+ // 处理子节点
335
+ if (prefabNode._children && prefabNode._children.length > 0) {
336
+ prefabNode._children.forEach((childRef, idx) => {
337
+ const childIsLast = idx === prefabNode._children.length - 1;
338
+ result += buildTree(data, scriptMap, childRef.__id__, '', childIsLast, false);
339
+ });
340
+ }
341
+ return result;
342
+ } else {
343
+ const connector = isRoot ? '' : (isLast ? '└── ' : '├── ');
344
+ result = prefix + connector + (isRoot ? '' : active + ' ') + nodeName;
345
+ result += buildComponentInfo(data, node, scriptMap, uuidRegex);
310
346
  result += '\n';
311
347
  }
312
348
 
313
349
  // 处理子节点
314
350
  if (node._children && node._children.length > 0) {
351
+ const childPrefix = prefix + (isSceneRoot ? '' : (isRoot ? '' : (isLast ? ' ' : '│ ')));
315
352
  node._children.forEach((childRef, idx) => {
316
353
  const childIsLast = idx === node._children.length - 1;
317
- const childPrefix = prefix + (isSceneRoot ? '' : (isRoot ? '' : (isLast ? ' ' : '│ ')));
318
- result += buildTree(data, scriptMap, childRef.__id__, childPrefix, childIsLast, isSceneRoot);
354
+ result += buildTree(data, scriptMap, childRef.__id__, childPrefix, childIsLast, false);
319
355
  });
320
356
  }
321
357