mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-09-03 04:03:46 +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 类型定义与导出规范 优化接口注释与类型约束,提升开发体验
157 lines
5.3 KiB
TypeScript
157 lines
5.3 KiB
TypeScript
import type { Node } from 'cc';
|
||
import { Component, _decorator } from 'cc';
|
||
import { oops } from '../../Oops';
|
||
import type { UIConfig } from './UIConfig';
|
||
|
||
const EventOnAdded = 'onAdded';
|
||
const EventOnBeforeRemove = 'onBeforeRemove';
|
||
const EventOnRemoved = 'onRemoved';
|
||
|
||
const { ccclass } = _decorator;
|
||
|
||
/** 窗口元素组件 */
|
||
@ccclass('LayerUIElement')
|
||
export class LayerUIElement extends Component {
|
||
/** 视图参数 */
|
||
state: UIState = null!;
|
||
/** 关闭窗口之前 */
|
||
onClose: Function = null!;
|
||
|
||
/** 添加界面且界面设置到父节点之前 */
|
||
add(): Promise<boolean> {
|
||
return new Promise(async (resolve, reject) => {
|
||
// 触发窗口组件上添加到父节点后的事件
|
||
for (let i = 0; i < this.node.components.length; i++) {
|
||
const component: any = this.node.components[i];
|
||
const func = component[EventOnAdded];
|
||
if (func) {
|
||
if (await func.call(component, this.state.params.data) == false) {
|
||
resolve(false);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 触发外部窗口显示前的事件(辅助实现自定义动画逻辑)
|
||
if (typeof this.state.params.onAdded === 'function') {
|
||
this.state.params.onAdded(this.node, this.state.params.data);
|
||
}
|
||
|
||
resolve(true);
|
||
});
|
||
}
|
||
|
||
/** 删除节点,该方法只能调用一次,将会触发onBeforeRemoved回调 */
|
||
remove(isDestroy: boolean) {
|
||
if (this.state.valid) {
|
||
// 触发窗口移除舞台之前事件
|
||
this.applyComponentsFunction(this.node, EventOnBeforeRemove, this.state.params.data);
|
||
|
||
// 通知外部对象窗口组件上移除之前的事件(关闭窗口前的关闭动画处理)
|
||
if (typeof this.state.params.onBeforeRemove === 'function') {
|
||
this.state.params.onBeforeRemove(this.node, this.onBeforeRemoveNext.bind(this, isDestroy));
|
||
}
|
||
else {
|
||
this.onBeforeRemoveNext(isDestroy);
|
||
}
|
||
}
|
||
else {
|
||
this.onBeforeRemoveNext(isDestroy);
|
||
}
|
||
}
|
||
|
||
/** 窗口关闭前动画处理完后的回调方法,主要用于释放资源 */
|
||
private onBeforeRemoveNext(isDestroy: boolean) {
|
||
this.state.valid = false;
|
||
|
||
if (this.state.params && typeof this.state.params.onRemoved === 'function') {
|
||
this.state.params.onRemoved(this.node, this.state.params.data);
|
||
}
|
||
|
||
// 关闭动画播放完后,界面移除舞台事件
|
||
this.onClose && this.onClose();
|
||
|
||
if (isDestroy) {
|
||
// 释放界面显示对象
|
||
this.node.destroy();
|
||
|
||
// 预制已由根节点 GameComponent + ResAutoTracker 管理时可不额外 release,否则会与 decRef 重复
|
||
if (!this.state.prefabTrackedByView) {
|
||
oops.res.release(this.state.config.prefab, this.state.config.bundle);
|
||
}
|
||
|
||
// oops.log.logView(`【界面管理】释放【${uip.config.prefab}】界面资源`);
|
||
}
|
||
else {
|
||
this.node.removeFromParent();
|
||
}
|
||
|
||
// 触发窗口组件上窗口移除之后的事件
|
||
this.applyComponentsFunction(this.node, EventOnRemoved, this.state.params.data);
|
||
}
|
||
|
||
private applyComponentsFunction(node: Node, funName: string, params: any) {
|
||
for (let i = 0; i < node.components.length; i++) {
|
||
const component: any = node.components[i];
|
||
const func = component[funName];
|
||
if (func) {
|
||
func.call(component, params);
|
||
}
|
||
}
|
||
}
|
||
|
||
onDestroy() {
|
||
this.state = null!;
|
||
this.onClose = null!;
|
||
}
|
||
}
|
||
|
||
/** 本类型仅供gui模块内部使用,请勿在功能逻辑中使用 */
|
||
export class UIState {
|
||
/** 界面唯一编号 */
|
||
uiid: string = null!;
|
||
/** 界面配置 */
|
||
config: UIConfig = null!;
|
||
/** 窗口事件 */
|
||
params: UIParam = null!;
|
||
/** 是否在使用状态 */
|
||
valid = true;
|
||
/** 界面根节点 */
|
||
node: Node = null!;
|
||
/**
|
||
* 根节点上存在 GameComponent 时,LayerUI 已将预制资源交给 ResAutoTracker,关闭界面时不再调用 oops.res.release
|
||
*/
|
||
prefabTrackedByView = false;
|
||
}
|
||
|
||
/*** 界面打开参数 */
|
||
export interface UIParam {
|
||
/** 自定义传递参数 */
|
||
data?: any;
|
||
|
||
/** 是否开启预加载(默认不开启 - 开启后加载完不显示界面) */
|
||
preload?: boolean;
|
||
|
||
/**
|
||
* 节点添加到层级以后的回调
|
||
* @param node 当前界面节点
|
||
* @param params 外部传递参数
|
||
*/
|
||
onAdded?: (node: Node, params: any) => void,
|
||
|
||
/**
|
||
* 如果指定onBeforeRemoved,则next必须调用,否则节点不会被正常删除。
|
||
*
|
||
* 比如希望节点做一个FadeOut然后删除,则可以在`onBeforeRemoved`当中播放action动画,动画结束后调用next
|
||
* @param node 当前界面节点
|
||
* @param next 回调方法
|
||
*/
|
||
onBeforeRemove?: (node: Node, next: Function) => void,
|
||
|
||
/**
|
||
* 窗口节点 destroy 之后回调
|
||
* @param node 当前界面节点
|
||
* @param params 外部传递参数
|
||
*/
|
||
onRemoved?: (node: Node, params: any) => void
|
||
} |