Files
rougelike-demo/client/assets/scripts/Framework/UI/UIBase.ts

188 lines
4.9 KiB
TypeScript
Raw Normal View History

2025-12-14 23:35:54 +08:00
import { Node, Component, Button } from 'cc';
2025-12-14 22:40:38 +08:00
/**
* UI基类
* :
* - UI的基础接口和生命周期
* - UI根节点
* - /
*
* UI必须继承此类并实现onGetUrl方法
*/
export abstract class UIBase {
/** UI根节点 */
protected _node: Node | null = null;
/** UI是否已加载 */
protected _isLoaded: boolean = false;
/** UI是否显示中 */
protected _isShowing: boolean = false;
/**
* UI资源路径 ()
* @returns UI预制体路径
* @example
* onGetUrl(): string {
* return 'UI/Login/UILogin';
* }
*/
abstract onGetUrl(): string;
/**
* UI开始时调用 ()
* UI预制体加载完成后调用
* UI数据
* @param params
* @example
* onStart(params?: any): void {
* console.log('UI初始化', params);
* // 绑定按钮事件
* this.bindEvents();
* }
*/
onStart?(params?: any): void | Promise<void>;
/**
* UI结束时调用 ()
* UI被卸载前调用
*
* @example
* onEnd(): void {
* console.log('UI清理');
* // 解绑按钮事件
* this.unbindEvents();
* }
*/
onEnd?(): void;
/**
* UI更新 ()
* (UI显示时)
* @param dt ()
* @example
* onUpdate(dt: number): void {
* // 更新倒计时
* this.updateTimer(dt);
* }
*/
onUpdate?(dt: number): void;
/**
* UI根节点
* UIMgr在加载完成后调用
* @param node UI根节点
*/
setNode(node: Node): void {
this._node = node;
this._isLoaded = true;
}
/**
* UI根节点
* @returns UI根节点,null
*/
getNode(): Node | null {
return this._node;
}
/**
* UI
*/
show(): void {
if (this._node) {
this._node.active = true;
this._isShowing = true;
}
}
/**
* UI
*/
hide(): void {
if (this._node) {
this._node.active = false;
this._isShowing = false;
}
}
/**
* UI是否显示中
* @returns true表示正在显示,false表示已隐藏
*/
isShowing(): boolean {
return this._isShowing;
}
/**
* UI是否已加载
* @returns true表示已加载,false表示未加载
*/
isLoaded(): boolean {
return this._isLoaded;
}
2025-12-14 23:35:54 +08:00
/**
*
* @param path ,(: 'mid/input_account')
* @param componentType
* @returns ,null
* @example
* const editBox = this.GetChild('mid/input_account', EditBox);
* const button = this.GetChild('btn_login', Button);
*/
protected GetChild<T extends Component>(path: string, componentType: { new(): T }): T | null {
if (!this._node) {
console.error('[UIBase] GetChild失败: UI根节点不存在');
return null;
}
const childNode = this._node.getChildByPath(path);
if (!childNode) {
console.error(`[UIBase] GetChild失败: 未找到节点 ${path}`);
return null;
}
const component = childNode.getComponent(componentType);
if (!component) {
console.error(`[UIBase] GetChild失败: 节点 ${path} 未挂载 ${componentType.name} 组件`);
return null;
}
return component;
}
/**
*
* @param button Button组件或包含Button组件的Node
* @param callback
* @param target this指向
* @example
* const btn = this.GetChild('btn_login', Button);
* this.SetClick(btn, this.onLoginClick, this);
*/
protected SetClick(button: Button | Node | null, callback: () => void, target?: any): void {
if (!button) {
console.error('[UIBase] SetClick失败: button为null');
return;
}
let targetNode: Node | null = null;
// 判断是Button组件还是Node
if (button instanceof Button) {
targetNode = button.node;
} else if (button instanceof Node) {
targetNode = button;
}
if (!targetNode) {
console.error('[UIBase] SetClick失败: 无法获取目标节点');
return;
}
// 绑定点击事件
targetNode.on(Node.EventType.TOUCH_END, callback, target);
}
2025-12-14 22:40:38 +08:00
}