| using System.Collections.Generic; | 
| using UnityEngine; | 
| using UnityEngine.Sprites; | 
| using UnityEngine.UI; | 
|   | 
| [AddComponentMenu("UI/Custom/Circle Image")] | 
| [RequireComponent(typeof(Image))] | 
| public class CircleImage : BaseMeshEffect, ICanvasRaycastFilter { | 
|   | 
|     [Range(0, 1)] | 
|     [SerializeField] | 
|     float m_FillPercent = 1f; | 
|     public float fillPercent { get { return m_FillPercent; } } | 
|   | 
|     [SerializeField] | 
|     private bool m_Reversed = false; | 
|     public bool reversed { get { return m_Reversed; } } | 
|   | 
|     [SerializeField] | 
|     Align m_Align = Align.Top; | 
|     public Align align { get { return m_Align; } } | 
|   | 
|     [SerializeField] | 
|     bool m_FullFill = true; | 
|     public bool fullFill { get { return m_FullFill; } } | 
|   | 
|     [Range(0, 1)] | 
|     [SerializeField] | 
|     float m_Thickness = 0f; | 
|     public float thickness { | 
|         get { return m_Thickness; } | 
|         set { m_Thickness = value; } | 
|     } | 
|   | 
|     [Range(4, 128)] | 
|     [SerializeField] | 
|     int m_Segements = 30; | 
|     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 = (int)(segements * fillPercent); | 
|   | 
|         var width = image.rectTransform.rect.width; | 
|         var height = image.rectTransform.rect.height; | 
|         var outerArea = new Vector2(0.5f * width, 0.5f * height); | 
|         var innerArea = outerArea - thickness * outerArea; | 
|   | 
|         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 * (int)align; | 
|         var position = Vector2.zero; | 
|         var uv0 = Vector2.zero; | 
|   | 
|         var verticeCount = 0; | 
|         var triangleCount = 0; | 
|   | 
|         if (fullFill) { | 
|             verticeCount = realSegements + 1; | 
|             uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY); | 
|             uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color); | 
|             vh.AddVert(uiVertex); | 
|   | 
|             for (int i = 1; i < verticeCount; i++) { | 
|                 var cosA = Mathf.Cos(degree); | 
|                 var sinA = Mathf.Sin(degree); | 
|                 degree = reversed ? degree + degreeDelta : degree - degreeDelta; | 
|   | 
|                 position = new Vector2(cosA * outerArea.x, sinA * 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; | 
|             for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++) { | 
|                 vh.AddTriangle(vIdx, 0, vIdx + 1); | 
|             } | 
|             if (fillPercent == 1) { | 
|                 vh.AddTriangle(verticeCount - 1, 0, 1); | 
|             } | 
|         } | 
|         else { | 
|             verticeCount = realSegements * 2; | 
|             for (int i = 0; i < verticeCount; i += 2) { | 
|                 var cosA = Mathf.Cos(degree); | 
|                 var sinA = Mathf.Sin(degree); | 
|                 degree = reversed ? degree + degreeDelta : degree - degreeDelta; | 
|   | 
|                 position = new Vector3(cosA * innerArea.x, sinA * innerArea.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(cosA * outerArea.x, sinA * 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); | 
|             } | 
|             if (fillPercent == 1) { | 
|                 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; | 
|     } | 
|   | 
|     public enum Align { | 
|         Top = 1, | 
|         Left = 2, | 
|         Bottom = 3, | 
|         Right = 4, | 
|     } | 
|   | 
| } |