public void OnDrawGizmos()
    {
        if (!values.drawGizmos)
        {
            return;
        }

        OrientedPoint p = values.spline.GetOrientedPoint(values.t);

        for (int i = 0; i < shape2D.lines.Length; i += 2)
        {
            int     v0   = shape2D.lines[i];
            int     v1   = shape2D.lines[i + 1];
            Vector3 pos0 = p.LocalToWorldPosition((Vector3)shape2D.vertices[v0].point * values.scale + values.localOffset);
            Vector3 pos1 = p.LocalToWorldPosition((Vector3)shape2D.vertices[v1].point * values.scale + values.localOffset);
            Gizmos.DrawLine(pos0, pos1);
        }
    }
    private void GenerateMesh(bool useScaleAsOffset = false, MeshCrossection parentC = null)
    {
        values.mesh.Clear();

        float          uSpan   = shape2D.GetLinesLength();
        List <Vector3> verts   = new List <Vector3>();
        List <Vector3> normals = new List <Vector3>();
        List <Vector2> uvs     = new List <Vector2>();

        for (int currentEdgeRing = 0; currentEdgeRing < values.edgeRingCount; currentEdgeRing++)
        {
            float splineLength = values.spline.GetSplineLength(10f);
            float t            = currentEdgeRing / (values.edgeRingCount - 1f);

            if (values.scaleToEnd)
            {
                values.scale = Mathf.Lerp(values.scaleAtStart, values.scaleAtEnd, t);
            }
            else if (values.scaleByCurve)
            {
                values.scale = values.scaleCurve.Evaluate(t);
            }
            else
            {
                values.scale = values.scaleAtStart;
            }

            values.scaleToEnd = (values.scaleAtEnd != values.scaleAtStart);

            float         multiplier = (values.useMultiplier) ? values.scale : 1f;
            OrientedPoint op         = values.spline.GetOrientedPoint(t);

            Vector3 innerNeg = new Vector3();
            Vector3 innerPos = new Vector3();

            if (scaleSubmeshes && parentC != null)
            {
                int   inNeg = -1;
                int   inPos = -1;
                float inP   = 100000f;
                float inN   = -100000f;
                for (int u = 0; u < parentC.VertexCount; u++)
                {
                    float xpos = parentC.vertices[u].point.x;
                    if (xpos >= inN)
                    {
                        inN   = xpos;
                        inNeg = u;
                    }
                    if (xpos <= inP)
                    {
                        inP   = xpos;
                        inPos = u;
                    }
                }

                innerNeg = parentC.vertices[inNeg].point * transform.lossyScale;
                innerPos = parentC.vertices[inPos].point * transform.lossyScale;
            }

            for (int i = 0; i < shape2D.VertexCount; i++)
            {
                Vector3 p = (Vector3)(shape2D.vertices[i].point);

                if (!useScaleAsOffset)
                {
                    p.x = ((values.scaleX) ? p.x * values.scale : p.x) * transform.lossyScale.x;
                    p.y = ((values.scaleY) ? p.y * values.scale : p.y) * transform.lossyScale.y;
                    p.z = ((values.scaleZ) ? p.z * values.scale : p.z) * transform.lossyScale.z;
                }
                else
                {
                    p.x = (p.x == 0) ? p.x : ((p.x < 0) ? p.x - values.scale : p.x + values.scale) * transform.lossyScale.x;
                    p.y = ((values.scaleY) ? p.y * values.scale : p.y) * transform.lossyScale.y;
                    p.z = ((values.scaleZ) ? p.z * values.scale : p.z) * transform.lossyScale.z;
                    if (p.x < 0)
                    {
                        float o = (innerNeg * values.scale).x;
                        p.x = (p.x - o) + innerNeg.x + (values.scale * transform.lossyScale.x);
                    }
                    else if (p.x > 0)
                    {
                        float o = (innerPos * values.scale).x;
                        p.x = (p.x - o) + innerPos.x - (values.scale * transform.lossyScale.x);
                    }
                }
                verts.Add(transform.InverseTransformPoint(op.LocalToWorldPosition(p * multiplier) + values.localOffset));

                normals.Add(op.LocalToWorldVector((Vector3)(shape2D.vertices[i].normal)));

                uvs.Add(
                    new Vector2(values.uvOffset.x + (currentEdgeRing / (float)values.edgeRingCount - 1) *
                                values.uMultiplier, values.uvOffset.y + (i / (float)shape2D.VertexCount) *
                                splineLength / uSpan * (1 / values.uvRepeatScale)
                                ));
            }
        }

        List <int> triangleIndices = new List <int>();

        for (int r = 0; r < values.edgeRingCount - 1; r++)
        {
            int rootIndex     = r * shape2D.VertexCount;
            int rootIndexNext = (r + 1) * shape2D.VertexCount;

            for (int l = 0; l < shape2D.LineCount; l += 2)
            {
                int lineIndexA = shape2D.lines[l];
                int lineIndexB = shape2D.lines[l + 1];

                int currentA = rootIndex + lineIndexA;
                int currentB = rootIndex + lineIndexB;

                int nextA = rootIndexNext + lineIndexA;
                int nextB = rootIndexNext + lineIndexB;

                // tri 1
                triangleIndices.Add(currentA);
                triangleIndices.Add(nextA);
                triangleIndices.Add(nextB);
                // tri 2
                triangleIndices.Add(currentA);
                triangleIndices.Add(nextB);
                triangleIndices.Add(currentB);
            }
        }

        values.mesh.SetVertices(verts);
        values.mesh.SetNormals(normals);
        values.mesh.SetTriangles(triangleIndices, 0);
        values.mesh.RecalculateBounds();
        values.mesh.RecalculateNormals();
        values.mesh.RecalculateTangents();
        values.mesh.uv = uvs.ToArray();
        GetComponent <MeshCollider>().sharedMesh = values.mesh;
        gameObject.layer = values.layerToAssign;
    }