cocos2d-cli 1.4.0 → 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.
Files changed (45) 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 +128 -109
  7. package/src/commands/get.js +113 -18
  8. package/src/commands/prefab-create.js +43 -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 +1 -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/src/lib/components/button.js +0 -137
  38. package/src/lib/components/camera.js +0 -107
  39. package/src/lib/components/canvas.js +0 -89
  40. package/src/lib/components/index.js +0 -157
  41. package/src/lib/components/label.js +0 -120
  42. package/src/lib/components/layout.js +0 -110
  43. package/src/lib/components/particle-system.js +0 -160
  44. package/src/lib/components/sprite.js +0 -98
  45. package/src/lib/components/widget.js +0 -122
@@ -1,75 +1,120 @@
1
1
  /**
2
- * create-scene 命令 - 从 JSON 结构创建场景文件
2
+ * create-scene 命令 - 创建场景文件
3
3
  */
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
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');
7
+ const { CCNode, CCScene, CCSceneAsset, CCCanvas, CCWidget, CCCamera } = require('../lib/cc');
8
+ const { buildTree } = require('../lib/node-utils');
9
+ const { loadScriptMap } = require('../lib/fire-utils');
10
+ const { generateUUID, generateCompressedUUID } = require('../lib/utils');
11
+ const { fromJSON } = require('../lib/json-parser');
11
12
 
12
13
  /**
13
- * 从 JSON 定义创建场景数据
14
+ * 从项目配置读取设计分辨率
14
15
  */
15
- function createSceneData(nodeDefs, sceneName) {
16
- const data = createScene(sceneName);
16
+ function getDesignResolution(outputPath) {
17
+ const defaultResolution = { width: 960, height: 640 };
17
18
 
18
- // Canvas 节点索引
19
- const canvasIndex = 2;
20
-
21
- // 支持数组或单个节点
22
- const nodes = Array.isArray(nodeDefs) ? nodeDefs : [nodeDefs];
19
+ let currentDir = path.dirname(path.resolve(outputPath));
20
+ while (currentDir !== path.dirname(currentDir)) {
21
+ const settingsPath = path.join(currentDir, 'settings', 'project.json');
22
+ if (fs.existsSync(settingsPath)) {
23
+ try {
24
+ const config = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
25
+ if (config['design-resolution-width'] && config['design-resolution-height']) {
26
+ return {
27
+ width: config['design-resolution-width'],
28
+ height: config['design-resolution-height']
29
+ };
30
+ }
31
+ } catch (e) {}
32
+ }
33
+ currentDir = path.dirname(currentDir);
34
+ }
23
35
 
24
- // 添加用户节点到 Canvas
25
- for (const nodeDef of nodes) {
26
- addUserNode(data, nodeDef, canvasIndex);
36
+ return defaultResolution;
37
+ }
38
+
39
+ /**
40
+ * 从 meta 文件读取 uuid
41
+ */
42
+ function readUuidFromMeta(scenePath) {
43
+ const metaPath = scenePath + '.meta';
44
+ if (fs.existsSync(metaPath)) {
45
+ try {
46
+ const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
47
+ return meta.uuid || null;
48
+ } catch (e) {
49
+ return null;
50
+ }
27
51
  }
52
+ return null;
53
+ }
28
54
 
29
- return data;
55
+ /**
56
+ * 为节点树设置 _id
57
+ */
58
+ function setNodeId(node) {
59
+ node._id = generateCompressedUUID();
60
+ if (node._children) {
61
+ node._children.forEach(child => setNodeId(child));
62
+ }
30
63
  }
31
64
 
32
65
  /**
33
- * 添加用户节点
66
+ * 创建默认场景结构(Canvas + Main Camera)
34
67
  */
35
- function addUserNode(data, def, parentIndex) {
36
- const nodeIndex = data.length;
37
- const node = createNodeData(def.name || 'Node', parentIndex, def);
68
+ function createDefaultScene(asset, resolution) {
69
+ const { width, height } = resolution;
70
+ const scene = asset._scene;
38
71
 
39
- data.push(node);
72
+ // 创建 Canvas 节点
73
+ const canvas = new CCNode('Canvas');
74
+ canvas._contentSize.width = width;
75
+ canvas._contentSize.height = height;
76
+ canvas._anchorPoint.x = 0.5;
77
+ canvas._anchorPoint.y = 0.5;
78
+ canvas._trs.array[0] = width / 2;
79
+ canvas._trs.array[1] = height / 2;
80
+ canvas._is3DNode = false;
81
+ canvas._id = generateCompressedUUID();
40
82
 
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 });
51
- }
52
- }
53
- }
54
- }
83
+ // Canvas 组件
84
+ const canvasComp = new CCCanvas();
85
+ canvasComp.setDesignResolution(width, height);
86
+ canvasComp.node = canvas;
55
87
 
