using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [DisallowMultipleComponent] [ExecuteInEditMode] public class SmoothMask:UIBehaviour,ICanvasRaycastFilter { [Range(0,1)] [SerializeField] private float m_Horizontal = 0f; public float horizontal { get { return m_Horizontal; } } [Range(0,1)] [SerializeField] private float m_Vertical = 0f; public float vertical { get { return m_Vertical; } } [SerializeField] private Material[] m_ImageMaterials; public Material[] imageMaterials { get { return m_ImageMaterials; } } [SerializeField] private Material[] m_TextMaterials; public Material[] textMaterials { get { return m_TextMaterials; } } [SerializeField] private CanvasScaler m_CanvasScaler; public CanvasScaler canvasScaler { get { return m_CanvasScaler ?? (m_CanvasScaler = GetComponentInParent()); } } public RectTransform rectTransform { get { return this.transform as RectTransform; } } private Vector2 leftBottom; private Vector2 rightTop; public bool IsRaycastLocationValid(Vector2 sp,Camera eventCamera) { return RectTransformUtility.RectangleContainsScreenPoint(rectTransform,sp,eventCamera); } void LateUpdate() { UpdateChildMaterialSmoothMask(); } [ContextMenu("SetMaterial")] public void UpdateChildrenMaterial() { SetChildrenImageMaterial(this.transform); SetChildrenTextMaterial(this.transform); } private void SetChildrenImageMaterial(Transform _transform) { Image image; Transform transform; for(int i = 0;i < _transform.childCount;i++) { transform = _transform.GetChild(i); image = transform.GetComponent(); if(image != null) { image.material = imageMaterials.Length > 0 ? imageMaterials[0] : null; } else { var imageex = transform.GetComponent(); if (imageex != null) { imageex.material = imageMaterials.Length > 0 ? imageMaterials[0] : null; } } if(transform.childCount > 0) { SetChildrenImageMaterial(transform); } } } private void SetChildrenTextMaterial(Transform _parent) { Text text; Transform transform; for(int i = 0;i < _parent.childCount;i++) { transform = _parent.GetChild(i); text = transform.GetComponent(); if(text != null) { text.material = textMaterials.Length > 0 ? textMaterials[0] : null; } if(transform.childCount > 0) { SetChildrenTextMaterial(transform); } } } private void UpdateChildMaterialSmoothMask() { var scaleX = canvasScaler.transform.localScale.x; var scaleY = canvasScaler.transform.localScale.y; leftBottom = scaleX == 0f ? Vector2.zero : rectTransform.GetMinWorldPosition() / scaleX; rightTop = scaleY == 0f ? Vector2.zero : rectTransform.GetMaxWorldPosition() / scaleY; if(imageMaterials != null) { for(int i = 0;i < imageMaterials.Length;i++) { SetSmoothMask(imageMaterials[i],leftBottom,rightTop,new Vector2(horizontal,vertical)); } } if(textMaterials != null) { for(int i = 0;i < textMaterials.Length;i++) { SetSmoothMask(textMaterials[i],leftBottom,rightTop,new Vector2(horizontal,vertical)); } } } static void SetSmoothMask(Material material,Vector2 leftBottom,Vector2 rightTop,Vector2 smoothRect) { material.SetVector("_LeftBottom",leftBottom); material.SetVector("_RightTop",rightTop); material.SetVector("_SmoothRect",smoothRect); } }