private void BridgeFillLineLoops(VertexHelper vh, Color col, List <Vector2> innerVerts, List <Vector2> outerVerts, BoundRect br)
        {
            // Debug.Assert(outerVerts.Count == innerVerts.Count, "BridgeFillLineLoops: different size verts.");

            int vstart = vh.currentVertCount;

            // Add vertices
            UIVertex uivert = UIVertex.simpleVert;

            float bw = br.GetWidth();
            float bh = br.GetHeight();

            UIVertex[] uiv01 = new UIVertex[2];

            for (int i = 0; i < outerVerts.Count; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    var v = (j == 0)? innerVerts[i] : outerVerts[i];

                    float tx = (v.x - br.left) / bw;
                    float ty = (v.y - br.bottom) / bh;
                    uivert.position = new Vector2(v.x, v.y);
                    uivert.uv0      = new Vector2(tx, ty);
                    uivert.color    = col;
                    vh.AddVert(uivert);

                    if (i == 0)
                    {
                        uiv01[j] = uivert;
                    }
                }
            }
            vh.AddVert(uiv01[0]);
            vh.AddVert(uiv01[1]);

            // Add faces
            int i0     = 0 + vstart;
            int i1     = 1 + vstart;
            int vcount = outerVerts.Count * 2 + 2;

            for (int i = 2; i < vcount; i++)
            {
                int i2 = i + vstart;

                if ((i & 1) == 0)
                {
                    vh.AddTriangle(i0, i1, i2);
                }
                else
                {
                    vh.AddTriangle(i1, i0, i2);
                }

                i0 = i1;
                i1 = i2;
            }
        }
        private List <Vector2> MakeCapsuleLineLoop(BoundRect br, float arcMax)
        {
            float capRadius = Mathf.Min(br.GetWidth(), br.GetHeight()) * 0.5f;
            int   capDiv    = Mathf.Max(4, (int)Mathf.Ceil(capRadius * Mathf.PI / arcMax)) & (~0x1);
            // Debug.Log("div:" + cornerDiv);

            float angle_offset;
            var   capPivots = new Vector2[4];

            if (br.GetAspectRatio() < 1.0f)
            {
                angle_offset = Mathf.PI * -0.5f;
                capPivots[0] = new Vector2((br.left + br.right) * 0.5f, br.top - capRadius);
                capPivots[1] = new Vector2((br.left + br.right) * 0.5f, br.bottom + capRadius);
            }
            else
            {
                angle_offset = 0.0f;
                capPivots[0] = new Vector2(br.right - capRadius, (br.top + br.bottom) * 0.5f);
                capPivots[1] = new Vector2(br.left + capRadius, (br.top + br.bottom) * 0.5f);
            }

            var ret = new List <Vector2>(capDiv * 2 + 2);

            for (int i = 0; i < 2; i++)
            {
                Vector2 cp         = capPivots[i];
                float   base_angle = Mathf.PI * 2.0f * (float)i * 0.5f + angle_offset;

                for (int div = 0; div <= capDiv; div++)
                {
                    float angle = (float)div / (float)capDiv * Mathf.PI + base_angle;

                    var v = new Vector2(
                        Mathf.Sin(angle) * capRadius + cp.x,
                        Mathf.Cos(angle) * capRadius + cp.y
                        );
                    ret.Add(v);
                }
            }

            // To make beaty fill mesh.
            for (int i = 0; i < capDiv / 2; i++)
            {
                var tmpv = ret[0];
                ret.RemoveAt(0);
                ret.Add(tmpv);
            }

            return(ret);
        }
        private void FillConvexLineLoop(VertexHelper vh, Color col, List <Vector2> verts, BoundRect br)
        {
            int vstart = vh.currentVertCount;

            // Add vertices
            UIVertex uivert = UIVertex.simpleVert;

            float bw = br.GetWidth();
            float bh = br.GetHeight();

            foreach (Vector2 v in verts)
            {
                float tx = (v.x - br.left) / bw;
                float ty = (v.y - br.bottom) / bh;
                uivert.position = new Vector2(v.x, v.y);
                uivert.uv0      = new Vector2(tx, ty);
                uivert.color    = col;
                vh.AddVert(uivert);
                // iv++;
            }

            // Add faces
            int i0     = 0 + vstart;
            int i1     = 1 + vstart;
            int vcount = verts.Count;

            for (int i = 0; i < vcount - 2; i++)
            {
                int i2;

                if ((i & 1) == 0)
                {
                    i2 = vcount - 1 - i / 2 + vstart;
                    vh.AddTriangle(i0, i1, i2);
                }
                else
                {
                    i2 = 2 + i / 2 + vstart;
                    vh.AddTriangle(i1, i0, i2);
                }

                i0 = i1;
                i1 = i2;
            }
        }
        private List <Vector2> MakeElipseLineLoop(BoundRect br, float arcMax)
        {
            // Ellipse parameters
            float a = br.GetWidth() * 0.5f;                                                           // x radius
            float b = br.GetHeight() * 0.5f;                                                          // y radius
            float h = ((a - b) * (a - b)) / ((a + b) * (a + b));
            float c = Mathf.PI * (a + b) * (1.0f + 3.0f * h / (10.0f + Mathf.Sqrt(4.0f - 3.0f * h))); // Ramanujan's approximation.
            // Debug.Log("h:" + h + ", c:" + c);

            int DIV = Mathf.Max(8, (int)Mathf.Ceil(c / arcMax)) & (~0x1);

            var   ret          = new List <Vector2>(DIV);
            float cx           = (br.left + br.right) * 0.5f;
            float cy           = (br.bottom + br.top) * 0.5f;
            float angle_offset = (a < b) ? 0.0f : (Mathf.PI * 0.5f);

            for (int i = 0; i < DIV; i++)
            {
                float angle = (float)i / (float)DIV * Mathf.PI * 2.0f + angle_offset;
                ret.Add(new Vector2(Mathf.Sin(angle) * a + cx, Mathf.Cos(angle) * b + cy));
            }

            return(ret);
        }
        protected override void OnPopulateMesh(VertexHelper vh)
        {
            var rect        = GetPixelAdjustedRect();
            var shapebounds = new BoundRect(
                rect.yMax - margin.top,
                rect.xMax - margin.right,
                rect.yMin + margin.bottom,
                rect.xMin + margin.left
                );

            if (shapebounds.GetWidth() < 0.0f || shapebounds.GetHeight() < 0.0f)
            {
                vh.Clear();
                return;
            }

            // Vertices list is clock wise.
            List <Vector2> verts;

            switch (shapeType)
            {
            default:
            case ShapeType.Rectangle:
                verts = MakeRectangleLineLoop(shapebounds);
                break;

            case ShapeType.Ellipse:
                verts = MakeElipseLineLoop(shapebounds, maxArcLength);
                break;

            case ShapeType.Capsule:
                verts = MakeCapsuleLineLoop(shapebounds, maxArcLength);
                break;

            case ShapeType.RoundRect:
                verts = MakeRoundRectLineLoop(shapebounds, cornerRadius, maxArcLength);
                break;

            case ShapeType.TrimedRect:
                verts = MakeTrimedRectLineLoop(shapebounds, cornerRadius);
                break;
            }
            // var verts = MakeRectangleLineLoop(shapebounds);
            // var verts = MakeElipseLineLoop(shapebounds);
            // var verts = MakeCapsuleLineLoop(shapebounds);
            // var verts = MakeRoundRectLineLoop(shapebounds);

            RemoveDegenerateEdges(verts, 0.1f);

            vh.Clear();

            if (borderWidth > 0.0f)
            {
                // Inset loop
                var insetverts = MakeInsetLineLoop(verts, borderWidth);
                // Create border
                BridgeFillLineLoops(vh, borderColor, insetverts, verts, shapebounds);

                // Fill shape
                FillConvexLineLoop(vh, color, insetverts, shapebounds);
            }
            else
            {
                // Fill shape
                FillConvexLineLoop(vh, color, verts, shapebounds);
            }
        }