2026-06-12 17:56:35 +08:00

271 lines
8.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 文件位置: 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;
}
}