cocos2d-cli 1.6.4 → 2.0.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/data/script_map.json +25 -25
- package/dist/bin/cocos2d-cli.js +64 -0
- package/dist/src/commands/add-component.js +3 -0
- package/dist/src/commands/add.js +3 -0
- package/dist/src/commands/build.js +6 -0
- package/dist/src/commands/create-scene.js +3 -0
- package/dist/src/commands/get.js +3 -0
- package/dist/src/commands/prefab-create.js +109 -0
- package/dist/src/commands/remove-component.js +3 -0
- package/dist/src/commands/remove.js +3 -0
- package/dist/src/commands/screenshot.js +41 -0
- package/dist/src/commands/set-component.js +3 -0
- package/dist/src/commands/set.js +3 -0
- package/dist/src/commands/tree.js +24 -0
- package/{src → dist/src}/lib/cc/CCButton.js +26 -33
- package/{src → dist/src}/lib/cc/CCCamera.js +20 -30
- package/{src → dist/src}/lib/cc/CCCanvas.js +10 -15
- package/{src → dist/src}/lib/cc/CCColor.js +6 -8
- package/{src → dist/src}/lib/cc/CCComponent.js +8 -29
- package/{src → dist/src}/lib/cc/CCLabel.js +44 -51
- package/{src → dist/src}/lib/cc/CCNode.js +52 -118
- package/{src → dist/src}/lib/cc/CCObject.js +4 -8
- package/{src → dist/src}/lib/cc/CCPrefab.js +77 -100
- package/{src → dist/src}/lib/cc/CCRect.js +6 -8
- package/{src → dist/src}/lib/cc/CCRichText.js +10 -16
- package/{src → dist/src}/lib/cc/CCScene.js +3 -13
- package/dist/src/lib/cc/CCSceneAsset.js +242 -0
- package/{src → dist/src}/lib/cc/CCSize.js +4 -8
- package/{src → dist/src}/lib/cc/CCSprite.js +21 -33
- package/{src → dist/src}/lib/cc/CCTrs.js +4 -29
- package/{src → dist/src}/lib/cc/CCVec2.js +4 -8
- package/{src → dist/src}/lib/cc/CCVec3.js +5 -8
- package/{src → dist/src}/lib/cc/CCWidget.js +20 -24
- package/dist/src/lib/fire-utils.js +86 -0
- package/dist/src/lib/json-parser.js +114 -0
- package/dist/src/lib/node-utils.js +131 -0
- package/{src → dist/src}/lib/screenshot-core.js +54 -119
- package/dist/src/lib/templates.js +17 -0
- package/dist/src/lib/utils.js +81 -0
- package/package.json +40 -33
- package/bin/cocos2d-cli.js +0 -152
- package/src/commands/add-component.js +0 -112
- package/src/commands/add.js +0 -177
- package/src/commands/build.js +0 -78
- package/src/commands/create-scene.js +0 -181
- package/src/commands/get.js +0 -108
- package/src/commands/prefab-create.js +0 -111
- package/src/commands/remove-component.js +0 -111
- package/src/commands/remove.js +0 -99
- package/src/commands/screenshot.js +0 -108
- package/src/commands/set-component.js +0 -119
- package/src/commands/set.js +0 -107
- package/src/commands/tree.js +0 -29
- package/src/lib/cc/CCSceneAsset.js +0 -303
- package/src/lib/cc/index.js +0 -42
- package/src/lib/fire-utils.js +0 -374
- package/src/lib/json-parser.js +0 -185
- package/src/lib/node-utils.js +0 -395
- package/src/lib/screenshot/favicon.ico +0 -0
- package/src/lib/screenshot/index.html +0 -30
- package/src/lib/templates.js +0 -49
- package/src/lib/utils.js +0 -202
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const fs = require('fs').promises;
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const http = require('http');
|
|
10
|
-
const url = require('url');
|
|
11
|
-
const os = require('os');
|
|
12
|
-
|
|
13
|
-
// 默认配置
|
|
1
|
+
import { chromium } from 'playwright';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as http from 'http';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
7
|
const DEFAULT_CONFIG = {
|
|
15
|
-
jsonPath: null,
|
|
16
8
|
outputDir: process.cwd(),
|
|
17
9
|
viewport: { width: 750, height: 1334 },
|
|
18
10
|
fullPage: true,
|
|
@@ -20,32 +12,27 @@ const DEFAULT_CONFIG = {
|
|
|
20
12
|
timeout: 30000,
|
|
21
13
|
waitTime: 1000
|
|
22
14
|
};
|
|
23
|
-
|
|
24
|
-
// 获取内置资源目录
|
|
25
15
|
function getAssetsDir() {
|
|
26
|
-
|
|
16
|
+
const projectRoot = process.cwd();
|
|
17
|
+
return path.join(projectRoot, 'src', 'lib', 'screenshot');
|
|
27
18
|
}
|
|
28
|
-
|
|
29
|
-
// 创建临时工作目录
|
|
30
19
|
async function createTempWorkDir() {
|
|
31
|
-
const tempBase =
|
|
20
|
+
const tempBase = process.env.TEMP || process.env.TMP || '/tmp';
|
|
32
21
|
const timestamp = Date.now();
|
|
33
22
|
const tempDir = path.join(tempBase, `cocos2d-screenshot-${timestamp}`);
|
|
34
23
|
await fs.mkdir(tempDir, { recursive: true });
|
|
35
24
|
return tempDir;
|
|
36
25
|
}
|
|
37
|
-
|
|
38
|
-
// 复制内置资源到临时目录
|
|
39
26
|
async function copyBuiltInAssets(tempDir, logs) {
|
|
40
27
|
const assetsDir = getAssetsDir();
|
|
41
28
|
const assets = ['index.html', 'favicon.ico'];
|
|
42
|
-
|
|
43
29
|
for (const asset of assets) {
|
|
44
30
|
const src = path.join(assetsDir, asset);
|
|
45
31
|
const dest = path.join(tempDir, asset);
|
|
46
32
|
try {
|
|
47
33
|
await fs.copyFile(src, dest);
|
|
48
|
-
}
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
49
36
|
logs.push({
|
|
50
37
|
timestamp: new Date().toISOString(),
|
|
51
38
|
type: 'warning',
|
|
@@ -54,21 +41,16 @@ async function copyBuiltInAssets(tempDir, logs) {
|
|
|
54
41
|
}
|
|
55
42
|
}
|
|
56
43
|
}
|
|
57
|
-
|
|
58
|
-
// 静态文件服务器
|
|
59
44
|
async function startServer(staticDir, logs) {
|
|
60
45
|
return new Promise((resolve, reject) => {
|
|
61
46
|
const server = http.createServer(async (req, res) => {
|
|
62
47
|
try {
|
|
63
|
-
const
|
|
64
|
-
let filePath = path.join(staticDir,
|
|
65
|
-
|
|
66
|
-
if (parsedUrl.pathname === '/') {
|
|
48
|
+
const reqUrl = new URL(req.url || '/', `http://${req.headers.host}`);
|
|
49
|
+
let filePath = path.join(staticDir, reqUrl.pathname);
|
|
50
|
+
if (reqUrl.pathname === '/') {
|
|
67
51
|
filePath = path.join(staticDir, 'index.html');
|
|
68
52
|
}
|
|
69
|
-
|
|
70
53
|
const data = await fs.readFile(filePath);
|
|
71
|
-
|
|
72
54
|
const ext = path.extname(filePath).toLowerCase();
|
|
73
55
|
const contentTypes = {
|
|
74
56
|
'.html': 'text/html',
|
|
@@ -86,18 +68,18 @@ async function startServer(staticDir, logs) {
|
|
|
86
68
|
'.txt': 'text/plain',
|
|
87
69
|
'.xml': 'application/xml'
|
|
88
70
|
};
|
|
89
|
-
|
|
90
|
-
res.writeHead(200, {
|
|
71
|
+
res.writeHead(200, {
|
|
91
72
|
'Content-Type': contentTypes[ext] || 'application/octet-stream',
|
|
92
73
|
'Access-Control-Allow-Origin': '*'
|
|
93
74
|
});
|
|
94
75
|
res.end(data);
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
97
78
|
if (err.code === 'ENOENT') {
|
|
98
79
|
res.writeHead(404);
|
|
99
80
|
res.end();
|
|
100
|
-
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
101
83
|
logs.push({
|
|
102
84
|
timestamp: new Date().toISOString(),
|
|
103
85
|
type: 'server-error',
|
|
@@ -108,16 +90,14 @@ async function startServer(staticDir, logs) {
|
|
|
108
90
|
}
|
|
109
91
|
}
|
|
110
92
|
});
|
|
111
|
-
|
|
112
93
|
server.listen(0, '127.0.0.1', () => resolve(server));
|
|
113
94
|
});
|
|
114
95
|
}
|
|
115
|
-
|
|
116
|
-
// 递归删除目录
|
|
117
96
|
async function removeDir(dirPath, logs) {
|
|
118
97
|
try {
|
|
119
98
|
await fs.rm(dirPath, { recursive: true, force: true });
|
|
120
|
-
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
121
101
|
if (logs) {
|
|
122
102
|
logs.push({
|
|
123
103
|
timestamp: new Date().toISOString(),
|
|
@@ -127,32 +107,17 @@ async function removeDir(dirPath, logs) {
|
|
|
127
107
|
}
|
|
128
108
|
}
|
|
129
109
|
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* 截图核心函数
|
|
133
|
-
* @param {Object} userConfig - 配置选项
|
|
134
|
-
* @param {string} userConfig.jsonPath - JSON 文件路径
|
|
135
|
-
* @param {string} userConfig.outputDir - 输出目录
|
|
136
|
-
* @param {Object} userConfig.viewport - 视口大小 {width, height}
|
|
137
|
-
* @param {boolean} userConfig.fullPage - 是否全页截图
|
|
138
|
-
* @param {number} userConfig.timeout - 超时时间(毫秒)
|
|
139
|
-
* @param {number} userConfig.waitTime - 等待时间(毫秒)
|
|
140
|
-
* @returns {Promise<{screenshotPath: string, logs: Array}>}
|
|
141
|
-
*/
|
|
142
|
-
async function takeScreenshot(userConfig = {}) {
|
|
110
|
+
export async function takeScreenshot(userConfig = {}) {
|
|
143
111
|
const config = { ...DEFAULT_CONFIG, ...userConfig };
|
|
144
|
-
|
|
145
112
|
if (!config.jsonPath) {
|
|
146
113
|
throw new Error('JSON file path is required');
|
|
147
114
|
}
|
|
148
|
-
|
|
149
115
|
let server = null;
|
|
150
116
|
let browser = null;
|
|
151
117
|
let tempDir = null;
|
|
152
118
|
const logs = [];
|
|
153
119
|
let screenshotPath = null;
|
|
154
120
|
let logDir = null;
|
|
155
|
-
|
|
156
121
|
const addLog = (type, text, extra = {}) => {
|
|
157
122
|
logs.push({
|
|
158
123
|
timestamp: new Date().toISOString(),
|
|
@@ -161,70 +126,47 @@ async function takeScreenshot(userConfig = {}) {
|
|
|
161
126
|
...extra
|
|
162
127
|
});
|
|
163
128
|
};
|
|
164
|
-
|
|
165
129
|
try {
|
|
166
130
|
const timestamp = Date.now();
|
|
167
|
-
|
|
168
|
-
// 检查 JSON 文件是否存在
|
|
169
131
|
try {
|
|
170
132
|
await fs.access(config.jsonPath);
|
|
171
|
-
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
172
135
|
throw new Error(`JSON file not found: ${config.jsonPath}`);
|
|
173
136
|
}
|
|
174
|
-
|
|
175
|
-
// 确保输出目录存在
|
|
176
137
|
await fs.mkdir(config.outputDir, { recursive: true });
|
|
177
|
-
|
|
178
|
-
// 创建临时工作目录
|
|
179
138
|
tempDir = await createTempWorkDir();
|
|
180
139
|
addLog('info', `Temp dir: ${tempDir}`);
|
|
181
|
-
|
|
182
|
-
// 复制内置资源到临时目录
|
|
183
140
|
await copyBuiltInAssets(tempDir, logs);
|
|
184
|
-
|
|
185
|
-
// 复制用户的 JSON 文件到临时目录
|
|
186
141
|
const destJsonPath = path.join(tempDir, 'data.json');
|
|
187
142
|
await fs.copyFile(config.jsonPath, destJsonPath);
|
|
188
143
|
addLog('info', `JSON: ${config.jsonPath}`);
|
|
189
|
-
|
|
190
|
-
// 截图输出路径
|
|
191
144
|
screenshotPath = path.join(config.outputDir, `screenshot-${timestamp}.png`);
|
|
192
|
-
|
|
193
|
-
// 启动HTTP服务器
|
|
194
145
|
addLog('info', 'Starting Server');
|
|
195
146
|
server = await startServer(tempDir, logs);
|
|
196
|
-
const
|
|
147
|
+
const address = server.address();
|
|
148
|
+
const serverUrl = `http://127.0.0.1:${address.port}`;
|
|
197
149
|
addLog('info', `Server: ${serverUrl}`);
|
|
198
|
-
|
|
199
|
-
// 启动浏览器
|
|
200
150
|
addLog('info', 'Launching Browser');
|
|
201
151
|
browser = await chromium.launch({
|
|
202
|
-
headless: true
|
|
203
|
-
channel: 'chrome'
|
|
152
|
+
headless: true
|
|
204
153
|
});
|
|
205
154
|
addLog('info', 'Browser launched');
|
|
206
|
-
|
|
207
155
|
const page = await browser.newPage({
|
|
208
156
|
viewport: config.viewport
|
|
209
157
|
});
|
|
210
|
-
|
|
211
|
-
// 监听浏览器控制台日志
|
|
212
|
-
page.on('console', msg => {
|
|
158
|
+
page.on('console', (msg) => {
|
|
213
159
|
const text = msg.text();
|
|
214
160
|
addLog(msg.type(), text);
|
|
215
161
|
});
|
|
216
|
-
|
|
217
|
-
page.on('pageerror', error => {
|
|
162
|
+
page.on('pageerror', (error) => {
|
|
218
163
|
addLog('pageerror', error.message);
|
|
219
164
|
});
|
|
220
|
-
|
|
221
|
-
page.on('requestfailed', request => {
|
|
165
|
+
page.on('requestfailed', (request) => {
|
|
222
166
|
const failure = request.failure();
|
|
223
167
|
const errorText = failure ? failure.errorText : 'Unknown error';
|
|
224
168
|
addLog('requestfailed', request.url(), { error: errorText });
|
|
225
169
|
});
|
|
226
|
-
|
|
227
|
-
// 加载页面
|
|
228
170
|
addLog('info', 'Loading Page');
|
|
229
171
|
const pageUrl = config.debugBounds
|
|
230
172
|
? `${serverUrl}/index.html?debugBounds=true`
|
|
@@ -234,13 +176,9 @@ async function takeScreenshot(userConfig = {}) {
|
|
|
234
176
|
timeout: config.timeout
|
|
235
177
|
});
|
|
236
178
|
addLog('info', 'Page loaded');
|
|
237
|
-
|
|
238
|
-
// 等待渲染
|
|
239
179
|
addLog('info', 'Waiting for Render');
|
|
240
180
|
await page.waitForTimeout(config.waitTime);
|
|
241
181
|
addLog('info', 'Wait complete');
|
|
242
|
-
|
|
243
|
-
// 截图
|
|
244
182
|
addLog('info', 'Taking Screenshot');
|
|
245
183
|
await page.screenshot({
|
|
246
184
|
path: screenshotPath,
|
|
@@ -248,39 +186,36 @@ async function takeScreenshot(userConfig = {}) {
|
|
|
248
186
|
});
|
|
249
187
|
addLog('info', `Screenshot saved: ${screenshotPath}`);
|
|
250
188
|
addLog('info', 'Done');
|
|
251
|
-
|
|
252
189
|
return { screenshotPath, logs };
|
|
253
|
-
|
|
254
|
-
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
255
192
|
addLog('error', error.message);
|
|
256
193
|
try {
|
|
257
194
|
logDir = path.join(config.outputDir, `screenshot-logs-${Date.now()}`);
|
|
258
195
|
await fs.mkdir(logDir, { recursive: true });
|
|
259
|
-
await fs.writeFile(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
'utf8'
|
|
274
|
-
);
|
|
275
|
-
} catch (_) {}
|
|
196
|
+
await fs.writeFile(path.join(logDir, 'logs.json'), JSON.stringify({
|
|
197
|
+
error: error.message,
|
|
198
|
+
jsonPath: config.jsonPath,
|
|
199
|
+
outputDir: config.outputDir,
|
|
200
|
+
viewport: config.viewport,
|
|
201
|
+
fullPage: config.fullPage,
|
|
202
|
+
debugBounds: config.debugBounds,
|
|
203
|
+
timeout: config.timeout,
|
|
204
|
+
waitTime: config.waitTime,
|
|
205
|
+
screenshotPath,
|
|
206
|
+
logs
|
|
207
|
+
}, null, 2), 'utf8');
|
|
208
|
+
}
|
|
209
|
+
catch (_) { }
|
|
276
210
|
error.logDir = logDir;
|
|
277
211
|
throw error;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (browser)
|
|
281
|
-
|
|
282
|
-
if (
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
if (browser)
|
|
215
|
+
await browser.close().catch(() => { });
|
|
216
|
+
if (server)
|
|
217
|
+
server.close();
|
|
218
|
+
if (tempDir)
|
|
219
|
+
await removeDir(tempDir, logs);
|
|
283
220
|
}
|
|
284
221
|
}
|
|
285
|
-
|
|
286
|
-
module.exports = { takeScreenshot };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import CCNode from './cc/CCNode.js';
|
|
2
|
+
import CCScene from './cc/CCScene.js';
|
|
3
|
+
import CCSceneAsset from './cc/CCSceneAsset.js';
|
|
4
|
+
import { CCPrefab, CCPrefabInfo } from './cc/CCPrefab.js';
|
|
5
|
+
export function createPrefab(name = 'Prefab') {
|
|
6
|
+
const prefab = new CCPrefab();
|
|
7
|
+
const root = new CCNode(name);
|
|
8
|
+
prefab.setRoot(root);
|
|
9
|
+
return prefab;
|
|
10
|
+
}
|
|
11
|
+
export function createScene(name = 'NewScene') {
|
|
12
|
+
const asset = new CCSceneAsset();
|
|
13
|
+
const scene = new CCScene(name);
|
|
14
|
+
asset._scene = scene;
|
|
15
|
+
return asset;
|
|
16
|
+
}
|
|
17
|
+
export { CCNode, CCScene, CCSceneAsset, CCPrefab, CCPrefabInfo };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
export function parseColor(color) {
|
|
3
|
+
if (!color)
|
|
4
|
+
return null;
|
|
5
|
+
if (color.startsWith('#')) {
|
|
6
|
+
const hex = color.slice(1);
|
|
7
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
8
|
+
return {
|
|
9
|
+
r: parseInt(hex.slice(0, 2), 16),
|
|
10
|
+
g: parseInt(hex.slice(2, 4), 16),
|
|
11
|
+
b: parseInt(hex.slice(4, 6), 16),
|
|
12
|
+
a: hex.length === 8 ? parseInt(hex.slice(6, 8), 16) : 255
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
|
17
|
+
if (rgbMatch) {
|
|
18
|
+
return {
|
|
19
|
+
r: parseInt(rgbMatch[1]),
|
|
20
|
+
g: parseInt(rgbMatch[2]),
|
|
21
|
+
b: parseInt(rgbMatch[3]),
|
|
22
|
+
a: rgbMatch[4] ? Math.round(parseFloat(rgbMatch[4]) * 255) : 255
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
export function parseColorToCcColor(color) {
|
|
28
|
+
const parsed = parseColor(color);
|
|
29
|
+
if (!parsed)
|
|
30
|
+
return null;
|
|
31
|
+
return { __type__: 'cc.Color', ...parsed };
|
|
32
|
+
}
|
|
33
|
+
export function colorToHex(r, g, b, a = 255) {
|
|
34
|
+
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}${a !== 255 ? a.toString(16).padStart(2, '0') : ''}`;
|
|
35
|
+
}
|
|
36
|
+
export function generateUUID() {
|
|
37
|
+
return crypto.randomUUID().replace(/-/g, '');
|
|
38
|
+
}
|
|
39
|
+
export function compressUUID(uuid) {
|
|
40
|
+
const hex = uuid.replace(/-/g, '');
|
|
41
|
+
const bytes = Buffer.from(hex, 'hex');
|
|
42
|
+
return bytes.toString('base64url').slice(0, 22);
|
|
43
|
+
}
|
|
44
|
+
export function generateCompressedUUID() {
|
|
45
|
+
return compressUUID(generateUUID());
|
|
46
|
+
}
|
|
47
|
+
export function generateId() {
|
|
48
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
49
|
+
let result = '';
|
|
50
|
+
for (let i = 0; i < 22; i++) {
|
|
51
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
export function parseOptions(args) {
|
|
56
|
+
const options = {};
|
|
57
|
+
for (let i = 0; i < args.length; i++) {
|
|
58
|
+
const arg = args[i];
|
|
59
|
+
if (arg.startsWith('--')) {
|
|
60
|
+
const key = arg.slice(2);
|
|
61
|
+
const nextArg = args[i + 1];
|
|
62
|
+
if (nextArg && !nextArg.startsWith('--')) {
|
|
63
|
+
options[key] = nextArg;
|
|
64
|
+
i++;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
options[key] = true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return options;
|
|
72
|
+
}
|
|
73
|
+
export function outputJson(data) {
|
|
74
|
+
console.log(JSON.stringify(data, null, 2));
|
|
75
|
+
}
|
|
76
|
+
export function outputError(message) {
|
|
77
|
+
console.log(JSON.stringify({ error: message }));
|
|
78
|
+
}
|
|
79
|
+
export function outputSuccess(message) {
|
|
80
|
+
console.log(JSON.stringify({ success: message }));
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,33 +1,40 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "cocos2d-cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Command-line tools for AI to read and manipulate Cocos Creator 2.4.x project scenes",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
"data"
|
|
13
|
-
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
}
|
|
33
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "cocos2d-cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Command-line tools for AI to read and manipulate Cocos Creator 2.4.x project scenes",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/bin/cocos2d-cli.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"cocos2d-cli": "dist/bin/cocos2d-cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"data"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"watch": "tsc --watch",
|
|
17
|
+
"prepare": "npm run build",
|
|
18
|
+
"test": "echo \"No tests specified\" && exit 1"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"cocos",
|
|
22
|
+
"cocos-creator",
|
|
23
|
+
"cli",
|
|
24
|
+
"scene",
|
|
25
|
+
"fire",
|
|
26
|
+
"screenshot"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"playwright": "^1.58.2"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.15.17",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/bin/cocos2d-cli.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Cocos Creator CLI
|
|
4
|
-
* Command-line tools for AI to read and manipulate Cocos Creator 2.4.x project scenes
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
// 命令映射
|
|
10
|
-
const commands = {
|
|
11
|
-
tree: '../src/commands/tree',
|
|
12
|
-
get: '../src/commands/get',
|
|
13
|
-
set: '../src/commands/set',
|
|
14
|
-
'set-component': '../src/commands/set-component',
|
|
15
|
-
add: '../src/commands/add',
|
|
16
|
-
'add-component': '../src/commands/add-component',
|
|
17
|
-
'remove-component': '../src/commands/remove-component',
|
|
18
|
-
'remove': '../src/commands/remove',
|
|
19
|
-
build: '../src/commands/build',
|
|
20
|
-
'create-prefab': '../src/commands/prefab-create',
|
|
21
|
-
'create-scene': '../src/commands/create-scene',
|
|
22
|
-
'screenshot': '../src/commands/screenshot'
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// 帮助信息
|
|
26
|
-
function showHelp() {
|
|
27
|
-
console.log(`
|
|
28
|
-
Cocos Creator CLI - 场景/预制体操作工具集
|
|
29
|
-
|
|
30
|
-
用法:
|
|
31
|
-
cocos2d-cli <command> [options]
|
|
32
|
-
|
|
33
|
-
命令:
|
|
34
|
-
tree <场景.fire | 预制体.prefab> 查看节点树
|
|
35
|
-
get <场景.fire | 预制体.prefab> <节点路径> [属性名|组件类型] 获取节点或组件属性
|
|
36
|
-
set <场景.fire | 预制体.prefab> <节点路径> <属性名> <值> 修改节点属性
|
|
37
|
-
set-component <文件> <节点路径> <组件类型> <属性名> <值> 修改组件属性
|
|
38
|
-
add <场景.fire | 预制体.prefab> <父节点路径> <名称> 添加节点
|
|
39
|
-
add-component <文件> <节点路径> <类型> 给节点添加组件
|
|
40
|
-
remove-component <文件> <节点路径> <类型> 删除节点组件
|
|
41
|
-
remove <文件> <节点路径> 删除节点
|
|
42
|
-
build <项目目录> 构建组件映射
|
|
43
|
-
create-prefab [JSON文件路径] <输出.prefab> 创建预制体(不传JSON则创建默认)
|
|
44
|
-
create-scene [JSON文件路径] <输出.fire> 创建场景(不传JSON则创建默认)
|
|
45
|
-
screenshot <json文件> [选项] 渲染JSON并截图
|
|
46
|
-
|
|
47
|
-
节点路径格式:
|
|
48
|
-
Canvas - 根节点下的 Canvas
|
|
49
|
-
Canvas/MidNode - Canvas 下的 MidNode
|
|
50
|
-
Canvas/GameScene/NodeA - 多层嵌套路径
|
|
51
|
-
|
|
52
|
-
set 支持的节点属性:
|
|
53
|
-
name 节点名称
|
|
54
|
-
active 激活状态 (true/false)
|
|
55
|
-
x X 坐标
|
|
56
|
-
y Y 坐标
|
|
57
|
-
width 宽度
|
|
58
|
-
height 高度
|
|
59
|
-
anchorX 锚点 X (0-1)
|
|
60
|
-
anchorY 锚点 Y (0-1)
|
|
61
|
-
opacity 透明度 (0-255)
|
|
62
|
-
scaleX X 缩放
|
|
63
|
-
scaleY Y 缩放
|
|
64
|
-
rotation 旋转角度
|
|
65
|
-
|
|
66
|
-
set-component 示例:
|
|
67
|
-
cocos2d-cli set-component xxx.fire Canvas/Label Label string "Hello"
|
|
68
|
-
cocos2d-cli set-component xxx.fire Canvas/Label Label fontSize 32
|
|
69
|
-
cocos2d-cli set-component xxx.fire Canvas/Sprite Sprite sizeMode 0
|
|
70
|
-
|
|
71
|
-
add 支持的选项:
|
|
72
|
-
--x=<数值> 设置 X 坐标
|
|
73
|
-
--y=<数值> 设置 Y 坐标
|
|
74
|
-
--width=<数值> 设置宽度
|
|
75
|
-
--height=<数值> 设置高度
|
|
76
|
-
--scaleX=<数值> 设置 X 缩放
|
|
77
|
-
--scaleY=<数值> 设置 Y 缩放
|
|
78
|
-
--rotation=<角度> 设置旋转角度
|
|
79
|
-
--active=true/false 设置激活状态
|
|
80
|
-
--type=sprite/label/button 添加节点时指定组件类型
|
|
81
|
-
--string=<文字> Label 文字内容 (配合 --type=label)
|
|
82
|
-
--fontSize=<数值> Label 字体大小 (配合 --type=label)
|
|
83
|
-
|
|
84
|
-
JSON 格式:
|
|
85
|
-
详见 SKILL.md 完整文档。简要示例:
|
|
86
|
-
{
|
|
87
|
-
"name": "Node",
|
|
88
|
-
"width": 400, "height": 300,
|
|
89
|
-
"x": 0, "y": 0,
|
|
90
|
-
"anchorX": 0, "color": "#336699",
|
|
91
|
-
"components": [
|
|
92
|
-
{ "type": "label", "string": "Hello", "horizontalAlign": "left" },
|
|
93
|
-
{ "type": "richText", "string": "<color=#3cb034>绿色</color>" }
|
|
94
|
-
],
|
|
95
|
-
"children": [...]
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
提示:配合 anchorX + horizontalAlign 实现靠左/靠右布局(见 SKILL.md)
|
|
99
|
-
|
|
100
|
-
示例:
|
|
101
|
-
cocos2d-cli tree assets/main.fire
|
|
102
|
-
cocos2d-cli get assets/main.fire Canvas/MidNode
|
|
103
|
-
cocos2d-cli get assets/main.fire Canvas/MidNode x
|
|
104
|
-
cocos2d-cli get assets/main.fire Canvas/MidNode Label
|
|
105
|
-
cocos2d-cli set assets/main.fire Canvas/MidNode x 100
|
|
106
|
-
cocos2d-cli set assets/main.fire Canvas/MidNode width 200
|
|
107
|
-
cocos2d-cli set-component assets/main.fire Canvas/Label Label string "Hello World"
|
|
108
|
-
cocos2d-cli add assets/main.fire Canvas NewSprite --type=sprite --x=100
|
|
109
|
-
cocos2d-cli add-component assets/main.fire Canvas/MidNode label
|
|
110
|
-
cocos2d-cli remove-component assets/main.fire Canvas/MidNode label
|
|
111
|
-
cocos2d-cli remove assets/main.fire Canvas/MidNode
|
|
112
|
-
|
|
113
|
-
# 从 JSON 文件创建场景
|
|
114
|
-
cocos2d-cli create-scene scene.json assets/scene.fire
|
|
115
|
-
|
|
116
|
-
# 从 JSON 文件创建预制体
|
|
117
|
-
cocos2d-cli create-prefab panel.json assets/panel.prefab
|
|
118
|
-
|
|
119
|
-
# 创建默认预制体(不传JSON)
|
|
120
|
-
cocos2d-cli create-prefab assets/NewNode.prefab
|
|
121
|
-
|
|
122
|
-
# 截图
|
|
123
|
-
cocos2d-cli screenshot data.json
|
|
124
|
-
cocos2d-cli screenshot data.json -o ./screenshots --width 1080 --height 1920
|
|
125
|
-
`);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// 解析参数
|
|
129
|
-
const args = process.argv.slice(2);
|
|
130
|
-
|
|
131
|
-
if (args.length === 0 || args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
|
|
132
|
-
showHelp();
|
|
133
|
-
process.exit(0);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const commandName = args[0];
|
|
137
|
-
const commandPath = commands[commandName];
|
|
138
|
-
|
|
139
|
-
if (!commandPath) {
|
|
140
|
-
console.error(`未知命令: ${commandName}`);
|
|
141
|
-
console.error('运行 cocos2d-cli --help 查看可用命令');
|
|
142
|
-
process.exit(1);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// 加载并执行命令
|
|
146
|
-
try {
|
|
147
|
-
const command = require(commandPath);
|
|
148
|
-
command.run(args.slice(1));
|
|
149
|
-
} catch (err) {
|
|
150
|
-
console.error(`命令执行失败: ${err.message}`);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|