using System.Collections.Generic; using UnityEngine; using UnityEngine.Sprites; using UnityEngine.UI; [RequireComponent(typeof(Image))] public class DivideImage : BaseMeshEffect, ICanvasRaycastFilter { [SerializeField] int m_Divide = 5; public int Divide { get { return m_Divide; } } [SerializeField] int m_CurrentDivide = 1; public int CurrenDivide { get { return m_CurrentDivide; } } [Range(0, 1)] [SerializeField] float m_FillPercent = 1f; public float fillPercent { get { return m_FillPercent; } } [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()); } } private List outterVertices; protected override void Awake() { outterVertices = new List(); } public override void ModifyMesh(VertexHelper vh) { vh.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 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; var outerArea = new Vector2(0.5f * width, 0.5f * height); UIVertex uiVertex; var position = Vector2.zero; var uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY); uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color); vh.AddVert(uiVertex); var everyRad = (float)(2 * Mathf.PI / Divide); var currentRad = everyRad*CurrenDivide - Mathf.PI*0.1f; var verticeCount = 0; var triangleCount = 0; 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(currentRad); var sinA = Mathf.Sin(currentRad); currentRad = currentRad - 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); } } 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); } private bool Contains(Vector2 p, List outterVertices) { var crossNumber = 0; crossNumber += UIUtility.RayCrossingCount(p, outterVertices); return (crossNumber & 1) == 1; } }