feat: 支持UI包从指定的Asset Bundle中加载

- 现在可以为每个FairyGUI包配置其所在的Asset Bundle名称。
- WindowManager和WindowResPool已更新,以处理从不同bundle加载UI包的逻辑。
- 这使得UI资源可以不打包在中,方便进行更灵活的资源管理和分包加载。
This commit is contained in:
gongxh 2025-07-15 14:31:00 +08:00
parent c77e047fe7
commit bc77e45562
4 changed files with 60 additions and 14 deletions

View File

@ -7,6 +7,10 @@
interface IPackageConfig {
/** UI所在resources中的路径 */
uiPath: string;
/** 如果UI不在 resources 中,则需要配置 所在bundle下的路径名*/
bundlePaths?: { [bundleName: string]: string };
/**
*
* 1. UI包,

View File

@ -40,6 +40,8 @@ export namespace _uidecorator {
pkg: string;
/** 窗口名 */
name: string;
/** 窗口bundle名 */
bundle: string;
};
}
/** 用来存储窗口注册信息 @internal */
@ -56,7 +58,7 @@ export namespace _uidecorator {
* @param {string} pkgName fgui包名
* @param {string} name (fgui中的组件名一一对应)
*/
export function uiclass(groupName: string, pkgName: string, name: string): Function {
export function uiclass(groupName: string, pkgName: string, name: string, bundle?: string): Function {
/** target 类的构造函数 */
return function (ctor: any): void {
// debug(`uiclass >${JSON.stringify(res)}<`);
@ -71,6 +73,7 @@ export namespace _uidecorator {
group: groupName,
pkg: pkgName,
name: name,
bundle: bundle || "",
},
});
};
@ -127,6 +130,8 @@ export namespace _uidecorator {
pkg: string;
/** 组件名 */
name: string;
/** headerbundle名 */
bundle: string;
};
}
/** 用来存储组件注册信息 @internal */
@ -142,7 +147,7 @@ export namespace _uidecorator {
* @param {string} pkg
* @param {string} name
*/
export function uiheader(pkg: string, name: string): Function {
export function uiheader(pkg: string, name: string, bundle?: string): Function {
return function (ctor: any): void {
// log(`pkg:【${pkg}】 uiheader prop >${JSON.stringify(ctor[UIPropMeta] || {})}<`);
uiheaderMap.set(ctor, {
@ -154,6 +159,7 @@ export namespace _uidecorator {
res: {
pkg: pkg,
name: name,
bundle: bundle || "",
}
});
};

View File

@ -213,13 +213,13 @@ export class WindowManager {
// 窗口注册
for (const { ctor, res } of _uidecorator.getWindowMaps().values()) {
debug(`窗口注册 窗口名:${res.name} 包名:${res.pkg} 组名:${res.group}`);
this._resPool.add(ctor, res.group, res.pkg, res.name);
this._resPool.add(ctor, res.group, res.pkg, res.name, res.bundle);
}
// 窗口header注册
for (const { ctor, res } of _uidecorator.getHeaderMaps().values()) {
debug(`header注册 header名:${res.name} 包名:${res.pkg}`);
this._resPool.addHeader(ctor, res.pkg, res.name);
this._resPool.addHeader(ctor, res.pkg, res.name, res.bundle);
}
// 组件注册
ComponentExtendHelper.register();

View File

@ -4,6 +4,7 @@
* @Description:
*/
import { assetManager, resources } from "cc";
import { UIObjectFactory, UIPackage } from "fairygui-cc";
import { warn } from "../kunpocc";
import { IPackageConfigRes } from "./IPackageConfig";
@ -17,11 +18,17 @@ export interface WindowInfo {
pkg: string;
/** 窗口名 */
name: string;
/** bundle名 */
bundle: string;
}
export interface HeaderInfo {
/** 类的构造函数 */
ctor: any;
/** fgui包名 */
pkg: string;
/** bundle名 */
bundle: string;
}
/** @internal */
@ -30,6 +37,8 @@ export class WindowResPool {
protected _windowInfos: Map<string, WindowInfo> = new Map<string, any>();
/** 窗口header信息池 @internal */
protected _headerInfos: Map<string, HeaderInfo> = new Map<string, any>();
/** UI包所在的bundle名 */
private _pkgBundles: Map<string, string> = new Map<string, string>();
/** 是否设置过配置内容 @internal */
private _isInit: boolean = false;
@ -37,8 +46,12 @@ export class WindowResPool {
private _windowPkgs: Map<string, string[]> = new Map();
/** 包的引用计数 @internal */
private _pkgRefs: { [pkg: string]: number } = {};
/** UI包路径 @internal */
private _uipath: string = "";
// private _uipath: string = "";
/** UI包在bundle中的路径 @internal */
private _uiPaths: { [bundle: string]: string } = {};
/** 手动管理的包 @internal */
private _manualPackages: Set<string> = new Set();
/** 立即释放的包 @internal */
@ -58,7 +71,7 @@ export class WindowResPool {
*
* @param info
*/
public add(ctor: any, group: string, pkg: string, name: string): void {
public add(ctor: any, group: string, pkg: string, name: string, bundle: string): void {
if (this.has(name)) {
return;
}
@ -66,8 +79,10 @@ export class WindowResPool {
ctor: ctor,
group: group,
pkg: pkg,
name: name
name: name,
bundle: bundle
});
this._pkgBundles.set(pkg, bundle || "resources");
this.addWindowPkg(name, pkg);
// 窗口组件扩展
UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
@ -88,14 +103,16 @@ export class WindowResPool {
* header信息
* @param info
*/
public addHeader(ctor: any, pkg: string, name: string): void {
public addHeader(ctor: any, pkg: string, name: string, bundle: string): void {
if (this.hasHeader(name)) {
return;
}
this._headerInfos.set(name, {
ctor: ctor,
pkg: pkg
pkg: pkg,
bundle: bundle
});
this._pkgBundles.set(pkg, bundle || "resources");
// 窗口header扩展
UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
}
@ -124,10 +141,13 @@ export class WindowResPool {
this._hideWaitWindow = res?.hideWaitWindow;
this._fail = res?.fail;
this._uipath = res.config?.uiPath || "";
// 如果uipath不以/结尾 则添加/
if (this._uipath != "" && !this._uipath.endsWith("/")) {
this._uipath += "/";
this._uiPaths = res.config?.bundlePaths || {};
this._uiPaths["resources"] = res.config?.uiPath || "";
for (const bundle in this._uiPaths) {
if (this._uiPaths[bundle] != "" && !this._uiPaths[bundle].endsWith("/")) {
this._uiPaths[bundle] += "/";
}
}
this._manualPackages = new Set(res.config.manualPackages || []);
@ -249,7 +269,12 @@ export class WindowResPool {
return;
}
for (const pkg of needLoadPkgs) {
UIPackage.loadPackage(this._uipath + pkg, (err: any) => {
let bundleName = this.getPkgBundle(pkg);
let bundle = bundleName === "resources" ? resources : assetManager.getBundle(bundleName);
if (!bundle) {
throw new Error(`UI包【${pkg}】所在的bundle【${bundleName}】未加载`);
}
UIPackage.loadPackage(bundle, this.getPkgPath(pkg), (err: any) => {
total--;
err ? failPkgs.push(pkg) : successPkgs.push(pkg);
if (total > 0) {
@ -264,6 +289,17 @@ export class WindowResPool {
}
}
/** 获取UI包所在的bundle名 */
private getPkgBundle(pkg: string): string {
return this._pkgBundles.get(pkg) || "resources";
}
/** 获取UI包在bundle中的路径 */
private getPkgPath(pkg: string): string {
let bundle = this._pkgBundles.get(pkg);
return this._uiPaths[bundle] + pkg;
}
/** 获取窗口对应的包名列表 */
private getWindowPkgs(windowName: string): string[] {
if (this._windowPkgs.has(windowName)) {