JJBB/Assets/Project/Script/GUI/Base/UICameraMask.cs
2024-08-23 15:49:34 +08:00

121 lines
3.5 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.

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System.Collections.Generic;
using UnityEngine.EventSystems;
/// <summary>
/// 用于在Ui中切割Renderer的组件类似RectMask2d
/// 暂时未处理Mask嵌套的情况
/// </summary>
[DisallowMultipleComponent]
[RequireComponent(typeof(RectTransform))]
public class UICameraMask : UIBehaviour, IClipper
{
private RectTransform rectTransform;
private bool m_ShouldRecalculateClipRects;
private List<UICameraMaskable> maskableList;
private Vector4 clipArea;
protected override void Awake()
{
base.Awake();
rectTransform = (RectTransform)transform;
maskableList = new List<UICameraMaskable>();
}
protected override void OnEnable()
{
base.OnEnable();
m_ShouldRecalculateClipRects = true;
ClipperRegistry.Register(this);
}
protected override void OnDisable()
{
base.OnDisable();
maskableList.Clear();
ClipperRegistry.Unregister(this);
}
// 暂时使用低端的transform.hasChanged Api来追踪Transform状态变化。
// 用ClipperRegistry获得Clipping流程时间点。
public virtual void PerformClipping()
{
if (IsTransformDirty(rectTransform))
m_ShouldRecalculateClipRects = true;
if (m_ShouldRecalculateClipRects)
{
m_ShouldRecalculateClipRects = false;
ResetClipArea();
}
}
public void AddClippable(UICameraMaskable clippable)
{
if (clippable == null)
return;
if (!maskableList.Contains(clippable))
maskableList.Add(clippable);
SetClipForOne(clippable);
}
public void RemoveClippable(UICameraMaskable clippable)
{
if (clippable == null)
return;
var index = maskableList.IndexOf(clippable);
if (index >= 0)
{
maskableList.RemoveAt(index);
RemoveClipForOne(clippable);
}
}
private void ResetClipArea()
{
var corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);
for (int i = 0; i < corners.Length; i++)
{
corners[i] = RectTransformUtility.WorldToScreenPoint(GetWorldCamera(), corners[i]);
corners[i].x = corners[i].x / Screen.width * 2f - 1f;
corners[i].y = corners[i].y / Screen.height * 2f - 1f;
}
clipArea = new Vector4(corners[0].x, corners[0].y, corners[2].x, corners[2].y);
for (int i = 0; i < maskableList.Count; i++)
SetClipForOne(maskableList[i]);
}
private void SetClipForOne(UICameraMaskable clippable)
{
clippable.SetClipRect(clipArea);
}
private Camera GetWorldCamera()
{
var uiManager = UIManager.Instance();
if (uiManager)
return uiManager.UICamera;
else
return Camera.main;
}
// 暂时使用transform.hasChanged api来检测Mask是否有变化
Rect lastRect;
private bool IsTransformDirty(RectTransform rectTransform)
{
bool result = false;
if (rectTransform.hasChanged)
{
rectTransform.hasChanged = false;
result = true;
}
else if (rectTransform.rect != lastRect)
result = true;
if (result)
lastRect = rectTransform.rect;
return result;
}
public static void RemoveClipForOne(UICameraMaskable clippable)
{
clippable.SetClipRect(new Vector4(-1f, -1f, 1f, 1f));
}
}