public void AddShapes(SVGShape[] shapes) { SVGShape[] current = new SVGShape[_layer.shapes.Length]; _layer.shapes.CopyTo(current, 0); _layer.shapes = new SVGShape[current.Length + shapes.Length]; current.CopyTo(_layer.shapes, 0); shapes.CopyTo(_layer.shapes, current.Length); }
public void AddCollider2D(int targetLayerIndex) { if (_svgAssets == null || _svgAssets.Count <= 0) { return; } int verticeStartIndex = 0; int spliceLayerIndex = targetLayerIndex / this._sliceLayerNum; int startLayerIndex = spliceLayerIndex * this._sliceLayerNum; for (int i = startLayerIndex; i < targetLayerIndex; i++) { int totalShapes = _svgAssets[0].layers[i].shapes.Length; for (int j = 0; j < totalShapes; j++) { verticeStartIndex += _svgAssets[0].layers[i].shapes[j].vertexCount; } } GameObject obj = null; PolygonCollider2D polygonCollider2D = null; if (colliderPool.Count > 0) { obj = colliderPool[0]; colliderPool.RemoveAt(0); polygonCollider2D = obj.GetComponent <PolygonCollider2D>(); obj.name = "collider_" + targetLayerIndex; } if (obj == null) { obj = new GameObject("collider_" + targetLayerIndex); } obj.transform.parent = colliderLayer.transform; obj.transform.localScale = svgPreview.transform.localScale; obj.transform.position = svgPreview.transform.position; if (polygonCollider2D == null) { polygonCollider2D = obj.AddComponent <PolygonCollider2D>(); } SVGShape svgShape = _svgAssets[0].layers[targetLayerIndex].shapes[0]; Vector2[] points = new Vector2[svgShape.triangles.Length]; int vindex = 0; for (int i = 0; i < svgShape.triangles.Length; i++) { vindex = svgShape.triangles[i]; points[i] = new Vector2(svgShape.vertices[vindex].x, svgShape.vertices[vindex].y); } polygonCollider2D.SetPath(0, points); }
public bool InsideShape(SVGShape shape, Vector2 position) { if (shape.bounds.Contains(position)) { for (int i = 0; i < shape.triangles.Length; i += 3) { if (PointInTriangle(position, shape.vertices[shape.triangles[i]], shape.vertices[shape.triangles[i + 1]], shape.vertices[shape.triangles[i + 2]])) { return(true); } } } return(false); }
public static SVGShape[] GetShapes(List <List <Vector2> > inputShapes, SVGPaintable paintable, SVGMatrix matrix, bool isStroke = false) { SVGShape[] shapes = null;; SVGShape shape; SVGShape antialiasingShape; if (SVGSimplePath.CreatePolygon(inputShapes, paintable, matrix, out shape, out antialiasingShape, isStroke, _antialiasing)) { if (_antialiasing) { shapes = new SVGShape[] { shape, antialiasingShape }; } else { shapes = new SVGShape[] { shape }; } } return(shapes); }
public override void OnInspectorGUI() { SVGDebugLayers go = target as SVGDebugLayers; SVGRenderer svgrenderer = go.GetComponent <SVGRenderer>(); if (svgrenderer == null || svgrenderer.vectorGraphics == null) { return; } currentAsset = svgrenderer.vectorGraphics; SVGLayer[] svgLayers = currentAsset.layers; if (svgLayers == null) { return; } for (int i = 0; i < svgLayers.Length; i++) { string layerName = svgLayers[i].name; GUILayout.Label(layerName, SVGGUI.helpBox); Rect lastRect = GUILayoutUtility.GetLastRect(); if (lastRect.Contains(Event.current.mousePosition)) { hilightedLayer = svgLayers[i]; SceneView.RepaintAll(); } if (svgLayers[i].shapes != null) { for (int j = 0; j < svgLayers[i].shapes.Length; j++) { GUILayout.Label(" "+ layerName + " " + svgLayers[i].shapes[j].type.ToString(), SVGGUI.helpBox); lastRect = GUILayoutUtility.GetLastRect(); if (lastRect.Contains(Event.current.mousePosition)) { hilightedShape = svgLayers[i].shapes[j]; SceneView.RepaintAll(); } } } } }
public static void HilightShape(SVGShape shape) { if (shape.triangles == null || shape.vertices == null) { return; } if (Event.current.type != EventType.Repaint) { return; } Color c = Handles.color * new Color(1f, 1f, 1f, 0.25f); ApplyInvertMaterial(); GL.PushMatrix(); GL.MultMatrix(Handles.matrix); GL.Begin(GL.TRIANGLES); GL.Color(c); int trianglesLength = shape.triangles.Length; Vector2 vertex; for (int i = 0; i < trianglesLength; i += 3) { vertex = shape.vertices[shape.triangles[i]]; GL.Vertex3(vertex.x, vertex.y, 0f); vertex = shape.vertices[shape.triangles[i + 1]]; GL.Vertex3(vertex.x, vertex.y, 0f); vertex = shape.vertices[shape.triangles[i + 2]]; GL.Vertex3(vertex.x, vertex.y, 0f); } GL.End(); GL.PopMatrix(); }
void DebugPoints(SVGShape svgShape, SVGAsset svgAsset) { if (svgShape.vertexCount == 0) { return; } if (Event.current.type == EventType.Repaint) { SVGDebugLayers go = target as SVGDebugLayers; Matrix4x4 handlesMatrix = Handles.matrix; Handles.matrix = go.transform.localToWorldMatrix; Vector3 lastPosition = svgShape.vertices[0]; Vector3 currentPosition; for (int j = 1; j < svgShape.vertexCount; j++) { currentPosition = svgShape.vertices[j]; Handles.DrawLine(lastPosition, currentPosition); lastPosition = currentPosition; } Handles.matrix = handlesMatrix; } }
public static bool CreateAntialiasing(List <List <Vector2> > inputShapes, out SVGShape svgShape, Color colorA, float width, ClosePathRule closePath = ClosePathRule.NEVER) { svgShape = new SVGShape(); if (inputShapes == null || inputShapes.Count == 0) { return(false); } Color colorB = new Color(colorA.r, colorA.g, colorA.b, 0f); if (inputShapes.Count > 1) { List <SVGShape> shapes = new List <SVGShape>(); SVGShape currentLayer; for (int i = 0; i < inputShapes.Count; i++) { if (SVGMeshUtils.VectorLine(inputShapes[i].ToArray(), out currentLayer, colorA, colorB, width, width * 0.5f, closePath)) { shapes.Add(currentLayer); } } if (shapes.Count > 0) { svgShape = SVGShape.MergeShapes(shapes); return(true); } else { return(false); } } else { return(SVGMeshUtils.VectorLine(inputShapes[0].ToArray(), out svgShape, colorA, colorB, width, width * 0.5f, closePath)); } }
public static bool CreatePolygon(List <List <Vector2> > inputShapes, SVGPaintable paintable, SVGMatrix matrix, out SVGShape layer, out SVGShape antialiasingLayer, bool isStroke = false, bool antialiasing = false) { layer = new SVGShape(); antialiasingLayer = new SVGShape(); if (inputShapes == null || inputShapes.Count == 0) { return(false); } List <List <Vector2> > simplifiedShapes = new List <List <Vector2> >(); PolyFillType fillType = PolyFillType.pftNonZero; if (paintable.fillRule == SVGFillRule.EvenOdd) { fillType = PolyFillType.pftEvenOdd; } simplifiedShapes = SVGGeom.SimplifyPolygons(inputShapes, fillType); if (simplifiedShapes == null || simplifiedShapes.Count == 0) { return(false); } AddInputShape(simplifiedShapes); Rect bounds = GetRect(simplifiedShapes); Rect viewport = paintable.viewport; if (!isStroke) { switch (paintable.GetPaintType()) { case SVGPaintMethod.SolidFill: { layer.type = SVGShapeType.FILL; Color color = Color.black; SVGColorType colorType = paintable.fillColor.Value.colorType; if (colorType == SVGColorType.Unknown || colorType == SVGColorType.None) { color.a *= paintable.fillOpacity; paintable.svgFill = new SVGFill(color); } else { color = paintable.fillColor.Value.color; color.a *= paintable.fillOpacity; paintable.svgFill = new SVGFill(color); } paintable.svgFill.fillType = FILL_TYPE.SOLID; if (color.a == 1) { paintable.svgFill.blend = FILL_BLEND.OPAQUE; } else { paintable.svgFill.blend = FILL_BLEND.ALPHA_BLENDED; } } break; case SVGPaintMethod.LinearGradientFill: { layer.type = SVGShapeType.FILL; SVGLinearGradientBrush linearGradBrush = paintable.GetLinearGradientBrush(bounds, matrix, viewport); paintable.svgFill = linearGradBrush.fill; } break; case SVGPaintMethod.RadialGradientFill: { layer.type = SVGShapeType.FILL; SVGRadialGradientBrush radialGradBrush = paintable.GetRadialGradientBrush(bounds, matrix, viewport); paintable.svgFill = radialGradBrush.fill; } break; case SVGPaintMethod.ConicalGradientFill: { layer.type = SVGShapeType.FILL; SVGConicalGradientBrush conicalGradBrush = paintable.GetConicalGradientBrush(bounds, matrix, viewport); paintable.svgFill = conicalGradBrush.fill; } break; case SVGPaintMethod.PathDraw: { layer.type = SVGShapeType.STROKE; Color color = Color.black; SVGColorType colorType = paintable.fillColor.Value.colorType; if (colorType == SVGColorType.Unknown || colorType == SVGColorType.None) { color.a *= paintable.strokeOpacity; paintable.svgFill = new SVGFill(color); } else { color = paintable.fillColor.Value.color; color.a *= paintable.strokeOpacity; paintable.svgFill = new SVGFill(color); } paintable.svgFill.fillType = FILL_TYPE.SOLID; if (color.a == 1) { paintable.svgFill.blend = FILL_BLEND.OPAQUE; } else { paintable.svgFill.blend = FILL_BLEND.ALPHA_BLENDED; } } break; default: break; } } else { layer.type = SVGShapeType.STROKE; Color color = paintable.strokeColor.Value.color; color.a *= paintable.strokeOpacity; paintable.svgFill = new SVGFill(color, FILL_BLEND.OPAQUE, FILL_TYPE.SOLID); if (color.a != 1f) { paintable.svgFill.blend = FILL_BLEND.ALPHA_BLENDED; } paintable.svgFill.color = color; } // Use LibTessDotNet if (true) { LibTessDotNet.Tess tesselation = new LibTessDotNet.Tess(); LibTessDotNet.ContourVertex[] path; int pathLength; for (int i = 0; i < simplifiedShapes.Count; i++) { if (simplifiedShapes[i] == null) { continue; } pathLength = simplifiedShapes[i].Count; path = new LibTessDotNet.ContourVertex[pathLength]; Vector2 position; for (int j = 0; j < pathLength; j++) { position = simplifiedShapes[i][j]; path[j].Position = new LibTessDotNet.Vec3 { X = position.x, Y = position.y, Z = 0f }; } tesselation.AddContour(path, SVGImporter.LibTessDotNet.ContourOrientation.Clockwise); } tesselation.Tessellate(LibTessDotNet.WindingRule.EvenOdd, LibTessDotNet.ElementType.Polygons, 3); int meshVertexCount = tesselation.Vertices.Length; if (meshVertexCount == 0) { return(false); } int numTriangles = tesselation.ElementCount; layer.triangles = new int[numTriangles * 3]; layer.vertices = new Vector2[meshVertexCount]; for (int i = 0; i < numTriangles; i++) { layer.triangles[i * 3] = tesselation.Elements[i * 3]; layer.triangles[i * 3 + 1] = tesselation.Elements[i * 3 + 1]; layer.triangles[i * 3 + 2] = tesselation.Elements[i * 3 + 2]; } for (int i = 0; i < meshVertexCount; i++) { layer.vertices[i] = new Vector2(tesselation.Vertices[i].Position.X, tesselation.Vertices[i].Position.Y) * SVGAssetImport.meshScale; } } /* * else { * // Use Triangle.net library * SVGImporter.TriangleNet.Mesh triangleMesh = new SVGImporter.TriangleNet.Mesh(); * SVGImporter.TriangleNet.Geometry.InputGeometry triangleInput = new SVGImporter.TriangleNet.Geometry.InputGeometry(); * * int pathLength, m = 0; * for(int i = 0; i < simplifiedShapes.Count; i++) * { * if(simplifiedShapes[i] == null) * continue; * * pathLength = simplifiedShapes[i].Count; * Vector2 position; * for(int j = 0; j < pathLength; j++) * { * triangleInput.AddPoint(simplifiedShapes[i][j].x, simplifiedShapes[i][j].y); * } * } * * triangleMesh.Triangulate(triangleInput); * * int totalVertices = triangleMesh.vertices.Count; * layer.vertices = new Vector2[totalVertices]; * for(int i = 0; i < totalVertices; i++) * { * layer.vertices[i].x = (float)triangleMesh.vertices[i].x * SVGAssetImport.meshScale; * layer.vertices[i].y = (float)triangleMesh.vertices[i].y * SVGAssetImport.meshScale; * } * * int totalTriangles = triangleMesh.triangles.Count; * layer.triangles = new int[totalTriangles * 3]; * int ti = 0; * for(int i = 0; i < totalTriangles; i++) * { * ti = i * 3; * layer.triangles[ti] = triangleMesh.triangles[i].P0; * layer.triangles[ti + 1] = triangleMesh.triangles[i].P1; * layer.triangles[ti + 2] = triangleMesh.triangles[i].P2; * } * } */ layer.fill = paintable.svgFill; layer.fill.opacity = paintable.opacity; if (layer.fill.opacity < 1f && layer.fill.blend == FILL_BLEND.OPAQUE) { layer.fill.blend = FILL_BLEND.ALPHA_BLENDED; } if (layer.fill.fillType == FILL_TYPE.GRADIENT && layer.fill.gradientColors != null) { layer.fill.color = Color.white; } else if (layer.fill.fillType == FILL_TYPE.TEXTURE) { layer.fill.color = Color.white; } viewport.x *= SVGAssetImport.meshScale; viewport.y *= SVGAssetImport.meshScale; viewport.size *= SVGAssetImport.meshScale; layer.fill.viewport = viewport; SVGMatrix scaleMatrix = SVGMatrix.identity.Scale(SVGAssetImport.meshScale); layer.fill.transform = scaleMatrix.Multiply(layer.fill.transform); layer.fill.transform = layer.fill.transform.Multiply(scaleMatrix.Inverse()); Vector2 boundsMin = bounds.min * SVGAssetImport.meshScale; Vector2 boundsMax = bounds.max * SVGAssetImport.meshScale; layer.bounds = new Rect(boundsMin.x, boundsMin.y, boundsMax.x - boundsMin.x, boundsMax.y - boundsMin.y); if (antialiasing) { if (CreateAntialiasing(simplifiedShapes, out antialiasingLayer, Color.white, -1f, ClosePathRule.ALWAYS)) { int verticesLength = antialiasingLayer.vertices.Length; for (int i = 0; i < verticesLength; i++) { antialiasingLayer.vertices[i] *= SVGAssetImport.meshScale; } antialiasingLayer.type = SVGShapeType.ANTIALIASING; antialiasingLayer.RecalculateBounds(); antialiasingLayer.fill = layer.fill.Clone(); antialiasingLayer.fill.blend = FILL_BLEND.ALPHA_BLENDED; } } return(true); }
/* * public static Mesh CreateStrokeMesh(List<Vector2> inputShapes, SVGPaintable paintable, ClosePathRule closePath = ClosePathRule.NEVER) * { * if(inputShapes == null || inputShapes.Count == 0 || paintable == null || paintable.strokeWidth <= 0f) * return null; * * return CreateStrokeMesh(new List<List<Vector2>>(){inputShapes}, paintable, closePath); * } * * public static Mesh CreateStrokeMesh(List<List<Vector2>> inputShapes, SVGPaintable paintable, ClosePathRule closePath = ClosePathRule.NEVER) * { * if(inputShapes == null || inputShapes.Count == 0 || paintable == null || paintable.strokeWidth <= 0f) * return null; * * List<StrokeSegment[]> segments = new List<StrokeSegment[]>(); * for(int i = 0; i < inputShapes.Count; i++) * { * if(inputShapes[i] == null || inputShapes[i].Count < 2) * continue; * * segments.Add(GetSegments(inputShapes[i])); * } * * return SVGLineUtils.StrokeMesh(segments, paintable.strokeWidth, GetStrokeColor(paintable), GetStrokeLineJoin(paintable.strokeLineJoin), GetStrokeLineCap(paintable.strokeLineCap), paintable.miterLimit, paintable.dashArray, paintable.dashOffset, closePath, SVGGraphics.roundQuality); * } */ /* * public static Mesh CreateStrokeSimple(SVGPaintable paintable, ClosePathRule closePath = ClosePathRule.NEVER) * { * return CreateStrokeSimple(new List<List<Vector2>>(){new List<Vector2>(SVGGraphics.position_buffer.ToArray())}, paintable, closePath); * } */ public static Mesh CreateStrokeSimple(List <List <Vector2> > inputShapes, SVGPaintable paintable, ClosePathRule closePath = ClosePathRule.NEVER) { if (inputShapes == null || inputShapes.Count == 0 || paintable == null || paintable.strokeWidth <= 0f) { return(null); } AddInputShape(inputShapes); Color color = GetStrokeColor(paintable); float strokeWidth = paintable.strokeWidth; if (inputShapes.Count > 1) { CombineInstance[] combineInstances = new CombineInstance[inputShapes.Count]; for (int i = 0; i < inputShapes.Count; i++) { combineInstances[i] = new CombineInstance(); SVGShape svgLayer = new SVGShape(); if (SVGMeshUtils.VectorLine(inputShapes[i].ToArray(), out svgLayer, color, color, strokeWidth, 0f, closePath)) { Mesh localMesh = new Mesh(); int totalVertices = svgLayer.vertices.Length; Vector3[] vertices = new Vector3[totalVertices]; for (int j = 0; j < totalVertices; j++) { vertices[j] = svgLayer.vertices[j]; } localMesh.vertices = vertices; localMesh.triangles = svgLayer.triangles; localMesh.colors32 = svgLayer.colors; combineInstances[i].mesh = localMesh; } } Mesh mesh = new Mesh(); mesh.CombineMeshes(combineInstances, true, false); return(mesh); } else { SVGShape svgLayer = new SVGShape(); if (SVGMeshUtils.VectorLine(inputShapes[0].ToArray(), out svgLayer, color, color, strokeWidth, 0f, closePath)) { Mesh localMesh = new Mesh(); int totalVertices = svgLayer.vertices.Length; Vector3[] vertices = new Vector3[totalVertices]; for (int j = 0; j < totalVertices; j++) { vertices[j] = svgLayer.vertices[j]; } localMesh.vertices = vertices; localMesh.triangles = svgLayer.triangles; localMesh.colors32 = svgLayer.colors; return(localMesh); } return(null); } }