hch
5 小时以前 1f7688ee049312e095eb9eee2388fa58fa15ff81
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
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;
    }
 
}