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.
- 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 +133 -109
- package/src/commands/get.js +113 -18
- package/src/commands/prefab-create.js +49 -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 +75 -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/data/prefab-template.json +0 -72
- package/data/scene-template.json +0 -241
- 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, createSceneMeta, saveMetaFile } = 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,56 @@ 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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
164
|
+
// 设置 Scene._id
|
|
165
|
+
const uuid = readUuidFromMeta(outputPath);
|
|
166
|
+
scene._id = uuid || generateUUID();
|
|
167
|
+
|
|
168
|
+
// 保存
|
|
169
|
+
const data = asset.toJSON();
|
|
170
|
+
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
|
|
171
|
+
|
|
172
|
+
// 生成并保存 meta 文件(如果不存在)
|
|
173
|
+
if (!uuid) {
|
|
174
|
+
saveMetaFile(outputPath, createSceneMeta(scene._id));
|
|
149
175
|
}
|
|
150
176
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
components: compCount
|
|
155
|
-
});
|
|
177
|
+
// 输出 tree
|
|
178
|
+
const scriptMap = loadScriptMap(outputPath);
|
|
179
|
+
console.log(buildTree(data, scriptMap, 1).trim());
|
|
156
180
|
|
|
157
181
|
} catch (err) {
|
|
158
|
-
|
|
182
|
+
console.log(JSON.stringify({ error: err.message }));
|
|
159
183
|
}
|
|
160
184
|
}
|
|
161
185
|
|
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, createPrefabMeta, saveMetaFile } = 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,56 @@ 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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
});
|
|
155
|
-
return;
|
|
156
|
-
} catch (err) {
|
|
157
|
-
outputError(err.message);
|
|
63
|
+
// 生成并保存 meta 文件
|
|
64
|
+
saveMetaFile(outputPath, createPrefabMeta());
|
|
65
|
+
|
|
66
|
+
const scriptMap = loadScriptMap(outputPath);
|
|
67
|
+
console.log(buildTree(data, scriptMap, 1).trim());
|
|
158
68
|
return;
|
|
159
69
|
}
|
|
160
|
-
}
|
|
161
70
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
71
|
+
// 从 JSON 文件创建
|
|
72
|
+
if (!fs.existsSync(jsonPath)) {
|
|
73
|
+
outputError(`JSON 文件不存在: ${jsonPath}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
166
76
|
|
|
167
|
-
try {
|
|
168
77
|
const input = fs.readFileSync(jsonPath, 'utf8');
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
78
|
+
const rootNode = fromJSON(input);
|
|
79
|
+
|
|
80
|
+
// 确保根节点名称
|
|
81
|
+
if (!rootNode._name || rootNode._name === 'Node') {
|
|
82
|
+
rootNode._name = prefabName;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 为所有节点添加 PrefabInfo
|
|
86
|
+
addPrefabInfo(rootNode, true);
|
|
87
|
+
|
|
88
|
+
// 创建预制体
|
|
89
|
+
const prefab = new CCPrefab();
|
|
90
|
+
prefab._root = rootNode;
|
|
174
91
|
|
|
175
92
|
const outputDir = path.dirname(outputPath);
|
|
176
93
|
if (!fs.existsSync(outputDir)) {
|
|
177
94
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
178
95
|
}
|
|
179
96
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
else if (item.__type__?.startsWith('cc.') && !['cc.Prefab', 'cc.PrefabInfo'].includes(item.__type__)) {
|
|
186
|
-
compCount++;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
97
|
+
const data = prefab.toJSON();
|
|
98
|
+
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8');
|
|
99
|
+
|
|
100
|
+
// 生成并保存 meta 文件
|
|
101
|
+
saveMetaFile(outputPath, createPrefabMeta());
|
|
189
102
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
nodes: nodeCount,
|
|
193
|
-
components: compCount
|
|
194
|
-
});
|
|
103
|
+
const scriptMap = loadScriptMap(outputPath);
|
|
104
|
+
console.log(buildTree(data, scriptMap, 1).trim());
|
|
195
105
|
|
|
196
106
|
} catch (err) {
|
|
197
107
|
outputError(err.message);
|
|
198
108
|
}
|
|
199
109
|
}
|
|
200
110
|
|
|
201
|
-
module.exports = { run };
|
|
111
|
+
module.exports = { run };
|