mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-06-23 19:22:47 +08:00
新增与优化核心模块 🎯 GUI 交互增强 ButtonInterceptor:按钮点击事件劫持器 劫持 EventHandler.emitEvents / ButtonSimple.onClick 核心方法 支持多类型按钮音效配置注册,按按钮类型自动匹配音效 单例模式管理,支持全局动态激活 / 停用拦截功能 🧩 对象池管理系统 GameNodePool:通用游戏节点对象池管理器 基于预制体(Prefab)UUID 实现池化隔离管理 支持特效、UI 元素等高频对象预加载、复用与回收 全局单例访问,统一管控对象创建 / 销毁逻辑 🔊 音频管理系统 AudioManager:音频核心管理器 独立背景音乐(AudioMusic)+ 音效池(AudioEffectPool)双模块 支持全局音量控制、播放状态恢复与场景切换管理 AudioEffect:基础音效播放器 AudioEnum:音频类型、音效分类枚举定义 📦 资源加载系统 ResLoader:资源加载核心控制器 资源包(Bundle)统一管理 + 并发加载限流控制 远程资源本地缓存、自动释放与内存优化 完整加载进度回调 + 错误异常处理机制 ResTypes:资源类型规范定义 ResErrors:资源加载错误码与异常处理 ResUtils:资源路径、格式转换等工具方法 🧱 模块化组件系统 GameComponent:游戏显示对象组件基类 集成资源自动引用计数(RC)管理 模块化部件(GamePartRegistry)插拔式架构 内置音频、按钮、事件、键盘、节点、对象池、资源七大部件 部件封装: GamePartAudio:音频功能部件 GamePartButton:按钮交互部件 GamePartEvent:全局事件部件 GamePartKeyboard:键盘输入部件 GamePartNode:节点操作部件 GamePartNodePool:对象池调用部件 GamePartRes:资源加载部件 📝 类型定义完善 新增 IAudio 音频数据与播放参数接口 统一全模块 TS 类型定义与导出规范 优化接口注释与类型约束,提升开发体验
142 lines
4.8 KiB
TypeScript
142 lines
4.8 KiB
TypeScript
import type { Asset, Sprite, __private } from 'cc';
|
|
import { SpriteFrame, isValid } from 'cc';
|
|
import type { GameComponent } from '../GameComponent';
|
|
import type { AssetType, CompleteCallback, IRemoteOptions, Paths, ProgressCallback } from '../../../core/common/loader/ResLoader';
|
|
import { resLoader } from '../../../core/common/loader/ResLoader';
|
|
import { resAutoTracker } from '../../../core/common/loader/ResAutoTracker';
|
|
import { GamePartBase } from '../GamePartBase';
|
|
import { DEBUG } from 'cc/env';
|
|
|
|
/** 资源加载与引用计数管理 */
|
|
export class GamePartRes extends GamePartBase {
|
|
/** 宿主组件 */
|
|
protected declare comp: GameComponent;
|
|
|
|
/** 获取资源
|
|
* @param path 资源路径
|
|
* @param type 资源类型
|
|
* @param bundleName 资源包名称
|
|
* @returns 资源对象
|
|
*/
|
|
get<T extends Asset>(path: string, type?: __private.__types_globals__Constructor<T> | null, bundleName?: string): T | null {
|
|
return resLoader.get(path, type, bundleName);
|
|
}
|
|
|
|
/** 加载资源
|
|
* @param bundleName 资源包名称
|
|
* @param paths 资源路径
|
|
* @param type 资源类型
|
|
* @returns 资源对象
|
|
*/
|
|
async load<T extends Asset>(bundleName: string, paths: Paths | AssetType<T>, type?: AssetType<T>): Promise<T> {
|
|
const result = await resLoader.load(bundleName, paths, type);
|
|
if (result) {
|
|
resAutoTracker.acquire(this.comp, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** 加载任意资源
|
|
* @param bundleName 资源包名称
|
|
* @param paths 资源路径数组
|
|
* @param onProgress 进度回调
|
|
* @param onComplete 完成回调
|
|
*/
|
|
loadAny(
|
|
bundleName: string | string[],
|
|
paths: string[] | ProgressCallback,
|
|
onProgress?: ProgressCallback | CompleteCallback,
|
|
onComplete?: CompleteCallback,
|
|
): void {
|
|
const originalComplete = onComplete as ((err: Error | null, data: Asset[]) => void) | undefined;
|
|
|
|
const wrappedComplete = (err: Error | null, data: Asset[]) => {
|
|
if (!err && data?.length) {
|
|
resAutoTracker.acquireMany(this.comp, data);
|
|
}
|
|
originalComplete?.(err, data);
|
|
};
|
|
|
|
resLoader.loadAny(bundleName, paths, onProgress, wrappedComplete);
|
|
}
|
|
|
|
/** 加载目录资源
|
|
* @param bundleName 资源包名称
|
|
* @param dir 目录路径
|
|
* @param type 资源类型
|
|
* @param onProgress 进度回调
|
|
* @param onComplete 完成回调
|
|
*/
|
|
loadDir<T extends Asset>(
|
|
bundleName: string,
|
|
dir?: string | AssetType<T> | ProgressCallback | CompleteCallback,
|
|
type?: AssetType<T> | ProgressCallback | CompleteCallback,
|
|
onProgress?: ProgressCallback | CompleteCallback,
|
|
onComplete?: CompleteCallback,
|
|
): void {
|
|
const originalComplete = onComplete as ((err: Error | null, data: T[]) => void) | undefined;
|
|
const wrappedComplete = (err: Error | null, data: T[]) => {
|
|
if (!err && data?.length) {
|
|
resAutoTracker.acquireMany(this.comp, data);
|
|
}
|
|
originalComplete?.(err, data);
|
|
};
|
|
|
|
resLoader.loadDir(bundleName, dir, type, onProgress, wrappedComplete);
|
|
}
|
|
|
|
/** 释放资源
|
|
* @param path 资源路径
|
|
* @param bundleName 资源包名称
|
|
*/
|
|
releaseRes(path: string, bundleName: string = resLoader.defaultBundleName): void {
|
|
resAutoTracker.releaseByPath(this.comp, path, bundleName);
|
|
}
|
|
|
|
/** 销毁资源模块 */
|
|
override destroy(): void {
|
|
const released = resAutoTracker.releaseAll(this.comp);
|
|
if (DEBUG && released > 0) {
|
|
console.log(`[GameComponent] ${this.comp.node?.name} 释放 ${released} 条资源登记`);
|
|
}
|
|
}
|
|
|
|
/** 加载远程资源
|
|
* @param url 资源URL
|
|
* @param options 加载选项
|
|
* @returns 资源对象
|
|
*/
|
|
async loadRemote<T extends Asset>(url: string, options?: IRemoteOptions): Promise<T> {
|
|
const result = await resLoader.loadRemote<T>(url, options);
|
|
if (result) {
|
|
resAutoTracker.acquire(this.comp, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** 释放远程资源
|
|
* @param url 资源URL
|
|
*/
|
|
releaseRemote(url: string): void {
|
|
resLoader.releaseRemote(url);
|
|
}
|
|
|
|
/** 设置精灵图片
|
|
* @param target 精灵组件
|
|
* @param path 图片路径
|
|
* @param bundle 资源包名称
|
|
* @returns 是否设置成功
|
|
*/
|
|
async setSprite(target: Sprite, path: string, bundle: string = resLoader.defaultBundleName): Promise<boolean> {
|
|
const spriteFrame = await this.load(bundle, path, SpriteFrame);
|
|
if (!spriteFrame) {
|
|
return false;
|
|
}
|
|
if (!isValid(target)) {
|
|
this.releaseRes(path, bundle);
|
|
return false;
|
|
}
|
|
target.spriteFrame = spriteFrame;
|
|
return true;
|
|
}
|
|
} |