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
package/src/lib/fire-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fire/Prefab 文件工具模块
|
|
3
|
-
*
|
|
2
|
+
* Fire/Prefab 文件工具模块
|
|
3
|
+
* 提供场景/预制体文件的读写和编辑器交互功能
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -33,18 +33,17 @@ function saveScene(scenePath, data) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* 构建 ID
|
|
36
|
+
* 构建 ID 和索引映射
|
|
37
37
|
*/
|
|
38
38
|
function buildMaps(data) {
|
|
39
|
-
const idMap = {};
|
|
40
|
-
const indexMap = {};
|
|
39
|
+
const idMap = {};
|
|
40
|
+
const indexMap = {};
|
|
41
41
|
const prefab = isPrefab(data);
|
|
42
42
|
|
|
43
43
|
function traverse(nodeIndex, parentPath = '') {
|
|
44
44
|
const node = data[nodeIndex];
|
|
45
45
|
if (!node) return;
|
|
46
46
|
|
|
47
|
-
// 跳过非节点类型
|
|
48
47
|
if (!node.__type__?.startsWith('cc.Node') && node.__type__ !== 'cc.Scene') {
|
|
49
48
|
return;
|
|
50
49
|
}
|
|
@@ -64,7 +63,6 @@ function buildMaps(data) {
|
|
|
64
63
|
type: node.__type__
|
|
65
64
|
};
|
|
66
65
|
|
|
67
|
-
// 递归处理子节点
|
|
68
66
|
if (node._children) {
|
|
69
67
|
node._children.forEach(childRef => {
|
|
70
68
|
traverse(childRef.__id__, nodePath);
|
|
@@ -72,13 +70,7 @@ function buildMaps(data) {
|
|
|
72
70
|
}
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
|
|
76
|
-
// 预制体:从索引 1(根节点)开始遍历
|
|
77
|
-
traverse(1);
|
|
78
|
-
} else {
|
|
79
|
-
// 场景:从索引 1(Scene)开始遍历
|
|
80
|
-
traverse(1);
|
|
81
|
-
}
|
|
73
|
+
traverse(1);
|
|
82
74
|
|
|
83
75
|
return { idMap, indexMap, prefab };
|
|
84
76
|
}
|
|
@@ -87,12 +79,10 @@ function buildMaps(data) {
|
|
|
87
79
|
* 查找节点索引
|
|
88
80
|
*/
|
|
89
81
|
function findNodeIndex(data, indexMap, nodeRef) {
|
|
90
|
-
// 如果是数字,直接返回
|
|
91
82
|
if (/^\d+$/.test(nodeRef)) {
|
|
92
83
|
return parseInt(nodeRef);
|
|
93
84
|
}
|
|
94
85
|
|
|
95
|
-
// 按名称/路径查找
|
|
96
86
|
for (const [idx, info] of Object.entries(indexMap)) {
|
|
97
87
|
if (info.name === nodeRef || info.path === nodeRef || info.path.endsWith('/' + nodeRef)) {
|
|
98
88
|
return parseInt(idx);
|
|
@@ -103,35 +93,7 @@ function findNodeIndex(data, indexMap, nodeRef) {
|
|
|
103
93
|
}
|
|
104
94
|
|
|
105
95
|
/**
|
|
106
|
-
*
|
|
107
|
-
*/
|
|
108
|
-
function collectNodeAndChildren(data, nodeIndex, collected = new Set()) {
|
|
109
|
-
if (collected.has(nodeIndex)) return collected;
|
|
110
|
-
|
|
111
|
-
const node = data[nodeIndex];
|
|
112
|
-
if (!node) return collected;
|
|
113
|
-
|
|
114
|
-
collected.add(nodeIndex);
|
|
115
|
-
|
|
116
|
-
// 收集所有组件
|
|
117
|
-
if (node._components) {
|
|
118
|
-
for (const compRef of node._components) {
|
|
119
|
-
collected.add(compRef.__id__);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// 递归收集子节点
|
|
124
|
-
if (node._children) {
|
|
125
|
-
for (const childRef of node._children) {
|
|
126
|
-
collectNodeAndChildren(data, childRef.__id__, collected);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return collected;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 重建所有 __id__ 引用(删除元素后索引变化)
|
|
96
|
+
* 重建所有 __id__ 引用
|
|
135
97
|
*/
|
|
136
98
|
function rebuildReferences(data, deletedIndices) {
|
|
137
99
|
const indexMap = {};
|
|
@@ -165,175 +127,76 @@ function rebuildReferences(data, deletedIndices) {
|
|
|
165
127
|
return indexMap;
|
|
166
128
|
}
|
|
167
129
|
|
|
168
|
-
/**
|
|
169
|
-
* 重新排列数组,使其与 _children 顺序一致(节点后跟组件)
|
|
170
|
-
*/
|
|
171
|
-
function reorderArrayToMatchChildren(data) {
|
|
172
|
-
const newArray = [];
|
|
173
|
-
const indexMap = {};
|
|
174
|
-
|
|
175
|
-
newArray[0] = data[0];
|
|
176
|
-
newArray[1] = data[1];
|
|
177
|
-
indexMap[0] = 0;
|
|
178
|
-
indexMap[1] = 1;
|
|
179
|
-
|
|
180
|
-
const dataByIndex = {};
|
|
181
|
-
for (let i = 0; i < data.length; i++) {
|
|
182
|
-
if (data[i]) dataByIndex[i] = data[i];
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function addNodeAndChildren(nodeIndex) {
|
|
186
|
-
if (nodeIndex === null || nodeIndex === undefined) return;
|
|
187
|
-
|
|
188
|
-
const node = data[nodeIndex];
|
|
189
|
-
if (!node) return;
|
|
190
|
-
|
|
191
|
-
const newIndex = newArray.length;
|
|
192
|
-
indexMap[nodeIndex] = newIndex;
|
|
193
|
-
newArray.push(node);
|
|
194
|
-
|
|
195
|
-
if (node._components) {
|
|
196
|
-
for (const compRef of node._components) {
|
|
197
|
-
const compIndex = compRef.__id__;
|
|
198
|
-
if (compIndex !== undefined && dataByIndex[compIndex]) {
|
|
199
|
-
const compNewIndex = newArray.length;
|
|
200
|
-
indexMap[compIndex] = compNewIndex;
|
|
201
|
-
newArray.push(dataByIndex[compIndex]);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (node._children) {
|
|
207
|
-
for (const childRef of node._children) {
|
|
208
|
-
addNodeAndChildren(childRef.__id__);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const scene = data[1];
|
|
214
|
-
if (scene && scene._children) {
|
|
215
|
-
for (const childRef of scene._children) {
|
|
216
|
-
addNodeAndChildren(childRef.__id__);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function addRootComponents(nodeIndex) {
|
|
221
|
-
const node = data[nodeIndex];
|
|
222
|
-
if (!node || !node._components) return;
|
|
223
|
-
|
|
224
|
-
for (const compRef of node._components) {
|
|
225
|
-
const compIndex = compRef.__id__;
|
|
226
|
-
if (compIndex !== undefined && dataByIndex[compIndex] && indexMap[compIndex] === undefined) {
|
|
227
|
-
const compNewIndex = newArray.length;
|
|
228
|
-
indexMap[compIndex] = compNewIndex;
|
|
229
|
-
newArray.push(dataByIndex[compIndex]);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
addRootComponents(1);
|
|
235
|
-
addRootComponents(2);
|
|
236
|
-
|
|
237
|
-
function updateRefs(obj) {
|
|
238
|
-
if (!obj || typeof obj !== 'object') return;
|
|
239
|
-
|
|
240
|
-
if (obj.__id__ !== undefined) {
|
|
241
|
-
const oldId = obj.__id__;
|
|
242
|
-
if (indexMap[oldId] !== undefined) {
|
|
243
|
-
obj.__id__ = indexMap[oldId];
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
for (const key of Object.keys(obj)) {
|
|
247
|
-
updateRefs(obj[key]);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
for (const item of newArray) {
|
|
253
|
-
updateRefs(item);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return newArray;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
130
|
/**
|
|
260
131
|
* 检查 CLI Helper 插件状态
|
|
261
|
-
* @returns {object|null} - 插件状态信息,未启动返回 null
|
|
262
132
|
*/
|
|
263
133
|
function checkPluginStatus() {
|
|
264
|
-
const
|
|
134
|
+
const http = require('http');
|
|
265
135
|
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
136
|
+
return new Promise((resolve) => {
|
|
137
|
+
const req = http.request({
|
|
138
|
+
hostname: 'localhost',
|
|
139
|
+
port: 7455,
|
|
140
|
+
path: '/status',
|
|
141
|
+
method: 'GET'
|
|
142
|
+
}, (res) => {
|
|
143
|
+
let data = '';
|
|
144
|
+
res.on('data', chunk => data += chunk);
|
|
145
|
+
res.on('end', () => {
|
|
146
|
+
try {
|
|
147
|
+
resolve(JSON.parse(data));
|
|
148
|
+
} catch (e) {
|
|
149
|
+
resolve(null);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
271
152
|
});
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
153
|
+
|
|
154
|
+
req.on('error', () => resolve(null));
|
|
155
|
+
req.setTimeout(3000, () => { req.destroy(); resolve(null); });
|
|
156
|
+
req.end();
|
|
157
|
+
});
|
|
276
158
|
}
|
|
277
159
|
|
|
278
160
|
/**
|
|
279
|
-
*
|
|
280
|
-
* 智能判断:如果修改的场景就是当前打开的场景,才重新打开;否则只刷新资源
|
|
281
|
-
* 编辑器有可能没打开,调用失败不报错
|
|
282
|
-
* @param {string} scenePath - 场景文件路径(必须)
|
|
161
|
+
* 触发编辑器刷新
|
|
283
162
|
*/
|
|
284
163
|
function refreshEditor(scenePath) {
|
|
285
|
-
|
|
286
|
-
if (!scenePath) {
|
|
287
|
-
console.log(JSON.stringify({ warning: 'refreshEditor: 未提供 scenePath 参数,编辑器不会自动刷新场景' }));
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
164
|
+
if (!scenePath) return;
|
|
290
165
|
|
|
291
|
-
const path = require('path');
|
|
292
166
|
const http = require('http');
|
|
293
167
|
|
|
294
|
-
// 转换场景路径为 db:// 格式
|
|
295
168
|
const assetsPath = path.dirname(scenePath);
|
|
296
169
|
const projectPath = path.dirname(assetsPath);
|
|
297
170
|
const relativePath = path.relative(projectPath, scenePath).replace(/\\/g, '/');
|
|
298
171
|
const targetSceneUrl = 'db://' + relativePath.replace(/^assets\//, 'assets/');
|
|
299
172
|
|
|
300
|
-
// 先查询当前打开的场景
|
|
301
173
|
const getCurrentScene = () => {
|
|
302
174
|
return new Promise((resolve) => {
|
|
303
|
-
const
|
|
175
|
+
const req = http.request({
|
|
304
176
|
hostname: 'localhost',
|
|
305
177
|
port: 7455,
|
|
306
178
|
path: '/current-scene',
|
|
307
179
|
method: 'GET'
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const req = http.request(options, (res) => {
|
|
180
|
+
}, (res) => {
|
|
311
181
|
let data = '';
|
|
312
182
|
res.on('data', chunk => data += chunk);
|
|
313
183
|
res.on('end', () => {
|
|
314
184
|
try {
|
|
315
|
-
|
|
316
|
-
resolve(result.sceneUrl || null);
|
|
185
|
+
resolve(JSON.parse(data).sceneUrl || null);
|
|
317
186
|
} catch (e) {
|
|
318
187
|
resolve(null);
|
|
319
188
|
}
|
|
320
189
|
});
|
|
321
190
|
});
|
|
322
|
-
|
|
323
191
|
req.on('error', () => resolve(null));
|
|
324
|
-
req.setTimeout(3000, () => {
|
|
325
|
-
req.destroy();
|
|
326
|
-
resolve(null);
|
|
327
|
-
});
|
|
192
|
+
req.setTimeout(3000, () => { req.destroy(); resolve(null); });
|
|
328
193
|
req.end();
|
|
329
194
|
});
|
|
330
195
|
};
|
|
331
196
|
|
|
332
|
-
// 发送刷新请求
|
|
333
197
|
const sendRefreshRequest = (sceneUrl) => {
|
|
334
198
|
const postData = sceneUrl ? JSON.stringify({ sceneUrl }) : '';
|
|
335
|
-
|
|
336
|
-
const options = {
|
|
199
|
+
const req = http.request({
|
|
337
200
|
hostname: 'localhost',
|
|
338
201
|
port: 7455,
|
|
339
202
|
path: '/refresh',
|
|
@@ -342,80 +205,46 @@ function refreshEditor(scenePath) {
|
|
|
342
205
|
'Content-Type': 'application/json',
|
|
343
206
|
'Content-Length': Buffer.byteLength(postData)
|
|
344
207
|
}
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
// 忽略响应
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
req.on('error', () => {
|
|
352
|
-
// 插件未启动,静默处理
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
if (postData) {
|
|
356
|
-
req.write(postData);
|
|
357
|
-
}
|
|
208
|
+
}, () => {});
|
|
209
|
+
req.on('error', () => {});
|
|
210
|
+
if (postData) req.write(postData);
|
|
358
211
|
req.end();
|
|
359
212
|
};
|
|
360
213
|
|
|
361
|
-
// 执行刷新逻辑
|
|
362
214
|
getCurrentScene().then(currentSceneUrl => {
|
|
363
|
-
|
|
364
|
-
// 是当前打开的场景,重新打开
|
|
365
|
-
sendRefreshRequest(targetSceneUrl);
|
|
366
|
-
} else {
|
|
367
|
-
// 不是当前场景,只刷新资源
|
|
368
|
-
sendRefreshRequest(null);
|
|
369
|
-
}
|
|
215
|
+
sendRefreshRequest(currentSceneUrl === targetSceneUrl ? targetSceneUrl : null);
|
|
370
216
|
});
|
|
371
217
|
}
|
|
372
218
|
|
|
373
219
|
/**
|
|
374
|
-
*
|
|
375
|
-
* @param {string} scenePath - 场景文件路径
|
|
376
|
-
* @returns {boolean} - 是否已安装
|
|
220
|
+
* 安装 CLI Helper 插件
|
|
377
221
|
*/
|
|
378
222
|
function installPlugin(scenePath) {
|
|
379
223
|
try {
|
|
380
|
-
const fs = require('fs');
|
|
381
|
-
const path = require('path');
|
|
382
|
-
|
|
383
|
-
// 获取项目路径
|
|
384
224
|
const assetsPath = path.dirname(scenePath);
|
|
385
225
|
const projectPath = path.dirname(assetsPath);
|
|
386
226
|
const packagesPath = path.join(projectPath, 'packages');
|
|
387
|
-
const pluginPath = path.join(packagesPath, '
|
|
227
|
+
const pluginPath = path.join(packagesPath, 'cocos2d-cli-helper');
|
|
388
228
|
|
|
389
|
-
|
|
390
|
-
if (fs.existsSync(pluginPath)) {
|
|
391
|
-
return true;
|
|
392
|
-
}
|
|
229
|
+
if (fs.existsSync(pluginPath)) return true;
|
|
393
230
|
|
|
394
|
-
// 创建 packages 目录
|
|
395
231
|
if (!fs.existsSync(packagesPath)) {
|
|
396
232
|
fs.mkdirSync(packagesPath, { recursive: true });
|
|
397
233
|
}
|
|
398
234
|
|
|
399
|
-
|
|
400
|
-
const cliPluginPath = path.join(__dirname, '..', '..', 'editor-plugin', 'cocos-cli-helper');
|
|
235
|
+
const cliPluginPath = path.join(__dirname, '..', '..', 'editor-plugin', 'cocos2d-cli-helper');
|
|
401
236
|
|
|
402
|
-
if (!fs.existsSync(cliPluginPath))
|
|
403
|
-
console.log('[CLI] 插件源文件不存在');
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
237
|
+
if (!fs.existsSync(cliPluginPath)) return false;
|
|
406
238
|
|
|
407
|
-
// 复制插件
|
|
408
239
|
fs.cpSync(cliPluginPath, pluginPath, { recursive: true });
|
|
409
|
-
console.log('[CLI] CLI Helper 插件已安装到项目,请在编辑器中启用');
|
|
410
240
|
return true;
|
|
411
241
|
} catch (e) {
|
|
412
|
-
console.log(`[CLI] 安装插件失败: ${e.message}`);
|
|
413
242
|
return false;
|
|
414
243
|
}
|
|
415
244
|
}
|
|
416
245
|
|
|
417
246
|
/**
|
|
418
|
-
*
|
|
247
|
+
* 加载脚本映射
|
|
419
248
|
*/
|
|
420
249
|
function loadScriptMap(scenePath) {
|
|
421
250
|
const projectPath = path.dirname(path.dirname(scenePath));
|
|
@@ -428,62 +257,6 @@ function loadScriptMap(scenePath) {
|
|
|
428
257
|
return {};
|
|
429
258
|
}
|
|
430
259
|
|
|
431
|
-
/**
|
|
432
|
-
* 构建节点树输出(自动适配场景和预制体)
|
|
433
|
-
*/
|
|
434
|
-
function buildTree(data, scriptMap, nodeIndex, prefix = '', isLast = true, isRoot = true) {
|
|
435
|
-
const node = data[nodeIndex];
|
|
436
|
-
if (!node) return '';
|
|
437
|
-
|
|
438
|
-
// 跳过 Scene 类型(场景根节点)
|
|
439
|
-
const isSceneRoot = node.__type__ === 'cc.Scene';
|
|
440
|
-
const nodeName = isRoot ? 'Root' : (node._name || '(unnamed)');
|
|
441
|
-
const active = node._active !== false ? '●' : '○';
|
|
442
|
-
const uuidRegex = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
|
|
443
|
-
|
|
444
|
-
let result = '';
|
|
445
|
-
|
|
446
|
-
// 场景根节点特殊处理
|
|
447
|
-
if (isSceneRoot) {
|
|
448
|
-
result = prefix + '[Scene]\n';
|
|
449
|
-
} else {
|
|
450
|
-
result = prefix + (isRoot ? '' : active + ' ') + nodeName + ' #' + nodeIndex;
|
|
451
|
-
|
|
452
|
-
// 添加组件信息
|
|
453
|
-
if (node._components && node._components.length > 0) {
|
|
454
|
-
const comps = node._components.map(c => {
|
|
455
|
-
const comp = data[c.__id__];
|
|
456
|
-
if (!comp) return `? #${c.__id__}`;
|
|
457
|
-
const typeName = comp.__type__;
|
|
458
|
-
let displayName;
|
|
459
|
-
if (uuidRegex.test(typeName)) {
|
|
460
|
-
const scriptInfo = scriptMap[typeName];
|
|
461
|
-
displayName = (scriptInfo && scriptInfo.name) ? scriptInfo.name : '[MissingScript]';
|
|
462
|
-
} else if (typeName === 'MissingScript') {
|
|
463
|
-
displayName = '[MissingScript]';
|
|
464
|
-
} else {
|
|
465
|
-
displayName = typeName.replace('cc.', '');
|
|
466
|
-
}
|
|
467
|
-
return `${displayName} #${c.__id__}`;
|
|
468
|
-
}).join(', ');
|
|
469
|
-
result += ` (${comps})`;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
result += '\n';
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// 处理子节点
|
|
476
|
-
if (node._children && node._children.length > 0) {
|
|
477
|
-
node._children.forEach((childRef, idx) => {
|
|
478
|
-
const childIsLast = idx === node._children.length - 1;
|
|
479
|
-
const childPrefix = prefix + (isSceneRoot ? '' : (isRoot ? '' : (isLast ? ' ' : '│ ')));
|
|
480
|
-
result += buildTree(data, scriptMap, childRef.__id__, childPrefix, childIsLast, isSceneRoot);
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return result;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
260
|
/**
|
|
488
261
|
* 生成 fileId(用于 PrefabInfo)
|
|
489
262
|
*/
|
|
@@ -496,139 +269,32 @@ function generateFileId() {
|
|
|
496
269
|
return result;
|
|
497
270
|
}
|
|
498
271
|
|
|
499
|
-
/**
|
|
500
|
-
* 创建新预制体
|
|
501
|
-
* @param {string} name - 预制体名称
|
|
502
|
-
* @returns {Array} - 预制体数据
|
|
503
|
-
*
|
|
504
|
-
* 预制体结构说明:
|
|
505
|
-
* [0] cc.Prefab - 预制体元数据
|
|
506
|
-
* [1] cc.Node - 根节点,_prefab 指向最后一个 PrefabInfo
|
|
507
|
-
* [2] cc.PrefabInfo - 根节点的 PrefabInfo(在最后)
|
|
508
|
-
*
|
|
509
|
-
* 当添加子节点时,结构变为:
|
|
510
|
-
* [0] cc.Prefab
|
|
511
|
-
* [1] cc.Node (根) _prefab -> [N]
|
|
512
|
-
* [2] cc.Node (子1) _prefab -> [3]
|
|
513
|
-
* [3] cc.PrefabInfo (子1的)
|
|
514
|
-
* ...
|
|
515
|
-
* [N] cc.PrefabInfo (根节点的,在最后)
|
|
516
|
-
*/
|
|
517
|
-
function createPrefab(name) {
|
|
518
|
-
const fileId = generateFileId();
|
|
519
|
-
return [
|
|
520
|
-
{
|
|
521
|
-
"__type__": "cc.Prefab",
|
|
522
|
-
"_name": "",
|
|
523
|
-
"_objFlags": 0,
|
|
524
|
-
"_native": "",
|
|
525
|
-
"data": { "__id__": 1 },
|
|
526
|
-
"optimizationPolicy": 0,
|
|
527
|
-
"asyncLoadAssets": false,
|
|
528
|
-
"readonly": false
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
"__type__": "cc.Node",
|
|
532
|
-
"_name": name,
|
|
533
|
-
"_objFlags": 0,
|
|
534
|
-
"_parent": null,
|
|
535
|
-
"_children": [],
|
|
536
|
-
"_active": true,
|
|
537
|
-
"_components": [],
|
|
538
|
-
"_prefab": { "__id__": 2 }, // 指向最后的 PrefabInfo
|
|
539
|
-
"_opacity": 255,
|
|
540
|
-
"_color": { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 },
|
|
541
|
-
"_contentSize": { "__type__": "cc.Size", "width": 0, "height": 0 },
|
|
542
|
-
"_anchorPoint": { "__type__": "cc.Vec2", "x": 0.5, "y": 0.5 },
|
|
543
|
-
"_trs": { "__type__": "TypedArray", "ctor": "Float64Array", "array": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] },
|
|
544
|
-
"_eulerAngles": { "__type__": "cc.Vec3", "x": 0, "y": 0, "z": 0 },
|
|
545
|
-
"_skewX": 0,
|
|
546
|
-
"_skewY": 0,
|
|
547
|
-
"_is3DNode": false,
|
|
548
|
-
"_groupIndex": 0,
|
|
549
|
-
"groupIndex": 0,
|
|
550
|
-
"_id": ""
|
|
551
|
-
},
|
|
552
|
-
{
|
|
553
|
-
"__type__": "cc.PrefabInfo",
|
|
554
|
-
"root": { "__id__": 1 },
|
|
555
|
-
"asset": { "__id__": 0 },
|
|
556
|
-
"fileId": fileId,
|
|
557
|
-
"sync": false
|
|
558
|
-
}
|
|
559
|
-
];
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* 创建预制体节点数据(带 PrefabInfo)
|
|
564
|
-
* @param {string} name - 节点名称
|
|
565
|
-
* @param {number} parentId - 父节点索引
|
|
566
|
-
* @param {number} rootId - 预制体根节点索引
|
|
567
|
-
* @param {object} options - 可选参数
|
|
568
|
-
*/
|
|
569
|
-
function createPrefabNodeData(name, parentId, rootId, options = {}) {
|
|
570
|
-
const fileId = generateFileId();
|
|
571
|
-
const nodeIndex = -1; // 占位,插入时确定
|
|
572
|
-
const prefabInfoIndex = nodeIndex + 1; // PrefabInfo 紧跟节点
|
|
573
|
-
|
|
574
|
-
const nodeData = {
|
|
575
|
-
"__type__": "cc.Node",
|
|
576
|
-
"_name": name,
|
|
577
|
-
"_objFlags": 0,
|
|
578
|
-
"_parent": { "__id__": parentId },
|
|
579
|
-
"_children": [],
|
|
580
|
-
"_active": options.active !== false,
|
|
581
|
-
"_components": [],
|
|
582
|
-
"_prefab": { "__id__": prefabInfoIndex },
|
|
583
|
-
"_opacity": 255,
|
|
584
|
-
"_color": { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 },
|
|
585
|
-
"_contentSize": { "__type__": "cc.Size", "width": options.width || 0, "height": options.height || 0 },
|
|
586
|
-
"_anchorPoint": { "__type__": "cc.Vec2", "x": 0.5, "y": 0.5 },
|
|
587
|
-
"_trs": { "__type__": "TypedArray", "ctor": "Float64Array", "array": [options.x || 0, options.y || 0, 0, 0, 0, 0, 1, 1, 1, 1] },
|
|
588
|
-
"_eulerAngles": { "__type__": "cc.Vec3", "x": 0, "y": 0, "z": 0 },
|
|
589
|
-
"_skewX": 0,
|
|
590
|
-
"_skewY": 0,
|
|
591
|
-
"_is3DNode": false,
|
|
592
|
-
"_groupIndex": 0,
|
|
593
|
-
"groupIndex": 0,
|
|
594
|
-
"_id": ""
|
|
595
|
-
};
|
|
596
|
-
|
|
597
|
-
const prefabInfo = {
|
|
598
|
-
"__type__": "cc.PrefabInfo",
|
|
599
|
-
"root": { "__id__": rootId },
|
|
600
|
-
"asset": { "__id__": 0 },
|
|
601
|
-
"fileId": fileId,
|
|
602
|
-
"sync": false
|
|
603
|
-
};
|
|
604
|
-
|
|
605
|
-
return { nodeData, prefabInfo };
|
|
606
|
-
}
|
|
607
|
-
|
|
608
272
|
/**
|
|
609
273
|
* 获取预制体根节点索引
|
|
610
274
|
*/
|
|
611
275
|
function getPrefabRootIndex(data) {
|
|
612
276
|
if (!isPrefab(data)) return null;
|
|
613
|
-
return 1;
|
|
277
|
+
return 1;
|
|
614
278
|
}
|
|
615
279
|
|
|
616
280
|
module.exports = {
|
|
281
|
+
// 文件操作
|
|
617
282
|
loadScene,
|
|
618
283
|
saveScene,
|
|
284
|
+
isPrefab,
|
|
285
|
+
|
|
286
|
+
// 索引映射
|
|
619
287
|
buildMaps,
|
|
620
288
|
findNodeIndex,
|
|
621
|
-
collectNodeAndChildren,
|
|
622
289
|
rebuildReferences,
|
|
623
|
-
|
|
290
|
+
|
|
291
|
+
// 编辑器交互
|
|
624
292
|
refreshEditor,
|
|
625
293
|
installPlugin,
|
|
626
294
|
checkPluginStatus,
|
|
295
|
+
|
|
296
|
+
// 工具函数
|
|
627
297
|
loadScriptMap,
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
createPrefabNodeData,
|
|
632
|
-
getPrefabRootIndex,
|
|
633
|
-
generateFileId
|
|
634
|
-
};
|
|
298
|
+
generateFileId,
|
|
299
|
+
getPrefabRootIndex
|
|
300
|
+
};
|