| using System.Collections.Generic; | 
| using UnityEngine; | 
| using UnityEngine.Sprites; | 
| using UnityEngine.UI; | 
|   | 
| [AddComponentMenu("UI/Custom/CircleHollow Image")] | 
| [DisallowMultipleComponent] | 
| [RequireComponent(typeof(Image))] | 
| public class CircleHollowImage:BaseMeshEffect,ICanvasRaycastFilter { | 
|   | 
|     [SerializeField] | 
|     Vector2 m_Center=Vector2.zero; | 
|     public Vector2 center { | 
|         get { return m_Center; } | 
|         set { | 
|             m_Center = value; | 
|             if(this.graphic != null) { | 
|                 this.graphic.SetVerticesDirty(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     [SerializeField] | 
|     Vector2 m_HollowArea=new Vector2(50,50); | 
|     public Vector2 hollowArea { | 
|         get { return m_HollowArea; } | 
|         set { | 
|             m_HollowArea = value; | 
|             if(this.graphic != null) { | 
|                 this.graphic.SetVerticesDirty(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     [Range(32,128)] | 
|     [SerializeField] | 
|     int m_Segements = 32; | 
|     public int segements { get { return m_Segements; } } | 
|   | 
|     private Image m_Image; | 
|     public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } } | 
|   | 
|     private List<Vector3> innerVertices; | 
|     private List<Vector3> outterVertices; | 
|   | 
|     protected override void Awake() { | 
|         innerVertices = new List<Vector3>(); | 
|         outterVertices = new List<Vector3>(); | 
|     } | 
|   | 
|     public override void ModifyMesh(VertexHelper vh) { | 
|         vh.Clear(); | 
|         innerVertices.Clear(); | 
|         outterVertices.Clear(); | 
|   | 
|         var degreeDelta = (float)(2 * Mathf.PI / segements); | 
|         var realSegements = segements; | 
|   | 
|         var width = image.rectTransform.rect.width; | 
|         var height = image.rectTransform.rect.height; | 
|         var outerArea = new Vector2(0.5f * width,0.5f * height); | 
|   | 
|         var realCenter = new Vector2(Mathf.Clamp(center.x,-width * 0.5f + hollowArea.x,width * 0.5f - hollowArea.x), | 
|             Mathf.Clamp(center.y,-height * 0.5f + hollowArea.y,height * 0.5f - hollowArea.y)); | 
|   | 
|         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) / width; | 
|         var uvScaleY = (uv.w - uv.y) / height; | 
|   | 
|         UIVertex uiVertex; | 
|         var degree = Mathf.PI * 0.5f; | 
|         var position = Vector2.zero; | 
|         var uv0 = Vector2.zero; | 
|   | 
|         var verticeCount = 0; | 
|         var triangleCount = 0; | 
|   | 
|         verticeCount = realSegements * 2; | 
|         for(int i = 0;i < verticeCount;i += 2) { | 
|             var cosA = Mathf.Cos(degree); | 
|             var sinA = Mathf.Sin(degree); | 
|             degree = degree - degreeDelta; | 
|   | 
|             position = new Vector3(realCenter.x + cosA * hollowArea.x,realCenter.y + sinA * hollowArea.y); | 
|             uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); | 
|             uiVertex = UIUtility.PackageUIVertex(position,uv0,image.color); | 
|             vh.AddVert(uiVertex); | 
|             innerVertices.Add(position); | 
|   | 
|             position = new Vector3(Mathf.Sign(cosA * 2f) * outerArea.x,Mathf.Sign(sinA * 2f) * outerArea.y); | 
|             uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); | 
|             uiVertex = UIUtility.PackageUIVertex(position,uv0,image.color); | 
|             vh.AddVert(uiVertex); | 
|             outterVertices.Add(position); | 
|         } | 
|   | 
|         triangleCount = realSegements * 3 * 2; | 
|         for(int i = 0,vIdx = 0;i < triangleCount - 6;i += 6,vIdx += 2) { | 
|             vh.AddTriangle(vIdx + 1,vIdx,vIdx + 3); | 
|             vh.AddTriangle(vIdx,vIdx + 2,vIdx + 3); | 
|         } | 
|         vh.AddTriangle(verticeCount - 1,verticeCount - 2,1); | 
|         vh.AddTriangle(verticeCount - 2,0,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,outterVertices,innerVertices); | 
|     } | 
|   | 
|     private bool Contains(Vector2 p,List<Vector3> outterVertices,List<Vector3> innerVertices) { | 
|         var crossNumber = 0; | 
|         crossNumber += UIUtility.RayCrossingCount(p,innerVertices); | 
|         crossNumber += UIUtility.RayCrossingCount(p,outterVertices); | 
|         return (crossNumber & 1) == 1; | 
|     } | 
|   | 
| } |