├── .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 | ![builder_setting](images/builder_setting.png) 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 | --------------------------------------------------------------------------------