using Cysharp.Threading.Tasks;
using DG.Tweening;
using Framework;
using PhxhSDK;
using UnityEngine.UI;
public abstract partial class UIWindow
{
/*
╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ UIWindow 生命周期 (Lifecycle) ║
╠═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
║ ║
║ 【生命周期流程】 ║
║ 1. Load → UIManager.CreateWindow() 加载预制体 ║
║ 2. Init → Init(data) 初始化UI组件 ║
║ 3. Show → ShowWindow(data) 显示窗口 ║
║ 4. Update → Update(dt) 每帧更新 ║
║ 5. Refresh → Refresh(data) 刷新数据 ║
║ 6. Close → CloseWindow(false) 关闭窗口(保留内存) ║
║ 7. Destroy → CloseWindow(true) 销毁窗口(释放资源) ║
║ ║
║ 【核心虚方法】(子类可重写) ║
║ • OnInit() - 初始化UI组件,绑定事件 ║
║ • OnBeforeShow() - 显示前验证,返回false取消显示 ║
║ • OnAfterShow() - 显示后处理,播放动画 ║
║ • OnUpdate(dt) - 每帧更新(避免重度计算) ║
║ • OnRefresh() - 刷新显示内容 ║
║ • OnHide() - 隐藏时清理,暂停逻辑 ║
║ • OnRelease() - 销毁时释放资源(重要:防止内存泄漏) ║
║ ║
║ 【注意事项】 ║
║ ⚠️ 不要重写公共接口方法(Init, ShowWindow, Update等) ║
║ ⚠️ 不要直接调用OnXxx虚方法,必须通过公共接口 ║
║ ⚠️ CloseWindow(true)销毁窗口,CloseWindow(false)仅隐藏 ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
*/
#region Lifecycle Management
///
/// 初始化窗口
///
public void Init(object data = null)
{
try
{
OnBeforeInit(data);
if (isInited)
{
DebugUtil.LogWarning("window : {0} already inited", WindowName);
}
else
{
DoInit();
OnInit();
isInited = true;
}
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} init window error: {1}\n===Stack===\n{2}\n======", WindowName, e.Message, e.StackTrace);
}
}
///
/// 显示窗口
///
public void ShowWindow(object data = null)
{
try
{
if (_isShow)
{
DebugUtil.LogWarning("window : {0} is show, can't show again", WindowName);
}
if (!OnBeforeShow(data))
{
DebugUtil.LogError("window : {0} on before show return false", WindowName);
return;
}
DoShow();
OnShow(data);
if (gameObject is null)
{
DebugUtil.Log("UI已被销毁:{0}", WindowName);
}
else
{
gameObject.SetActive(true);
}
_isShow = true;
OnAfterShow(data);
bool isShowOpenAnim = IsShowOpenAnim;
if (isShowOpenAnim)
{
AnimShow(() =>
{
//TODO
EventManager.Instance.Send(EventManager.EventName.UIOpen, WindowName);
}).Forget();
}
else
{
//OnAfterShow(data);
EventManager.Instance.Send(EventManager.EventName.UIOpen, WindowName);
}
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} show window error: {1}\n===Stack===\n{2}\n======", WindowName, e.Message, e.StackTrace);
}
}
///
/// 在显示前截图(如果需要)
///
private void CaptureScreenshotIfNeeded()
{
var config = UIManager.Instance.GetWindowInfo(WindowName);
if (config.NeedScreenshot)
{
var oldActive = gameObject.activeSelf;
gameObject.SetActive(false);
ScreenshotManager.Instance.CaptureScreenshot();
gameObject.SetActive(oldActive);
}
}
///
/// 自动设置模糊背景(如果需要)
///
private void SetupBlurBackgroundIfNeeded()
{
var config = UIManager.Instance.GetWindowInfo(WindowName);
if (!config.NeedScreenshot) return;
// 查找约定的 GaussianBlurMask 节点
var blurTransform = transform.Find("GaussianBlurMask");
if (blurTransform != null)
{
var blurMask = blurTransform.GetComponent();
if (blurMask != null)
{
blurMask.texture = ScreenshotManager.Instance.GetScreenTexture2D();
blurMask.gameObject.SetActive(true);
}
}
}
///
/// 更新入口,界面打开的时候更新
///
public void Update(float dt)
{
try
{
_notchScreenAdapter?.UpdateCheck();
OnUpdate(dt);
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} update window error: {1}\n===Stack===\n{2}\n======", WindowName, e.Message, e.StackTrace);
}
}
///
/// 刷新窗口数据
///
public void Refresh(object data)
{
try
{
if (isInited)
{
OnRefresh(data);
}
else
{
DebugUtil.LogError("window : {0} not inited", WindowName);
}
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} refresh with data error: {1}\n===Stack===\n{2}\n======", WindowName, e.Message, e.StackTrace);
}
}
///
/// 关闭窗口
/// destroy = false: 关闭但保留内存(快速重开)
/// destroy = true: 销毁并释放资源
///
public async void CloseWindow(bool destroy)
{
try
{
// 如果窗口已关闭
if (!_isShow)
{
// 如果不需要销毁,直接返回
if (!destroy)
{
DebugUtil.LogWarning("window : {0} is already closed", WindowName);
return;
}
// 如果需要销毁,跳过关闭逻辑,直接执行销毁
DebugUtil.LogG($"窗口已关闭,直接销毁UI:{WindowName}");
IsClosing = true;
UIManager.Instance.RemoveWindow(mWindowName);
DoDestroy();
IsClosing = false;
return;
}
IsClosing = true;
// 1. 获取窗口配置
var config = UIManager.Instance.GetWindowInfo(WindowName);
// 2. 可见性管理(由 UIWindowVisibilityManager 根据配置决定是否处理)
UIWindowVisibilityManager.Instance.HandleVisibilityOnClose(this, config.VisibilityStrategy);
// 3. 相机管理(在可见性管理之后处理)
UIWindowCameraManager.Instance.HandleCameraOnClose(this);
// 4. 隐藏逻辑
OnHide();
gameObject?.SetActive(false);
_isShow = false;
EventManager.Instance.Send(EventManager.EventName.UIHide, WindowName);
// 5. 播放关闭动画
bool isShowCloseAnim = IsShowOpenAnim;
if (isShowCloseAnim)
{
UIManager.Instance.BlockUIForCloseOperation();
await AnimHide(() =>
{
// 动画播放完毕后的回调
if (destroy)
{
DoDestroy();
UIManager.Instance.RemoveWindow(mWindowName);
}
IsClosing = false;
});
}
else
{
// 7. 如果需要销毁(无动画情况)
if (destroy)
{
DoDestroy();
UIManager.Instance.RemoveWindow(mWindowName);
}
IsClosing = false;
}
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} close window error: {1}\n===Stack===\n{2}\n======", WindowName, e.Message, e.StackTrace);
}
}
#endregion
#region User Interaction
#endregion
#region Internal Implementation
///
/// 恢复主相机状态(已废弃,由 UIWindowCameraManager 统一管理)
///
[System.Obsolete("RestoreMainCamera已废弃,相机状态由 UIWindowCameraManager 统一管理")]
private void RestoreMainCamera()
{
// 相机管理逻辑已移至 UIWindowCameraManager.HandleCameraOnClose
// 保留此方法以防止破坏性更改
}
///
/// 执行基础初始化
///
private void DoInit()
{
_isShow = false;
var metaInfo = UIManager.Instance.GetWindowInfo(WindowName);
IsShowOpenAnim = metaInfo.IsAutoAnim;
BackStrategy = UIBackStrategyFactory.CreateStrategy(metaInfo.BackStrategyType);
AutoBindField();
InitScreenAdaption();
BindDefaultCloseButtons();
BindDefaultHomeButtons();
BindDefaultBackButtons();
}
///
/// 执行显示逻辑
///
private void DoShow()
{
// 🎯 在显示前截图(如果需要)
CaptureScreenshotIfNeeded();
// 🎯 自动设置模糊背景(如果需要)
SetupBlurBackgroundIfNeeded();
// 🎯 相机管理(在窗口显示后处理)
var config = UIManager.Instance.GetWindowInfo(WindowName);
UIWindowVisibilityManager.Instance.HandleVisibilityOnOpen(this, config.VisibilityStrategy);
UIWindowCameraManager.Instance.HandleCameraOnOpen(this);
}
///
/// 执行销毁逻辑
///
private void DoDestroy()
{
DebugUtil.LogG($"DoDestroy:{WindowName}");
// 如果窗口还在显示状态,先调用 OnHide
if (_isShow)
{
OnHide();
_isShow = false;
}
// 确保 GameObject 隐藏
if (gameObject != null)
{
gameObject.SetActive(false);
}
// 发送隐藏事件
EventManager.Instance.Send(EventManager.EventName.UIHide, WindowName);
// 资源释放
if (gameObject)
{
if (isInited)
{
OnRelease();
DoRelease();
isInited = false;
}
if (UIManager.Instance.UIWindowObjDic.ContainsKey(gameObject))
{
UIManager.Instance.UIWindowObjDic.Remove(gameObject);
}
UnityEngine.Object.Destroy(gameObject);
}
// 卸载资源
AssetManager.Instance.Unload(string.Format(UIManager.UI_PREFAB_PATH, mWindowName), true);
gameObject = null;
}
///
/// 基础资源释放
///
private void DoRelease()
{
EventManager.Instance.Send(EventManager.EventName.UIDestroy, WindowName);
UnLoad();
_openAnimSeq?.Kill();
_assetReferenceManager?.Dispose();
_assetReferenceManager = null;
_notchScreenAdapter = null;
_graphicRaycasterManager = null;
}
#endregion
#region Virtual Methods
// Init Phase
///
/// 初始化前预处理(已废弃,建议使用OnInit)
///
[System.Obsolete("OnBeforeInit已废弃,请使用OnInit方法替代。OnInit提供更清晰的初始化流程和更好的代码组织。")]
protected virtual void OnBeforeInit(object data = null){}
///
/// UI初始化
///
protected virtual void OnInit(){}
///
/// 自动绑定字段
///
protected virtual void AutoBindField(){}
// Show Phase
///
/// 显示前检查(返回false可取消显示)
///
protected virtual bool OnBeforeShow(object data)
{
return true;
}
///
/// 显示时处理(已废弃,建议使用OnAfterShow)
///
[System.Obsolete("OnShow已废弃,请使用OnAfterShow方法替代。OnAfterShow在窗口完全显示后调用,提供更稳定的显示时机。")]
protected virtual void OnShow(object data){}
///
/// 显示后处理
///
protected virtual void OnAfterShow(object data){}
///
/// 每帧更新
///
protected virtual void OnUpdate(float dt){}
// Refresh Phase
///
/// 数据刷新
///
protected virtual void OnRefresh(object data) {}
// Hide Phase
///
/// 隐藏时处理
///
protected virtual void OnHide(){}
// Release Phase
///
/// 资源释放
///
protected virtual void OnRelease(){}
#endregion
}