271 lines
8.2 KiB
C#
271 lines
8.2 KiB
C#
// 文件位置: Assets/Scripts/TH1_UI/View/Base/View.cs
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using Animancer;
|
||
using TH1Resource;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TH1_UI.View.Base
|
||
{
|
||
public class View : MonoBehaviour
|
||
{
|
||
|
||
public Canvas ViewCanvas { get { return _canvas; } }
|
||
|
||
public void Initialize(UIWindowProperty windowProperty)
|
||
{
|
||
//step #1 设置_winProperty 存储参数,和_canvas 存储canvas对象(提前存引用,避免之后反复getcomponent
|
||
_winProperty = windowProperty;
|
||
//_canvas = transform.GetComponent<Canvas>(); 暂时删掉了, 用不着 只有depth会用
|
||
|
||
//step #2 初始化
|
||
PreInitStart();
|
||
OnInit();
|
||
|
||
//step #3 如果需要重新调整size
|
||
if(_reSize)
|
||
{
|
||
_Resize();
|
||
}
|
||
}
|
||
|
||
//目前先架空了
|
||
protected virtual void PreInitStart() { }
|
||
|
||
protected virtual void OnInit()
|
||
{
|
||
// ✅ [修复] 必须在这里初始化 AnimancerComponent
|
||
ApplyDefaultScrollSensitivity();
|
||
_animancer = GetComponent<AnimancerComponent>();
|
||
ApplyUiAnimancerDisablePolicy();
|
||
|
||
// 如果 Inspector 中没有手动指定打开动画,则使用默认的淡入动画
|
||
if (_showAnimationClip == null)
|
||
{
|
||
_showAnimationClip = ResourceCache.Instance.AnimCache.UICommonPanelFadeIn;
|
||
}
|
||
// 如果 Inspector 中没有手动指定关闭动画,则使用默认的淡出动画
|
||
if (_hideAnimationClip == null)
|
||
{
|
||
_hideAnimationClip = ResourceCache.Instance.AnimCache.UICommonPanelFadeOut;
|
||
}
|
||
|
||
// 保留旧系统组件
|
||
//_viewAnimation = gameObject.GetComponent<Animation>();
|
||
//_viewAnimationManager = gameObject.GetComponent<AnimationManager>();
|
||
_canvasGroup = gameObject.GetComponent<CanvasGroup>();
|
||
if(!(this is ViewSub))
|
||
{
|
||
//ViDebuger.AssertError(_canvasGroup != null, "UI预制根节点必须有CanvasGroup");
|
||
}
|
||
}
|
||
|
||
void ApplyDefaultScrollSensitivity()
|
||
{
|
||
var scrollRects = GetComponentsInChildren<ScrollRect>(true);
|
||
foreach (var scrollRect in scrollRects)
|
||
{
|
||
if (scrollRect.scrollSensitivity > 0f && scrollRect.scrollSensitivity < DefaultScrollSensitivity)
|
||
{
|
||
scrollRect.scrollSensitivity = DefaultScrollSensitivity;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ApplyUiAnimancerDisablePolicy()
|
||
{
|
||
var animancers = GetComponentsInChildren<AnimancerComponent>(true);
|
||
foreach (var animancer in animancers)
|
||
{
|
||
if (animancer == null) continue;
|
||
animancer.ActionOnDisable = AnimancerComponent.DisableAction.Pause;
|
||
}
|
||
}
|
||
|
||
void _Resize()
|
||
{
|
||
// ... (此部分代码未做修改,保持原样)
|
||
RectTransform rect = transform.Find("Content").GetComponent<RectTransform>();
|
||
CanvasScaler canvasScaler = GetComponent<CanvasScaler>();
|
||
RectTransform canvasRect = GetComponent<RectTransform>();
|
||
if (canvasScaler.matchWidthOrHeight == 0) { if (canvasRect.rect.height <= 1600) { canvasScaler.matchWidthOrHeight = 1; } }
|
||
else if (canvasScaler.matchWidthOrHeight - 1 < 0.01f) { if (canvasRect.rect.width <= 720) { canvasScaler.matchWidthOrHeight = 0; } }
|
||
float canvasRectHeight = canvasRect.rect.height;
|
||
float factRatio = canvasRectHeight / Screen.height;
|
||
float safeAreaY = Screen.safeArea.y * factRatio;
|
||
float safeAreaHeight = Screen.safeArea.height * factRatio;
|
||
var offset = canvasRectHeight - safeAreaHeight;
|
||
if (safeAreaY == 0) { if (offset > 0) { rect.offsetMax = new Vector2(rect.offsetMax.x, rect.offsetMax.y - offset); } }
|
||
else
|
||
{
|
||
if ((int)offset == (int)safeAreaY) { rect.offsetMin = new Vector2(rect.offsetMin.x, rect.offsetMin.y + offset); }
|
||
else if ((int)offset > (int)safeAreaY)
|
||
{
|
||
var bottomOffset = safeAreaY;
|
||
var topOffset = canvasRectHeight - safeAreaHeight - bottomOffset;
|
||
rect.offsetMin = new Vector2(rect.offsetMin.x, rect.offsetMin.y + bottomOffset);
|
||
rect.offsetMax = new Vector2(rect.offsetMax.x, rect.offsetMax.y - topOffset);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void SetSortingOrder(int depth)
|
||
{
|
||
//暂时删掉了,没有canvas需要的情况
|
||
//_canvas.sortingOrder = depth;
|
||
}
|
||
|
||
public virtual bool IsShow()
|
||
{
|
||
return _show && gameObject.activeInHierarchy && _canvasGroup.alpha > 0;
|
||
}
|
||
|
||
// 🔄 [修改] 重构 Show 方法,确保交互性和回调正确
|
||
public virtual void Show()
|
||
{
|
||
_show = true;
|
||
// 备注: gameObject.SetActive(true) 通常由 ViewController 管理,这里保留以防特定情况需要
|
||
if (!gameObject.activeSelf)
|
||
{
|
||
gameObject.SetActive(true);
|
||
}
|
||
_SetAlphaActive(true);
|
||
|
||
if (_animancer != null && _showAnimationClip != null)
|
||
{
|
||
var state = _animancer.Play(_showAnimationClip);
|
||
if (!_enableClick)
|
||
{
|
||
_canvasGroup.interactable = false; // 播放期间禁止交互
|
||
}
|
||
|
||
state.Events.OnEnd = () =>
|
||
{
|
||
OnShowAnimFinished();
|
||
state.Events.OnEnd = null;
|
||
};
|
||
|
||
}
|
||
else
|
||
{
|
||
// 如果没有动画,直接调用完成方法
|
||
OnShowAnimFinished();
|
||
}
|
||
}
|
||
|
||
// 🔄 [修改] 重构 Hide 方法,修复语法错误和逻辑漏洞
|
||
public virtual void Hide(Action onHideCompleted = null)
|
||
{
|
||
// step #1 关闭过程中,一律禁止交互
|
||
_show = false;
|
||
if (_canvasGroup != null)
|
||
{
|
||
_canvasGroup.interactable = false;
|
||
_canvasGroup.blocksRaycasts = false;
|
||
}
|
||
|
||
// step #2 设置结束时的回调动画包(包含了传入的onHideCompleted)
|
||
Action onAnimEnd = () =>
|
||
{
|
||
_OnHideAnimFinished();
|
||
onHideCompleted?.Invoke();
|
||
};
|
||
|
||
//step #3 如果animancer正常工作,播放动画,并设定动画结束OnEnd时要执行的回调,并且要清除OnEnd的状态,避免anim没有正常结束反复触发
|
||
if (_animancer != null && _hideAnimationClip != null)
|
||
{
|
||
var state = _animancer.Play(_hideAnimationClip);
|
||
state.Events.OnEnd = () =>
|
||
{
|
||
onAnimEnd();
|
||
state.Events.OnEnd = null;
|
||
};
|
||
}
|
||
//step #4 如果anmancer不正常工作,直接执行动画结束时的回调动画包
|
||
else
|
||
{
|
||
onAnimEnd();
|
||
}
|
||
}
|
||
|
||
void _SetAlphaActive(bool value)
|
||
{
|
||
if (_canvasGroup == null) return;
|
||
_canvasGroup.alpha = value ? 1.0f : 0;
|
||
_canvasGroup.interactable = value;
|
||
_canvasGroup.blocksRaycasts = value;
|
||
}
|
||
|
||
// ✅ [新增] 一个无参数版本以适配 Animancer
|
||
protected virtual void OnShowAnimFinished()
|
||
{
|
||
if (_canvasGroup != null)
|
||
{
|
||
_canvasGroup.interactable = true; // 动画播完,恢复交互
|
||
}
|
||
// 保留旧的注释代码
|
||
//UIUtil.SetViewTouchable(true);
|
||
}
|
||
|
||
// 🔄 [修改] 旧版本,让他调用新版本,以保持向后兼容性
|
||
protected virtual void OnShowAnimFinished(ViTimeNodeInterface node)
|
||
{
|
||
OnShowAnimFinished();
|
||
}
|
||
|
||
void _OnHideAnimFinished()
|
||
{
|
||
_SetAlphaActive(false);
|
||
gameObject.SetActive(false);
|
||
// 保留旧的注释代码
|
||
//UIUtil.SetViewTouchable(true);
|
||
}
|
||
|
||
// 🔄 [修改] 旧版本,让他调用新版本,以保持向后兼容性
|
||
void _OnHideAnimFinished(ViTimeNodeInterface node)
|
||
{
|
||
_OnHideAnimFinished();
|
||
}
|
||
|
||
public void SetEnableClick(bool value)
|
||
{
|
||
_enableClick = value;
|
||
}
|
||
|
||
//暂时架空了
|
||
protected virtual void OnDispose()
|
||
{
|
||
//_viewAnimationManager?.Dispose();
|
||
//UIUtil.SetViewTouchable(true);
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
OnDispose();
|
||
}
|
||
|
||
//动画部分
|
||
private AnimancerComponent _animancer;
|
||
[Header("Animancer Animation")]
|
||
[Tooltip("使用 Animancer 播放的打开动画")]
|
||
[SerializeField] protected AnimationClip _showAnimationClip;
|
||
[Tooltip("使用 Animancer 播放的关闭动画")]
|
||
[SerializeField] protected AnimationClip _hideAnimationClip;
|
||
|
||
//其他部分
|
||
protected bool _show;
|
||
protected Canvas _canvas;
|
||
protected UIWindowProperty _winProperty;
|
||
//protected string _showAnimName = string.Empty;
|
||
//protected string _hideAnimName = string.Empty;
|
||
//protected Animation _viewAnimation;
|
||
//protected AnimationManager _viewAnimationManager;
|
||
protected bool _reSize = false;
|
||
protected CanvasGroup _canvasGroup;
|
||
bool _enableClick = false;
|
||
const float DefaultScrollSensitivity = 20f;
|
||
}
|
||
}
|