56
- // 更新父节点的 _children
57
- data[parentIndex]._children.push({ "__id__": nodeIndex });
88
+ // Widget 组件
89
+ const widget = new CCWidget();
90
+ widget.node = canvas;
58
91
 
59
- // 递归处理子节点
60
- if (def.children && def.children.length > 0) {
61
- for (const childDef of def.children) {
62
- addUserNode(data, childDef, nodeIndex);
63
- }
64
- }
92
+ canvas._components = [canvasComp, widget];
93
+ canvas._parent = scene;
94
+ scene._children = [canvas];
95
+
96
+ // 创建 Main Camera 节点
97
+ const camera = new CCNode('Main Camera');
98
+ camera._contentSize.width = 0;
99
+ camera._contentSize.height = 0;
100
+ camera._anchorPoint.x = 0.5;
101
+ camera._anchorPoint.y = 0.5;
102
+ camera._is3DNode = false;
103
+ camera._id = generateCompressedUUID();
104
+
105
+ // Camera 组件
106
+ const cameraComp = new CCCamera();
107
+ cameraComp.node = camera;
108
+
109
+ camera._components = [cameraComp];
110
+ camera._parent = canvas;
111
+ canvas._children = [camera];
65
112
  }
66
113
 
67
114
  function run(args) {
68
115
  if (args.length < 1) {
69
- outputError({
70
- message: '用法: cocos2d-cli create-scene [JSON文件路径] <输出路径.fire>',
71
- hint: '不传 JSON 则创建默认场景'
72
- });
116
+ console.log(JSON.stringify({ error: '用法: cocos2d-cli create-scene [JSON文件路径] <输出路径.fire>' }));
117
+ console.log(JSON.stringify({ hint: '不传 JSON 则创建默认场景(含 Canvas 和 Main Camera)' }));
73
118
  return;
74
119
  }
75
120
 
@@ -85,77 +130,51 @@ function run(args) {
85
130
 
86
131
  const sceneName = path.basename(outputPath, '.fire');
87
132
 
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');
133
+ try {
134
+ // 创建场景
135
+ const asset = new CCSceneAsset();
136
+ const scene = new CCScene(sceneName);
137
+ asset._scene = scene;
138
+ scene._children = [];
139
+
140
+ // 从 JSON 创建
141
+ if (jsonPath && fs.existsSync(jsonPath)) {
142
+ const input = fs.readFileSync(jsonPath, 'utf8');
143
+ const nodeDef = JSON.parse(input.replace(/^\uFEFF/, '').trim());
103
144
 
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
- }
145
+ const nodes = Array.isArray(nodeDef) ? nodeDef : [nodeDef];
146
+ for (const def of nodes) {
147
+ const node = fromJSON(def);
148
+ setNodeId(node);
149
+ node._parent = scene;
150
+ scene._children.push(node);
110
151
  }
111
-
112
- outputSuccess({
113
- path: outputPath,
114
- nodes: nodeCount,
115
- components: compCount
116
- });
117
- return;
118
- } catch (err) {
119
- outputError(err.message);
120
- return;
152
+ } else {
153
+ // 没有 JSON,创建默认场景结构
154
+ const resolution = getDesignResolution(outputPath);
155
+ createDefaultScene(asset, resolution);
121
156
  }
122
- }
123
-
124
- if (!fs.existsSync(jsonPath)) {
125
- outputError(`JSON 文件不存在: ${jsonPath}`);
126
- return;
127
- }
128
157
 
129
- try {
130
- const input = fs.readFileSync(jsonPath, 'utf8');
131
- const cleanInput = input.replace(/^\uFEFF/, '').trim();
132
- const nodeDef = JSON.parse(cleanInput);
133
-
134
- const sceneData = createSceneData(nodeDef, sceneName);
135
-
136
- const outputDir = path.dirname(outputPath);
137
- if (!fs.existsSync(outputDir)) {
138
- fs.mkdirSync(outputDir, { recursive: true });
158
+ // 确保目录存在
159
+ const dir = path.dirname(outputPath);
160
+ if (!fs.existsSync(dir)) {
161
+ fs.mkdirSync(dir, { recursive: true });
139
162
  }
140
163
 
141
- fs.writeFileSync(outputPath, JSON.stringify(sceneData, null, 2), 'utf8');
164
+ // 设置 Scene._id
165
+ const uuid = readUuidFromMeta(outputPath);
166
+ scene._id = uuid || generateUUID();
142
167
 
143
- let nodeCount = 0, compCount = 0;
144
- for (const item of sceneData) {
145
- if (item.__type__ === 'cc.Node') nodeCount++;
146
- else if (item.__type__?.startsWith('cc.') && !['cc.Scene', 'cc.SceneAsset'].includes(item.__type__)) {
147
- compCount++;
148
- }
149
- }
168
+ // 保存
169
+ const data = asset.toJSON();
170
+ fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
150
171
 
151
- outputSuccess({
152
- path: outputPath,
153
- nodes: nodeCount,
154
- components: compCount
155
- });
172
+ // 输出 tree
173
+ const scriptMap = loadScriptMap(outputPath);
174
+ console.log(buildTree(data, scriptMap, 1).trim());
156
175
 
157
176
  } catch (err) {
158
- outputError(err.message);
177
+ console.log(JSON.stringify({ error: err.message }));
159
178
  }
160
179
  }
161
180
 
@@ -1,38 +1,133 @@
1
1
  /**
2
- * get 命令 - 获取节点信息
2
+ * get 命令 - 获取节点或组件属性
3
3
  */
4
4
 
5
- const { loadScene, buildMaps, findNodeIndex } = require('../lib/fire-utils');
6
- const { getNodeState } = require('../lib/node-utils');
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+ const { CCSceneAsset, CCPrefab } = require('../lib/cc');
8
+
9
+ /**
10
+ * 查找节点
11
+ */
12
+ function findNode(root, path) {
13
+ if (!path) return root;
14
+
15
+ const parts = path.split('/').filter(p => p);
16
+ if (parts.length === 0) return root;
17
+
18
+ let current = root;
19
+
20
+ if (parts[0] === root._name) {
21
+ parts.shift();
22
+ }
23
+
24
+ for (const part of parts) {
25
+ if (!current._children || current._children.length === 0) return null;
26
+ const found = current._children.find(c => c._name === part);
27
+ if (!found) return null;
28
+ current = found;
29
+ }
30
+
31
+ return current;
32
+ }
33
+
34
+ /**
35
+ * 查找组件
36
+ */
37
+ function findComponent(node, compType) {
38
+ if (!node._components) return null;
39
+
40
+ const type = compType.toLowerCase();
41
+ const typeName = 'cc.' + type.charAt(0).toUpperCase() + type.slice(1);
42
+
43
+ return node._components.find(c => c.__type__ === typeName);
44
+ }
45
+
46
+ /**
47
+ * 获取节点属性值
48
+ */
49
+ function getNodeProp(node, prop) {
50
+ switch (prop.toLowerCase()) {
51
+ case 'name': return node._name;
52
+ case 'active': return node._active;
53
+ case 'x': return node._trs.array[0];
54
+ case 'y': return node._trs.array[1];
55
+ case 'width': return node._contentSize.width;
56
+ case 'height': return node._contentSize.height;
57
+ case 'scalex': return node._trs.array[7];
58
+ case 'scaley': return node._trs.array[8];
59
+ case 'rotation': return node._eulerAngles.z;
60
+ case 'anchorx': return node._anchorPoint.x;
61
+ case 'anchory': return node._anchorPoint.y;
62
+ case 'opacity': return node._opacity;
63
+ case 'color': return node._color;
64
+ default: return undefined;
65
+ }
66
+ }
7
67
 
8
68
  function run(args) {
9
- if (args.length < 2) {
10
- console.log(JSON.stringify({ error: '用法: cocos2d-cli get <场景.fire | 预制体.prefab> <节点索引|名称>' }));
69
+ if (args.length < 3) {
70
+ console.log(JSON.stringify({ error: '用法: cocos2d-cli get <场景.fire|预制体.prefab> <节点路径> <属性名|组件.属性>' }));
11
71
  return;
12
72
  }
13
73
 
14
- const scenePath = args[0];
15
- const nodeRef = args[1];
74
+ const filePath = args[0];
75
+ const nodePath = args[1];
76
+ const propPath = args[2];
77
+
78
+ const ext = path.extname(filePath).toLowerCase();
16
79
 
17
80
  try {
18
- const data = loadScene(scenePath);
19
- const { indexMap } = buildMaps(data);
20
-
21
- const idx = findNodeIndex(data, indexMap, nodeRef);
81
+ let root;
82
+ const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
22
83
 
23
- if (idx === null || idx < 0 || idx >= data.length) {
24
- console.log(JSON.stringify({ error: `无效的节点索引: ${nodeRef}` }));
84
+ if (ext === '.fire') {
85
+ const asset = CCSceneAsset.fromJSON(json);
86
+ root = asset._scene;
87
+ } else if (ext === '.prefab') {
88
+ const asset = CCPrefab.fromJSON(json);
89
+ root = asset._root;
90
+ } else {
91
+ console.log(JSON.stringify({ error: '不支持的文件类型,仅支持 .fire 和 .prefab' }));
25
92
  return;
26
93
  }
27
94
 
28
- const node = data[idx];
95
+ const node = findNode(root, nodePath);
96
+
29
97
  if (!node) {
30
- console.log(JSON.stringify({ error: `节点不存在: ${nodeRef}` }));
98
+ console.log(JSON.stringify({ error: `节点不存在: ${nodePath}` }));
31
99
  return;
32
100
  }
33
-
34
- console.log(JSON.stringify(getNodeState(data, node, idx)));
35
-
101
+
102
+ // 检查是否是组件属性(格式: 组件.属性)
103
+ const parts = propPath.split('.');
104
+
105
+ if (parts.length === 2) {
106
+ // 组件属性
107
+ const comp = findComponent(node, parts[0]);
108
+ if (!comp) {
109
+ console.log(JSON.stringify({ error: `组件不存在: ${parts[0]}` }));
110
+ return;
111
+ }
112
+
113
+ const value = comp[parts[1]];
114
+ if (value === undefined) {
115
+ console.log(JSON.stringify({ error: `属性不存在: ${parts[1]}` }));
116
+ return;
117
+ }
118
+
119
+ console.log(JSON.stringify({ value }));
120
+ } else {
121
+ // 节点属性
122
+ const value = getNodeProp(node, propPath);
123
+ if (value === undefined) {
124
+ console.log(JSON.stringify({ error: `属性不存在: ${propPath}` }));
125
+ return;
126
+ }
127
+
128
+ console.log(JSON.stringify({ value }));
129
+ }
130
+
36
131
  } catch (err) {
37
132
  console.log(JSON.stringify({ error: err.message }));
38
133
  }
@@ -4,108 +4,21 @@
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
- const { outputError, outputSuccess } = require('../lib/utils');
8
- const { createNodeData } = require('../lib/node-utils');
9
- const { parseComponent, createComponent, applyComponentProps } = require('../lib/components');
10
- const { createPrefab, generateFileId } = require('../lib/templates');
7
+ const { outputError } = require('../lib/utils');
8
+ const { buildTree } = require('../lib/node-utils');
9
+ const { createPrefab } = require('../lib/templates');
10
+ const { CCPrefab, CCPrefabInfo } = require('../lib/cc');
11
+ const { loadScriptMap } = require('../lib/fire-utils');
12
+ const { fromJSON } = require('../lib/json-parser');
11
13
 
12
14
  /**
13
- * JSON 定义创建预制体数据
15
+ * 为节点树添加 PrefabInfo
14
16
  */
15
- function createPrefabData(nodeDef) {
16
- const data = createPrefab(nodeDef.name || 'Node');
17
+ function addPrefabInfo(node, isRoot = false) {
18
+ node._prefab = new CCPrefabInfo();
17
19
 
18
- // 更新根节点
19
- const root = data[1];
20
- applyNodeDefToNode(root, nodeDef, null);
21
-
22
- // 递归添加子节点
23
- if (nodeDef.children && nodeDef.children.length > 0) {
24
- for (const childDef of nodeDef.children) {
25
- addChildNode(data, childDef, 1);
26
- }
27
- }
28
-
29
- return data;
30
- }
31
-
32
- /**
33
- * 应用 JSON 定义到节点
34
- */
35
- function applyNodeDefToNode(node, def, parentId) {
36
- if (def.name) node._name = def.name;
37
- if (def.active !== undefined) node._active = def.active;
38
- if (def.opacity !== undefined) node._opacity = def.opacity;
39
- if (def.width !== undefined) node._contentSize.width = def.width;
40
- if (def.height !== undefined) node._contentSize.height = def.height;
41
- if (def.x !== undefined) node._trs.array[0] = def.x;
42
- if (def.y !== undefined) node._trs.array[1] = def.y;
43
- if (def.rotation !== undefined) {
44
- node._trs.array[5] = def.rotation * Math.PI / 180;
45
- node._eulerAngles.z = def.rotation;
46
- }
47
- if (def.scaleX !== undefined) node._trs.array[7] = def.scaleX;
48
- if (def.scaleY !== undefined) node._trs.array[8] = def.scaleY;
49
- if (def.anchorX !== undefined) node._anchorPoint.x = def.anchorX;
50
- if (def.anchorY !== undefined) node._anchorPoint.y = def.anchorY;
51
- if (def.color) {
52
- const { parseColor } = require('../lib/utils');
53
- const parsed = parseColor(def.color);
54
- if (parsed) {
55
- node._color = { "__type__": "cc.Color", ...parsed };
56
- }
57
- }
58
- if (parentId !== null) {
59
- node._parent = { "__id__": parentId };
60
- }
61
- }
62
-
63
- /**
64
- * 添加子节点
65
- */
66
- function addChildNode(data, def, parentIndex) {
67
- const nodeIndex = data.length;
68
- const node = createNodeData(def.name || 'Node', parentIndex, def);
69
-
70
- // 设置 _prefab 为 null,后面会添加 PrefabInfo
71
- node._prefab = null;
72
-
73
- data.push(node);
74
-
75
- // 添加组件
76
- if (def.components) {
77
- for (const compDef of def.components) {
78
- const parsed = parseComponent(compDef);
79
- if (parsed) {
80
- const comp = createComponent(parsed.type, nodeIndex);
81
- if (comp) {
82
- applyComponentProps(comp, parsed.props, node);
83
- data.push(comp);
84
- node._components.push({ "__id__": data.length - 1 });
85
- }
86
- }
87
- }
88
- }
89
-
90
- // 添加 PrefabInfo
91
- const prefabInfo = {
92
- "__type__": "cc.PrefabInfo",
93
- "root": { "__id__": 1 },
94
- "asset": { "__id__": 0 },
95
- "fileId": generateFileId(),
96
- "sync": false
97
- };
98
- data.push(prefabInfo);
99
- node._prefab = { "__id__": data.length - 1 };
100
-
101
- // 更新父节点
102
- data[parentIndex]._children.push({ "__id__": nodeIndex });
103
-
104
- // 递归处理子节点
105
- if (def.children && def.children.length > 0) {
106
- for (const childDef of def.children) {
107
- addChildNode(data, childDef, nodeIndex);
108
- }
20
+ if (node._children) {
21
+ node._children.forEach(child => addPrefabInfo(child, false));
109
22
  }
110
23
  }
111
24
 
@@ -128,11 +41,11 @@ function run(args) {
128
41
  outputPath = args[1];
129
42
  }
130
43
 
131
- // 没有传 JSON,创建默认预制体
132
- if (!jsonPath) {
133
- const prefabName = path.basename(outputPath, '.prefab');
134
-
135
- try {
44
+ const prefabName = path.basename(outputPath, '.prefab');
45
+
46
+ try {
47
+ // 没有传 JSON,创建默认预制体
48
+ if (!jsonPath) {
136
49
  if (fs.existsSync(outputPath)) {
137
50
  outputError(`文件已存在: ${outputPath}`);
138
51
  return;
@@ -143,59 +56,50 @@ function run(args) {
143
56
  fs.mkdirSync(dir, { recursive: true });
144
57
  }
145
58
 
146
- const data = createPrefab(prefabName);
59
+ const prefab = createPrefab(prefabName);
60
+ const data = prefab.toJSON();
147
61
  fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
148
62
 
149
- outputSuccess({
150
- path: outputPath,
151
- rootName: prefabName,
152
- nodes: 1,
153
- components: 0
154
- });
155
- return;
156
- } catch (err) {
157
- outputError(err.message);
63
+ const scriptMap = loadScriptMap(outputPath);
64
+ console.log(buildTree(data, scriptMap, 1).trim());
158
65
  return;
159
66
  }
160
- }
161
67
 
162
- if (!fs.existsSync(jsonPath)) {
163
- outputError(`JSON 文件不存在: ${jsonPath}`);
164
- return;
165
- }
68
+ // JSON 文件创建
69
+ if (!fs.existsSync(jsonPath)) {
70
+ outputError(`JSON 文件不存在: ${jsonPath}`);
71
+ return;
72
+ }
166
73
 
167
- try {
168
74
  const input = fs.readFileSync(jsonPath, 'utf8');
169
- const cleanInput = input.replace(/^\uFEFF/, '').trim();
170
- const nodeDef = JSON.parse(cleanInput);
171
-
172
- const rootNode = Array.isArray(nodeDef) ? nodeDef[0] : nodeDef;
173
- const prefabData = createPrefabData(rootNode);
75
+ const rootNode = fromJSON(input);
76
+
77
+ // 确保根节点名称
78
+ if (!rootNode._name || rootNode._name === 'Node') {
79
+ rootNode._name = prefabName;
80
+ }
81
+
82
+ // 为所有节点添加 PrefabInfo
83
+ addPrefabInfo(rootNode, true);
84
+
85
+ // 创建预制体
86
+ const prefab = new CCPrefab();
87
+ prefab._root = rootNode;
174
88
 
175
89
  const outputDir = path.dirname(outputPath);
176
90
  if (!fs.existsSync(outputDir)) {
177
91
  fs.mkdirSync(outputDir, { recursive: true });
178
92
  }
179
93
 
180
- fs.writeFileSync(outputPath, JSON.stringify(prefabData, null, 2), 'utf8');
94
+ const data = prefab.toJSON();
95
+ fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
181
96
 
182
- let nodeCount = 0, compCount = 0;
183
- for (const item of prefabData) {
184
- if (item.__type__ === 'cc.Node') nodeCount++;
185
- else if (item.__type__?.startsWith('cc.') && !['cc.Prefab', 'cc.PrefabInfo'].includes(item.__type__)) {
186
- compCount++;
187
- }
188
- }
189
-
190
- outputSuccess({
191
- path: outputPath,
192
- nodes: nodeCount,
193
- components: compCount
194
- });
97
+ const scriptMap = loadScriptMap(outputPath);
98
+ console.log(buildTree(data, scriptMap, 1).trim());
195
99
 
196
100
  } catch (err) {
197
101
  outputError(err.message);
198
102
  }
199
103
  }
200
104
 
201
- module.exports = { run };
105
+ module.exports = { run };