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;
|
}
|
|
}
|