using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.Sprites; [AddComponentMenu("UI/Custom/SquareHollow Image")] [DisallowMultipleComponent] [RequireComponent(typeof(Image))] public class SquareHollowImage : BaseMeshEffect, ICanvasRaycastFilter { [SerializeField] Vector2 m_Center; public Vector2 center { get { return m_Center; } set { m_Center = value; base.graphic.SetVerticesDirty(); } } [SerializeField] Vector2 m_Cell; public Vector2 cell { get { return m_Cell; } set { m_Cell = value; base.graphic.SetVerticesDirty(); } } public RectTransform rectTransform { get { return this.transform as RectTransform; } } private List innerVertices = new List(); private List outterVertices = new List(); private Image m_Image; public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent()); } } public override void ModifyMesh(VertexHelper vh) { vh.Clear(); innerVertices.Clear(); outterVertices.Clear(); var width = image.rectTransform.rect.width; var height = image.rectTransform.rect.height; var outerArea = new Vector2(0.5f * width, 0.5f * height); var leftBottom = new Vector2(outerArea.x * -1f, outerArea.y * -1f); var innerArea = new Vector2(Mathf.Clamp(cell.x, 0, width), Mathf.Clamp(cell.y, 0, height)); var innerCenter = new Vector2(Mathf.Clamp(center.x, (innerArea.x - width) * 0.5f, (width - innerArea.x) * 0.5f), Mathf.Clamp(center.y, (innerArea.y - height) * 0.5f, (height - innerArea.y) * 0.5f)); 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 positions = new List(); var position = Vector3.zero; position = new Vector3(innerCenter.x + innerArea.x * -0.5f, innerCenter.y + innerArea.y * -0.5f); positions.Add(position); innerVertices.Add(position); position = new Vector3(outerArea.x * -1f, outerArea.y * -1f); positions.Add(position); outterVertices.Add(position); position = new Vector3(innerCenter.x + innerArea.x * 0.5f, innerCenter.y + innerArea.y * -0.5f); positions.Add(position); innerVertices.Add(position); position = new Vector3(outerArea.x * 1f, outerArea.y * -1f); positions.Add(position); outterVertices.Add(position); position = new Vector3(innerCenter.x + innerArea.x * 0.5f, innerCenter.y + innerArea.y * 0.5f); positions.Add(position); innerVertices.Add(position); position = new Vector3(outerArea.x * 1f, outerArea.y * 1f); positions.Add(position); outterVertices.Add(position); position = new Vector3(innerCenter.x + innerArea.x * -0.5f, innerCenter.y + innerArea.y * 0.5f); positions.Add(position); innerVertices.Add(position); position = new Vector3(outerArea.x * -1f, outerArea.y * 1f); positions.Add(position); outterVertices.Add(position); for (int i = 0; i < positions.Count; i++) { position = positions[i]; var uv0 = new Vector2(position.x * uvScaleX + uvCenterX, position.y * uvScaleY + uvCenterY); var uiVertex = UIUtility.PackageUIVertex(position, uv0, image.color); vh.AddVert(uiVertex); } var triangleCount = 8 * 3; 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(8 - 1, 8 - 2, 1); vh.AddTriangle(8 - 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 outterVertices, List innerVertices) { var crossNumber = 0; crossNumber += UIUtility.RayCrossingCount(p, innerVertices); crossNumber += UIUtility.RayCrossingCount(p, outterVertices); return (crossNumber & 1) == 1; } }