public static bool HasSimpleJoin( this PolylineJoins join ) {
			switch( join ) {
				case PolylineJoins.Simple: return false;
				case PolylineJoins.Miter:  return false;
				case PolylineJoins.Round:  return false;
				case PolylineJoins.Bevel:  return true;
				default:                   throw new ArgumentOutOfRangeException( nameof(join), join, null );
			}
		}
Beispiel #2
0
        [OvldGenCallTarget] public static void Polyline([OvldDefault(nameof(BlendMode))] ShapesBlendMode blendMode,
                                                        PolylinePath path,
                                                        [OvldDefault("false")] bool closed,
                                                        [OvldDefault(nameof(PolylineGeometry))] PolylineGeometry geometry,
                                                        [OvldDefault(nameof(PolylineJoins))] PolylineJoins joins,
                                                        [OvldDefault(nameof(LineThickness))] float thickness,
                                                        [OvldDefault(nameof(LineThicknessSpace))] ThicknessSpace thicknessSpace,
                                                        [OvldDefault(nameof(Color))] Color color)
        {
            if (path.EnsureMeshIsReadyToRender(closed, joins, out Mesh mesh) == false)
            {
                return;                 // no points defined in the mesh
            }
            switch (path.Count)
            {
            case 0:
                Debug.LogWarning("Tried to draw polyline with no points");
                return;

            case 1:
                Debug.LogWarning("Tried to draw polyline with only one point");
                return;
            }

            Material matPolyLine = ShapesMaterialUtils.GetPolylineMat(joins)[blendMode];

            ApplyGlobalProperties(matPolyLine);
            matPolyLine.SetFloat(ShapesMaterialUtils.propThickness, thickness);
            matPolyLine.SetFloat(ShapesMaterialUtils.propThicknessSpace, (int)thicknessSpace);
            matPolyLine.SetColor(ShapesMaterialUtils.propColor, color);
            matPolyLine.SetInt(ShapesMaterialUtils.propAlignment, (int)geometry);
            matPolyLine.SetInt(ShapesMaterialUtils.propScaleMode, (int)ScaleMode);
            if (joins == PolylineJoins.Miter)
            {
                DrawMesh(Vector3.zero, Quaternion.identity, mesh, matPolyLine);
            }
            else
            {
                Material matPolyLineJoins = ShapesMaterialUtils.GetPolylineJoinsMat(joins)[blendMode];
                ApplyGlobalProperties(matPolyLineJoins);
                matPolyLineJoins.SetFloat(ShapesMaterialUtils.propThickness, thickness);
                matPolyLineJoins.SetFloat(ShapesMaterialUtils.propThicknessSpace, (int)thicknessSpace);
                matPolyLineJoins.SetColor(ShapesMaterialUtils.propColor, color);
                matPolyLineJoins.SetInt(ShapesMaterialUtils.propAlignment, (int)geometry);
                matPolyLineJoins.SetInt(ShapesMaterialUtils.propScaleMode, (int)ScaleMode);
                DrawTwoSubmeshes(Vector3.zero, Quaternion.identity, mesh, matPolyLine, matPolyLineJoins);
            }
        }
Beispiel #3
0
        [OvldGenCallTarget] static void Polyline_Internal(PolylinePath path,
                                                          [OvldDefault("false")] bool closed,
                                                          [OvldDefault(nameof(PolylineGeometry))] PolylineGeometry geometry,
                                                          [OvldDefault(nameof(PolylineJoins))] PolylineJoins joins,
                                                          [OvldDefault(nameof(Thickness))] float thickness,
                                                          [OvldDefault(nameof(ThicknessSpace))] ThicknessSpace thicknessSpace,
                                                          [OvldDefault(nameof(Color))] Color color)
        {
            if (path.EnsureMeshIsReadyToRender(closed, joins, out Mesh mesh) == false)
            {
                return;                 // no points defined in the mesh
            }
            switch (path.Count)
            {
            case 0:
                Debug.LogWarning("Tried to draw polyline with no points");
                return;

            case 1:
                Debug.LogWarning("Tried to draw polyline with only one point");
                return;
            }

            void ApplyToMpb(MpbPolyline2D mpb)
            {
                mpb.thickness.Add(thickness);
                mpb.thicknessSpace.Add((int)thicknessSpace);
                mpb.color.Add(color.ColorSpaceAdjusted());
                mpb.alignment.Add((int)geometry);
                mpb.scaleMode.Add((int)ScaleMode);
            }

            if (DrawCommand.IsAddingDrawCommandsToBuffer)              // mark as used by this command to prevent destroy in dispose
            {
                path.RegisterToCommandBuffer(DrawCommand.CurrentWritingCommandBuffer);
            }

            using (new IMDrawer(mpbPolyline, ShapesMaterialUtils.GetPolylineMat(joins)[Draw.BlendMode], mesh, 0))
                ApplyToMpb(mpbPolyline);

            if (joins.HasJoinMesh())
            {
                using (new IMDrawer(mpbPolylineJoins, ShapesMaterialUtils.GetPolylineJoinsMat(joins)[Draw.BlendMode], mesh, 1))
                    ApplyToMpb(mpbPolylineJoins);
            }
        }
