hch
3 小时以前 90d08dded86ebd1ce4edddc388b2347dda26148d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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;
    }
 
}