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.
- package/README.md +142 -0
- package/bin/cocos2d-cli.js +21 -12
- package/package.json +1 -1
- package/src/commands/add-component.js +77 -85
- package/src/commands/add.js +116 -212
- package/src/commands/create-scene.js +128 -109
- package/src/commands/get.js +113 -18
- package/src/commands/prefab-create.js +43 -139
- package/src/commands/remove-component.js +111 -0
- package/src/commands/remove.js +59 -122
- package/src/commands/set.js +121 -36
- package/src/commands/tree.js +3 -8
- package/src/lib/cc/CCButton.js +122 -0
- package/src/lib/cc/CCCamera.js +93 -0
- package/src/lib/cc/CCCanvas.js +64 -0
- package/src/lib/cc/CCColor.js +32 -0
- package/src/lib/cc/CCComponent.js +60 -0
- package/src/lib/cc/CCLabel.js +109 -0
- package/src/lib/cc/CCNode.js +242 -0
- package/src/lib/cc/CCObject.js +23 -0
- package/src/lib/cc/CCPrefab.js +242 -0
- package/src/lib/cc/CCRect.js +32 -0
- package/src/lib/cc/CCScene.js +42 -0
- package/src/lib/cc/CCSceneAsset.js +271 -0
- package/src/lib/cc/CCSize.js +26 -0
- package/src/lib/cc/CCSprite.js +82 -0
- package/src/lib/cc/CCTrs.js +74 -0
- package/src/lib/cc/CCVec2.js +26 -0
- package/src/lib/cc/CCVec3.js +29 -0
- package/src/lib/cc/CCWidget.js +98 -0
- package/src/lib/cc/index.js +40 -0
- package/src/lib/fire-utils.js +1 -1
- package/src/lib/json-parser.js +166 -0
- package/src/lib/node-utils.js +64 -28
- package/src/lib/templates.js +31 -194
- package/src/lib/utils.js +63 -0
- package/src/lib/components/button.js +0 -137
- package/src/lib/components/camera.js +0 -107
- package/src/lib/components/canvas.js +0 -89
- package/src/lib/components/index.js +0 -157
- package/src/lib/components/label.js +0 -120
- package/src/lib/components/layout.js +0 -110
- package/src/lib/components/particle-system.js +0 -160
- package/src/lib/components/sprite.js +0 -98
- package/src/lib/components/widget.js +0 -122
|
@@ -1,75 +1,120 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* create-scene 命令 -
|
|
2
|
+
* create-scene 命令 - 创建场景文件
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
|
-
const {
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
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
|
-
*
|
|
14
|
+
* 从项目配置读取设计分辨率
|
|
14
15
|
*/
|
|
15
|
-
function
|
|
16
|
-
const
|
|
16
|
+
function getDesignResolution(outputPath) {
|
|
17
|
+
const defaultResolution = { width: 960, height: 640 };
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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
|
|
36
|
-
const
|
|
37
|
-
const
|
|
68
|
+
function createDefaultScene(asset, resolution) {
|
|
69
|
+
const { width, height } = resolution;
|
|
70
|
+
const scene = asset._scene;
|
|
38
71
|
|
|
39
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
//
|
|
57
|
-
|
|
88
|
+
// Widget 组件
|
|
89
|
+
const widget = new CCWidget();
|
|
90
|
+
widget.node = canvas;
|
|
58
91
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
70
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
105
|
-
for (const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
164
|
+
// 设置 Scene._id
|
|
165
|
+
const uuid = readUuidFromMeta(outputPath);
|
|
166
|
+
scene._id = uuid || generateUUID();
|
|
142
167
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
177
|
+
console.log(JSON.stringify({ error: err.message }));
|
|
159
178
|
}
|
|
160
179
|
}
|
|
161
180
|
|
package/src/commands/get.js
CHANGED
|
@@ -1,38 +1,133 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* get 命令 -
|
|
2
|
+
* get 命令 - 获取节点或组件属性
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
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 <
|
|
10
|
-
console.log(JSON.stringify({ error: '用法: cocos2d-cli get <场景.fire
|
|
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
|
|
15
|
-
const
|
|
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
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const idx = findNodeIndex(data, indexMap, nodeRef);
|
|
81
|
+
let root;
|
|
82
|
+
const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
22
83
|
|
|
23
|
-
if (
|
|
24
|
-
|
|
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 =
|
|
95
|
+
const node = findNode(root, nodePath);
|
|
96
|
+
|
|
29
97
|
if (!node) {
|
|
30
|
-
console.log(JSON.stringify({ error: `节点不存在: ${
|
|
98
|
+
console.log(JSON.stringify({ error: `节点不存在: ${nodePath}` }));
|
|
31
99
|
return;
|
|
32
100
|
}
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
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
|
-
*
|
|
15
|
+
* 为节点树添加 PrefabInfo
|
|
14
16
|
*/
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
+
function addPrefabInfo(node, isRoot = false) {
|
|
18
|
+
node._prefab = new CCPrefabInfo();
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
|
59
|
+
const prefab = createPrefab(prefabName);
|
|
60
|
+
const data = prefab.toJSON();
|
|
147
61
|
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
|
|
148
62
|
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
94
|
+
const data = prefab.toJSON();
|
|
95
|
+
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
|
|
181
96
|
|
|
182
|
-
|
|
183
|
-
|
|
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 };
|