Beispiel #4
0
        [OvldGenCallTarget] static void Polyline([OvldDefault(nameof(BlendMode))] ShapesBlendMode blendMode,
                                                 PolylinePath path,
                                                 [OvldDefault("false")] bool closed,
                                                 [OvldDefault(nameof(PolylineGeometry))] PolylineGeometry geometry,
                                                 [OvldDefault(nameof(PolylineJoins))] PolylineJoins joins,
                                                 [OvldDefault(nameof(LineThickness))] float thickness,
                                                 [OvldDefault(nameof(LineThicknessSpace))] ThicknessSpace thicknessSpace,
                                                 [OvldDefault(nameof(Color))] Color color)
        {
            if (path.EnsureMeshIsReadyToRender(closed, joins, out Mesh mesh) == false)
            {
                return;                 // no points defined in the mesh
            }
            switch (path.Count)
            {
            case 0:
                Debug.LogWarning("Tried to draw polyline with no points");
                return;

            case 1:
                Debug.LogWarning("Tried to draw polyline with only one point");
                return;
            }

            void ApplyToMpb(MpbPolyline mpb)
            {
                mpb.thickness.Add(thickness);
                mpb.thicknessSpace.Add((int)thicknessSpace);
                mpb.color.Add(color);
                mpb.alignment.Add((int)geometry);
                mpb.scaleMode.Add((int)ScaleMode);
            }

            using (new IMDrawer(mpbPolyline, ShapesMaterialUtils.GetPolylineMat(joins)[blendMode], mesh, 0))
                ApplyToMpb(mpbPolyline);

            if (joins.HasJoinMesh())
            {
                using (new IMDrawer(mpbPolylineJoins, ShapesMaterialUtils.GetPolylineJoinsMat(joins)[blendMode], mesh, 1))
                    ApplyToMpb(mpbPolylineJoins);
            }
        }
 public static ShapesMaterials GetPolylineJoinsMat(PolylineJoins join) => matsPolylineJoin[(int)join];
        public static void GenPolylineMesh(Mesh mesh, IList <PolylinePoint> path, bool closed, PolylineJoins joins, bool useColors)
        {
            mesh.Clear();             // todo maybe not always do this you know?

            int pointCount = path.Count;

            if (pointCount < 2)
            {
                return;
            }
            if (pointCount == 2 && closed)
            {
                closed = false;
            }

            PolylinePoint firstPoint = path[0];
            PolylinePoint lastPoint  = path[path.Count - 1];

            // if the last point is at the same place as the first and it's closed, ignore the last point
            if ((closed || pointCount == 2) && SamePosition(firstPoint.point, lastPoint.point))
            {
                pointCount--;                 // ignore last point
                if (pointCount < 2)           // check point count again
                {
                    return;
                }
                lastPoint = path[path.Count - 2];                 // second last point technically
            }

            // only mitered joints can be in the same submesh at the moment
            bool separateJoinMesh    = joins.HasJoinMesh();
            bool isSimpleJoin        = joins.HasSimpleJoin();      // only used when join meshes exist
            int  vertsPerPathPoint   = separateJoinMesh ? 5 : 2;
            int  trianglesPerSegment = separateJoinMesh ? 4 : 2;
            int  vertexCount         = pointCount * vertsPerPathPoint;
            int  vertexCountTotal    = vertexCount;
            int  segmentCount        = closed ? pointCount : pointCount - 1;
            int  triangleCount       = segmentCount * trianglesPerSegment;
            int  triangleIndexCount  = triangleCount * 3;

            // Joins mesh data
            int[] meshJoinsTriangles = default;
            int   joinVertsPerJoin   = default;

            if (separateJoinMesh)
            {
                joinVertsPerJoin = isSimpleJoin ? 3 : 5;
                int joinCount              = closed ? pointCount : pointCount - 2;
                int joinTrianglesPerJoin   = isSimpleJoin ? 1 : 3;
                int joinTriangleIndexCount = joinCount * joinTrianglesPerJoin * 3;
                int vertexCountJoins       = joinCount * joinVertsPerJoin;
                vertexCountTotal  += vertexCountJoins;
                meshJoinsTriangles = new int[joinTriangleIndexCount];
            }


            Color[]   meshColors   = useColors ? new Color[vertexCountTotal] : null;
            Vector3[] meshVertices = new Vector3[vertexCountTotal];

                        #if UNITY_2019_3_OR_NEWER
            Vector4[] meshUv0      = new Vector4[vertexCountTotal];        // UVs for masking. z contains endpoint status, w is thickness
            Vector3[] meshUv1Prevs = new Vector3[vertexCountTotal];
            Vector3[] meshUv2Nexts = new Vector3[vertexCountTotal];
                        #else
            // List<> is the only supported vec3 UV assignment method prior to Unity 2019.3
            List <Vector4> meshUv0      = new List <Vector4>(new Vector4[vertexCountTotal]);
            List <Vector3> meshUv1Prevs = new List <Vector3>(new Vector3[vertexCountTotal]);
            List <Vector3> meshUv2Nexts = new List <Vector3>(new Vector3[vertexCountTotal]);
                        #endif


            int[] meshTriangles = new int[triangleIndexCount];


            // indices used per triangle
            int iv0, iv1, iv2 = 0, iv3 = 0, iv4 = 0;
            int ivj0 = 0, ivj1 = 0, ivj2 = 0, ivj3 = 0, ivj4 = 0;
            int triId     = 0;
            int triIdJoin = 0;
            for (int i = 0; i < pointCount; i++)
            {
                bool  isLast          = i == pointCount - 1;
                bool  isFirst         = i == 0;
                bool  makeJoin        = closed || (!isLast && !isFirst);
                bool  isEndpoint      = closed == false && (isFirst || isLast);
                float uvEndpointValue = isEndpoint ? (isFirst ? -1 : 1) : 0;
                void SetUv0(int id, float x, float y) => meshUv0[id] = new Vector4(x, y, uvEndpointValue, path[i].thickness);


                // Indices & verts
                Vector3 vert  = path[i].point;
                Color   color = useColors ? path[i].color : default;
                iv0 = i * vertsPerPathPoint;
                if (separateJoinMesh)
                {
                    iv1 = iv0 + 1;                     // "prev" outer
                    iv2 = iv0 + 2;                     // "next" outer
                    iv3 = iv0 + 3;                     // "prev" inner
                    iv4 = iv0 + 4;                     // "next" inner
                    meshVertices[iv0] = vert;
                    meshVertices[iv1] = vert;
                    meshVertices[iv2] = vert;
                    meshVertices[iv3] = vert;
                    meshVertices[iv4] = vert;
                    if (useColors)
                    {
                        meshColors[iv0] = color;
                        meshColors[iv1] = color;
                        meshColors[iv2] = color;
                        meshColors[iv3] = color;
                        meshColors[iv4] = color;
                    }


                    // joins mesh
                    if (makeJoin)
                    {
                        int joinIndex = (closed ? i : i - 1);                           // Skip first if open
                        ivj0 = joinIndex * joinVertsPerJoin + vertexCount;
                        ivj1 = ivj0 + 1;
                        ivj2 = ivj0 + 2;
                        ivj3 = ivj0 + 3;
                        ivj4 = ivj0 + 4;
                        meshVertices[ivj0] = vert;
                        meshVertices[ivj1] = vert;
                        meshVertices[ivj2] = vert;
                        if (useColors)
                        {
                            meshColors[ivj0] = color;
                            meshColors[ivj1] = color;
                            meshColors[ivj2] = color;
                        }

                        if (isSimpleJoin == false)
                        {
                            meshVertices[ivj3] = vert;
                            meshVertices[ivj4] = vert;
                            if (useColors)
                            {
                                meshColors[ivj3] = color;
                                meshColors[ivj4] = color;
                            }
                        }
                    }
                }
                else
                {
                    iv1 = iv0 + 1;                     // Inner vert
                    meshVertices[iv0] = vert;
                    meshVertices[iv1] = vert;
                    if (useColors)
                    {
                        meshColors[iv0] = color;
                        meshColors[iv1] = color;
                    }
                }


                // Setting up next/previous positions
                Vector3 prevPos;
                Vector3 nextPos;
                if (i == 0)
                {
                    prevPos = closed ? lastPoint.point : (firstPoint.point * 2 - path[1].point);                       // Mirror second point
                    nextPos = path[i + 1].point;
                }
                else if (i == pointCount - 1)
                {
                    prevPos = path[i - 1].point;
                    nextPos = closed ? firstPoint.point : (path[pointCount - 1].point * 2 - path[pointCount - 2].point);                       // Mirror second last point
                }
                else
                {
                    prevPos = path[i - 1].point;
                    nextPos = path[i + 1].point;
                }

                void SetPrevNext(int atIndex)
                {
                    meshUv1Prevs[atIndex] = prevPos;
                    meshUv2Nexts[atIndex] = nextPos;
                }

                SetPrevNext(iv0);
                SetPrevNext(iv1);
                if (separateJoinMesh)
                {
                    SetPrevNext(iv2);
                    SetPrevNext(iv3);
                    SetPrevNext(iv4);
                    if (makeJoin)
                    {
                        SetPrevNext(ivj0);
                        SetPrevNext(ivj1);
                        SetPrevNext(ivj2);
                        if (isSimpleJoin == false)
                        {
                            SetPrevNext(ivj3);
                            SetPrevNext(ivj4);
                        }
                    }
                }

                if (separateJoinMesh)
                {
                    SetUv0(iv0, 0, 0);
                    SetUv0(iv1, -1, -1);
                    SetUv0(iv2, -1, 1);
                    SetUv0(iv3, 1, -1);
                    SetUv0(iv4, 1, 1);
                    if (makeJoin)
                    {
                        SetUv0(ivj0, 0, 0);
                        if (isSimpleJoin)
                        {
                            SetUv0(ivj1, 1, -1);
                            SetUv0(ivj2, 1, 1);
                        }
                        else
                        {
                            SetUv0(ivj1, 1, -1);
                            SetUv0(ivj2, -1, -1);
                            SetUv0(ivj3, -1, 1);
                            SetUv0(ivj4, 1, 1);
                        }
                    }
                }
                else
                {
                    SetUv0(iv0, -1, i);
                    SetUv0(iv1, 1, i);
                }


                if (isLast == false || closed)
                {
                    // clockwise order
                    void AddQuad(int a, int b, int c, int d)
                    {
                        meshTriangles[triId++] = a;
                        meshTriangles[triId++] = b;
                        meshTriangles[triId++] = c;
                        meshTriangles[triId++] = c;
                        meshTriangles[triId++] = d;
                        meshTriangles[triId++] = a;
                    }

                    if (separateJoinMesh)
                    {
                        int rootCenter = iv0;
                        int rootOuter  = iv2;
                        int rootInner  = iv4;
                        int nextCenter = isLast ? 0 : rootCenter + vertsPerPathPoint;
                        int nextOuter  = nextCenter + 1;
                        int nextInner  = nextCenter + 3;
                        AddQuad(rootCenter, rootOuter, nextOuter, nextCenter);
                        AddQuad(nextCenter, nextInner, rootInner, rootCenter);

                        if (makeJoin)
                        {
                            meshJoinsTriangles[triIdJoin++] = ivj0;
                            meshJoinsTriangles[triIdJoin++] = ivj1;
                            meshJoinsTriangles[triIdJoin++] = ivj2;

                            if (isSimpleJoin == false)
                            {
                                meshJoinsTriangles[triIdJoin++] = ivj2;
                                meshJoinsTriangles[triIdJoin++] = ivj3;
                                meshJoinsTriangles[triIdJoin++] = ivj0;

                                meshJoinsTriangles[triIdJoin++] = ivj0;
                                meshJoinsTriangles[triIdJoin++] = ivj3;
                                meshJoinsTriangles[triIdJoin++] = ivj4;
                            }
                        }
                    }
                    else
                    {
                        int rootOuter = iv0;
                        int rootInner = iv1;
                        int nextOuter = isLast ? 0 : rootOuter + vertsPerPathPoint;
                        int nextInner = nextOuter + 1;
                        AddQuad(rootInner, rootOuter, nextOuter, nextInner);
                    }
                }
            }

            // assign to segments mesh
            mesh.vertices     = meshVertices;
            mesh.subMeshCount = 2;
            mesh.SetTriangles(meshTriangles, 0);
            mesh.SetTriangles(meshJoinsTriangles, 1);
            mesh.SetUVs(0, meshUv0);
            mesh.SetUVs(1, meshUv1Prevs);
            mesh.SetUVs(2, meshUv2Nexts);
            if (useColors)
            {
                mesh.colors = meshColors;
            }
        }