├── .gitignore
├── @types
├── editor.d.ts
├── electron.d.ts
├── extension.d.ts
├── index.d.ts
├── message.d.ts
└── packages
│ ├── asset-db
│ └── @types
│ │ ├── message.d.ts
│ │ └── public.d.ts
│ ├── builder
│ └── @types
│ │ ├── index.d.ts
│ │ ├── protect
│ │ ├── asset-manager.d.ts
│ │ ├── build-plugin.d.ts
│ │ ├── build-result.d.ts
│ │ ├── global.d.ts
│ │ ├── import-map.d.ts
│ │ ├── index.d.ts
│ │ └── options.d.ts
│ │ └── public
│ │ ├── build-plugin.d.ts
│ │ ├── build-result.d.ts
│ │ ├── global.d.ts
│ │ ├── index.d.ts
│ │ ├── message.d.ts
│ │ ├── options.d.ts
│ │ └── texture-compress.d.ts
│ ├── console
│ └── @types
│ │ └── pritate.d.ts
│ ├── engine
│ └── @types
│ │ └── message.d.ts
│ ├── preview
│ └── @types
│ │ ├── index.d.ts
│ │ └── protect
│ │ └── index.d.ts
│ ├── programming
│ └── @types
│ │ └── message.d.ts
│ ├── scene
│ └── @types
│ │ ├── message.d.ts
│ │ └── public.d.ts
│ ├── server
│ └── @types
│ │ └── package.d.ts
│ └── shortcuts
│ └── @types
│ └── shortcut.d.ts
├── README.md
├── cocos-install.sh
├── cocos-pack.sh
├── i18n
├── en.js
└── zh.js
├── images
└── builder_setting.png
├── package-lock.json
├── package.json
├── src
├── browser.ts
├── builder.ts
└── hooks.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | dist/
3 | node_modules/
4 | .DS_Store
5 | ehthumbs.db
6 | Thumbs.db
7 |
--------------------------------------------------------------------------------
/@types/editor.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | ///
4 | ///
5 |
6 | import * as NodeJSPath from 'path';
7 | import { EventEmitter } from 'events';
8 | import { FileFilter, BrowserWindow, OpenDialogReturnValue, SaveDialogReturnValue, MessageBoxReturnValue } from 'electron';
9 |
10 | declare global {
11 | export module Editor {
12 | export module App {
13 | export const userAgent: string;
14 | /**
15 | * 是否是开发模式
16 | * Development mode
17 | */
18 | export const dev: boolean;
19 | /**
20 | * 编辑器版本号
21 | * Editor version
22 | */
23 | export const version: string;
24 | /**
25 | * 主目录
26 | * Home directory
27 | */
28 | export const home: string;
29 | /**
30 | * 编辑器程序文件夹
31 | * Program folder
32 | */
33 | export const path: string;
34 | /**
35 | * 获取当前编辑器的临时缓存目录
36 | * Temporary cache directory
37 | */
38 | export const temp: string;
39 | /**
40 | * 获取当前编辑器 icon 地址
41 | * Gets the icon address of the current editor
42 | */
43 | export const icon: string;
44 | /**
45 | * 获取当前编辑器使用的 url 地址
46 | * Gets the URL used by the current editor
47 | */
48 | export const urls: {
49 | manual: string;
50 | api: string;
51 | forum: string;
52 | };
53 | /**
54 | * 退出程序
55 | * Exit the program
56 | */
57 | export function quit(): void;
58 | }
59 | export module Clipboard {
60 | export type ICopyType = 'image' | 'text' | 'files' | string;
61 | /**
62 | * 获取剪贴板内容
63 | * @param type
64 | */
65 | export function read(type: ICopyType): any;
66 | /**
67 | * 写入剪贴板内容
68 | * @param type
69 | * @param value
70 | */
71 | export function write(type: 'image', value: string): boolean;
72 | export function write(type: 'text', value: string): boolean;
73 | export function write(type: 'files', value: FileList): boolean;
74 | export function write(type: string, value: any): boolean;
75 |
76 | /**
77 | * 判断当前剪贴板内是否是指定类型
78 | * @param type
79 | */
80 | export function has(type: ICopyType): boolean;
81 | /**
82 | * 清空剪贴板
83 | */
84 | export function clear(): void;
85 | }
86 | export module Dialog {
87 | export interface SelectDialogOptions {
88 | title?: string;
89 | path?: string;
90 | type?: 'directory' | 'file';
91 | button?: string;
92 | multi?: boolean;
93 | filters?: FileFilter[];
94 | extensions?: string;
95 | }
96 | export interface MessageDialogOptions {
97 | title?: string;
98 | detail?: string;
99 | default?: number;
100 | cancel?: number;
101 | checkboxLabel?: string;
102 | checkboxChecked?: boolean;
103 | buttons?: string[];
104 | }
105 |
106 | /**
107 | * 选择文件弹窗
108 | * Select the file popover
109 | *
110 | * @param options 选择弹窗参数 Select popover parameters
111 | * @param window 依附于哪个窗口(插件主进程才可使用) Which window it is attached to (only available to the plugin's main process)
112 | */
113 | export function select(options?: SelectDialogOptions, window?: BrowserWindow): Promise;
114 | /**
115 | * 保存文件弹窗
116 | * Save the file popup
117 | *
118 | * @param options 保存文件窗口参数 Save the file window parameters
119 | * @param window 依附于哪个窗口(插件主进程才可使用) Which window it is attached to (only available to the plugin's main process)
120 | */
121 | export function save(options?: SelectDialogOptions, window?: BrowserWindow): Promise;
122 | /**
123 | * 信息弹窗
124 | * Information popup window
125 | *
126 | * @param message 显示的消息 Displayed message
127 | * @param options 信息弹窗可选参数 Information popup optional parameter
128 | * @param window 依附于哪个窗口(插件主进程才可使用) Which window it is attached to (only available to the plugin's main process)
129 | */
130 | export function info(message: string, options?: MessageDialogOptions, window?: BrowserWindow): Promise;
131 | /**
132 | * 警告弹窗
133 | * Warning popup
134 | *
135 | * @param message 警告信息 Warning message
136 | * @param options 警告弹窗可选参数 Warning popover optional parameter
137 | * @param window 依附于哪个窗口(插件主进程才可使用) Which window it is attached to (only available to the plugin's main process)
138 | */
139 | export function warn(message: string, options?: MessageDialogOptions, window?: BrowserWindow): Promise;
140 | /**
141 | * 错误弹窗
142 | * Error popup window
143 | *
144 | * @param message 错误信息 The error message
145 | * @param options 错误弹窗可选参数 Error popover optional parameter
146 | * @param window 依附于哪个窗口(插件主进程才可使用) Which window it is attached to (only available to the plugin's main process)
147 | */
148 | export function error(message: string, options?: MessageDialogOptions, window?: BrowserWindow): Promise;
149 | }
150 | export module EditMode {
151 | /**
152 | * 标记编辑器进入了一种编辑模式
153 | * The tag editor goes into an edit mode
154 | *
155 | * @param mode 编辑模式的名字 The name of the edit mode
156 | */
157 | export function enter(mode: string): any;
158 | /**
159 | * 当前所处的编辑模式
160 | * The current editing mode
161 | *
162 | */
163 | export function getMode(): string;
164 | }
165 | export module I18n {
166 | export type I18nMap = {
167 | [key: string]: I18nMap | string;
168 | };
169 | /**
170 | * 获取当前的语言
171 | * Get the current language
172 | */
173 | export function getLanguage(): any;
174 | /**
175 | * 传入 key,翻译成当前语言
176 | * Passing in the key translates into the current language
177 | * 允许翻译变量 {a},传入的第二个参数 obj 内定义 a
178 | * The translation variable {a} is allowed, and a is defined in the second argument passed in obj
179 | *
180 | * @param key 用于翻译的 key 值 The key value for translation
181 | * @param obj 翻译字段内如果有 {key} 等可以在这里传入替换字段 If you have {key} in the translation field, you can pass in the replacement field here
182 | */
183 | export function t(key: string, obj?: {
184 | [key: string]: string;
185 | }): any;
186 | /**
187 | * 选择一种翻译语言
188 | * Choose a translation language
189 | *
190 | * @param language 选择当前使用的语言 Select the language currently in use
191 | */
192 | export function select(language: string): any;
193 | }
194 | export module Layout {
195 | /**
196 | * 应用布局信息
197 | * Application layout information
198 | *
199 | * @param json 布局文件内容 Layout file content
200 | */
201 | export function apply(json: any): any;
202 | /**
203 | * 初始化布局系统
204 | * Initialize the layout system
205 | */
206 | export function init(): any;
207 | }
208 | export module Logger {
209 | /**
210 | * 清空所有的日志
211 | * Clear all logs
212 | */
213 | export function clear(): any;
214 | /**
215 | * 查询所有日志
216 | * Query all logs
217 | */
218 | export function query(): any;
219 | }
220 | export module Menu {
221 | export interface BaseMenuItem {
222 | template?: string;
223 | type?: string;
224 | label?: string;
225 | subLabel?: string;
226 | checked?: boolean;
227 | enabled?: boolean;
228 | icon?: string;
229 | accelerator?: string;
230 | order?: number;
231 | group?: string;
232 | message?: string;
233 | target?: string;
234 | params?: any[];
235 | click?: Function | null;
236 | role?: string;
237 | submenu?: MenuTemplateItem[];
238 | }
239 | export interface MainMenuItem extends BaseMenuItem {
240 | path: string;
241 | }
242 | export interface ContextMenuItem extends BaseMenuItem {
243 | accelerator?: string;
244 | }
245 | export interface MenuTemplateItem extends BaseMenuItem {
246 | }
247 | export interface PopupOptions {
248 | x?: number;
249 | y?: number;
250 | menu: ContextMenuItem[];
251 | }
252 | /**
253 | * 右键弹窗
254 | * Right-click pop-up
255 | * 只有面板进程可以使用
256 | * Only panel processes can be used
257 | *
258 | * @param json
259 | */
260 | export function popup(json: PopupOptions): any;
261 | }
262 | export module Message {
263 | export interface MessageInfo {
264 | methods: string[];
265 | public?: boolean;
266 | description?: string;
267 | doc?: string;
268 | sync?: boolean;
269 | }
270 |
271 | export interface TableBase {
272 | [x: string]: any;
273 | params: any[];
274 | }
275 | /**
276 | * 发送一个消息,并等待返回
277 | * Send a message and wait for it to return
278 | *
279 | * @param name 目标插件的名字 The name of the target plug-in
280 | * @param message 触发消息的名字 The name of the trigger message
281 | * @param args 消息需要的参数 The parameters required for the message
282 | */
283 | export function request(name: J, message: K, ...args: EditorMessageMaps[J][K]['params']): Promise;
284 | /**
285 | * 发送一个消息,没有返回
286 | * Send a message, no return
287 | *
288 | * @param name 目标插件的名字 The name of the target plug-in
289 | * @param message 触发消息的名字 The name of the trigger message
290 | * @param args 消息需要的参数 The parameters required for the message
291 | */
292 | export function send(name: M, message: N, ...args: EditorMessageMaps[M][N]['params']): void;
293 | /**
294 | * 广播一个消息
295 | * Broadcast a message
296 | *
297 | * @param message 消息的名字 Name of message
298 | * @param args 消息附加的参数 Parameter attached to the message
299 | */
300 | export function broadcast(message: string, ...args: any[]): void;
301 | /**
302 | * 新增一个广播消息监听器
303 | * Add a new broadcast message listener
304 | * 不监听的时候,需要主动取消监听
305 | * When not listening, you need to take the initiative to cancel listening
306 | *
307 | * @param message 消息名 Message name
308 | * @param func 处理函数 The processing function
309 | */
310 | export function addBroadcastListener(message: string, func: Function): any;
311 | /**
312 | * 新增一个广播消息监听器
313 | * Removes a broadcast message listener
314 | *
315 | * @param message 消息名 Message name
316 | * @param func 处理函数 The processing function
317 | */
318 | export function removeBroadcastListener(message: string, func: Function): any;
319 | }
320 | export module Network {
321 | /**
322 | * 查询当前电脑的 ip 列表
323 | * Query the IP list of the current computer
324 | */
325 | export function queryIPList(): string[];
326 | /**
327 | * 测试是否可以联通 passport.cocos.com 服务器
328 | * Test whether you can connect to the passport.cocos.com server
329 | */
330 | export function testConnectServer(): Promise;
331 | /**
332 | * 检查一个端口是否被占用
333 | * Checks if a port is used
334 | *
335 | * @param port
336 | */
337 | export function portIsOccupied(port: number): Promise;
338 | /**
339 | * 测试是否可以联通某一台主机
340 | * Test whether a host can be connected
341 | *
342 | * @param ip
343 | */
344 | export function testHost(ip: string): Promise;
345 | /**
346 | * Get 方式请求某个服务器数据
347 | * GET requests data from a server
348 | *
349 | * @param url
350 | * @param data
351 | */
352 | export function get(url: string, data?: {
353 | [index: string]: string | string[];
354 | }): Promise;
355 | /**
356 | * Post 方式请求某个服务器数据
357 | * POST requests data from a server
358 | *
359 | * @param url
360 | * @param data
361 | */
362 | export function post(url: string, data?: {
363 | [index: string]: string | number | string[];
364 | }): Promise;
365 | }
366 | export module Package {
367 | // export module VERSION: string;
368 | export interface GetPackageOptions {
369 | name?: string;
370 | debug?: boolean;
371 | path?: string;
372 | enable?: boolean;
373 | invalid?: boolean;
374 | }
375 | export interface PackageJson {
376 | author?: string;
377 | debug?: boolean;
378 | description?: string;
379 | main?: string;
380 | menu?: any;
381 | name: string;
382 | version: string;
383 | windows: string;
384 | editor?: string;
385 | panel?: any;
386 | }
387 | export type PathType = 'home' | 'data' | 'temp';
388 | /**
389 | * 查询插件列表
390 | * Query Plug-in List
391 | *
392 | * @param options
393 | */
394 | export function getPackages(options?: GetPackageOptions): Editor.Interface.PackageInfo[];
395 | /**
396 | * 注册一个插件
397 | * Register a plug-in
398 | * 谨慎使用,之后会被移除
399 | * Use with caution and it will be removed later
400 | *
401 | * @param path
402 | */
403 | export function register(path: string): any;
404 | /**
405 | * 反注册一个插件
406 | * Unregister a plug-in
407 | * 谨慎使用,之后会被移除
408 | * Use with caution and it will be removed later
409 | *
410 | * @param path
411 | */
412 | export function unregister(path: string): any;
413 | /**
414 | * 启动一个插件
415 | * Enable a plug-in
416 | *
417 | * @param path
418 | */
419 | export function enable(path: string): any;
420 | /**
421 | * 关闭一个插件
422 | * Disable a plug-in
423 | *
424 | * @param path
425 | */
426 | export function disable(path: string, options: any): any;
427 | /**
428 | * 获取一个插件的几个预制目录地址
429 | * Gets several prefab directory addresses for a plug-in
430 | *
431 | * @param extensionName 扩展的名字 Name of the extension
432 | * @param type 地址类型(temp 临时目录,data 需要同步的数据目录,不传则返回现在打开的插件路径) Address type (temp temporary directory, data need to synchronize data directory, do not pass to return the current open plug-in path)
433 | */
434 | export function getPath(extensionName: string, type?: PathType): any;
435 | }
436 | export module Panel {
437 | export const _kitControl: any;
438 | /**
439 | * 打开一个面板
440 | * Open up a panel
441 | *
442 | * @param name
443 | * @param args
444 | */
445 | export function open(name: string, ...args: any[]): any;
446 | /**
447 | * 关闭一个面板
448 | * Close a panel
449 | *
450 | * @param name
451 | */
452 | export function close(name: string): any;
453 | /**
454 | * 将焦点传递给一个面板
455 | * Pass focus to a panel
456 | *
457 | * @param name
458 | */
459 | export function focus(name: string): any;
460 | /**
461 | * 检查面板是否已经打开
462 | * Check that the panel is open
463 | *
464 | * @param name
465 | */
466 | export function has(name: string): Promise;
467 | /**
468 | * 查询当前窗口里某个面板里的元素列表
469 | * @param name
470 | * @param selector
471 | */
472 | export function querySelector(name: string, selector: string): Promise;
473 |
474 | export type Selector<$> = { $: Record }
475 |
476 | export type Options void> = {
477 | /**
478 | * @en Listening to panel events
479 | * @zh 监听面板事件
480 | */
481 | listeners?: {
482 | /**
483 | * @en Hooks triggered when the panel is displayed
484 | * @zh 面板显示的时候触发的钩子
485 | */
486 | show?: () => any;
487 | /**
488 | * @en Hooks triggered when the panel is hidden
489 | * @zh 面板隐藏的时候触发的钩子
490 | */
491 | hide?: () => any;
492 | };
493 |
494 | /**
495 | * @en Template of the panel
496 | * @zh 面板的内容
497 | */
498 | template: string;
499 | /**
500 | * @en Style of the panel
501 | * @zh 面板上的样式
502 | * */
503 | style?: string;
504 | /**
505 | * @en Selector of the panel
506 | * @zh 快捷选择器
507 | */
508 | $?: S;
509 | /**
510 | * @en Panel built-in function methods that can be called in Messages, Listeners, lifecycle functions
511 | * @zh panel 内置的函数方法,可以在 messages、listeners、生命周期函数内调用
512 | */
513 | methods?: M;
514 | /**
515 | * @en Hooks triggered when the panel is update
516 | * @zh 面板数据更新后触发的钩子函数
517 | */
518 | update?: (...args: Parameters) => void;
519 | /**
520 | * @en Hooks triggered when the panel is ready
521 | * @zh 面板启动后触发的钩子函数
522 | */
523 | ready?: () => void;
524 | /**
525 | * @en The function that will be triggered when the panel is ready to close, and will terminate the closing of the panel if it
526 | * returns false
527 | * @zh 面板准备关闭的时候会触发的函数,return false 的话,会终止关闭面板
528 | * 生命周期函数,在 panel 准备关闭的时候触发
529 | * 如果 return false,则会中断关闭流程,请谨慎使用,错误的判断会导致编辑器无法关闭。
530 | */
531 | beforeClose?: () => Promise | boolean | void;
532 | /**
533 | * @en Hook functions after panel closure
534 | * @zh 面板关闭后的钩子函数
535 | */
536 | close?: () => void;
537 |
538 | } & ThisType & M> // merge them together
539 |
540 | export function define void, Selector = Record, M = Record>(options: Options): any;
541 | }
542 | export module Profile {
543 | export type preferencesProtocol = 'default' | 'global' | 'local';
544 | export type projectProtocol = 'default' | 'project';
545 | export type tempProtocol = 'temp';
546 | export interface ProfileGetOptions {
547 | type: 'deep' | 'current' | 'inherit';
548 | }
549 | export interface ProfileObj {
550 | get: (key?: string, options?: ProfileGetOptions) => any;
551 | set: (key?: string, value?: any) => any;
552 | remove: (key: string) => void;
553 | save: () => void;
554 | clear: () => void;
555 | reset: () => void;
556 | }
557 | /**
558 | * 读取插件配置
559 | * Read the plug-in configuration
560 | *
561 | * @param name 插件名 The plugin name
562 | * @param key 配置路径 Configure path
563 | * @param type 配置的类型,选填 Type of configuration, optional(global,local,default)
564 | */
565 | export function getConfig(name: string, key?: string, type?: preferencesProtocol): Promise;
566 | /**
567 | * 设置插件配置
568 | * Set the plug-in configuration
569 | *
570 | * @param name 插件名 The plugin name
571 | * @param key 配置路径 Configure path
572 | * @param value 配置的值 The value of the configuration
573 | * @param type 配置的类型,选填 Type of configuration, optional(global,local,default)
574 | */
575 | export function setConfig(name: string, key: string, value: any, type?: preferencesProtocol): Promise;
576 | /**
577 | * 删除某个插件配置
578 | * Delete a plug-in configuration
579 | *
580 | * @param name 插件名 The plugin name
581 | * @param key 配置路径 Configure path
582 | * @param type 配置的类型,选填 Type of configuration, optional(global,local,default)
583 | */
584 | export function removeConfig(name: string, key: string, type?: preferencesProtocol): Promise;
585 | /**
586 | * 读取插件内的项目配置
587 | * Read the project configuration within the plug-in
588 | *
589 | * @param name 插件名 The plugin name
590 | * @param key 配置路径 Configure path
591 | * @param type 配置的类型,选填 Type of configuration, optional(project,default)
592 | */
593 | export function getProject(name: string, key?: string, type?: projectProtocol): Promise;
594 | /**
595 | * 设置插件内的项目配置
596 | * Set the project configuration within the plug-in
597 | *
598 | * @param name 插件名 The plugin name
599 | * @param key 配置路径 Configure path
600 | * @param value 配置的值 The value of the configuration
601 | * @param type 配置的类型,选填 Type of configuration, optional(project,default)
602 | */
603 | export function setProject(name: string, key: string, value: any, type?: projectProtocol): Promise;
604 | /**
605 | * 删除插件内的项目配置
606 | * Delete the project configuration within the plug-in
607 | *
608 | * @param name 插件名 The plugin name
609 | * @param key 配置路径 Configure path
610 | * @param type 配置的类型,选填 Type of configuration, optional(project,default)
611 | */
612 | export function removeProject(name: string, key: string, type?: projectProtocol): Promise;
613 | /**
614 | * 读取插件配置
615 | * Read the plug-in configuration
616 | *
617 | * @param name 插件名 The plugin name
618 | * @param key 配置路径 Configure path
619 | */
620 | export function getTemp(name: string, key?: string): Promise;
621 | /**
622 | * 设置插件配置
623 | * Set the plug-in configuration
624 | *
625 | * @param name 插件名 The plugin name
626 | * @param key 配置路径 Configure path
627 | * @param value 配置的值 The value of the configuration
628 | */
629 | export function setTemp(name: string, key: string, value: any): Promise;
630 | /**
631 | * 删除某个插件配置
632 | * Delete a plug-in configuration
633 | *
634 | * @param name 插件名 The plugin name
635 | * @param key 配置路径 Configure path
636 | */
637 | export function removeTemp(name: string, key: string): Promise;
638 | /**
639 | * 迁移插件某个版本的本地配置数据到编辑器最新版本
640 | * Migrate the local configuration data of a certain version of the plugin to the latest version of the editor
641 | *
642 | * @param pkgName
643 | * @param profileVersion
644 | * @param profileData
645 | */
646 | export function migrateLocal(pkgName: string, profileVersion: string, profileData: any): any;
647 | /**
648 | * 迁移插件某个版本的全局配置数据到编辑器最新版本
649 | * Migrate the global configuration data of a certain version of the plugin to the latest version of the editor
650 | *
651 | * @param pkgName
652 | * @param profileVersion
653 | * @param profileData
654 | */
655 | export function migrateGlobal(pkgName: string, profileVersion: string, profileData: any): any;
656 | /**
657 | * 迁移插件某个版本的项目配置数据到编辑器最新版本
658 | * Migrate the project configuration data of a certain version of the plugin to the latest version of the editor
659 | *
660 | * @param pkgName
661 | * @param profileVersion
662 | * @param profileData
663 | */
664 | export function migrateProject(pkgName: string, profileVersion: string, profileData: any): any;
665 | }
666 | export module Project {
667 | /**
668 | * 创建一个项目
669 | * Creating a project
670 | * 谨慎使用,之后会被移除
671 | * Use with caution and it will be removed later
672 | */
673 | export function create(): any;
674 | /**
675 | * 打开一个项目
676 | * Open a project
677 | * 谨慎使用,之后会被移除
678 | * Use with caution and it will be removed later
679 | *
680 | * @param path
681 | */
682 | export function open(path?: string): Promise;
683 | /**
684 | * 添加一个项目
685 | * Add a project
686 | * 谨慎使用,之后会被移除
687 | * Use with caution and it will be removed later
688 | *
689 | * @param path
690 | */
691 | export function add(path: string): any;
692 | /**
693 | * 当前项目路径
694 | * Current project path
695 | */
696 | export const path: string;
697 | /**
698 | * 当前项目 uuid
699 | * The current project UUID
700 | */
701 | export const uuid: string;
702 | /**
703 | * 当前项目名称(取自 package.json)
704 | * The current project name
705 | */
706 | export const name: string;
707 | /**
708 | * 当前项目临时文件夹
709 | * Temporary folder for current project
710 | */
711 | export const tmpDir: string;
712 | /**
713 | * 当前项目类型
714 | * 谨慎使用,之后会被移除
715 | * Use with caution and it will be removed later
716 | */
717 | export const type: '2d' | '3d';
718 | }
719 | export module Selection {
720 | /**
721 | * 选中一个或者一组元素
722 | * Select one or a group of elements
723 | *
724 | * @param type
725 | * @param uuid
726 | */
727 | export function select(type: string, uuid: string | string[]): any;
728 | /**
729 | * 取消一个或者一组元素的选中状态
730 | * To deselect one or a group of elements
731 | *
732 | * @param type
733 | * @param uuid
734 | */
735 | export function unselect(type: string, uuid: string | string[]): any;
736 | /**
737 | * 清空一个类型的所有选中元素
738 | * Clears all selected elements of a type
739 | *
740 | * @param type
741 | */
742 | export function clear(type: string): any;
743 | /**
744 | * 更新当前选中的类型数据
745 | * Updates the currently selected type data
746 | *
747 | * @param type
748 | * @param uuids
749 | */
750 | export function update(type: string, uuids: string[]): any;
751 | /**
752 | * 悬停触碰了某个元素
753 | * Hover touches an element
754 | * 会发出 selection:hover 的广播消息
755 | * A broadcast message for selection:hover is issued
756 | *
757 | * @param type
758 | * @param uuid
759 | */
760 | export function hover(type: string, uuid?: string): any;
761 | /**
762 | * 获取最后选中的元素的类型
763 | * Gets the type of the last selected element
764 | */
765 | export function getLastSelectedType(): string;
766 | /**
767 | * 获取某个类型内,最后选中的元素
768 | * Gets the last selected element of a type
769 | *
770 | * @param type
771 | */
772 | export function getLastSelected(type: string): string;
773 | /**
774 | * 获取一个类型选中的所有元素数组
775 | * Gets an array of all elements selected for a type
776 | *
777 | * @param type
778 | */
779 | export function getSelected(type: string): string[];
780 | }
781 | export module Task {
782 | export interface NoticeOptions {
783 | title: string;
784 | message?: string;
785 | type?: 'error' | 'warn' | 'log' | 'success';
786 | source?: string;
787 | timeout?: number;
788 | }
789 | /**
790 | * 添加一个同步任务
791 | * Add a synchronous task
792 | * 会在主窗口显示一个遮罩层
793 | * A mask layer is displayed in the main window
794 | *
795 | * @param title 任务名字 The task name
796 | * @param describe 任务描述 Task description
797 | * @param message 任务内容 Content of the task
798 | */
799 | export function addSyncTask(title: string, describe?: string, message?: string): any;
800 | /**
801 | * 更新某一个同步任务显示的数据
802 | * Update the data displayed by a synchronous task
803 | *
804 | * @param title 任务名字 The task name
805 | * @param describe 任务描述 Task description
806 | * @param message 任务内容 Content of the task
807 | */
808 | export function updateSyncTask(title: string, describe?: string, message?: string): any;
809 | /**
810 | * 删除一个同步任务
811 | * Delete a synchronous task
812 | *
813 | * @param title 任务的名字 The name of the task
814 | */
815 | export function removeSyncTask(title: string): any;
816 | /**
817 | * 添加一个通知
818 | * Add a notification
819 | *
820 | * @param options 消息配置 Message configuration
821 | */
822 | export function addNotice(options: NoticeOptions): any;
823 | /**
824 | * 删除一个通知
825 | * Delete a notification
826 | *
827 | * @param id 通知 id Notification ID
828 | */
829 | export function removeNotice(id: number): any;
830 | /**
831 | * 修改 notice 自动移除的时间
832 | * Modify notice automatic removal time
833 | *
834 | * @param id 通知 id Notification ID
835 | * @param time 超时时间 timeout
836 | */
837 | export function changeNoticeTimeout(id: number, time: number): any;
838 | /**
839 | * 查询所有通知
840 | * Query all notifications
841 | */
842 | export function queryNotices(): any;
843 | /**
844 | * 页面进程立即同步一次主进程数据
845 | * The page process synchronizes the master process data immediately
846 | * 谨慎使用,之后会被移除
847 | * Use with caution and it will be removed later
848 | */
849 | export function sync(): any;
850 | }
851 | export module Theme {
852 | /**
853 | * 获取所有主题的名字
854 | * Gets the names of all topics
855 | */
856 | export function getList(): any;
857 | /**
858 | * 使用某个皮肤
859 | * Use a certain skin
860 | *
861 | * @param name
862 | */
863 | export function use(name?: string): any;
864 | }
865 | export module UI {
866 | /**
867 | * 在当前页面上注册一个自定义节点
868 | * Registers a custom node on the current page
869 | * 谨慎使用,之后会被移除
870 | * Use with caution and it will be removed later
871 | *
872 | * @param tagName 元素名字
873 | * @param element 元素的定义函数
874 | */
875 | export function register(tagName: string, element: any): void;
876 | export const Base: any;
877 | export const Button: any;
878 | export const Input: any;
879 | export const NumInput: any;
880 | export const Loading: any;
881 | export const Checkbox: any;
882 | export const Section: any;
883 | export const Select: any;
884 | export const Bit: any;
885 | export const Slider: any;
886 | export const ColorPicker: any;
887 | export const Color: any;
888 | export const DragItem: any;
889 | export const DragArea: any;
890 | export const DragObject: any;
891 | export const Prop: any;
892 | export const Tooltip: any;
893 | export const TextArea: any;
894 | export const Progress: any;
895 | export const Label: any;
896 | export const Code: any;
897 | export const Tab: any;
898 | export const Gradient: any;
899 | export const GradientPicker: any;
900 | export const Icon: any;
901 | export const File: any;
902 | export const Link: any;
903 | export const Image: any;
904 | export const QRCode: any;
905 | export const Markdown: any;
906 | export const Curve: any;
907 | export const CurveEditor: any;
908 | export const NodeGraph: any;
909 | }
910 | export module User {
911 | export interface UserData {
912 | session_id: string;
913 | session_key: string;
914 | cocos_uid: string;
915 | email: string;
916 | nickname: string;
917 | }
918 | /**
919 | * 跳过 User
920 | * Skip the User
921 | * 谨慎使用,之后会被移除
922 | * Use with caution and it will be removed later
923 | */
924 | export function skip(): any;
925 | /**
926 | * 获取 user 数据
927 | * Get user data
928 | */
929 | export function getData(): Promise;
930 | /**
931 | * 检查用户是否登陆
932 | * Check if the user is logged in
933 | */
934 | export function isLoggedIn(): Promise;
935 | /**
936 | * 用户登陆
937 | * The user login
938 | * 失败会抛出异常
939 | * Failure throws an exception
940 | *
941 | * @param username
942 | * @param password
943 | */
944 | export function login(username: string, password: string): Promise;
945 | /**
946 | * 退出登陆
947 | * Logged out
948 | * 失败会抛出异常
949 | * Failure throws an exception
950 | */
951 | export function logout(): void;
952 | /**
953 | * 获取用户 token
954 | * Get user token
955 | * 失败会抛出异常
956 | * Failure throws an exception
957 | */
958 | export function getUserToken(): Promise;
959 | /**
960 | * 根据插件 id 返回 session code
961 | * Returns the session code based on the plug-in ID
962 | *
963 | * @param extensionId
964 | */
965 | export function getSessionCode(extensionId: number): Promise;
966 | /**
967 | * 显示用户登陆遮罩层
968 | * Shows user login mask layer
969 | * 谨慎使用,之后会被移除
970 | * Use with caution and it will be removed later
971 | */
972 | export function showMask(): void;
973 | /**
974 | * 隐藏用户登陆遮罩层
975 | * Hide user login mask layer
976 | * 谨慎使用,之后会被移除
977 | * Use with caution and it will be removed later
978 | */
979 | export function hideMask(): void;
980 | /**
981 | * 监听事件
982 | * Listen for an event
983 | * 谨慎使用,之后会被移除
984 | * Use with caution and it will be removed later
985 | * @param action
986 | * @param handle
987 | */
988 | export function on(action: string, handle: Function): any;
989 | /**
990 | * 监听一次事件
991 | * Listening for one event
992 | * 谨慎使用,之后会被移除
993 | * Use with caution and it will be removed later
994 | * @param action
995 | * @param handle
996 | */
997 | export function once(action: string, handle: Function): any;
998 | /**
999 | * 取消已经监听的事件
1000 | * Cancels the event you are listening for
1001 | * 谨慎使用,之后会被移除
1002 | * Use with caution and it will be removed later
1003 | * @param action
1004 | * @param handle
1005 | */
1006 | export function removeListener(action: string, handle: Function): any;
1007 | }
1008 | export module Utils {
1009 | export module File {
1010 | /**
1011 | * 初始化一个可用的文件名
1012 | * Initializes a available filename
1013 | * 返回可用名称的文件路径
1014 | * Returns the file path with the available name
1015 | *
1016 | * @param file 初始文件路径 Initial file path
1017 | */
1018 | export function getName(file: string): string;
1019 | interface UnzipOptions {
1020 | peel?: boolean;
1021 | }
1022 | /**
1023 | * 解压文件夹
1024 | * Unzip folder
1025 | *
1026 | * @param zip
1027 | * @param target
1028 | * @param options
1029 | */
1030 | export function unzip(zip: string, target: string, options?: UnzipOptions): Promise;
1031 | /**
1032 | * 复制一个文件到另一个位置
1033 | * Copy a file to another location
1034 | *
1035 | * @param source
1036 | * @param target
1037 | */
1038 | export function copy(source: string, target: string): void;
1039 | }
1040 | export module Path {
1041 |
1042 | /**
1043 | * 返回一个不含扩展名的文件名
1044 | * @param path
1045 | */
1046 | export function basenameNoExt(path: string): string;
1047 | /**
1048 | * 将 \ 统一换成 /
1049 | * @param path
1050 | */
1051 | export function slash(path: string): string;
1052 | /**
1053 | * 去除路径最后的斜杆,返回一个不带斜杆的路径
1054 | * @param path
1055 | */
1056 | export function stripSep(path: string): string;
1057 | /**
1058 | * 删除一个路径的扩展名
1059 | * @param path
1060 | */
1061 | export function stripExt(path: string): string;
1062 | /**
1063 | * 判断路径 pathA 是否包含 pathB
1064 | * pathA = foo/bar, pathB = foo/bar/foobar, return true
1065 | * pathA = foo/bar, pathB = foo/bar, return true
1066 | * pathA = foo/bar/foobar, pathB = foo/bar, return false
1067 | * pathA = foo/bar/foobar, pathB = foobar/bar/foo, return false
1068 | * @param pathA
1069 | * @param pathB
1070 | */
1071 | export function contains(pathA: string, pathB: string): boolean;
1072 | /**
1073 | * 格式化路径
1074 | * 如果是 Windows 平台,需要将盘符转成小写进行判断
1075 | * @param path
1076 | */
1077 | export function normalize(path: string): string;
1078 | export const join: typeof NodeJSPath.join;
1079 | export const resolve: typeof NodeJSPath.resolve;
1080 | export const isAbsolute: typeof NodeJSPath.isAbsolute;
1081 | export const relative: typeof NodeJSPath.relative;
1082 | export const dirname: typeof NodeJSPath.dirname;
1083 | export const basename: typeof NodeJSPath.basename;
1084 | export const extname: typeof NodeJSPath.extname;
1085 | export const sep: '\\' | '/';
1086 | export const delimiter: ';' | ':';
1087 | export const parse: typeof NodeJSPath.parse;
1088 | export const format: typeof NodeJSPath.format;
1089 |
1090 |
1091 | }
1092 | export module Math {
1093 | /**
1094 | * 取给定边界范围的值
1095 | * Take the value of the given boundary range
1096 | * @param {number} val
1097 | * @param {number} min
1098 | * @param {number} max
1099 | */
1100 | export function clamp(val: number, min: number, max: number): any;
1101 | /**
1102 | * @function clamp01
1103 | * @param {number} val
1104 | * @returns {number}
1105 | *
1106 | * Clamps a value between 0 and 1.
1107 | */
1108 | export function clamp01(val: number): number;
1109 | /**
1110 | * 加法函数
1111 | * 入参:函数内部转化时会先转字符串再转数值,因而传入字符串或 number 均可
1112 | * 返回值:arg1 加上 arg2 的精确结果
1113 | * @param {number|string} arg1
1114 | * @param {number|string} arg2
1115 | */
1116 | export function add(arg1: number | string, arg2: number | string): number;
1117 | /**
1118 | * 减法函数
1119 | * 入参:函数内部转化时会先转字符串再转数值,因而传入字符串或number均可
1120 | * 返回值:arg1 减 arg2的精确结果
1121 | * @param {number|string} arg1
1122 | * @param {number|string} arg2
1123 | */
1124 | export function sub(arg1: number | string, arg2: number | string): number;
1125 | /**
1126 | * 保留小数点
1127 | * @param val
1128 | * @param num
1129 | */
1130 | export function toFixed(val: number, num: number): number;
1131 | }
1132 | export module Parse {
1133 | interface WhenParam {
1134 | PanelName?: string;
1135 | EditMode?: string;
1136 | }
1137 | /**
1138 | * 解析 when 参数
1139 | * when 的格式:
1140 | * PanelName === '' && EditMode === ''
1141 | * 整理后的数据格式:
1142 | * {
1143 | * PanelName: '',
1144 | * EditMode: '',
1145 | * }
1146 | */
1147 | export function when(when: string): WhenParam;
1148 | /**
1149 | * 判断一个 when 数据是否符合当前条件
1150 | * @param when
1151 | */
1152 | export function checkWhen(when: string): boolean;
1153 | }
1154 | export module Url {
1155 | /**
1156 | * 快捷获取文档路径
1157 | * @param relativeUrl
1158 | * @param type
1159 | */
1160 | export function getDocUrl(relativeUrl: string, type?: 'manual' | 'api'): string;
1161 | }
1162 |
1163 | export module UUID {
1164 | /**
1165 | * 压缩 UUID
1166 | * compress UUID
1167 | * @param uuid
1168 | * @param min
1169 | */
1170 | export function compressUUID(uuid: string, min: boolean): string;
1171 | /**
1172 | * 解压 UUID
1173 | * decompress the UUID
1174 | * @param str
1175 | */
1176 | export function decompressUUID(str: string): string;
1177 | /**
1178 | * 检查输入字符串是否是 UUID
1179 | * Check whether the input string is a UUID
1180 | * @param str
1181 | */
1182 | export function isUUID(str: string): string;
1183 | /**
1184 | * 生成一个新的 uuid
1185 | */
1186 | export function generate(): string;
1187 | }
1188 | }
1189 | }
1190 | }
1191 |
1192 |
--------------------------------------------------------------------------------
/@types/extension.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace Editor {
2 |
3 | namespace Interface {
4 | // ---- Package ---- start
5 | interface PackageInfo {
6 | debug: boolean;
7 | enable: boolean;
8 | info: PackageJson;
9 | invalid: boolean;
10 | name: string;
11 | path: string;
12 | version: string;
13 | }
14 |
15 | interface PackageJson {
16 | name: string;
17 | version: string;
18 |
19 | title?: string;
20 | author?: string;
21 | debug?: boolean;
22 | description?: string;
23 | main?: string;
24 | editor?: string;
25 | panel?: any;
26 | contributions?: { [key: string]: any };
27 | }
28 | // ---- Package ---- end
29 |
30 | // ---- UI ---- start
31 | interface PanelInfo {
32 | template?: string;
33 | style?: string;
34 | listeners?: { [key: string]: () => {} };
35 | methods?: { [key: string]: Function };
36 | $?: { [key: string]: string };
37 | ready?(): void;
38 | update?(...args: any[]): void;
39 | beforeClose?(): void;
40 | close?(): void;
41 | }
42 |
43 | namespace UIKit {
44 | interface UIPanelInfo extends PanelInfo {
45 | // 向上触发事件
46 | dispath(eventName: string, ...arg: any): void;
47 | }
48 |
49 | interface EditorElementBase extends HTMLElement {
50 | value: any;
51 | dispath: (name: string, event: any) => void;
52 | }
53 |
54 | }
55 | // ---- UI ---- end
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/@types/index.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | ///
5 | export * from './packages/builder/@types/public';
--------------------------------------------------------------------------------
/@types/message.d.ts:
--------------------------------------------------------------------------------
1 | import * as AssetDB from './packages/asset-db/@types/message';
2 | import * as Scene from './packages/scene/@types/message';
3 | import * as Engine from './packages/engine/@types/message';
4 | import * as Builder from './packages/builder/@types/public/message';
5 | import * as Programming from './packages/programming/@types/message';
6 | // import * as Extension from './packages/extension/@types/message';
7 |
8 | declare global {
9 | interface EditorMessageContent {
10 | params: any[],
11 | result: any;
12 | }
13 |
14 | interface EditorMessageMap {
15 | [x: string]: EditorMessageContent;
16 | }
17 |
18 | interface EditorMessageMaps {
19 | [x: string]: EditorMessageMap;
20 | 'asset-db': AssetDB.message;
21 | 'scene': Scene.message;
22 | 'engine': Engine.message;
23 | 'builder': Builder.message;
24 | 'programming': Programming.message,
25 | // 'extension': Extension.message;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/@types/packages/asset-db/@types/message.d.ts:
--------------------------------------------------------------------------------
1 | import { AssetInfo, QueryAssetsOption, AssetOperationOption, AssetDBOptions, IAssetMeta } from './public';
2 |
3 | export interface message extends EditorMessageMap {
4 | 'query-ready': {
5 | params: [],
6 | result: boolean,
7 | },
8 | 'create-asset': {
9 | params: [
10 | string,
11 | string | Buffer | null,
12 | ] | [
13 | string,
14 | string | Buffer | null,
15 | AssetOperationOption,
16 | ],
17 | result: AssetInfo | null,
18 | },
19 | 'import-asset': {
20 | params: [
21 | string,
22 | string,
23 | ] | [
24 | string,
25 | string,
26 | AssetOperationOption,
27 | ],
28 | result: AssetInfo | null,
29 | },
30 | 'copy-asset': {
31 | params: [
32 | string,
33 | string,
34 | ] | [
35 | string,
36 | string,
37 | AssetOperationOption,
38 | ],
39 | result: AssetInfo | null,
40 | },
41 | 'move-asset': {
42 | params: [
43 | string,
44 | string,
45 | ] | [
46 | string,
47 | string,
48 | AssetOperationOption,
49 | ],
50 | result: AssetInfo | null,
51 | },
52 | 'delete-asset': {
53 | params: [
54 | string,
55 | ],
56 | result: AssetInfo | null,
57 | },
58 | 'open-asset': {
59 | params: [
60 | string,
61 | ],
62 | result: void,
63 | },
64 | 'save-asset': {
65 | params: [
66 | string,
67 | string | Buffer,
68 | ],
69 | result: AssetInfo | null,
70 | },
71 | 'save-asset-meta': {
72 | params: [
73 | string,
74 | string,
75 | ],
76 | result: AssetInfo | null,
77 | },
78 | 'reimport-asset': {
79 | params: [
80 | string,
81 | ],
82 | result: boolean,
83 | },
84 | 'refresh-asset': {
85 | params: [
86 | string
87 | ],
88 | result: boolean,
89 | },
90 | 'query-asset-info': {
91 | params: [
92 | string,
93 | ],
94 | result: AssetInfo | null,
95 | },
96 | 'query-asset-meta': {
97 | params: [
98 | string,
99 | ],
100 | result: IAssetMeta | null,
101 | },
102 | 'query-path': {
103 | params: [
104 | string,
105 | ],
106 | result: string | null,
107 | },
108 | 'query-url': {
109 | params: [
110 | string
111 | ],
112 | result: string | null,
113 | },
114 | 'query-uuid': {
115 | params: [
116 | string
117 | ],
118 | result: string | null,
119 | },
120 | 'query-assets': {
121 | params: [] | [
122 | QueryAssetsOption,
123 | ],
124 | result: AssetInfo[],
125 | },
126 | 'generate-available-url': {
127 | params: [
128 | string,
129 | ],
130 | result: string,
131 | },
132 |
133 | // private
134 |
135 | 'query-asset-mtime': {
136 | params: [
137 | string
138 | ],
139 | result: string | null,
140 | },
141 | 'refresh': {
142 | params: [],
143 | result: void,
144 | },
145 | 'open-devtools': {
146 | params: [],
147 | result: void,
148 | },
149 | 'query-db-info': {
150 | params: [
151 | string,
152 | ],
153 | result: AssetDBOptions,
154 | },
155 | 'create-asset-dialog': {
156 | params: [
157 | string,
158 | ] | [
159 | string,
160 | string,
161 | ],
162 | result: string | null,
163 | },
164 | 'init-asset': {
165 | params: [
166 | string,
167 | string,
168 | ],
169 | result: AssetInfo | null,
170 | },
171 | 'query-all-importer': {
172 | params: [],
173 | result: string[],
174 | },
175 | 'query-all-asset-types': {
176 | params: [],
177 | result: string[],
178 | },
179 | }
180 |
--------------------------------------------------------------------------------
/@types/packages/asset-db/@types/public.d.ts:
--------------------------------------------------------------------------------
1 | // Basic information about the resource
2 | // 资源的基础信息
3 | export interface AssetInfo {
4 | // Asset name
5 | // 资源名字
6 | name: string;
7 | // Asset display name
8 | // 资源用于显示的名字
9 | displayName: string;
10 | // URL
11 | source: string;
12 | // loader 加载的层级地址
13 | path: string;
14 | // loader 加载地址会去掉扩展名,这个参数不去掉
15 | url: string;
16 | // 绝对路径
17 | file: string;
18 | // 资源的唯一 ID
19 | uuid: string;
20 | // 使用的导入器名字
21 | importer: string;
22 | // 类型
23 | type: string;
24 | // 是否是文件夹
25 | isDirectory: boolean;
26 | // 导入资源的 map
27 | library: { [key: string]: string };
28 | // 子资源 map
29 | subAssets: { [key: string]: AssetInfo };
30 | // 是否显示
31 | visible: boolean;
32 | // 是否只读
33 | readonly: boolean;
34 |
35 | // 虚拟资源可以实例化成实体的话,会带上这个扩展名
36 | instantiation?: string;
37 | // 跳转指向资源
38 | redirect?: IRedirectInfo;
39 | // 继承类型
40 | extends?: string[];
41 | // 是否导入完成
42 | imported: boolean;
43 | // 是否导入失败
44 | invalid: boolean;
45 | }
46 |
47 | export interface IRedirectInfo {
48 | // 跳转资源的类型
49 | type: string;
50 | // 跳转资源的 uuid
51 | uuid: string;
52 | }
53 |
54 | export interface QueryAssetsOption {
55 | type?: string;
56 | pattern?: string;
57 | ccType?: string;
58 | extname?: string;
59 | importer?: string;
60 | isBundle?: boolean;
61 | }
62 |
63 | export interface AssetOperationOption {
64 | // 是否强制覆盖已经存在的文件,默认 false
65 | overwrite?: boolean;
66 | // 是否自动重命名冲突文件,默认 false
67 | rename?: boolean;
68 | }
69 |
70 | export interface AssetDBOptions {
71 | name: string;
72 | target: string;
73 | library: string;
74 | temp: string;
75 | /**
76 | * 0: 忽略错误
77 | * 1: 仅仅打印错误
78 | * 2: 打印错误、警告
79 | * 3: 打印错误、警告、日志
80 | * 4: 打印错误、警告、日志、调试信息
81 | */
82 | level: number;
83 | ignoreFiles: string[];
84 | readonly: boolean;
85 | }
86 |
87 | export interface ContributionInfo {
88 | mount?: {
89 | path: string;
90 | readonly?: boolean;
91 | };
92 | }
93 |
94 | export interface ExecuteAssetDBScriptMethodOptions {
95 | name: string;
96 | method: string;
97 | args: any[];
98 | }
99 |
100 | export interface IAssetMeta {
101 | ver: string;
102 | importer: string;
103 | imported: boolean;
104 | uuid: string;
105 | files: string[];
106 | subMetas: {
107 | [index: string]: IAssetMeta;
108 | };
109 | userData: {
110 | [index: string]: any;
111 | };
112 | displayName: string;
113 | id: string;
114 | name: string;
115 | }
116 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/index.d.ts:
--------------------------------------------------------------------------------
1 |
2 | export * from './public';
3 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/asset-manager.d.ts:
--------------------------------------------------------------------------------
1 | import { AssetInfo } from "../../../asset-db/@types/public";
2 | import { UUID } from "../public";
3 | import { IInternalBuildOptions } from "./options";
4 | export interface IBuildStatiscInfo {
5 | packageName: string;
6 | gameName: string;
7 | platform: string;
8 | scenesNum: number;
9 | assetsNum: number;
10 | scriptNum: number;
11 |
12 | includeModules: string[];
13 | orientation: string;
14 | remoteServerAddress: string;
15 | appid: string;
16 |
17 | size: number;
18 | time: number;
19 | err: string;
20 | }
21 |
22 | // ********************************* asset-manager *********************************
23 |
24 | export class BuilderAssetCache {
25 | // 场景资源的 assets 信息缓存
26 | public readonly sceneUuids: Array;
27 |
28 | // 脚本资源的 assets 信息缓存
29 | public readonly scriptUuids: Array;
30 |
31 | // 除场景、脚本资源外的资源 assets uuid 缓存
32 | public readonly assetUuids: Array;
33 |
34 | init: () => Promise;
35 | addAsset: (asset: IAssetInfo) => void;
36 | addInstance: (instance: any) => void;
37 | clearAsset: (uuid: string) => void;
38 | getMeta: (uuid: string) => Promise;
39 | getAssetInfo: (uuid: string) => IAssetInfo;
40 | getDependUuids: (uuid: string) => Promise;
41 | getDependUuidsDeep: (uuid: string) => Promise;
42 | /**
43 | * 获取序列化文件
44 | */
45 | getLibraryJSON: (uuid: string) => Promise;
46 | getSerializedJSON: (uuid: string, options: IInternalBuildOptions) => Promise;
47 | forEach: (type: string, handle: Function) => Promise;
48 | getInstance: (uuid: string) => Promise;
49 | __addStaticsInfo: (info: any) => void;
50 | }
51 |
52 | export interface IAssetInfo extends AssetInfo {
53 | meta?: any;
54 | temp?: string; // 资源的构建缓存目录
55 | fatherInfo?: any;
56 | // fatherUuid?: string | undefined;
57 | userData?: any;
58 | subAssets: Record;
59 | dirty?: boolean;
60 | // 内置资源没有 mtime
61 | mtime?: number;
62 | }
63 | export type IUrl = string; // 需要的是符合 url 标准的字符串,例如 asset/script/text.ts
64 | export type IAssetInfoMap = Record;
65 | export type IUuidDependMap = Record;
66 | export type IJsonGroupMap = Record;
67 | export type IAssetGroupMap = Record;
68 |
69 | // TODO meta 的类型定义
70 | export type IMetaMap = Record;
71 | export type IJsonMap = Record;
72 | export type IInstanceMap = Record;
73 |
74 | export type ICompressOptions = Record;
75 | export interface IAssetGroupItem {
76 | // 分组名字
77 | // name: string;
78 | // 分组的根 url
79 | baseUrls: string[];
80 | // 脚本编译后的实际地址
81 | scriptDest: string;
82 | // 脚本 uuid 列表
83 | scriptUuids: UUID[];
84 | // raw 资源 uuid 列表
85 | assetUuids: UUID[];
86 | }
87 |
88 | export interface IJSONGroupItem {
89 | // 分组名字
90 | name?: string;
91 | // 分组名字
92 | type: string;
93 | // json 资源 uuid 列表
94 | uuids: UUID[];
95 | }
96 |
97 | export interface IAssetGroupOptions {
98 | // 脚本打包后的输出路径
99 | scriptUrl: string;
100 | baseUrl: string;
101 | }
102 |
103 | export type IGroupType = 'json' | 'script' | 'asset';
104 | export interface PacInfo {
105 | meta: any;
106 | asset: IAssetInfo;
107 | spriteFrames: any[];
108 | relativePath: string;
109 | relativeDir: string;
110 | }
111 |
112 | export type IUpdateType = 'asset-change' | 'asset-add' | 'asset-delete';
113 | export interface IUpdateInfo {
114 | type: IUpdateType;
115 | uuid: string;
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/build-plugin.d.ts:
--------------------------------------------------------------------------------
1 | // ********************************* plugin ****************************************
2 |
3 | import { BundleCompressionType, IBuildPluginConfig, IBuildTaskOption, IDisplayOptions, ISettings, IVerificationRuleMap } from '../public';
4 | import { BuilderAssetCache } from './asset-manager';
5 | import { InternalBuildResult } from './build-result';
6 | import { IInternalBuildOptions } from './options';
7 | import { ITextureCompressPlatform, ITextureCompressType } from '../public/texture-compress';
8 |
9 | export interface IBuildWorkerPluginInfo {
10 | assetHandlers?: string;
11 | // 注册到各个平台的钩子函数
12 | hooks?: Record;
13 | pkgName: string;
14 | internal: boolean; // 是否为内置插件
15 | priority: number; // 优先级
16 | }
17 |
18 | export type IPluginHookName =
19 | | 'onBeforeBuild'
20 | | 'onAfterInit'
21 | | 'onBeforeInit'
22 | | 'onAfterInit'
23 | | 'onBeforeBuildAssets'
24 | | 'onAfterBuildAssets'
25 | | 'onBeforeCompressSettings'
26 | | 'onAfterCompressSettings'
27 | | 'onAfterBuild';
28 | // | 'onBeforeCompile'
29 | // | 'compile'
30 | // | 'onAfterCompile'
31 | // | 'run';
32 |
33 | export type IPluginHook = Record;
34 | export interface IInternalHook {
35 | throwError?: boolean; // 插件注入的钩子函数,在执行失败时是否直接退出构建流程
36 | title?: string; // 插件任务整体 title,支持 i18n 写法
37 | // ------------------ 钩子函数 --------------------------
38 | onBeforeBuild?: IInternalBaseHooks;
39 | onBeforeInit?: IInternalBaseHooks;
40 | onAfterInit?: IInternalBaseHooks;
41 | onBeforeBuildAssets?: IInternalBaseHooks;
42 | onAfterBuildAssets?: IInternalBaseHooks;
43 | onBeforeCompressSettings?: IInternalBaseHooks;
44 | onAfterCompressSettings?: IInternalBaseHooks;
45 | onAfterBuild?: IInternalBaseHooks;
46 | // ------------------ 其他操作函数 ---------------------
47 | // 内置插件才有可能触发这个函数
48 | run?: (dest: string, options: IBuildTaskOption) => Promise;
49 | // 内置插件才有可能触发这个函数
50 | compile?: (dest: string, options: IBuildTaskOption) => boolean;
51 | }
52 |
53 | export type IInternalBaseHooks = (options: IInternalBuildOptions, result: InternalBuildResult, cache: BuilderAssetCache, ...args: any[]) => void;
54 | export interface IBuildTask {
55 | handle: (options: IInternalBuildOptions, result: InternalBuildResult, cache: BuilderAssetCache, settings?: ISettings) => {};
56 | title: string;
57 | name: string;
58 | }
59 |
60 | export interface IBuildHooksInfo {
61 | pkgNameOrder: string[];
62 | infos: Record;
63 | }
64 | export interface IBuildAssetHandlerInfo {
65 | pkgNameOrder: string[];
66 | handles: {[pkgName: string]: Function};
67 | }
68 | export interface IInternalBuildPluginConfig extends IBuildPluginConfig {
69 | platformName?: string; // 平台名,可以指定为 i18n 写法, 只有官方构建插件的该字段有效
70 | hooks?: string; // 钩子函数的存储路径
71 | panel?: string; // 存储导出 vue 组件、button 配置的脚本路径
72 | textureCompressConfig?: {
73 | // 仅对内部插件开放
74 | platformType: ITextureCompressPlatform; // 注册的纹理压缩平台类型
75 | support: {
76 | rgba: ITextureCompressType[];
77 | rgb: ITextureCompressType[];
78 | }; // 该平台支持的纹理压缩格式,按照推荐优先级排列
79 | };
80 | assetBundleConfig?: {
81 | // asset bundle 的配置
82 | supportedCompressionTypes: BundleCompressionType[];
83 | };
84 | priority?: number;
85 | wrapWithFold?: boolean; // 是否将选项显示在折叠框内(默认 true )
86 | options?: IDisplayOptions; // 需要注入的平台参数配置
87 | verifyRuleMap?: IVerificationRuleMap; // 注入的需要更改原有参数校验规则的函数
88 | commonOptions?: Record;
89 | // TODO 之前为 ios-app-clip HACK 出来的接口,之后需要重新设计
90 | realInFileExplorer?: (options: IInternalBuildOptions | any) => void; // 根据构建配置计算输出地址(界面中的在文件夹中显示)
91 | debugConfig?: IDebugConfig;
92 | internal?: boolean;
93 | }
94 |
95 | export interface BuildCheckResult {
96 | error: string;
97 | newValue: any;
98 | }
99 |
100 | export type IBuildVerificationFunc = (value: any, options: IBuildTaskOption) => boolean | Promise;
101 |
102 | export interface IButtonConfigItem {
103 | label: string; // 按钮名称
104 | click?: (event: Event, options: IBuildTaskOption) => void; // 点击事件响应函数
105 | hookHandle?: string; // 点击后执行的方法,与 click 二选一
106 | tooltip?: string; // 鼠标上移到按钮上的文本提示
107 | // 只有指定 hookHandle 配置的按钮,才可以影响进度条,构建将会自动为每个按钮创建一个构建内置任务,并提供对应的进度 log 更新等等。
108 | // attributes?: any; // 想要添加在按钮上的一些属性值(class, style, title)
109 | }
110 |
111 | export interface IDebugConfig {
112 | options?: IDisplayOptions; // 显示在构建平台编译运行调试工具上的配置选项
113 | custom?: string; // 显示在构建平台编译运行调试工具上的配置 vue 组件
114 | }
115 |
116 | // ui-panel 注册数据
117 | export interface PanelInfo {
118 | $?: { [name: string]: string | HTMLElement | null };
119 | template?: string; // TODO 暂时设置为可选
120 | style?: string;
121 | methods?: { [name: string]: Function };
122 | ready?: Function;
123 | close?: Function;
124 | update?: (options: IBuildTaskOption, path: string, value: any) => void | Promise;
125 | }
126 |
127 | export interface IPanelThis {
128 | $: Record;
129 | dispatch: (name: string, ...args: any[]) => void;
130 | }
131 |
132 | export interface IPanelInfo extends PanelInfo {
133 | component?: any; // 注入面板的 vue 组件,可与与 options 共存,options 会优先显示
134 | buttonConfig?: IButtonConfig; // 要注入的构建选项脚本
135 | }
136 |
137 | export interface IButtonConfig {
138 | configs?: Record;
139 | custom?: any;
140 | }
141 |
142 | export interface ICompInfo {
143 | custom?: any;
144 | options?: IDisplayOptions;
145 | panelInfo?: PanelInfo;
146 | displayName?: string;
147 | wrapWithFold: boolean;
148 |
149 | // ..... 初始化时未存在的字段 .....
150 | panel?: any; // 实例化后的 panel 对象
151 | pkgName?: string; // 插件名称
152 | }
153 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/build-result.d.ts:
--------------------------------------------------------------------------------
1 | import { BundleCompressionType, IAssetPathInfo, IBuildPaths, IBuildTaskOption, IBundleConfig, IJsonPathInfo, ISettings, UUID } from "../public";
2 | import { IAssetInfo } from "./asset-manager";
3 | import { ImportMapWithImports } from "./import-map";
4 |
5 | export class InternalBuildResult {
6 | settings: ISettings;
7 | readonly bundles: IBundle[];
8 | readonly bundleMap: Record;
9 | // 构建实际使用到的插件脚本 uuid 列表
10 | plugins: UUID[];
11 | // 脚本资源包分组(子包/分包)
12 | scriptPackages: string[];
13 | // MD5 后缀 map
14 | pluginVers: Record;
15 | // 纹理压缩任务
16 | imageTaskMap: Record;
17 | compressImageResult: ICompressImageResult;
18 | importMap: ImportMapWithImports;
19 | // 传入构建的 options
20 | rawOptions: IBuildTaskOption;
21 | // 输出路径集合
22 | paths: IBuildPaths;
23 | // 允许自定义编译选项
24 | compileOptions?: any;
25 | addBundle: (bundle: IBundle) => void;
26 | addPlugin: (plugin: IAssetInfo) => void;
27 | }
28 |
29 | export interface IImageTask {
30 | src: string;
31 | // TODO 这个名称已和意义有冲突需要整理调整
32 | dest: string[];
33 | presetId: string;
34 | hasAlpha: boolean;
35 | mtime?: any;
36 | // 生成阶段将会重新获取 bundle 的输出地址
37 | bundleNames: string[];
38 | }
39 |
40 | export interface IVersionMap {
41 | import: Record;
42 | native: Record;
43 | }
44 |
45 | export interface IMD5Map {
46 | 'raw-assets': Record;
47 | import: Record;
48 | plugin?: Record;
49 | }
50 | export interface IAtlasResult {
51 | assetsToImage: Record;
52 | imageToAtlas: Record;
53 | atlasToImages: Record;
54 | }
55 |
56 | export class IBundle {
57 | readonly scenes: UUID[]; // 该 bundle 中的所有场景,包含重定向的
58 | readonly assets: UUID[]; // 该 bundle 中的所有资源,包含重定向的
59 | readonly assetsWithoutRedirect: UUID[]; // 该 bundle 中的未重定向的资源
60 | readonly scripts: UUID[]; // 该 bundle 中的所有脚本
61 | readonly rootAssets: UUID[]; // 该 bundle 中的根资源,即直接放在 bundle 目录下的资源,包含重定向的资源
62 | readonly isSubpackage: boolean; // 该 bundle 是否是子包
63 | root: string; // bundle 的根目录, 开发者勾选的目录,如果是 main 包,这个字段为 ''
64 | dest: string; // bundle 的输出目录
65 | importBase: string;
66 | nativeBase: string;
67 | scriptDest: string; // 脚本的输出目录
68 | name: string; // bundle 的名称
69 | priority: number; // bundle 的优先级
70 | compressionType: BundleCompressionType; // bundle 的压缩类型
71 | assetVer: IVersionMap; // bundle 内的资源版本
72 | version: string; // bundle 本身的版本信息
73 | readonly isRemote: boolean; // bundle 是否是远程包
74 | redirect: Record; // bundle 中的重定向资源
75 | deps: Set; // bundle 的依赖 bundle
76 | groups: IGroup[]; // 该 bundle 中的资源分组
77 | cache: any;
78 | configOutPutName: string;
79 | config: IBundleConfig; // 该 bundle 的资源清单
80 | readonly isZip: boolean; // 该 bundle 是否是 zip 模式
81 | zipVer: string; // Zip 压缩模式,压缩包的版本
82 | atlasRes: IAtlasResult;
83 | _rootAssets: Set; // 该 bundle 直接包含的资源
84 | _scenes: Set;
85 | _scripts: Set;
86 | _assets: Set;
87 |
88 | addScene(scene: IAssetInfo): void;
89 | addScript(script: IAssetInfo): void;
90 | addRootAsset(asset: IAssetInfo): void;
91 | addAsset(asset: IAssetInfo): void;
92 | removeAsset(asset: UUID): void;
93 | addRedirectWithUuid(asset: UUID, redirect: string): void;
94 | addRedirect(asset: IAssetInfo, redirect: string): void;
95 | addAssetWithUuid(asset: UUID): void;
96 | getRedirect(uuid: UUID): string | undefined;
97 | addGroup(type: IJSONGroupType, uuids: UUID[]): void;
98 | addToGroup(type: IJSONGroupType, uuid: UUID): void;
99 | removeFromGroups(uuid: UUID): void;
100 | getJsonPath(uuid: string): string;
101 | getAssetPathInfo(uuid: string): IAssetPathInfo | null;
102 | containsAsset(uuid: string): boolean;
103 | getRawAssetPaths(uuid: string): string[];
104 | getJsonPathInfo(uuid: string): IJsonPathInfo | null;
105 |
106 | _resolveImportPath: (name: string) => string;
107 | _resolveNativePath: (libraryPath: string, extName: string) => string;
108 | }
109 |
110 | export type ICompressImageResult = Record;
114 |
115 | export interface IGroup {
116 | // 分组名字
117 | name?: string;
118 | // 分组类型
119 | type: IJSONGroupType;
120 | // 该组中的资源 uuid 列表
121 | uuids: UUID[];
122 | }
123 |
124 | export type IJSONGroupType = 'NORMAL' | 'TEXTURE' | 'IMAGE';
125 |
126 | export interface IDefaultGroup {
127 | assetUuids: UUID[];
128 | scriptUuids: UUID[];
129 | jsonUuids: UUID[];
130 | }
131 |
132 | export interface IBundleOptions {
133 | root: string, // bundle 的根目录, 开发者勾选的目录,如果是 main 包,这个字段为''
134 | dest: string, // bundle 的输出目录
135 | scriptDest: string, // 脚本的输出目录
136 | name: string, // bundle 的名称
137 | priority: number, // bundle 的优先级
138 | compressionType: BundleCompressionType, // bundle 的压缩类型
139 | isRemote: boolean // bundle 是否是远程包
140 | // isEncrypted: boolean // bundle 中的代码是否加密,原生平台使用
141 | }
142 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/global.d.ts:
--------------------------------------------------------------------------------
1 | import { IBuildPanel, IInternalBuild } from ".";
2 |
3 | // 定义 builder 进程内的全局变量
4 | declare global {
5 | // 构建进程可用
6 | // @ts-ignore
7 | const Build: IInternalBuild;
8 |
9 | const __manager: {
10 | taskManager: any;
11 | currentCompileTask: any;
12 | currentBuildTask: any;
13 | __taskId: string;
14 | };
15 |
16 | // 渲染进程可用
17 | const BuildPanel: IBuildPanel;
18 | }
19 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/import-map.d.ts:
--------------------------------------------------------------------------------
1 |
2 | export interface ImportMap {
3 | imports?: Record;
4 | scopes?: Record>;
5 | }
6 |
7 | export type ImportMapWithImports = ImportMap & { imports: NonNullable };
8 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/index.d.ts:
--------------------------------------------------------------------------------
1 | import { IBuild, IBuildUtils, ITaskState } from '../public';
2 | import { InternalBuildResult } from './build-result';
3 |
4 | export * from './asset-manager';
5 | export * from './import-map';
6 | export * from './options';
7 | export * from './build-result';
8 | export * from './build-plugin';
9 | export * from '../public';
10 |
11 | export type Physics = 'cannon' | 'ammo' | 'builtin';
12 | export type Url = string; // 需要的是符合 url 标准的字符串
13 | export type AssetInfoArr = Array; // 固定两位或三位数组 [url,ccType,isSubAsset]
14 | export type IProcessingFunc = (process: number, message: string, state?: ITaskState) => void;
15 | export interface IBuildManager {
16 | taskManager: any;
17 | currentCompileTask: any;
18 | currentBuildTask: any;
19 | __taskId: string;
20 | }
21 |
22 | export interface IQuickSpawnOption {
23 | cwd?: string;
24 | env?: any;
25 | downGradeWaring?: boolean; // 将会转为 log 打印,默认为 false
26 | downGradeLog?: boolean; // 将会转为 debug 打印,默认为 true
27 | downGradeError?: boolean; // 将会转为警告,默认为 false
28 | ignoreLog?: boolean; // 忽略 log 信息
29 | }
30 | export interface IInternalBuildUtils extends IBuildUtils {
31 | /**
32 | * 获取构建出的所有模块或者模块包文件。
33 | */
34 | getModuleFiles(result: InternalBuildResult): Promise;
35 |
36 | /**
37 | * 快速开启子进程
38 | * @param command
39 | * @param cmdParams
40 | * @param options
41 | */
42 | quickSpawn(command: string, cmdParams: string[], options?: IQuickSpawnOption): Promise;
43 |
44 | /**
45 | * 将某个 hash 值添加到某个路径上
46 | * @param targetPath
47 | * @param hash
48 | * @returns
49 | */
50 | patchMd5ToPath(targetPath: string, hash: string): string;
51 | }
52 |
53 | export interface IInternalBuild extends IBuild {
54 | Utils: IInternalBuildUtils;
55 | }
56 |
57 | export interface IBuildProcessInfo {
58 | state: ITaskState; // 任务状态
59 | progress: number; // 任务进度
60 | message: string; // 最后一次更新的进度消息
61 | id: string; // 任务唯一标识符
62 | options: any; // 构建参数
63 | }
64 |
65 | export interface fileMap {
66 | src: string;
67 | dest: string;
68 | }
69 |
70 | export interface IScriptInfo {
71 | file: string;
72 | uuid: string;
73 | }
74 |
75 | type ICheckRule = 'pathExist' | 'valid' | 'required' | 'normalName' | 'noChinese' | 'array' | 'string' | 'number' | 'http';
76 |
77 | export interface IBuildPanel {
78 | // 内部使用的 Vue
79 | Vue: any;
80 | // 内置 vue 组件
81 | vueComps: {
82 | buildProp: any;
83 | templateComp: any;
84 | },
85 | validator: {
86 | has: (ruleName: string) => boolean;
87 | check: (ruleName: ICheckRule, val: any) => boolean;
88 | },
89 | }
90 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/protect/options.d.ts:
--------------------------------------------------------------------------------
1 | import { IBuildTimeConstantValue } from "@cocos/build-engine/dist/build-time-constants";
2 | import { IBuildDesignResolution, IBuildTaskOption } from "../public";
3 |
4 | export interface ScriptAssetuserData {
5 | isPlugin?: boolean;
6 | isNative?: boolean;
7 | loadPluginInNative?: boolean;
8 | loadPluginInWeb?: boolean;
9 | }
10 |
11 | export interface IBuildScriptParam {
12 | /**
13 | * 若存在,表示将 import map 转换为指定的模块格式。
14 | */
15 | importMapFormat?: 'commonjs' | 'esm';
16 |
17 | polyfills?: IPolyFills;
18 |
19 | /**
20 | * 擦除模块结构。当选择后会获得更快的脚本导入速度,但无法再使用模块特性,如 `import.meta`、`import()` 等。
21 | * @experimental
22 | */
23 | experimentalEraseModules?: boolean;
24 | outputName: string; // 输出文件夹名称(带后缀)
25 | targets?: ITransformTarget;
26 |
27 | system?: {
28 | preset?: 'web' | 'commonjs-like',
29 | },
30 |
31 | flags: Record,
32 | }
33 |
34 | export interface IPolyFills {
35 | /**
36 | * True if async functions polyfills(i.e. regeneratorRuntime) needs to be included.
37 | * You need to turn on this field if you want to use async functions in language.
38 | */
39 | asyncFunctions?: boolean;
40 |
41 | /**
42 | * If true, [core-js](https://github.com/zloirock/core-js) polyfills are included.
43 | * The default options of [core-js-builder](https://github.com/zloirock/core-js/tree/master/packages/core-js-builder)
44 | * will be used to build the core-js.
45 | */
46 | coreJs?: boolean;
47 |
48 | targets?: string;
49 | }
50 | /**
51 | * 模块保留选项。
52 | * - 'erase' 擦除模块信息。生成的代码中将不会保留模块信息。
53 | * - 'preserve' 保留原始模块信息。生成的文件将和原始模块文件结构一致。
54 | * - 'facade' 保留原始模块信息,将所有模块转化为一个 SystemJS 模块,但这些模块都打包在一个单独的 IIFE bundle 模块中。
55 | * 当这个 bundle 模块执行时,所有模块都会被注册。
56 | * 当你希望代码中仍旧使用模块化的特性(如动态导入、import.meta.url),但又不希望模块零散在多个文件时可以使用这个选项。
57 | */
58 | export type ModulePreservation = 'erase' | 'preserve' | 'facade';
59 |
60 | export type INewConsoleType = 'log' | 'warn' | 'error' | 'debug';
61 |
62 | export interface IInternalBuildOptions extends IBuildTaskOption {
63 | dest: string;
64 | // 编译 application.js 参数配置
65 | appTemplateData: appTemplateData;
66 | // 编译引擎参数配置
67 | buildEngineParam: IBuildEngineParam;
68 | // 编译脚本配置选项
69 | buildScriptParam: IBuildScriptParam;
70 | // 序列化打包资源时的特殊处理
71 | assetSerializeOptions: {
72 | 'cc.EffectAsset': {
73 | glsl1: boolean;
74 | glsl3: boolean;
75 | glsl4: boolean;
76 | };
77 | // 是否输出 ccon 格式
78 | exportCCON?: boolean;
79 |
80 | allowCCONExtension?: boolean;
81 | };
82 | updateOnly: boolean;
83 | nextTasks?: string[];
84 | generateCompileConfig?: boolean;
85 | recompileConfig?: IRecompileConfig;
86 | logDest?: string; // log 输出地址
87 |
88 | // 项目设置,重复定义为必选参数
89 | includeModules: string[];
90 | renderPipeline: string;
91 | designResolution: IBuildDesignResolution;
92 | physicsConfig: any;
93 | flags: Record;
94 | }
95 |
96 |
97 | export interface appTemplateData {
98 | debugMode: boolean;
99 | renderMode: boolean; // !!options.renderMode,
100 | // ImportMapSupported: boolean;
101 | // NonconformingCommonJs: boolean;
102 | showFPS: boolean;
103 | importMapFile?: string;
104 | resolution: {
105 | policy: number;
106 | width: number;
107 | height: number;
108 | };
109 | // hasPhysicsAmmo: boolean;
110 | md5Cache: boolean;
111 | server: string; // 服务器地址
112 |
113 | cocosTemplate?: string; // 注入的子模板路径
114 | }
115 |
116 | export interface IBuildEngineParam {
117 | entry?: string; // 引擎入口文件
118 | debug: boolean;
119 | sourceMaps: boolean;
120 | platform: string;
121 | includeModules: string[];
122 | engineVersion: string;
123 | md5Map: string[];
124 | engineName: string;
125 | useCache: boolean;
126 | split?: boolean;
127 | targets?: ITransformTarget;
128 | skip?: boolean;
129 | ammoJsWasm?: boolean | 'fallback';
130 | assetURLFormat?:
131 | | 'relative-from-out'
132 | | 'relative-from-chunk'
133 | | 'runtime-resolved';
134 | baseUrl?: string;
135 | }
136 |
137 | export type ITransformTarget = string | string[] | Record;
138 |
139 | export interface IRecompileConfig {
140 | enable: boolean;
141 | generateAssets: boolean;
142 | generateScripts: boolean;
143 | generateEngine: boolean; // 是否生成引擎
144 | generateEngineByCache: boolean; // 是否使用缓存引擎
145 | }
146 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/build-plugin.d.ts:
--------------------------------------------------------------------------------
1 | import { ITextureCompressType, IPVRQuality, IASTCQuality, IETCQuality } from './texture-compress';
2 | import { IBuildTaskOption } from './options';
3 | import { IBuildResult } from './build-result';
4 |
5 | export interface IBuildPluginConfig {
6 | hooks?: string; // relate url about IHook
7 | options?: IDisplayOptions; // config of options
8 | verifyRuleMap?: IVerificationRuleMap;
9 | }
10 |
11 | export type IVerificationFunc = (val: any, ...arg: any[]) => boolean | Promise;
12 |
13 | export type IVerificationRuleMap = Record<
14 | string,
15 | {
16 | func?: IVerificationFunc;
17 | message?: string;
18 | }
19 | >;
20 |
21 | export type IDisplayOptions = Record;
22 |
23 | export type ArrayItem = {
24 | label: string;
25 | value: string;
26 | };
27 | export interface IConfigItem {
28 | // 配置显示的名字,如果需要翻译,则传入 i18n:${key}
29 | label?: string;
30 | // 设置的简单说明
31 | description?: string;
32 | // 默认值
33 | default?: any;
34 | // 配置的类型
35 | type?: 'array' | 'object';
36 | itemConfigs?: IConfigItem[] | Record;
37 | verifyRules?: string[];
38 | attributes?: any;
39 | render?: {
40 | ui: string;
41 | attributes?: any;
42 | items?: ArrayItem[];
43 | };
44 | }
45 |
46 | export interface IBuildPlugin {
47 | configs?: BuildPlugin.Configs;
48 | assetHandlers?: BuildPlugin.AssetHandlers;
49 | load?: BuildPlugin.load;
50 | unload?: BuildPlugin.Unload;
51 | }
52 | export type IBaseHooks = (options: IBuildTaskOption, result: IBuildResult) => Promise | void;
53 |
54 | export namespace BuildPlugin {
55 | export type Configs = Record;
56 | export type AssetHandlers = string;
57 | export type load = () => Promise | void;
58 | export type Unload = () => Promise | void;
59 | }
60 |
61 | export namespace BuildHook {
62 | export type throwError = boolean; // 插件注入的钩子函数,在执行失败时是否直接退出构建流程
63 | export type title = string; // 插件任务整体 title,支持 i18n 写法
64 | export type onBeforeBuild = IBaseHooks;
65 | export type onBeforeCompressSettings = IBaseHooks;
66 | export type onAfterCompressSettings = IBaseHooks;
67 | export type onAfterBuild = IBaseHooks;
68 | export type load = () => Promise | void;
69 | export type unload = () => Promise | void;
70 | }
71 |
72 | export namespace AssetHandlers {
73 | export type compressTextures = (
74 | tasks: { src: string; dest: string; quality: number | IPVRQuality | IASTCQuality | IETCQuality; format: ITextureCompressType }[],
75 | ) => Promise;
76 | }
77 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/build-result.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * settings.js 里定义的数据
3 | */
4 |
5 | import { ISplashSetting, ICustomJointTextureLayout, UUID } from "./options";
6 |
7 | // ****************************** settings ************************************************
8 |
9 | // debug: true
10 | // designResolution: {width: "960", height: "640", policy: 4}
11 | // jsList: ["assets/resources/b.js", "assets/resources/a.js"]
12 | // launchScene: "db://assets/New Scene-001.scene"
13 | // platform: "web-desktop"
14 | // rawAssets: {
15 | // assets: {
16 | // "0e95a9f8-d4e7-4849-875a-7a11dd692b34": ["mesh/env/gltf/textures/birch_yellow_mat_baseColor.png", "cc.ImageAsset"]
17 | // }
18 | // internal: {
19 | // "1baf0fc9-befa-459c-8bdd-af1a450a0319": ["effects/builtin-standard.effect", "cc.EffectAsset"]
20 | // }
21 | // }
22 | // scenes: [{url: "db://assets/New Scene-001.scene", uuid: "69dc4a42-cc6c-49fb-9a57-7de0c212f83d"},…]
23 | // startScene: "current_scene"
24 | export interface ISettings {
25 | CocosEngine: string;
26 | debug: boolean;
27 | designResolution: ISettingsDesignResolution;
28 | jsList: string[];
29 | launchScene: string;
30 | moduleIds: string[];
31 | platform: string;
32 | renderPipeline: string;
33 | physics?: IPhysicsConfig;
34 | exactFitScreen: boolean;
35 |
36 | bundleVers: Record;
37 | subpackages: string[];
38 | remoteBundles: string[];
39 | server: string;
40 | hasResourcesBundle: boolean;
41 | hasStartSceneBundle: boolean;
42 |
43 | scriptPackages?: string[];
44 | splashScreen?: ISplashSetting;
45 |
46 | customJointTextureLayouts?: ICustomJointTextureLayout[];
47 |
48 | importMaps?: Array<{
49 | url: string;
50 | map: any;
51 | }>;
52 |
53 | macros?: Record;
54 | collisionMatrix?: any;
55 | groupList?: any;
56 | // preview
57 | engineModules: string[];
58 | customLayers: {name: string, bit: number}[];
59 | }
60 |
61 | // 物理配置
62 | export interface IVec3Like {
63 | x: number;
64 | y: number;
65 | z: number;
66 | }
67 |
68 | export interface ICollisionMatrix {
69 | [x: string]: number;
70 | }
71 |
72 | export interface IPhysicsMaterial {
73 | friction: number; // 0.5
74 | rollingFriction: number; // 0.1
75 | spinningFriction: number; // 0.1
76 | restitution: number; // 0.1
77 | }
78 |
79 | export interface IPhysicsConfig {
80 | gravity: IVec3Like; // (0,-10, 0)
81 | allowSleep: boolean; // true
82 | sleepThreshold: number; // 0.1,最小 0
83 | autoSimulation: boolean; // true
84 | fixedTimeStep: number; // 1 / 60 ,最小 0
85 | maxSubSteps: number; // 1,最小 0
86 | defaultMaterial: IPhysicsMaterial;
87 | useNodeChains: boolean; // true
88 | collisionMatrix: ICollisionMatrix;
89 | physicsEngine: string;
90 | }
91 |
92 | export interface IPackageInfo {
93 | name: string;
94 | path: string;
95 | uuids: UUID[];
96 | }
97 |
98 | export interface ISettingsDesignResolution {
99 | width: number;
100 | height: number;
101 | policy: number;
102 | }
103 |
104 | interface IAssetPathBase {
105 | bundleName?: string;
106 | redirect?: string; // 重定向的 bundle 包名
107 | }
108 |
109 | export interface IRawAssetPathInfo extends IAssetPathBase {
110 | raw: string[];
111 | }
112 | export declare interface IAssetPathInfo extends IAssetPathBase {
113 | raw?: string[];
114 | json?: string;
115 | groupIndex?: number;
116 | }
117 |
118 | export interface IJsonPathInfo extends IAssetPathBase {
119 | json?: string;
120 | groupIndex?: number;
121 | }
122 |
123 | export interface IBuildPaths {
124 | dir: string; // 构建资源输出地址( assets 所在的目录,并不一定与构建目录对应)
125 | settings: string; // settings.json 输出地址
126 | systemJs?: string; // system.js 生成地址
127 | engineDir?: string; // 引擎生成地址
128 | polyfillsJs?: string; // polyfill.js 生成地址
129 | assets: string; // assets 目录
130 | subpackages: string; // subpackages 目录
131 | remote: string; // remote 目录
132 | bundleScripts: string // bundle 的脚本,某些平台无法下载脚本,则将远程包中的脚本移到本地
133 | applicationJS: string; // application.js 的生成地址
134 | compileConfig?: string; // cocos.compile.config.json
135 | importMap: string; // import-map 文件地址
136 | }
137 |
138 | export declare class IBuildResult {
139 | dest: string; // options 指定的构建目录
140 |
141 | paths: IBuildPaths; // 构建后资源相关地址集合
142 |
143 | settings?: ISettings;
144 |
145 | /**
146 | * 指定的 uuid 资源是否包含在构建资源中
147 | */
148 | containsAsset: (uuid: string) => boolean;
149 |
150 | /**
151 | * 获取指定 uuid 原始资源的存放路径(不包括序列化 json)
152 | * 自动图集的小图 uuid 和自动图集的 uuid 都将会查询到合图大图的生成路径
153 | * 实际返回多个路径的情况:查询 uuid 为自动图集资源,且对应图集生成多张大图,纹理压缩会有多个图片格式路径
154 | */
155 | getRawAssetPaths: (uuid: string) => IRawAssetPathInfo[];
156 |
157 | /**
158 | * 获取指定 uuid 资源的序列化 json 路径
159 | */
160 | getJsonPathInfo: (uuid: string) => IJsonPathInfo[];
161 |
162 | /**
163 | * 获取指定 uuid 资源的路径相关信息
164 | * @return {raw?: string[]; json?: string; groupIndex?: number;}
165 | * @return.raw: 该资源源文件的实际存储位置
166 | * @return.json: 该资源序列化 json 的实际存储位置,不存在为空
167 | * @return.groupIndex: 若该资源的序列化 json 在某个 json 分组内,这里标识在分组内的 index,不存在为空
168 | */
169 | getAssetPathInfo: (uuid: string) => IAssetPathInfo[];
170 | }
171 |
172 | export interface IBundleConfig {
173 | importBase: string; // bundle 中 import 目录的名称,通常是 'import'
174 | nativeBase: string; // native 中 native 目录的名称,通常是 'native'
175 | name: string; // bundle 的名称,可以通过 bundle 名称加载 bundle
176 | deps: string[]; // 该 bundle 依赖的其他 bundle 名称
177 | uuids: UUID[]; // 该 bundle 中的所有资源的 uuid
178 | paths: Record; // 该 bundle 中可以通过路径加载的资源,参考以前 settings 中 rawAssets 的定义
179 | scenes: Record; // 该 bundle 中所有场景,场景名为 key, uuid 为 value
180 | packs: Record; // 该 bundle 中所有合并的 json, 参考以前 settings 中 packedAssets 的定义
181 | versions: { import: Array, native: Array }; // 该 bundle 中所有资源的版本号,参考以前 settings 中 md5AssetsMap 的定义
182 | redirect: Array; // 该 bundle 中重定向到其他 bundle 的资源
183 | debug: boolean; // 是否是 debug 模式,debug 模式会对 config.json 的数据进行压缩,所以运行时得解压
184 | types?: string[]; // paths 中的类型数组,参考以前 settings 中 assetTypes 的定义
185 | encrypted?: boolean; // 原生上使用,标记该 bundle 中的脚本是否加密
186 | isZip?: boolean; // 是否是 zip 模式
187 | zipVersion?: string;
188 | extensionMap: Record
189 | }
190 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/global.d.ts:
--------------------------------------------------------------------------------
1 | import { IBuild } from ".";
2 |
3 | // 定义 builder 进程内的全局变量
4 | declare global {
5 | // @ts-ignore
6 | const Build: IBuild;
7 | }
8 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/index.d.ts:
--------------------------------------------------------------------------------
1 | import { ITransformOptions } from './options';
2 |
3 | export * from './build-result';
4 | export * from './build-plugin';
5 | export * from './texture-compress';
6 | export * from './options';
7 |
8 | interface IAppendRes {
9 | hash: string;
10 | paths: string[];
11 | }
12 |
13 | interface ICreateBundleOptions {
14 | excludes?: string[];
15 | debug?: boolean;
16 | sourceMap?: boolean;
17 | }
18 | export interface IBuildUtils {
19 | /**
20 | * 压缩 uuid
21 | * 'fc991dd7-0033-4b80-9d41-c8a86a702e59' -> 'fc9913XADNLgJ1ByKhqcC5Z'
22 | */
23 | compressUuid: (uuid: string, min: boolean) => string;
24 |
25 | /**
26 | * 解压缩 uuid
27 | * 'fc9913XADNLgJ1ByKhqcC5Z' -> 'fc991dd7-0033-4b80-9d41-c8a86a702e59'
28 | */
29 | decompressUuid: (uuid: string) => string;
30 |
31 | /**
32 | * 翻译带有 i18n 开头的名称(i18n:test)(待定)
33 | * 'i18n:test' -> '测试'
34 | */
35 | transI18nName: (name: string) => string;
36 |
37 | /**
38 | * 移除 db 前缀
39 | * 'db://assets/test.jpg' -> 'assets/test.jpg'
40 | */
41 | removeDbHeader: (url: string) => string;
42 |
43 | /**
44 | * 将 db 开头的 url 转为项目里的实际 url
45 | * 'db://assets/test.jpg' -> 'c:/project/assets/test.jpg'
46 | */
47 | dbUrlToRawPath: (url: string) => string;
48 |
49 | /**
50 | * 从路径里获取存在的 uuid
51 | * 'E:\test3d\library\oc\0c0c1f5742-89b0-4a1e-b5eb-914d84f48c1c.json' -> '0c0c1f5742-89b0-4a1e-b5eb-914d84f48c1c'
52 | */
53 | getUuidFromPath: (path: string) => string;
54 |
55 | /**
56 | * 检查是否全局安装了 nodejs
57 | */
58 | isInstallNodeJs: () => Promise;
59 |
60 | /**
61 | * 逐文件拷贝
62 | */
63 | copyDirSync: (src: string, dest: string) => void;
64 |
65 | /**
66 | * 获取相对路径接口
67 | * 返回 / 拼接的相对路径
68 | */
69 | relativeUrl: (from: string, to: string) => string;
70 |
71 | transformCode: (code: string, options: ITransformOptions) => Promise;
72 |
73 | /**
74 | * 给指定路径添加 md5
75 | */
76 | appendMd5ToPaths: (paths: string[]) => Promise;
77 |
78 | calcMd5: (data: Buffer | string) => string;
79 |
80 | copyPaths: (paths: { src: string; dest: string }[]) => Promise;
81 |
82 | createBundle: (src: string, dest: string, options?: ICreateBundleOptions) => Promise;
83 | }
84 | export interface IBuild {
85 | Utils: IBuildUtils;
86 |
87 | LIBRARY_NAME: string;
88 | IMPORT_HEADER: string;
89 | NATIVE_HEADER: string;
90 | ASSETS_HEADER: string;
91 | SUBPACKAGES_HEADER: string;
92 | REMOTE_HEADER: string;
93 | BUNDLE_SCRIPTS_HEADER: string;
94 | SCRIPT_NAME: string;
95 | CONFIG_NAME: string;
96 | BUNDLE_ZIP_NAME: string;
97 | projectTempDir: string;
98 | globalTempDir: string;
99 | buildTemplateDir: string; // 构建模板地址 build-templates
100 | }
101 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/message.d.ts:
--------------------------------------------------------------------------------
1 | import { IBundleConfig, ISettings } from "./build-result";
2 | import { ITaskItemJSON } from "./options";
3 | export interface message extends EditorMessageMap {
4 | 'open-devtools': {
5 | params: [],
6 | result: void,
7 | },
8 | open: {
9 | params: [],
10 | result: void,
11 | },
12 | 'generate-preview-setting': {
13 | params: any[],
14 | result: Promise<{
15 | settings: ISettings;
16 | script2library: Record;
17 | bundleConfigs: IBundleConfig[];
18 | }>,
19 | },
20 | 'query-tasks-info': {
21 | params: [],
22 | result: {
23 | queue: Record,
24 | free: Promise,
25 | },
26 | },
27 | 'query-task': {
28 | params: string[],
29 | result: Promise,
30 | },
31 | /**
32 | * 预览合图
33 | * @param {object} pacUuid
34 | */
35 | 'preview-pac': {
36 | params: string[],
37 | result: Promise,
38 | },
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/options.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 构建所需的完整参数
3 | */
4 | export interface IBuildTaskOption {
5 | // 构建后的游戏文件夹生成的路径
6 | buildPath: string;
7 | debug: boolean;
8 | inlineSpriteFrames: boolean;
9 | md5Cache: boolean;
10 | // bundle 设置
11 | mainBundleCompressionType: BundleCompressionType;
12 | mainBundleIsRemote: boolean;
13 | moveRemoteBundleScript: boolean;
14 | mergeJson: boolean;
15 | name: string;
16 | packAutoAtlas: boolean;
17 | platform: Platform;
18 | scenes: IBuildSceneItem[];
19 | compressTexture: boolean;
20 | sourceMaps: boolean;
21 | startScene: string;
22 | outputName: string;
23 | experimentalEraseModules: boolean;
24 |
25 | /**
26 | * 是否是预览进程发送的构建请求。
27 | * @default false
28 | */
29 | preview?: boolean;
30 |
31 | // 项目设置
32 | includeModules?: string[];
33 | renderPipeline?: string;
34 | designResolution?: IBuildDesignResolution;
35 | physicsConfig?: any;
36 | flags?: Record;
37 |
38 |
39 | // 是否使用自定义插屏选项
40 | replaceSplashScreen?: boolean;
41 | splashScreen: ISplashSetting;
42 |
43 | packages?: Record;
44 | id?: string; // 手动配置构建任务 id
45 | // recompileConfig?: IRecompileConfig;
46 |
47 | customLayers: {name: string, value: number}[];
48 | }
49 |
50 | export type UUID = string;
51 |
52 | export interface ISplashSetting {
53 | base64src: string;
54 | displayRatio: number;
55 | totalTime: number;
56 | effect: string;
57 | clearColor: { x: number; y: number; z: number; w: number };
58 | displayWatermark: boolean;
59 | }
60 |
61 | export interface ICustomJointTextureLayout {
62 | textureLength: number;
63 | contents: IChunkContent[];
64 | }
65 |
66 | export interface IChunkContent {
67 | skeleton: null | string;
68 | clips: string[];
69 | }
70 |
71 | /**
72 | * 构建使用的设计分辨率数据
73 | */
74 | export interface IBuildDesignResolution {
75 | height: number;
76 | width: number;
77 | fitWidth?: boolean;
78 | fitHeight?: boolean;
79 | }
80 |
81 | /**
82 | * 构建使用的场景的数据
83 | */
84 | export interface IBuildSceneItem {
85 | url: string;
86 | uuid: string;
87 | }
88 |
89 | // **************************** options *******************************************
90 | export type Platform =
91 | | 'web-desktop'
92 | | 'web-mobile'
93 | | 'wechatgame'
94 | | 'oppo-mini-game'
95 | | 'vivo-mini-game'
96 | | 'huawei-quick-game'
97 | | 'alipay-mini-game'
98 | | 'mac'
99 | | 'ios'
100 | // | 'ios-app-clip'
101 | | 'android'
102 | | 'ohos'
103 | | 'windows'
104 | | 'xiaomi-quick-game'
105 | | 'baidu-mini-game'
106 | | 'bytedance-mini-game'
107 | | 'cocos-play'
108 | | 'huawei-agc'
109 | | 'link-sure'
110 | | 'qtt'
111 | | 'cocos-runtime'
112 | ;
113 |
114 | export type BundleCompressionType = 'none' | 'merge_dep' | 'merge_all_json' | 'subpackage' | 'zip';
115 | export type IModules = 'esm' | 'commonjs' | 'systemjs';
116 |
117 | export interface ITransformOptions {
118 | importMapFormat: IModules;
119 | }
120 |
121 | export type ITaskState = 'waiting' | 'success' | 'failure' | 'cancel' | 'processing';
122 |
123 | export interface ITaskItemJSON {
124 | id: string;
125 | progress: number;
126 | state: ITaskState;
127 | message: string;
128 | options: IBuildTaskOption;
129 | time: string;
130 | dirty: boolean;
131 | rawOptions: IBuildTaskOption;
132 | }
133 |
--------------------------------------------------------------------------------
/@types/packages/builder/@types/public/texture-compress.d.ts:
--------------------------------------------------------------------------------
1 | export type ITextureCompressType =
2 | | 'jpg'
3 | | 'png'
4 | | 'webp'
5 | | 'pvrtc_4bits_rgb'
6 | | 'pvrtc_4bits_rgba'
7 | | 'pvrtc_4bits_rgb_a'
8 | | 'pvrtc_2bits_rgb'
9 | | 'pvrtc_2bits_rgba'
10 | | 'pvrtc_2bits_rgb_a'
11 | | 'etc1_rgb'
12 | | 'etc1_rgb_a'
13 | | 'etc2_rgb'
14 | | 'etc2_rgba'
15 | | 'astc_4x4'
16 | | 'astc_5x5'
17 | | 'astc_6x6'
18 | | 'astc_8x8'
19 | | 'astc_10x5'
20 | | 'astc_10x10'
21 | | 'astc_12x12';
22 | export type ITextureCompressPlatform = 'miniGame' | 'web' | 'ios' | 'android';
23 | export type IQualityType = 'etc' | 'pvr' | 'number' | 'astc';
24 | export interface ITextureFormatInfo {
25 | displayName: string;
26 | qualityType: IQualityType;
27 | alpha?: boolean;
28 | }
29 | export interface ISupportFormat {
30 | rgb: ITextureCompressType[];
31 | rgba: ITextureCompressType[];
32 | }
33 | export interface IConfigGroupsInfo {
34 | defaultSupport?: ISupportFormat,
35 | support: ISupportFormat,
36 | displayName: string;
37 | icon: string;
38 | }
39 | export type IConfigGroups = Record;
40 |
41 | export type IPVRQuality = 'fastest' | 'fast' | 'normal' | 'high' | 'best';
42 | export type IETCQuality = 'slow' | 'fast';
43 | export type IASTCQuality = 'veryfast' | 'fast' | 'medium' | 'thorough' | 'exhaustive';
44 |
--------------------------------------------------------------------------------
/@types/packages/console/@types/pritate.d.ts:
--------------------------------------------------------------------------------
1 | export interface IMessageItem {
2 | rows: number;
3 | translateY: number;
4 | show: boolean;
5 | title: string;
6 | content: string[];
7 | count: number;
8 | fold: boolean;
9 | type: string;
10 | message: any;
11 | texture: string;
12 | date?: number;
13 | time?: number;
14 | process?: string;
15 | stack: string[];
16 | }
17 |
--------------------------------------------------------------------------------
/@types/packages/engine/@types/message.d.ts:
--------------------------------------------------------------------------------
1 | export interface message extends EditorMessageMap {
2 | 'query-info': {
3 | params: [] | [
4 | string,
5 | ],
6 | result: {
7 | type: string;
8 | version: string;
9 | path: string;
10 | nativeVersion: string; // 原生引擎类型 'custom' 'builtin'
11 | nativePath: string;
12 | editor: string;
13 | renderPipeline: string;
14 | },
15 | },
16 | }
17 |
--------------------------------------------------------------------------------
/@types/packages/preview/@types/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './protect/';
2 |
--------------------------------------------------------------------------------
/@types/packages/preview/@types/protect/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Platform } from "../../../builder/@types/public";
2 |
3 | export type IPreviewType = 'game-view' | 'simulator' | 'browser';
4 |
5 | export type ISupportDataType = 'settings' | 'renderData';
6 |
7 | export interface IHookConfig {
8 | methods: string;
9 | hook: string;
10 | }
11 | export interface IGenerateSettingsOptions {
12 | type: IPreviewType;
13 | startScene?: string;
14 | platform?: Platform;
15 | }
16 |
17 | export interface IPreviewPluginConfig {
18 | methods?: string;
19 | hooks?: Record;
20 | }
21 |
22 | // 界面渲染配置
23 | export interface IRenderData {
24 | title: string; // 预览页面 title
25 | enableDebugger: boolean; // 是否开启 vConsole
26 | config: { // 预览页面菜单栏配置
27 | device: string; // 设备名称
28 | // https://github.com/cocos-creator/engine/blob/3d/cocos/core/platform/debug.ts
29 | debugMode: string; // cc.DebugMode 枚举名称
30 | showFps: boolean;
31 | fps: number;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/@types/packages/programming/@types/message.d.ts:
--------------------------------------------------------------------------------
1 | export interface message extends EditorMessageMap {
2 | 'query-shared-settings': {
3 | params: [],
4 | result: {
5 | useDefineForClassFields: boolean;
6 | allowDeclareFields: boolean;
7 | loose: boolean;
8 | guessCommonJsExports: boolean;
9 | exportsConditions: string[];
10 | importMap?: {
11 | json: {
12 | imports?: Record;
13 | scopes?: Record>;
14 | };
15 | url: string;
16 | };
17 | }
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/@types/packages/scene/@types/message.d.ts:
--------------------------------------------------------------------------------
1 | import {
2 | SetPropertyOptions,
3 | } from './public';
4 |
5 | export interface message extends EditorMessageMap {
6 | 'update-create-node-template': {
7 | params: [],
8 | result: any,
9 | },
10 | 'open': {
11 | params: [],
12 | result: any,
13 | },
14 | 'open-devtools': {
15 | params: [],
16 | result: any,
17 | },
18 | 'graphical-tools': {
19 | params: [
20 | boolean,
21 | ],
22 | result: void,
23 | },
24 | 'open-scene': {
25 | params: [
26 | string,
27 | ],
28 | result: boolean,
29 | },
30 | 'save-scene': {
31 | params: [] | [
32 | boolean,
33 | ],
34 | result: boolean,
35 | },
36 | 'save-as-scene': {
37 | params: [
38 | boolean,
39 | ],
40 | result: boolean,
41 | },
42 | 'close-scene': {
43 | params: [],
44 | result: boolean,
45 | },
46 | 'set-property': {
47 | params: [
48 | SetPropertyOptions,
49 | ],
50 | result: boolean,
51 | },
52 | 'query-node-tree': {
53 | params: [] | [
54 | string,
55 | ],
56 | result: any,
57 | },
58 | 'execute-scene-script': {
59 | params: [] | [
60 | {
61 | name: string;
62 | method: string;
63 | args: any[];
64 | }
65 | ],
66 | result: any,
67 | },
68 | }
69 |
--------------------------------------------------------------------------------
/@types/packages/scene/@types/public.d.ts:
--------------------------------------------------------------------------------
1 | // ---- 一些 engine 基础数据 ---- start
2 | interface Vec2 {
3 | x: number;
4 | y: number;
5 | }
6 |
7 | export interface Vec3 {
8 | x: number;
9 | y: number;
10 | z: number;
11 | }
12 |
13 | interface Vec4 {
14 | x: number;
15 | y: number;
16 | z: number;
17 | w: number;
18 | }
19 |
20 | interface Quat {
21 | x: number;
22 | y: number;
23 | z: number;
24 | w: number;
25 | }
26 |
27 | interface Color3 {
28 | r: number;
29 | g: number;
30 | b: number;
31 | }
32 |
33 | interface Color4 {
34 | r: number;
35 | g: number;
36 | b: number;
37 | a: number;
38 | }
39 |
40 | interface Mat3 {
41 | m00: number;
42 | m01: number;
43 | m02: number;
44 |
45 | m03: number;
46 | m04: number;
47 | m05: number;
48 |
49 | m06: number;
50 | m07: number;
51 | m08: number;
52 | }
53 |
54 | interface Mat4 {
55 | m00: number;
56 | m01: number;
57 | m02: number;
58 | m03: number;
59 |
60 | m04: number;
61 | m05: number;
62 | m06: number;
63 | m07: number;
64 |
65 | m08: number;
66 | m09: number;
67 | m10: number;
68 | m11: number;
69 |
70 | m12: number;
71 | m13: number;
72 | m14: number;
73 | m15: number;
74 | }
75 | // ---- 一些 engine 基础数据 ---- end
76 |
77 | // ---- 操作消息的参数定义 --- strart
78 |
79 | // set-property 消息的 options 定义
80 | export interface SetPropertyOptions {
81 | uuid: string; // 修改属性的对象的 uuid
82 | path: string; // 属性挂载对象的搜索路径
83 | // key: string; // 属性的 key
84 | dump: IProperty; // 属性 dump 出来的数据
85 | }
86 |
87 | // move-array-element 消息的 options 定义
88 | export interface MoveArrayOptions {
89 | uuid: string;
90 | path: string;
91 | target: number;
92 | offset: number;
93 | }
94 |
95 | // remove-array-element 消息的 options 定义
96 | export interface RemoveArrayOptions {
97 | uuid: string;
98 | path: string;
99 | index: number;
100 | }
101 |
102 | export interface PasteNodeOptions {
103 | target: string; // 目标节点
104 | uuids: string | string[]; // 被复制的节点 uuids
105 | keepWorldTransform?: boolean; // 是否保持新节点的世界坐标不变
106 | }
107 |
108 | export interface CutNodeOptions {
109 | parent: string; // 父节点
110 | uuids: string | string[]; // 被移入的节点 uuids
111 | keepWorldTransform?: boolean; // 是否保持新节点的世界坐标不变
112 | }
113 |
114 | // create-node 消息的 options 定义
115 | export interface CreateNodeOptions {
116 | parent?: string;
117 | components?: string[];
118 |
119 | name?: string;
120 | dump?: INode | IScene; // node 初始化应用的数据
121 | keepWorldTransform?: boolean; // 是否保持新节点的世界坐标不变
122 | type?: string; // 资源类型
123 | assetUuid?: string; // asset uuid , type value 格式保持兼容拖动的数据格式,有资源 id,则从资源内创建对应的节点
124 | canvasRequired?: boolean; // 是否需要有 Canvas
125 | unlinkPrefab?: boolean; // 创建后取消 prefab 状态
126 | position?: Vec3; // 指定生成的位置
127 | }
128 |
129 | export interface ResetNodeOptions {
130 | uuid: string | string[];
131 | }
132 |
133 | export interface RemoveNodeOptions {
134 | uuid: string | string[];
135 | keepWorldTransform?: boolean;
136 | }
137 |
138 | export interface CreateComponentOptions {
139 | uuid: string;
140 | component: string;
141 | }
142 |
143 | export interface ResetComponentOptions {
144 | uuid: string;
145 | }
146 |
147 | export interface RemoveComponentOptions {
148 | uuid: string;
149 | component: string;
150 | }
151 |
152 | export interface ExecuteComponentMethodOptions {
153 | uuid: string;
154 | name: string;
155 | args: any[];
156 | }
157 |
158 | export interface IAnimOperation {
159 | funcName: string;
160 | args: any[];
161 | }
162 |
163 | export interface ExecuteSceneScriptMethodOptions {
164 | name: string;
165 | method: string;
166 | args: any[];
167 | }
168 |
169 | export type IPropertyValueType = IProperty | IProperty[] | null | undefined | number | boolean | string | Vec3 | Vec2;
170 |
171 | export interface IPropertyGroupOptions {
172 | id: string // 默认 'default'
173 | name: string,
174 | displayOrder: number, // 默认 Infinity, 排在最后面
175 | style: string // 默认为 'tab'
176 | }
177 |
178 | export interface IProperty {
179 | value: { [key: string]: IPropertyValueType } | IPropertyValueType;
180 | default?: any; // 默认值
181 |
182 | // 多选节点之后,这里存储多个数据,用于自行判断多选后的显示效果,无需更新该数据
183 | values?: ({ [key: string]: IPropertyValueType } | IPropertyValueType)[];
184 |
185 | cid?: string;
186 | type?: string;
187 | readonly?: boolean;
188 | visible?: boolean;
189 | name?: string;
190 |
191 | elementTypeData?: IProperty; // 数组里的数据的默认值 dump
192 |
193 | path?: string; // 数据的搜索路径,这个是由使用方填充的
194 |
195 | isArray?: boolean;
196 | invalid?: boolean;
197 | extends?: string[]; // 继承链
198 | displayName?: string; // 显示到界面上的名字
199 | displayOrder?: number; // 显示排序
200 | group?: IPropertyGroupOptions; // tab
201 | tooltip?: string; // 提示文本
202 | editor?: any; // 组件上定义的编辑器数据
203 | animatable?: boolean; // 是否可以在动画中编辑
204 |
205 | // Enum
206 | enumList?: any[]; // enum 类型的 list 选项数组
207 |
208 | bitmaskList?: any[];
209 |
210 | // Number
211 | min?: number; // 数值类型的最小值
212 | max?: number; // 数值类型的最大值
213 | step?: number; // 数值类型的步进值
214 | slide?: boolean; // 数组是否显示为滑块
215 | unit?: string; // 显示的单位
216 | radian?: boolean; // 标识是否为角度
217 |
218 | // Label
219 | multiline?: boolean; // 字符串是否允许换行
220 | // nullable?: boolean; 属性是否允许为空
221 | }
222 |
223 | export interface IRemovedComponentInfo {
224 | name: string;
225 | fileID: string;
226 | }
227 |
228 | export interface INode {
229 | active: IProperty;
230 | locked: IProperty;
231 | name: IProperty;
232 | position: IProperty;
233 |
234 | /**
235 | * 此为 dump 数据,非 node.rotation
236 | * 实际指向 node.eulerAngles
237 | * rotation 为了给用户更友好的文案
238 | */
239 | rotation: IProperty;
240 |
241 | scale: IProperty;
242 | layer: IProperty;
243 | uuid: IProperty;
244 |
245 | children: any[];
246 | parent: any;
247 |
248 | __comps__: IProperty[];
249 | __type__: string;
250 | __prefab__?: any;
251 | _prefabInstance?: any;
252 | removedComponents?: IRemovedComponentInfo[];
253 | mountedRoot?: string;
254 | }
255 |
256 | export interface IComponent extends IProperty {
257 | value: {
258 | enabled: IPropertyValueType;
259 | uuid: IPropertyValueType;
260 | name: IPropertyValueType;
261 | } & Record;
262 | mountedRoot?: string;
263 | }
264 |
265 | export interface IScene {
266 | name: IProperty;
267 | active: IProperty;
268 | locked: IProperty;
269 | _globals: any;
270 | isScene: boolean;
271 | autoReleaseAssets: IProperty;
272 |
273 | uuid: IProperty;
274 | children: any[];
275 | parent: any;
276 | __type__: string;
277 | targetOverrides?: any;
278 | }
279 |
280 | export interface ITargetOverrideInfo {
281 | source: string;
282 | sourceInfo?: string[];
283 | propertyPath: string[];
284 | target: string;
285 | targetInfo?: string[];
286 | }
287 | // ---- 操作消息的参数定义 --- end
288 |
289 | // ---- 场景插件返回的 info 信息 ---- start
290 | interface ScenePluginNodeInfo {
291 | uuid: string;
292 | components: ScenePluginComponentInfo[];
293 | }
294 |
295 | // 场景插件传回的场景信息
296 | export interface ScenePluginInfo {
297 | // 选中节点列表
298 | nodes: ScenePluginNodeInfo[];
299 |
300 | // gizmo 的一些信息
301 | gizmo: {
302 | is2D: boolean;
303 | };
304 | // 当前编辑模式数组
305 | modes: string[];
306 | }
307 |
308 | // 场景插件传回的组件信息
309 | export interface ScenePluginComponentInfo {
310 | uuid: string;
311 | enabled: boolean;
312 | type: string;
313 | }
314 |
315 | export interface QueryClassesOptions {
316 | extends?: string | string[];
317 | excludeSelf?: boolean;
318 | }
319 |
320 | // ---- 场景插件返回的 info 信息 ---- end
321 |
322 | // ---- 动画数据 ---- start
323 |
324 | export interface IKeyDumpData {
325 | frame: number;
326 | dump: any; // value的dump数据
327 | inTangent?: number;
328 | inTangentWeight?: number;
329 | outTangent?: number;
330 | outTangentWeight?: number;
331 | interpMode?: number;
332 | broken?: boolean;
333 | tangentWeightMode?: number;
334 | imgUrl?: string;
335 | easingMethod?: number;
336 | }
337 |
338 | export interface IDumpType {
339 | value: string;
340 | extends?: string[];
341 | }
342 |
343 | export interface IPropCurveDumpData {
344 | nodePath: string;
345 | keyframes: IKeyDumpData[];
346 | displayName: string;
347 | key: string;
348 | type?: IDumpType;
349 | preExtrap: number;
350 | postExtrap: number;
351 | isCurveSupport: boolean; // 是否支持贝塞尔曲线编辑
352 | }
353 |
354 | export interface IAnimCopyKeySrcInfo {
355 | curvesDump: IPropCurveDumpData[];
356 | }
357 |
358 | export interface IAnimCopyNodeSrcInfo {
359 | curvesDump: IPropCurveDumpData[];
360 | }
361 |
362 | export interface IAnimCopyNodeDstInfo {
363 | nodePath: string;
364 | }
365 |
366 | interface IEventDump {
367 | frame: number;
368 | func: string;
369 | params: string[];
370 | }
371 |
372 | export interface IAnimCopyEventSrcInfo {
373 | eventsDump: IEventDump[];
374 | }
375 |
376 | export interface IAnimCopyPropSrcInfo {
377 | curvesDump: IPropCurveDumpData[];
378 | }
379 |
380 | export interface IAnimCopyPropDstInfo {
381 | nodePath: string;
382 | propKeys?: string[];
383 | }
384 |
385 | export interface IAnimCopyKeyDstInfo {
386 | nodePath: string;
387 | propKeys?: string[];
388 | startFrame: number;
389 | }
390 |
391 | export interface IAnimCopyEventDstInfo {
392 | startFrame: number;
393 | }
394 | // ---- 动画数据 ---- end
395 |
396 | // ---- Contributions ---- start
397 |
398 | export interface ContributionDropItem {
399 | type: string;
400 | message: string;
401 | }
402 |
403 | // ---- Contributions ---- end
404 |
405 | export interface UnitTestInfo {
406 | name: string;
407 | }
408 |
--------------------------------------------------------------------------------
/@types/packages/server/@types/package.d.ts:
--------------------------------------------------------------------------------
1 | // 消息定义
2 | interface MessageInterface {
3 | params: any[],
4 | result: any;
5 | }
6 |
7 | // host
8 | export interface HostInfo {
9 | host: string;
10 | ip: string;
11 | port: number;
12 | }
13 |
14 | // 消息定义
15 | export interface main {
16 | scene: {
17 | [x: string]: MessageInterface;
18 | 'query-port': {
19 | params: [],
20 | result: number,
21 | };
22 | 'scan-lan': {
23 | params: [],
24 | result: HostInfo[],
25 | };
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/@types/packages/shortcuts/@types/shortcut.d.ts:
--------------------------------------------------------------------------------
1 | export interface ShortcutItem {
2 | when: string;
3 | message: string;
4 | shortcut: string;
5 | pkgName: string;
6 | rawShortcut?: string;
7 | key: string;
8 | missing?: boolean;
9 | }
10 |
11 | export type IShortcutItemMap = Record;
12 |
13 | export interface IShortcutEditInfo {
14 | key: string;
15 | shortcut: string;
16 | searches: ShortcutItem[];
17 | conflict: boolean;
18 | when: string;
19 | }
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 热更新插件
2 | ## 功能介绍
3 | - 官方热更方案融合到 Creator 构建流程中.
4 | - 插件支持平台: Windows & MacOS.
5 | - 构建热更支持的平台: iOS & android & windows & mac
6 | - 构建后自动拷贝资源文件, 生成 version.manifest、project.manifest 文件.
7 | - 自动在构建后的 main.js 中注入添加搜索目录代码.
8 | - 支持命令行构建, 进而可支持 Jenkins 等 CI 工具.
9 |
10 |
11 | ## 测试 Demo
12 | - 测试 Demo, 基于官方热更 Demo 修改
13 |
14 | Android 测试包, 使用 Creator 3.3.0 社区版构建, 热更重启时会 Crash, 不影响测试热更.
15 |
16 | [https://cocos.alphayan.cn/apk/tutorial-hot-update-debug.apk](https://cocos.alphayan.cn/apk/tutorial-hot-update-debug.apk)
17 |
18 | 测试工程, 上面测试包项目地址.
19 |
20 | [https://github.com/yanjifa/tutorial-hot-update](https://github.com/yanjifa/tutorial-hot-update)
21 |
22 | ## 使用教程
23 |
24 | - 手动构建:
25 | * [菜单->项目->构建发布->选择支持的发布平台] 会看到如下图的设置界面.
26 | * 勾选生成热更数据选框.
27 | * 资源服务地址对应 CDN 的域名等.
28 | * 设置 [热更存储名], 热更文件存储目录, 会自动加入到 searchPath.
29 |
30 | 
31 |
32 |
33 | - 命令行构建:
34 | * 配置格式和说明
35 | ```json
36 | // 命令行构建, packages 对应配置, 对应选项不传则使用默认配置
37 | {
38 | "hot-update": {
39 | // 是否构建热更数据
40 | "hotUpdateEnable": true,
41 | // 热更服务地址, CDN 地址...
42 | "remoteAddress": "http://192.168.123.108/",
43 | // 热更文件存储目录, 会自动加入到 searchPath,
44 | "storagePath": "hotupdate_storage",
45 | // 版本号
46 | "version": "1.0.0",
47 | // jenkins buildNum | 或其他构建工具
48 | "buildNum": 1
49 | }
50 | }
51 | ```
52 | * 构建命令示例
53 | ```bash
54 | # 构建参数 packages=JSON.stringify(`{"hot-update": {"hotUpdateEnable": true, ...}}`)
55 | /Applications/CocosCreator/Creator/3.3.0/CocosCreator.app/Contents/MacOS/CocosCreator --project /Volumes/WorkSpace/tutorial-hot-update --build "platform=android;packages={\"hot-update\":{\"hotUpdateEnable\":true,\"remoteAddress\":\"http://192.168.123.108/\",\"version\":\"1.0.0\",\"buildNum\":3}}"
56 | ```
57 | - 注意事项:
58 | - 创建 AssetsManager 不传比较函数的话, 热更新版本号不要填写超过 3 位数字, 因为插件会把 buildNum 拼到最后一位, C++ 中的默认比较函数只取 版本号的前 4 个数字进行比较.
59 |
60 | ## 构建结果
61 | - 构建后在项目目录下自动生成热更新文件, 目录结构如下:
62 |
63 | ```js
64 | .
65 | ├── hotupdate-assets // 热更新文件根目录, 插件创建
66 | │ └── android // 对应构建平台, 上传 CDN 需从此目录开始上传
67 | │ ├── 1.0.0.1 // 版本号 + buildNum
68 | │ │ ├── assets
69 | │ │ ├── jsb-adapter
70 | │ │ ├── project.manifest
71 | │ │ └── src
72 | │ ├── 1.0.0.3
73 | │ │ ├── assets
74 | │ │ ├── jsb-adapter
75 | │ │ ├── project.manifest
76 | │ │ └── src
77 | │ ├── project.manifest // 每次都会被替换为最新一次构建结果
78 | │ └── version.manifest // 每次都会被替换为最新一次构建结果
79 | ├── package.json
80 | └── tsconfig.json
81 | ```
82 | - project.manifest 构建结果示例
83 | ```json
84 | {
85 | // 实际下载资源的 url 为: packageUrl + assets[key]
86 | // 例如 http://192.168.123.108/android/1.0.0.3/src/application.js
87 | "packageUrl": "http://192.168.123.108/android/1.0.0.3",
88 | "version": "1.0.0.3",
89 | "searchPaths": [
90 | "hotupdate_storage"
91 | ],
92 | "remoteManifestUrl": "http://192.168.123.108/android/project.manifest",
93 | "remoteVersionUrl": "http://192.168.123.108/android/version.manifest",
94 | "assets": {
95 | "src/application.js": {
96 | "size": 5738,
97 | "md5": "aaf093a660c5fa8e6559e264a0eaeed3"
98 | },
99 | "其余资源文件省略": {}
100 | }
101 | }
102 | ```
103 | - main.js 脚本注入热更相关代码,添加搜索路径, 主要逻辑参考官方热更 Demo
104 | ```js
105 | // inject by extensions hot-update ---- start ----
106 | jsb.fileUtils.addSearchPath(jsb.fileUtils.getWritablePath() + "hotupdate_storage", true);
107 | var fileList = [];
108 | var storagePath = "hotupdate_storage";
109 | var tempPath = storagePath + "_temp/";
110 | var baseOffset = tempPath.length;
111 |
112 | if (jsb.fileUtils.isDirectoryExist(tempPath) && !jsb.fileUtils.isFileExist(tempPath + 'project.manifest.temp')) {
113 | jsb.fileUtils.listFilesRecursively(tempPath, fileList);
114 | fileList.forEach(srcPath => {
115 | var relativePath = srcPath.substr(baseOffset);
116 | var dstPath = storagePath + relativePath;
117 | if (srcPath[srcPath.length - 1] === "/") {
118 | jsb.fileUtils.createDirectory(dstPath)
119 | } else {
120 | if (jsb.fileUtils.isFileExist(dstPath)) {
121 | jsb.fileUtils.removeFile(dstPath)
122 | }
123 | jsb.fileUtils.renameFile(srcPath, dstPath);
124 | }
125 | })
126 | jsb.fileUtils.removeDirectory(tempPath);
127 | }
128 | // inject by extensions hot-update ---- end ----
129 |
130 | // SystemJS support.
131 | window.self = window;
132 | require("src/system.bundle.js");
133 |
134 | const importMapJson = jsb.fileUtils.getStringFromFile("src/import-map.json");
135 | const importMap = JSON.parse(importMapJson);
136 | System.warmup({
137 | importMap,
138 | importMapUrl: 'src/import-map.json',
139 | defaultHandler: (urlNoSchema) => {
140 | require(urlNoSchema.startsWith('/') ? urlNoSchema.substr(1) : urlNoSchema);
141 | },
142 | });
143 |
144 | System.import('./src/application.js').then(({ createApplication }) => {
145 | return createApplication({
146 | loadJsListFile: (url) => require(url),
147 | });
148 | }).then((application) => {
149 | return application.import('cc').then((cc) => {
150 | require('jsb-adapter/jsb-engine.js');
151 | cc.macro.CLEANUP_IMAGE_CACHE = false;
152 | }).then(() => {
153 | return application.start({
154 | settings: window._CCSettings,
155 | findCanvas: () => {
156 | var container = document.createElement('div');
157 | var frame = document.documentElement;
158 | var canvas = window.__canvas;
159 | return { frame, canvas, container };
160 | },
161 | });
162 | });
163 | }).catch((err) => {
164 | console.error(err.toString());
165 | });
166 | ```
167 |
--------------------------------------------------------------------------------
/cocos-install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # 编译
4 | tsc
5 | # 删除
6 | rm -rf "$HOME"/.CocosCreator/extensions/hot-update
7 | # 创建目录
8 | mkdir "$HOME"/.CocosCreator/extensions/hot-update
9 | # 拷贝
10 | cp -a ./package.json "$HOME"/.CocosCreator/extensions/hot-update
11 | cp -a ./dist "$HOME"/.CocosCreator/extensions/hot-update
12 | cp -a ./i18n "$HOME"/.CocosCreator/extensions/hot-update
13 | echo "Install Extension HotUpdate To CocosCreator Done"
14 |
--------------------------------------------------------------------------------
/cocos-pack.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 编译
3 | tsc
4 | # 删除
5 | rm -rf ./hot-update.zip
6 | # 创建目录
7 | mkdir ./hot-update
8 | # 拷贝
9 | cp -a ./package.json ./hot-update
10 | cp -a ./dist ./hot-update
11 | cp -a ./i18n ./hot-update
12 | # 压缩
13 | cd ./hot-update
14 | zip -r -m ../hot-update.zip *
15 | cd ..
16 | rm -rf hot-update
17 | echo "pack done"
18 |
--------------------------------------------------------------------------------
/i18n/en.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | description: 'Generate HotUpdate Files For Native Build',
3 | title: 'HotUpdate',
4 | builder: {
5 | hotupdate_enable: 'Generate HotUpdate Files',
6 | remote_address: 'Remote Address',
7 | build_num: 'Build Num',
8 | build_num_desc: 'From CI/CD tool, Like Jenkins',
9 | hotupdate_version: 'HotUpdate Version',
10 | hotupdate_version_desc: 'Max 3 ',
11 | hotupdate_version_verify_msg: 'Version is Valid',
12 | hotupdate_storage: 'Hotupdate Storage',
13 | hotupdate_storage_desc: 'Hotupdate Storage Dir Name',
14 | hotupdate_storage_verify_msg: 'Hotupdate Storage is Valid',
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/i18n/zh.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | description: '为构建原生平台项目, 生成热更新数据',
3 | title: '热更新',
4 | builder: {
5 | hotupdate_enable: '生成热更新数据',
6 | remote_address: '资源服务地址',
7 | build_num: 'Build Num',
8 | build_num_desc: 'CI/CD 工具提供, 比如 Jenkins',
9 | hotupdate_version: '热更新版本号',
10 | hotupdate_version_desc: '不要超过 3 位',
11 | hotupdate_version_verify_msg: '版本号有效',
12 | hotupdate_storage: '热更存储名',
13 | hotupdate_storage_desc: '热更新存储目录 & 搜索路径, 不要带斜杠',
14 | hotupdate_storage_verify_msg: '热更存储名有效',
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/images/builder_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yanjifa/cocos-ext-hot-update/89ad3f88352680ec95485ee3986c78beb44a5b2f/images/builder_setting.png
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hot-update",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@types/fs-extra": {
8 | "version": "5.1.0",
9 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz",
10 | "integrity": "sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ==",
11 | "dev": true,
12 | "requires": {
13 | "@types/node": "*"
14 | }
15 | },
16 | "@types/node": {
17 | "version": "14.17.4",
18 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz",
19 | "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==",
20 | "dev": true
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hot-update",
3 | "title": "i18n:hot-update.title",
4 | "package_version": 2,
5 | "version": "2.0.1",
6 | "author": "yanjifa",
7 | "editor": ">=3.0.0",
8 | "scripts": {
9 | "build": "tsc -b",
10 | "watch": "tsc -w",
11 | "cocos-install": "./cocos-install.sh",
12 | "cocos-pack": "./cocos-pack.sh"
13 | },
14 | "description": "i18n:hot-update.description",
15 | "main": "./dist/browser.js",
16 | "contributions": {
17 | "builder": "./dist/builder.js"
18 | },
19 | "devDependencies": {
20 | "@types/fs-extra": "^5.0.4",
21 | "@types/node": "^14.5.2"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/browser.ts:
--------------------------------------------------------------------------------
1 | const packageJSON = require('../package.json');
2 | // 必须保持和 package.json 一样
3 | export const PACKAGE_NAME = packageJSON.name;
4 |
5 | export function log(...arg: unknown[]) {
6 | return console.log(`[${PACKAGE_NAME}] `, ...arg);
7 | }
8 |
9 | export function load() {
10 | // log("browser loaded!");
11 | }
12 |
13 | export function unload() {
14 | // log("browser unload!");
15 | }
16 |
17 | export const methods = {
18 | //
19 | };
20 |
--------------------------------------------------------------------------------
/src/builder.ts:
--------------------------------------------------------------------------------
1 |
2 | import { BuildPlugin, IBuildPluginConfig } from '../@types';
3 |
4 | export const load: BuildPlugin.load = function () {
5 | // log("builder loaded!");
6 | }
7 |
8 | export const unload: BuildPlugin.Unload = function() {
9 | // log("builder unload!");
10 | }
11 |
12 | const buildPlugin: IBuildPluginConfig = {
13 | hooks: './hooks',
14 | options: {
15 | hotUpdateEnable: {
16 | label: 'i18n:hot-update.builder.hotupdate_enable',
17 | default: false,
18 | render: {
19 | ui: 'ui-checkbox'
20 | },
21 | verifyRules: [],
22 | },
23 | remoteAddress: {
24 | label: 'i18n:hot-update.builder.remote_address',
25 | description: 'i18n:hot-update.builder.remote_address',
26 | default: 'http://127.0.0.1',
27 | render: {
28 | ui: 'ui-input',
29 | attributes: {
30 | placeholder: 'i18n:hot-update.builder.remote_address',
31 | },
32 | },
33 | verifyRules: ['http'],
34 | },
35 | storagePath: {
36 | label: 'i18n:hot-update.builder.hotupdate_storage',
37 | description: 'i18n:hot-update.builder.hotupdate_storage_desc',
38 | default: 'hotupdate_storage',
39 | render: {
40 | ui: 'ui-input',
41 | attributes: {
42 | placeholder: 'i18n:hot-update.builder.hotupdate_storage_desc',
43 | },
44 | },
45 | verifyRules: ['isValidStorage'],
46 | },
47 | version: {
48 | label: 'i18n:hot-update.builder.hotupdate_version',
49 | description: 'i18n:hot-update.builder.hotupdate_version_desc',
50 | default: '1.0.0',
51 | render: {
52 | ui: 'ui-input',
53 | attributes: {
54 | placeholder: 'i18n:hot-update.builder.hotupdate_version_desc',
55 | },
56 | },
57 | verifyRules: ['isValidVersion'],
58 | },
59 | buildNum: {
60 | label: 'i18n:hot-update.builder.build_num',
61 | description: 'i18n:hot-update.builder.build_num_desc',
62 | default: 1,
63 | render: {
64 | ui: 'ui-num-input',
65 | attributes: {
66 | step: 1,
67 | min: 1,
68 | preci: 0,
69 | },
70 | },
71 | verifyRules: [],
72 | },
73 | },
74 | verifyRuleMap: {
75 | isValidVersion: {
76 | message: 'i18n:hot-update.builder.hotupdate_version_verify_msg',
77 | func(val, option) {
78 | if (val) {
79 | return true;
80 | }
81 | return false;
82 | },
83 | },
84 | isValidStorage: {
85 | message: 'i18n:hot-update.builder.hotupdate_storage_verify_msg',
86 | func(val, option) {
87 | if (val) {
88 | return true;
89 | }
90 | return false;
91 | },
92 | },
93 | },
94 | };
95 |
96 | export const configs: BuildPlugin.Configs = {
97 | 'ios': buildPlugin,
98 | 'mac': buildPlugin,
99 | 'android': buildPlugin,
100 | 'windows': buildPlugin,
101 | };
102 |
--------------------------------------------------------------------------------
/src/hooks.ts:
--------------------------------------------------------------------------------
1 | import * as crypto from 'crypto';
2 | import * as fs from 'fs';
3 | import * as path from 'path';
4 | import { IBuildResult, IBuildTaskOption } from '../@types';
5 | import { log, PACKAGE_NAME } from './browser';
6 |
7 | interface IFileStat {
8 | filePath: string;
9 | size: number;
10 | }
11 | interface IAsset {
12 | size: number;
13 | md5: string;
14 | compressed?: boolean
15 | }
16 | interface IAssets {
17 | [key: string]: IAsset;
18 | }
19 | interface IManifest {
20 | packageUrl: string;
21 | remoteManifestUrl: string;
22 | remoteVersionUrl: string;
23 | version: string;
24 | assets?: IAssets,
25 | searchPaths?: string[],
26 | }
27 | interface IPluginOptions {
28 | hotUpdateEnable: boolean;
29 | remoteAddress: string;
30 | storagePath: string;
31 | version: string;
32 | buildNum: number;
33 | }
34 |
35 | export async function load() {
36 | // log('Load in builder.');
37 | // allAssets = await Editor.Message.request('asset-db', 'query-assets');
38 | }
39 |
40 | export function unload() {
41 | // log('Unload in builder.');
42 | }
43 |
44 | export async function onBeforeBuild(options: IBuildTaskOption) {
45 | //
46 | }
47 |
48 | export async function onBeforeBuildAssets(options: IBuildTaskOption, result: IBuildResult) {
49 | //
50 | }
51 |
52 | export async function onAfterBuildAssets(options: IBuildTaskOption, result: IBuildResult) {
53 | generateEmptManifest(options, result);
54 | }
55 |
56 | export async function onBeforeCompressSettings(options: IBuildTaskOption, result: IBuildResult) {
57 | //
58 | }
59 |
60 | export async function onAfterCompressSettings(options: IBuildTaskOption, result: IBuildResult) {
61 | //
62 | }
63 |
64 | export async function onAfterBuild(options: IBuildTaskOption, result: IBuildResult) {
65 | injectMainScript(options, result);
66 | generateManifest(options, result);
67 | }
68 |
69 | export async function onBeforeMake(options: IBuildTaskOption, result: IBuildResult) {
70 | //
71 | }
72 |
73 | export async function onAfterMake(options: IBuildTaskOption, result: IBuildResult) {
74 | //
75 | }
76 |
77 | /**
78 | * 注入脚本
79 | * @param options
80 | */
81 | function injectMainScript(options: IBuildTaskOption, result: IBuildResult) {
82 | const packageOptions: IPluginOptions = options.packages?.[PACKAGE_NAME];
83 | if (!packageOptions.hotUpdateEnable) {
84 | return;
85 | }
86 | const mainScriptPath = path.resolve(`${result.paths.dir}/main.js`);
87 | let mainScript = fs.readFileSync(mainScriptPath).toString('utf-8');
88 |
89 | mainScript =
90 | `// inject by extensions ${PACKAGE_NAME} ---- start ----
91 | jsb.fileUtils.addSearchPath(jsb.fileUtils.getWritablePath() + "${packageOptions.storagePath}", true);
92 | var fileList = [];
93 | var storagePath = "${packageOptions.storagePath}";
94 | var tempPath = storagePath + "_temp/";
95 | var baseOffset = tempPath.length;
96 |
97 | if (jsb.fileUtils.isDirectoryExist(tempPath) && !jsb.fileUtils.isFileExist(tempPath + 'project.manifest.temp')) {
98 | jsb.fileUtils.listFilesRecursively(tempPath, fileList);
99 | fileList.forEach(srcPath => {
100 | var relativePath = srcPath.substr(baseOffset);
101 | var dstPath = storagePath + relativePath;
102 | if (srcPath[srcPath.length - 1] === "/") {
103 | jsb.fileUtils.createDirectory(dstPath)
104 | } else {
105 | if (jsb.fileUtils.isFileExist(dstPath)) {
106 | jsb.fileUtils.removeFile(dstPath)
107 | }
108 | jsb.fileUtils.renameFile(srcPath, dstPath);
109 | }
110 | })
111 | jsb.fileUtils.removeDirectory(tempPath);
112 | }
113 | // inject by extensions ${PACKAGE_NAME} ---- end ----` + mainScript;
114 |
115 | fs.writeFileSync(mainScriptPath, mainScript);
116 | log('inject main script success');
117 | }
118 |
119 |
120 | /**
121 | * 先生成 project.manifest, 存到 assets 目录下, 后面再替换, 主要不确定这时生成热更配置, 是不是最终的
122 | * 解决 ios | mac, cmake 生成的工程文件资源里缺少这两个文件
123 | *
124 | * @param options
125 | */
126 | function generateEmptManifest(options: IBuildTaskOption, result: IBuildResult) {
127 | const packageOptions: IPluginOptions = options.packages?.[PACKAGE_NAME];
128 | if (!packageOptions.hotUpdateEnable) {
129 | return;
130 | }
131 | const assetsRootPath = result.paths.dir;
132 | const projectManifestName = 'project.manifest';
133 | const destManifestPath = path.join(assetsRootPath, projectManifestName);
134 | fs.writeFileSync(destManifestPath, JSON.stringify({}));
135 | log('generateEmptManifest success');
136 | }
137 |
138 | /**
139 | * 生成热更文件
140 | * @param options
141 | */
142 | function generateManifest(options: IBuildTaskOption, result: IBuildResult) {
143 | const packageOptions: IPluginOptions = options.packages?.[PACKAGE_NAME];
144 | if (!packageOptions.hotUpdateEnable) {
145 | return;
146 | }
147 | let remoteUrl = packageOptions.remoteAddress;
148 | if (remoteUrl.endsWith('/')) {
149 | remoteUrl = remoteUrl.slice(0, -1);
150 | }
151 | // build num | from 1 to max
152 | const buildNum = !isNaN(Number(packageOptions.buildNum)) ? Number(packageOptions.buildNum) : 1;
153 | const hotupdateVersion = `${packageOptions.version.trim()}.${buildNum.toFixed()}`;
154 | const projectPath = Editor.Project.path;
155 | const assetsRootPath = result.paths.dir;
156 | //
157 | const projectManifestName = 'project.manifest';
158 | const versionManifestName = 'version.manifest';
159 | //
160 | let destManifestPath = path.join(assetsRootPath, projectManifestName);
161 | // 前面那步用完了, 这里先删掉, 生成 project.manifest 不希望有这个文件的记录
162 | fs.unlinkSync(destManifestPath);
163 | // 构建后默认资源目录
164 | const assetsPaths = ['src', 'assets', 'jsb-adapter'];
165 | // 初始化 manifest
166 | const packageUrl = `${remoteUrl}/${options.platform}/${hotupdateVersion}`;
167 | const manifest: IManifest = {
168 | packageUrl: encodeURI(packageUrl),
169 | version: hotupdateVersion,
170 | searchPaths: [packageOptions.storagePath],
171 | remoteManifestUrl: encodeURI(`${remoteUrl}/${options.platform}/${projectManifestName}`),
172 | remoteVersionUrl: encodeURI(`${remoteUrl}/${options.platform}/${versionManifestName}`),
173 | assets: {},
174 | };
175 | // 获取目录内所有文件
176 | const listDir = (assetPath: string) => {
177 | const fileList: IFileStat[] = [];
178 | const stat = fs.statSync(assetPath);
179 | if (stat.isDirectory()) {
180 | const subpaths = fs.readdirSync(assetPath);
181 | for (let i = 0; i < subpaths.length; i++) {
182 | let subpath = subpaths[i];
183 | if (subpath[0] === '.') {
184 | continue;
185 | }
186 | subpath = path.join(assetPath, subpath);
187 | fileList.push(...listDir(subpath));
188 | }
189 | } else if (stat.isFile()) {
190 | fileList.push({
191 | filePath: assetPath,
192 | size: stat.size,
193 | });
194 | }
195 | return fileList;
196 | };
197 | // 创建目录
198 | const mkdirSync = (dirName: string) => {
199 | try {
200 | fs.mkdirSync(dirName);
201 | } catch (e: any) {
202 | if (e.code !== 'EEXIST') throw e;
203 | }
204 | };
205 | // 递归删除目录及文件
206 | const deleteDirSync = (dirName: string) => {
207 | let files = [];
208 | if (fs.existsSync(dirName)) {
209 | // 返回文件和子目录的数组
210 | files = fs.readdirSync(dirName);
211 | files.forEach((file) => {
212 | const curPath = path.join(dirName, file);
213 | // fs.statSync同步读取文件夹文件,如果是文件夹,在重复触发函数
214 | if (fs.statSync(curPath).isDirectory()) {
215 | deleteDirSync(curPath);
216 | } else {
217 | fs.unlinkSync(curPath);
218 | }
219 | });
220 | // 清除文件夹
221 | fs.rmdirSync(dirName);
222 | }
223 | }
224 | // Iterate assets and src folder
225 | const assetsList: IFileStat[] = [];
226 | assetsPaths.forEach((o) => {
227 | assetsList.push(...listDir(path.join(assetsRootPath, o)));
228 | });
229 | // 填充 manifest.assets 对象
230 | let md5: string, compressed: boolean, assetUrl: string;
231 | const assetsObj: IAssets = {};
232 | assetsList.forEach((assetStat) => {
233 | md5 = crypto.createHash('md5').update(fs.readFileSync(assetStat.filePath)).digest('hex');
234 | compressed = path.extname(assetStat.filePath).toLowerCase() === '.zip';
235 | assetUrl = path.relative(assetsRootPath, assetStat.filePath);
236 | assetUrl = assetUrl.replace(/\\/g, '/');
237 | assetUrl = encodeURI(assetUrl);
238 | assetsObj[assetUrl] = {
239 | size: assetStat.size,
240 | md5: md5,
241 | };
242 | if (compressed) {
243 | assetsObj[assetUrl].compressed = true;
244 | }
245 | });
246 | manifest.assets = assetsObj;
247 | // 热更构建结果存储目录
248 | let hotupdateAssetsPath = path.join(projectPath, 'hotupdate-assets');
249 | mkdirSync(hotupdateAssetsPath);
250 | const manifestPath = path.join(hotupdateAssetsPath, options.platform);
251 | mkdirSync(manifestPath);
252 | hotupdateAssetsPath = path.join(manifestPath, hotupdateVersion);
253 | mkdirSync(hotupdateAssetsPath);
254 | // 如果目录不为空, 先清除
255 | deleteDirSync(hotupdateAssetsPath);
256 | // 保存 project.manifest 到磁盘
257 | fs.writeFileSync(destManifestPath, JSON.stringify(manifest));
258 | destManifestPath = path.join(manifestPath, projectManifestName);
259 | fs.writeFileSync(destManifestPath, JSON.stringify(manifest));
260 | log('Manifest successfully generated');
261 |
262 | delete manifest.assets;
263 | delete manifest.searchPaths;
264 |
265 | // 保存 version.manifest 到磁盘
266 | const destVersionPath = path.join(manifestPath, versionManifestName);
267 | fs.writeFileSync(destVersionPath, JSON.stringify(manifest));
268 | log('Version successfully generated');
269 | // 拷贝构建后的热更资源
270 | assetsPaths.push(projectManifestName);
271 | assetsPaths.forEach((assetPath) => {
272 | const destPath = path.join(hotupdateAssetsPath, assetPath);
273 | assetPath = path.join(assetsRootPath, assetPath);
274 | // 拷贝
275 | Build.Utils.copyDirSync(assetPath, destPath);
276 | });
277 | log('copy assets success');
278 | }
279 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "strict": true,
5 | "module": "commonjs",
6 | "inlineSourceMap": false,
7 | "outDir": "./dist",
8 | "rootDir": "./src",
9 | "lib": ["dom", "es7"],
10 | "esModuleInterop": true,
11 | "skipLibCheck": true,
12 | },
13 | "exclude": ["./dist"],
14 | "include": ["./src"]
15 | }
16 |
--------------------------------------------------------------------------------