using System.Collections.Generic; 
 | 
using UnityEngine; 
 | 
using UnityEngine.Sprites; 
 | 
using UnityEngine.UI; 
 | 
  
 | 
[DisallowMultipleComponent] 
 | 
[AddComponentMenu("UI/Custom/Circle Image")] 
 | 
[RequireComponent(typeof(Image))] 
 | 
public class RoundedRectangleImage:BaseMeshEffect,ICanvasRaycastFilter { 
 | 
  
 | 
    [SerializeField] 
 | 
    float m_Radius = 10f; 
 | 
    public float radius { get { return m_Radius; } } 
 | 
  
 | 
    [SerializeField] 
 | 
    [Range(16,128)] 
 | 
    int m_Segements = 16; 
 | 
    public int segements { get { return m_Segements; } } 
 | 
  
 | 
    [SerializeField] 
 | 
    Vector2 m_RealArea = Vector2.one * 100; 
 | 
    public Vector2 realArea { get { return m_RealArea; } } 
 | 
  
 | 
    private Image m_Image; 
 | 
    public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } } 
 | 
  
 | 
    List<Vector3> vertexPosition = new List<Vector3>(); 
 | 
    public override void ModifyMesh(VertexHelper vh) { 
 | 
        vh.Clear(); 
 | 
        vertexPosition.Clear(); 
 | 
  
 | 
        var tw = image.rectTransform.rect.width; 
 | 
        var th = image.rectTransform.rect.height; 
 | 
        var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero; 
 | 
  
 | 
        var uvCenterX = (uv.x + uv.z) * 0.5f; 
 | 
        var uvCenterY = (uv.y + uv.w) * 0.5f; 
 | 
        var uvScaleX = (uv.z - uv.x) / tw; 
 | 
        var uvScaleY = (uv.w - uv.y) / th; 
 | 
  
 | 
        var interval = radius / (segements - 1); 
 | 
  
 | 
        var center = new Vector2(realArea.x * 0.5f - radius,realArea.y * 0.5f - radius); 
 | 
        for(int i = 0;i < segements;i++) { 
 | 
            var position = new Vector2(); 
 | 
            var offsetX = interval * i; 
 | 
            position.x = center.x + offsetX; 
 | 
            position.y = center.y + Mathf.Sqrt(radius * radius - offsetX * offsetX); 
 | 
            vertexPosition.Add(position); 
 | 
            var vertex = new UIVertex(); 
 | 
            vertex.position = position; 
 | 
            vertex.color = image.color; 
 | 
            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); 
 | 
            vh.AddVert(vertex); 
 | 
        } 
 | 
  
 | 
        center = new Vector2(realArea.x * 0.5f - radius,-realArea.y * 0.5f + radius); 
 | 
        for(int i = 0;i < segements;i++) { 
 | 
            var position = new Vector2(); 
 | 
            var offsetX = interval * i; 
 | 
            position.x = center.x + radius - offsetX; 
 | 
            position.y = center.y - Mathf.Sqrt(radius * radius - (radius - offsetX) * (radius - offsetX)); 
 | 
            vertexPosition.Add(position); 
 | 
            var vertex = new UIVertex(); 
 | 
            vertex.position = position; 
 | 
            vertex.color = image.color; 
 | 
            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); 
 | 
            vh.AddVert(vertex); 
 | 
        } 
 | 
  
 | 
        center = new Vector2(-realArea.x * 0.5f + radius,-realArea.y * 0.5f + radius); 
 | 
        for(int i = 0;i < segements;i++) { 
 | 
            var position = new Vector2(); 
 | 
            var offsetX = interval * i; 
 | 
            position.x = center.x - offsetX; 
 | 
            position.y = center.y - Mathf.Sqrt(radius * radius - offsetX * offsetX); 
 | 
            vertexPosition.Add(position); 
 | 
            var vertex = new UIVertex(); 
 | 
            vertex.position = position; 
 | 
            vertex.color = image.color; 
 | 
            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); 
 | 
            vh.AddVert(vertex); 
 | 
        } 
 | 
  
 | 
        center = new Vector2(-realArea.x * 0.5f + radius,realArea.y * 0.5f - radius); 
 | 
        for(int i = 0;i < segements;i++) { 
 | 
            var position = new Vector2(); 
 | 
            var offsetX = interval * i; 
 | 
            position.x = center.x - radius + offsetX; 
 | 
            position.y = center.y + Mathf.Sqrt(radius * radius - (radius - offsetX) * (radius - offsetX)); 
 | 
            vertexPosition.Add(position); 
 | 
            var vertex = new UIVertex(); 
 | 
            vertex.position = position; 
 | 
            vertex.color = image.color; 
 | 
            vertex.uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); 
 | 
            vh.AddVert(vertex); 
 | 
        } 
 | 
  
 | 
        var triangleCount = segements * 12 - 3; 
 | 
        for(int i = 0,vIdx = 1;i < triangleCount - 3;i += 3,vIdx++) { 
 | 
            vh.AddTriangle(vIdx,0,vIdx + 1); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public virtual bool IsRaycastLocationValid(Vector2 screenPoint,Camera eventCamera) { 
 | 
        var sprite = image.overrideSprite; 
 | 
        if(sprite == null) { 
 | 
            return true; 
 | 
        } 
 | 
  
 | 
        Vector2 local; 
 | 
        RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform,screenPoint,eventCamera,out local); 
 | 
        return Contains(local,vertexPosition); 
 | 
    } 
 | 
  
 | 
    private bool Contains(Vector2 _p,List<Vector3> _vertexPositions) { 
 | 
        var crossNumber = 0; 
 | 
        crossNumber += UIUtility.RayCrossingCount(_p,_vertexPositions); 
 | 
        return (crossNumber & 1) == 1; 
 | 
    } 
 | 
  
 | 
} 
 |