HollowOutMask.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. /// <summary>
  4. /// 实现镂空效果的Mask组件
  5. /// </summary>
  6. public class HollowOutMask : MaskableGraphic, ICanvasRaycastFilter
  7. {
  8. [SerializeField]
  9. private RectTransform _target;
  10. private Vector3 _targetMin = Vector3.zero;
  11. private Vector3 _targetMax = Vector3.zero;
  12. private bool _canRefresh = true;
  13. private Transform _cacheTrans = null;
  14. [SerializeField]
  15. public bool isTargetRectCanThrough = true;
  16. /// <summary>
  17. /// 设置镂空的目标
  18. /// </summary>
  19. public void SetTarget(RectTransform target)
  20. {
  21. _canRefresh = true;
  22. _target = target;
  23. _RefreshView();
  24. }
  25. public RectTransform GetTarget()
  26. {
  27. return _target;
  28. }
  29. private void _SetTarget(Vector3 tarMin, Vector3 tarMax)
  30. {
  31. if (tarMin == _targetMin && tarMax == _targetMax) return;
  32. _targetMin = tarMin;
  33. _targetMax = tarMax;
  34. SetAllDirty();
  35. }
  36. private void _RefreshView()
  37. {
  38. if (!_canRefresh) return;
  39. _canRefresh = false;
  40. if (null == _target)
  41. {
  42. _SetTarget(Vector3.zero, Vector3.zero);
  43. SetAllDirty();
  44. }
  45. else
  46. {
  47. Bounds bounds = RectTransformUtility.CalculateRelativeRectTransformBounds(_cacheTrans, _target);
  48. _SetTarget(bounds.min, bounds.max);
  49. }
  50. }
  51. protected override void OnPopulateMesh(VertexHelper vh)
  52. {
  53. if (_targetMin == Vector3.zero && _targetMax == Vector3.zero)
  54. {
  55. base.OnPopulateMesh(vh);
  56. return;
  57. }
  58. vh.Clear();
  59. // 填充顶点
  60. UIVertex vert = UIVertex.simpleVert;
  61. vert.color = color;
  62. Vector2 selfPiovt = rectTransform.pivot;
  63. Rect selfRect = rectTransform.rect;
  64. float outerLx = -selfPiovt.x * selfRect.width;
  65. float outerBy = -selfPiovt.y * selfRect.height;
  66. float outerRx = (1 - selfPiovt.x) * selfRect.width;
  67. float outerTy = (1 - selfPiovt.y) * selfRect.height;
  68. // 0 - Outer:LT
  69. vert.position = new Vector3(outerLx, outerTy);
  70. vh.AddVert(vert);
  71. // 1 - Outer:RT
  72. vert.position = new Vector3(outerRx, outerTy);
  73. vh.AddVert(vert);
  74. // 2 - Outer:RB
  75. vert.position = new Vector3(outerRx, outerBy);
  76. vh.AddVert(vert);
  77. // 3 - Outer:LB
  78. vert.position = new Vector3(outerLx, outerBy);
  79. vh.AddVert(vert);
  80. // 4 - Inner:LT
  81. vert.position = new Vector3(_targetMin.x, _targetMax.y);
  82. vh.AddVert(vert);
  83. // 5 - Inner:RT
  84. vert.position = new Vector3(_targetMax.x, _targetMax.y);
  85. vh.AddVert(vert);
  86. // 6 - Inner:RB
  87. vert.position = new Vector3(_targetMax.x, _targetMin.y);
  88. vh.AddVert(vert);
  89. // 7 - Inner:LB
  90. vert.position = new Vector3(_targetMin.x, _targetMin.y);
  91. vh.AddVert(vert);
  92. // 设定三角形
  93. vh.AddTriangle(4, 0, 1);
  94. vh.AddTriangle(4, 1, 5);
  95. vh.AddTriangle(5, 1, 2);
  96. vh.AddTriangle(5, 2, 6);
  97. vh.AddTriangle(6, 2, 3);
  98. vh.AddTriangle(6, 3, 7);
  99. vh.AddTriangle(7, 3, 0);
  100. vh.AddTriangle(7, 0, 4);
  101. }
  102. bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera)
  103. {
  104. if (!isTargetRectCanThrough) return true;
  105. if (null == _target) return true;
  106. // 将目标对象范围内的事件镂空(使其穿过)
  107. return !RectTransformUtility.RectangleContainsScreenPoint(_target, screenPos, eventCamera);
  108. }
  109. protected override void Awake()
  110. {
  111. base.Awake();
  112. _cacheTrans = GetComponent<RectTransform>();
  113. }
  114. // #if UNITY_EDITOR
  115. // void Update()
  116. // {
  117. // _canRefresh = true;
  118. // _RefreshView();
  119. // }
  120. // #endif
  121. }