NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/UI/UIWindow.cs

906 lines
24 KiB
C#
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using DG.Tweening;
using Framework;
using PhxhSDK;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.Serialization;
using Object = System.Object;
using UniTask = Cysharp.Threading.Tasks.UniTask;
public abstract class UIWindow
{
public GameObject gameObject;
public Transform transform;
public RectTransform rectTransform;
public string name;
private const string DEFAULT_SHOW_ANIM = "show";
private const string DEFAULT_HIDE_ANIM = "hide";
private string mWindowName;
private ScreenOrientation _lastOrientation;
private Vector2 _offsets; //x,y代表左右的偏移量
public delegate void OnBgClose();
private OnBgClose _onBgCloseFunc;
protected Dictionary<string, int> AsyncLoadedAssetList = new ();
private bool _isNeedScreenAdaption;
private bool _bDoNotSetMainCamera = false; //不设置主相机
public bool IsNotSetMainCamera
{
get { return _bDoNotSetMainCamera; }
set { _bDoNotSetMainCamera = value; }
}
// 是否播放默认的打开对话框的声音
public bool isPlayDefaultOpenAudio = true;
// 是否播放默认的关闭对话框的声音
public bool isPlayDefaultCloseAudio = true;
private bool _isPlayingOpenAnim;
protected Sequence _openAnimSeq;
public bool IsShowOpenAnim;
public string WindowName
{
set { mWindowName = value; }
get { return mWindowName; }
}
[HideInInspector]
public UIWindowLayer uiWindowLayer;
[HideInInspector]
protected bool isCreated = false;
protected bool _isShow = false;
protected bool _isHide = false;
protected void RegisterScreenAdaption()
{
_lastOrientation = Screen.orientation;
InitScreenUIOffset();
UpdateScreenAdaption();
_isNeedScreenAdaption = true;
}
public async UniTask<T> LoadAssetAsync<T>(string path) where T : UnityEngine.Object
{
var asset = await AssetManager.Instance.LoadAssetAsync<T>(path);
if (!AsyncLoadedAssetList.ContainsKey(path))
{
AsyncLoadedAssetList.Add(path, 1);
}
else
{
AsyncLoadedAssetList[path]++ ;
}
return asset;
}
public T LoadAsset<T>(string path) where T : UnityEngine.Object
{
var asset = AssetManager.Instance.LoadAsset<T>(path);
return asset;
}
/// <summary>
/// 异步预加载
/// </summary>
/// <param name="path"></param>
public async UniTask PostPreload<T>(string path) where T : UnityEngine.Object
{
await AssetManager.Instance.PostPreload<T>(path);
if (!AsyncLoadedAssetList.ContainsKey(path))
AsyncLoadedAssetList.Add(path, 1);
else
AsyncLoadedAssetList[path]++;
}
public T GetPreLoadResult<T>(string path) where T : UnityEngine.Object
{
return AssetManager.Instance.GetPreLoadResult<T>(path);
}
protected void UnLoad()
{
foreach (var asset in AsyncLoadedAssetList)
{
var path = asset.Key;
var count = asset.Value;
for (int i = 0; i < count; i++)
{
AssetManager.Instance.Unload(path);
}
}
AsyncLoadedAssetList.Clear();
}
protected virtual void OnUpdate()
{
if (_isNeedScreenAdaption && _lastOrientation != Screen.orientation)
{
// Add your orientation-specific actions here
// Update the last orientation for the next frame
_lastOrientation = Screen.orientation;
UpdateScreenAdaption();
//左右分别找到指定节点移动,当前的方案
//刘海屏适配
}
}
public void Update()
{
OnUpdate();
}
#region MonoBehaviour Methods Override
protected void Destroy(GameObject obj)
{
UnityEngine.Object.Destroy(obj);
}
protected void DestroyImmediate(GameObject obj)
{
UnityEngine.Object.DestroyImmediate(obj);
}
protected void Destroy(Component cmp)
{
UnityEngine.Object.Destroy(cmp);
}
protected void DestroyImmediate(Component cmp)
{
UnityEngine.Object.DestroyImmediate(cmp);
}
protected GameObject Instantiate(GameObject prefab)
{
return UnityEngine.Object.Instantiate(prefab, transform);
}
protected GameObject Instantiate(GameObject prefab, Transform trans)
{
return UnityEngine.Object.Instantiate(prefab, trans);
}
#endregion
#region #ScreenAdaption
/// <summary>
/// 屏幕适配,目前方案是左右固定名称的节点下的各个物体需要适配,其他的不管
/// </summary>
protected void UpdateScreenAdaption()
{
var goLeft = transform.Find("UI_LiuHaiLeft")?.gameObject;
var goRight = transform.Find("UI_LiuHaiRight")?.gameObject;
if (goLeft)
{
var rectTrans = goLeft.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
rectTrans.anchoredPosition = new Vector2(_offsets.x, originPos.y);
}
if (goRight)
{
var rectTrans = goRight.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
rectTrans.anchoredPosition = new Vector2(_offsets.y, originPos.y);
}
}
protected void SetScreenOffsets(Vector2 offset)
{
_offsets = offset;
}
protected void InitScreenUIOffset()
{
var offset = DeviceHelper.GetWidthOffset();
var goLeft = transform.Find("UI_LiuHaiLeft")?.gameObject;
if (goLeft)
{
var rectTrans = goLeft.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
SetScreenOffsets(new Vector2(originPos.x + offset.x, 0));
}
GameObject goRight = transform.Find("UI_LiuHaiRight")?.gameObject;
if (goRight)
{
var rectTrans = goRight.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
SetScreenOffsets(new Vector2(_offsets.x, originPos.x - offset.y));
}
}
#endregion
#region Window Life
private void _TryBindBgClose()
{
var trans = transform.Find("BgClose");
if (trans)
{
var btn = trans.GetComponent<Button>();
if (btn)
{
BindButton(btn, () =>
{
var clickAudio = btn.GetComponent<ClickAudio>();
if (clickAudio)
{
AudioManager.Instance.PlayAudio(clickAudio.AudioKey);
}
if (_onBgCloseFunc == null)
{
CloseWindow();
return;
}
_onBgCloseFunc?.Invoke();
});
}
}
}
public void CreateWindow(object data = null, bool isNotSetCamera = false)
{
_bDoNotSetMainCamera = isNotSetCamera;
PreLoad(data);
if (!isCreated)
{
OnInit();
RegisterScreenAdaption();
_TryBindBgClose();
isCreated = true;
}
_isShow = false;
_isHide = false;
IsShowOpenAnim = UIManager.Instance.GetIsAutoPlayAnim(WindowName);
Show(data);
if (isPlayDefaultOpenAudio)
{
//AudioManager3.Instance.PlaySound("");
}
}
/// <summary>
/// 关闭窗口
/// </summary>
/// <param name="closeType"></param>
/// <param name="forceShowAnim"></param>强制设置动画,0不管1强制开-1强制不开
/// <param name="isOpenMainCamera"></param>
public async void CloseWindow(UIWindowCloseType closeType = UIWindowCloseType.HideAndDestroy, int forceShowAnim = 0,
bool isOpenMainCamera = true)
{
// if (UIManager.Instance.CheckWindowIsFullScreen(this))
// {
// CameraManager.Instance.SetMainCameraActive(isOpenMainCamera);
// }
if (UIManager.Instance.CheckWindowIsFullScreen(this))
{
if (!_bDoNotSetMainCamera)
{
CameraManager.Instance.SetMainCameraActive(isOpenMainCamera);
}
}
if (isPlayDefaultCloseAudio && isCreated)
{
//AudioManager3.Instance.PlaySound("");
}
if (closeType == UIWindowCloseType.HideAndDestroy)
{
var last = UIManager.Instance.GetLast();
if (last == this)
{
UIManager.Instance.PopWindow();
}
bool isShowCloseAnim = IsShowOpenAnim;
if (forceShowAnim > 0)
{
isShowCloseAnim = true;
}
if (forceShowAnim < 0)
{
isShowCloseAnim = false;
}
_OnClose();
if (isShowCloseAnim)
{
UIManager.Instance.OnClick(true);
await AnimHide(() =>
{
DestroyWindow();
UIManager.Instance.RemoveWindow(mWindowName);
});
}
else
{
DestroyWindow();
UIManager.Instance.RemoveWindow(mWindowName);
}
}
else if(closeType == UIWindowCloseType.OnlyHide)
{
Hide();
}
else if(closeType == UIWindowCloseType.HideAndPush)
{
Hide();
//UIManager.Instance.PushWindow(this);
}
else
{
//强制清除所有界面时使用
DestroyWindow();
UIManager.Instance.RemoveWindow(mWindowName);
}
}
public virtual async UniTask<bool> OnBack(object data = null)
{
if (UIManager.Instance.GetLast() != null)
{
OnDirectBack();
return true;
}
await OnBackApp();
return true;
}
protected void OnDirectBack()
{
CloseWindow();
}
protected async UniTask OnBackApp()
{
await UIManager.Instance.CreateAndOpenWindow(UINameConst.UIBackReturn);
}
public void ReloadWindow(object data)
{
if (isCreated)
{
OnReloadWindow(data);
return;
}
Show(data);
OnReloadWindow(data);
}
public bool IsCreated()
{
return isCreated;
}
public bool IsShow()
{
return _isShow;
}
public bool IsHide()
{
return _isHide;
}
private async void Show(object data)
{
// var toTrue = (isCreated == false);
// isCreated = true;
if (gameObject == null)
{
DebugUtil.Log("UI已被销毁:{0}", WindowName);
}
else
{
if (IsShowOpenAnim)
{
var canvasGroup = gameObject.GetComponent<CanvasGroup>();
if (!canvasGroup)
{
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
canvasGroup.alpha = 0;
}
gameObject.SetActive(true);
if (IsShowOpenAnim)
{
await AnimShow();
}
}
// if (toTrue)
// {
if (UIManager.Instance.WindowInfos.TryGetValue(WindowName, out var windowInfo))
{
// if (windowInfo.UIOpenType == UIOpenType.FullScreen)
// {
// if (CameraManager.Instance.CheckMainCameraIsActive())
// {
// CameraManager.Instance.SetMainCameraActive(false);
// }
// }
if (CameraManager.Instance.CheckMainCameraIsActive())
{
if (windowInfo.UIOpenType == UIOpenType.FullScreen)
{
//特殊处理主界面
if (!_bDoNotSetMainCamera && WindowName != UINameConst.UI_MainPanel)
{
CameraManager.Instance.SetMainCameraActive(false);
}
}
}
}
OnShowWindow(data);
_isShow = true;
_isHide = false;
//}
}
private void ShowAgain()
{
if (gameObject)
{
gameObject.SetActive(true);
}
//OnShow();
}
private void Hide(bool isOnlyHide = false)
{
gameObject?.SetActive(false);
//isOpen = false;
if (!isOnlyHide)
{
OnHideWindow();
_isHide = true;
_isShow = false;
if (UIManager.Instance.WindowInfos.TryGetValue(WindowName, out var windowInfo))
{
if (windowInfo.UIOpenType == UIOpenType.FullScreen)
{
if (!CameraManager.Instance.CheckMainCameraIsActive())
{
CameraManager.Instance.SetMainCameraActive(true);
}
}
}
}
}
private void _OnClose()
{
if (UIManager.Instance.UiWindowStack.Count <= 0)
{
return;
}
if (UIManager.Instance.CheckWindowIsFullScreen(this))
{
var window = UIManager.Instance.GetLastFullScreen();
if (window != null && window != this)
{
if (UIManager.Instance.CheckIsWindowInStack(this))
{
UIManager.Instance.ForceRemoveWindow(this);
}
}
for (int i = UIManager.Instance.UiWindowStack.Count - 1; i >= 0; i--)
{
var latestWindow = UIManager.Instance.UiWindowStack[i];
latestWindow.ShowWindow();
if (UIManager.Instance.CheckWindowIsFullScreen(latestWindow))
break;
}
}
else
{
UIManager.Instance.ForceRemoveWindow(this);
}
}
private void DestroyWindow()
{
OnHideWindow();
if (isCreated)
{
OnRelease();
isCreated = false;
}
UIManager.Instance.UIWindowObjDic.Remove(gameObject);
UnityEngine.Object.Destroy(gameObject);
AssetManager.Instance.Unload(string.Format(UIManager.UI_PREFAB_PATH, mWindowName));
}
#endregion
#region Framework
/// <summary>
///预加载,传入参数,不能添加监听
/// </summary>
public virtual void PreLoad(object data = null)
{
}
/// <summary>
/// 打开界面时调用
/// </summary>
/// <param name="data"></param>
protected virtual void OnShowWindow(object data)
{
EventManager.Instance.Send(EventManager.EventName.UIOpen, WindowName);
}
//protected virtual void OnOpenWindow() { }
/// <summary>
/// 关闭界面时调用
/// </summary>
protected virtual void OnHideWindow()
{
EventManager.Instance.Send(EventManager.EventName.UIClose, WindowName);
}
/// <summary>
/// 重新加载界面时调用
/// </summary>
protected virtual void OnReloadWindow(object data) { }
/// <summary>
/// 私有Awake方法会在基类Awake执行后调用
/// </summary>
public abstract void OnInit();
/// <summary>
/// 对应OnInit在销毁掉界面时调用
/// </summary>
public virtual void OnRelease()
{
UnLoad();
_openAnimSeq?.Kill();
}
#region #Bind Component
public GameObject BindButton(string target, Action action, bool playAudio = true)
{
GameObject obj = transform.Find(target)?.gameObject;
if (obj != null)
{
Button button = obj.GetComponent<Button>();
if (button != null)
{
button.onClick.AddListener
(
delegate ()
{
if (UIManager.IsClickDisabled)
{
return;
}
UIManager.Instance.OnClick();
if (playAudio)
{
var clickAudio = button.GetComponent<ClickAudio>();
if (clickAudio)
{
AudioManager.Instance.PlayAudio(clickAudio.AudioKey);
}
}
action?.Invoke();
}
);
}
}
else
{
DebugUtil.LogError("未找到 {0}/{1}", gameObject.name, target);
}
return obj;
}
//增加一个可绑定对应变量的点击事件
//传入GameObject
public GameObject BindButton(GameObject obj, Action action, bool playAudio = true)
{
if (obj != null)
{
Button button = obj.GetComponent<Button>();
if (button != null)
{
button.onClick.AddListener
(
delegate ()
{
if (UIManager.IsClickDisabled)
{
return;
}
UIManager.Instance.OnClick();
if (playAudio)
{
var clickAudio = button.GetComponent<ClickAudio>();
if (clickAudio)
{
AudioManager.Instance.PlayAudio(clickAudio.AudioKey);
}
}
action?.Invoke();
}
);
}
}
else
{
DebugUtil.LogError("未找到 {0}/{1}", gameObject.name, obj.name);
}
return obj;
}
//传入参数
public GameObject BindButton<T>(GameObject obj, Action<T> action, T parameter, bool playAudio = true)
{
if (obj != null)
{
Button button = obj.GetComponent<Button>();
if (button != null)
{
button.onClick.AddListener
(
delegate ()
{
if (UIManager.IsClickDisabled)
{
return;
}
UIManager.Instance.OnClick();
if (playAudio)
{
//AudioManager.Instance.PlaySound(SfxNameConst.button_s);
}
action?.Invoke(parameter);
}
);
}
}
else
{
DebugUtil.LogError("未找到 {0}/{1}", gameObject.name, obj.name);
}
return obj;
}
//直接绑按钮
public GameObject BindButton(Button button, Action action, bool playAudio = true)
{
if (button != null)
{
//Button button = button.GetComponent<Button>();
if (button != null)
{
button.onClick.AddListener
(
delegate ()
{
if (UIManager.IsClickDisabled)
{
return;
}
UIManager.Instance.OnClick();
if (playAudio)
{
var clickAudio = button.GetComponent<ClickAudio>();
if (clickAudio)
{
AudioManager.Instance.PlayAudio(clickAudio.AudioKey);
}
//AudioManager.Instance.PlaySound(SfxNameConst.button_s);
}
action?.Invoke();
}
);
}
}
else
{
DebugUtil.LogError("传入按钮为空,请检查按钮绑定参数!!!");
//DebugUtil.LogError($"未找到 {gameObject.name}/{button.name}");
return null;
}
return button.gameObject;
}
//可传入参数
public GameObject BindButton<T>(Button button, Action<T> action, T parameter, bool playAudio = true)
{
if (button != null)
{
//Button button = obj.GetComponent<Button>();
if (button != null)
{
button.onClick.AddListener
(
delegate ()
{
if (UIManager.IsClickDisabled)
{
return;
}
UIManager.Instance.OnClick();
if (playAudio)
{
//AudioManager.Instance.PlaySound(SfxNameConst.button_s);
}
if (parameter == null)
{
DebugUtil.LogError("=== 传入参数为空! ===");
}
action?.Invoke(parameter);
}
);
}
}
else
{
DebugUtil.LogError("传入按钮为空,请检查按钮绑定参数!!!");
return null;
}
return button.gameObject;
}
public void ClearBind(Button button)
{
if (button != null)
{
button.onClick.RemoveAllListeners();
}
}
public void ClearBind(GameObject go)
{
var button = go.GetComponent<Button>();
if (button != null)
{
button.onClick.RemoveAllListeners();
}
}
public GameObject FindObj(string path)
{
GameObject obj = transform.Find(path)?.gameObject;
if (obj == null)
{
DebugUtil.LogError("{0}未找到 {1}/{2}", mWindowName, gameObject.name, path);
}
return obj;
}
public T GetComponent<T>(string path = "") where T : Behaviour
{
var component = transform.Find(path)?.GetComponent<T>();
if (component == null)
{
DebugUtil.LogError("{0}未找到组件{1} {2}", mWindowName, typeof(T).Name, path);
}
return component;
}
#endregion
public void HideWindow(bool isOnlyHide = false)
{
Hide(isOnlyHide);
}
public void ShowWindowActive()
{
ShowAgain();
}
public void ShowWindow(object data = null)
{
Show(data);
}
protected void AddBgClose(OnBgClose onBgCloseFunc)
{
_onBgCloseFunc += onBgCloseFunc;
}
protected virtual void OnCloseClick()
{
}
#endregion
#region #Anim
public virtual async UniTask PlayAnimation(bool isShow, Action callBack = null)
{
var canvasGroup = gameObject.GetComponent<CanvasGroup>();
if (!canvasGroup)
{
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
var time = 0.3f;
_isPlayingOpenAnim = true;
_openAnimSeq = DOTween.Sequence();
if (isShow)
{
canvasGroup.alpha = 0;
var tw0 = canvasGroup.DOFade(1, time);
_openAnimSeq.Append(tw0);
_openAnimSeq.AppendCallback(() =>
{
_isPlayingOpenAnim = false;
callBack?.Invoke();
});
return;
}
canvasGroup.alpha = 1;
var tw1 = canvasGroup.DOFade(0, time);
_openAnimSeq.Append(tw1);
_openAnimSeq.AppendCallback(() =>
{
_isPlayingOpenAnim = false;
callBack?.Invoke();
});
}
public virtual async UniTask AnimShow(Action callBack = null)
{
await PlayAnimation(true, callBack);
}
public virtual async UniTask AnimHide(Action callBack = null)
{
await PlayAnimation(false, callBack);
}
#endregion
}