static void CreateStroke(SVGPolygonElement svgElement) { string name = svgElement.attrList.GetValue("id"); if (string.IsNullOrEmpty(name)) { name = "Polygon Stroke "; } List <List <Vector2> > path = SVGSimplePath.CreateStroke(SVGGraphics.position_buffer, svgElement.paintable, ClosePathRule.ALWAYS); if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { path = SVGGeom.ClipPolygon(path, svgElement.paintable.clipPathList); } SVGGraphics.AddLayer(name, path, svgElement.paintable, svgElement.transformMatrix, true); /* * Mesh antialiasingMesh; * Mesh mesh = SVGLineUtils.TessellateStroke(stroke, SVGSimplePath.GetStrokeColor(svgElement.paintable), out antialiasingMesh); * if(mesh == null) return; * mesh.name = name; * SVGGraphics.AddLayer(new SVGMesh(mesh, svgElement.paintable.svgFill, svgElement.paintable.opacity)); * if(antialiasingMesh != null) * { * SVGFill svgFill = svgElement.paintable.svgFill.Clone(); * svgFill.blend = FILL_BLEND.ALPHA_BLENDED; * SVGGraphics.AddLayer(new SVGMesh(antialiasingMesh, svgFill, svgElement.paintable.opacity)); * } */ }
static void CreateStroke(SVGRectElement svgElement) { string name = svgElement.attrList.GetValue("id"); if (string.IsNullOrEmpty(name)) { name = "Rectangle Stroke "; } List <List <Vector2> > stroke = SVGSimplePath.CreateStroke(SVGGraphics.position_buffer, svgElement.paintable, ClosePathRule.ALWAYS); if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { stroke = SVGGeom.ClipPolygon(stroke, svgElement.paintable.clipPathList); } Mesh antialiasingMesh; Mesh mesh = SVGLineUtils.TessellateStroke(stroke, SVGSimplePath.GetStrokeColor(svgElement.paintable), out antialiasingMesh); if (mesh == null) { return; } mesh.name = name; SVGGraphics.AddMesh(new SVGMesh(mesh, svgElement.paintable.svgFill, svgElement.paintable.opacity)); if (antialiasingMesh != null) { SVGFill svgFill = svgElement.paintable.svgFill.Clone(); svgFill.blend = FILL_BLEND.ALPHA_BLENDED; SVGGraphics.AddMesh(new SVGMesh(antialiasingMesh, svgFill, svgElement.paintable.opacity)); } }
private void ReadClipPath(string clipPathValue) { if (clipPathValue.IndexOf("url") >= 0) { string clipPathURL = SVGStringExtractor.ExtractUrl(clipPathValue); if (!string.IsNullOrEmpty(clipPathURL) && SVGParser._defs.ContainsKey(clipPathURL)) { Node clipPathNode = SVGParser._defs[clipPathURL]; if (clipPathNode != null) { SVGMatrix svgMatrix = SVGMatrix.identity; string clipPathUnitsString = clipPathNode.attributes.GetValue("clipPathUnits"); switch (clipPathUnitsString.ToLower()) { case "userSpaceOnUse": _clipPathUnits = SVGClipPathUnits.UserSpaceOnUse; break; case "objectBoundingBox": _clipPathUnits = SVGClipPathUnits.ObjectBoundingBox; break; } List <Node> clipPathNodes = clipPathNode.GetNodes(); List <List <Vector2> > currentClipPathList = new List <List <Vector2> >(); if (clipPathNodes != null && clipPathNodes.Count > 0) { for (int i = 0; i < clipPathNodes.Count; i++) { List <List <Vector2> > clipPath = GetClipPath(clipPathNodes[i], svgMatrix); if (clipPath != null) { currentClipPathList.AddRange(clipPath); } } } if (currentClipPathList.Count > 0) { currentClipPathList = SVGGeom.MergePolygon(currentClipPathList); } if (_clipPathList != null && _clipPathList.Count > 0) { _clipPathList = SVGGeom.ClipPolygon(_clipPathList, currentClipPathList); } else { _clipPathList = currentClipPathList; } } } } }
static void CreateFill(SVGPolygonElement svgElement) { string name = svgElement.attrList.GetValue("id"); if (string.IsNullOrEmpty(name)) { name = "Polygon Fill"; } List <List <Vector2> > path; if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { path = SVGGeom.ClipPolygon(new List <List <Vector2> >() { SVGGraphics.position_buffer }, svgElement.paintable.clipPathList); } else { path = new List <List <Vector2> >() { SVGGraphics.position_buffer }; } SVGGraphics.AddLayer(name, path, svgElement.paintable, svgElement.transformMatrix); /* * Mesh antialiasingMesh; * Mesh mesh = SVGSimplePath.CreatePolygon(path, svgElement.paintable, svgElement.transformMatrix, out antialiasingMesh); * if(mesh == null) return; * mesh.name = name; * SVGGraphics.AddLayer(new SVGMesh(mesh, svgElement.paintable.svgFill, svgElement.paintable.opacity)); * if(antialiasingMesh != null) * { * SVGFill svgFill = svgElement.paintable.svgFill.Clone(); * svgFill.blend = FILL_BLEND.ALPHA_BLENDED; * SVGGraphics.AddLayer(new SVGMesh(antialiasingMesh, svgFill, svgElement.paintable.opacity)); * } */ }
static void CreateFill(SVGPathElement svgElement) { string name = svgElement.attrList.GetValue("id"); if (string.IsNullOrEmpty(name)) { name = "Path Fill"; } List <List <Vector2> > path; if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { path = SVGGeom.ClipPolygon(paths, svgElement.paintable.clipPathList); } else { path = paths; } Mesh antialiasingMesh; Mesh mesh = SVGSimplePath.CreatePolygon(path, svgElement.paintable, svgElement.transformMatrix, out antialiasingMesh); if (mesh == null) { return; } mesh.name = name; SVGGraphics.AddMesh(new SVGMesh(mesh, svgElement.paintable.svgFill, svgElement.paintable.opacity)); if (antialiasingMesh != null) { SVGFill svgFill = svgElement.paintable.svgFill.Clone(); svgFill.blend = FILL_BLEND.ALPHA_BLENDED; SVGGraphics.AddMesh(new SVGMesh(antialiasingMesh, svgFill, svgElement.paintable.opacity)); } }
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 void StartProcess(SVGAsset asset) { if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) { return; } if (errors == null) { errors = new List <SVGError>(); } else { errors.Clear(); } _importingSVG = true; System.Reflection.FieldInfo _editor_runtimeMaterials = typeof(SVGAsset).GetField("_runtimeMaterials", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_runtimeMaterials.SetValue(asset, null); System.Reflection.FieldInfo _editor_runtimeMesh = typeof(SVGAsset).GetField("_runtimeMesh", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_runtimeMesh.SetValue(asset, null); UnityEditor.SerializedObject svgAsset = new UnityEditor.SerializedObject(asset); UnityEditor.SerializedProperty sharedMesh = svgAsset.FindProperty("_sharedMesh"); UnityEditor.SerializedProperty sharedShaders = svgAsset.FindProperty("_sharedShaders"); Clear(); SVGParser.Init(); SVGGraphics.Init(); atlasData = new SVGAtlasData(); atlasData.Init(SVGAtlas.defaultAtlasTextureWidth * SVGAtlas.defaultAtlasTextureHeight); atlasData.AddGradient(SVGAtlasData.GetDefaultGradient()); SVGElement _rootSVGElement = null; #if IGNORE_EXCEPTIONS try { #else Debug.LogWarning("Exceptions are turned on!"); #endif // Create new Asset CreateEmptySVGDocument(); _rootSVGElement = this._svgDocument.rootElement; #if IGNORE_EXCEPTIONS } catch (System.Exception exception) { _rootSVGElement = null; errors.Add(SVGError.Syntax); Debug.LogError("SVG Document Exception: " + exception.Message, asset); } #endif if (_rootSVGElement == null) { Debug.LogError("SVG Document is corrupted! " + UnityEditor.AssetDatabase.GetAssetPath(asset), asset); _importingSVG = false; return; } #if IGNORE_EXCEPTIONS try { #endif _rootSVGElement.Render(); Rect viewport = _rootSVGElement.paintable.viewport; viewport.x *= SVGAssetImport.meshScale; viewport.y *= SVGAssetImport.meshScale; viewport.size *= SVGAssetImport.meshScale; Vector2 offset; SVGGraphics.CorrectSVGLayers(SVGGraphics.layers, viewport, asset, out offset); // Handle gradients bool hasGradients = false; // Create actual Mesh Shader[] outputShaders; Mesh mesh = new Mesh(); SVGMesh.CombineMeshes(SVGGraphics.layers.ToArray(), mesh, out outputShaders, useGradients, format, compressDepth, asset.antialiasing); if (mesh == null) { return; } if (useGradients == SVGUseGradients.Always) { if (outputShaders != null) { for (int i = 0; i < outputShaders.Length; i++) { if (outputShaders[i] == null) { continue; } if (outputShaders[i].name == SVGShader.SolidColorOpaque.name) { outputShaders[i] = SVGShader.GradientColorOpaque; } else if (outputShaders[i].name == SVGShader.SolidColorAlphaBlended.name) { outputShaders[i] = SVGShader.GradientColorAlphaBlended; } else if (outputShaders[i].name == SVGShader.SolidColorAlphaBlendedAntialiased.name) { outputShaders[i] = SVGShader.GradientColorAlphaBlendedAntialiased; } } } hasGradients = true; } else { if (outputShaders != null) { for (int i = 0; i < outputShaders.Length; i++) { if (outputShaders[i] == null) { continue; } if (outputShaders[i].name == SVGShader.GradientColorOpaque.name || outputShaders[i].name == SVGShader.GradientColorAlphaBlended.name || outputShaders[i].name == SVGShader.GradientColorAlphaBlendedAntialiased.name || outputShaders[i].name == SVGShader.GradientColorAlphaBlendedAntialiasedCompressed.name) { hasGradients = true; break; } } } } if (!asset.useLayers) { sharedMesh.objectReferenceValue = AddObjectToAsset <Mesh>(mesh, asset, HideFlags.HideInHierarchy); } // Material sharedMaterial; if (outputShaders != null && outputShaders.Length > 0) { sharedShaders.arraySize = outputShaders.Length; if (hasGradients) { for (int i = 0; i < outputShaders.Length; i++) { sharedShaders.GetArrayElementAtIndex(i).stringValue = outputShaders[i].name; } } else { for (int i = 0; i < outputShaders.Length; i++) { if (outputShaders[i].name == SVGShader.GradientColorAlphaBlended.name) { outputShaders[i] = SVGShader.SolidColorAlphaBlended; } else if (outputShaders[i].name == SVGShader.GradientColorOpaque.name) { outputShaders[i] = SVGShader.SolidColorOpaque; } sharedShaders.GetArrayElementAtIndex(i).stringValue = outputShaders[i].name; } } } // Serialize the Asset svgAsset.ApplyModifiedProperties(); // Handle Canvas Rectangle System.Reflection.MethodInfo _editor_SetCanvasRectangle = typeof(SVGAsset).GetMethod("_editor_SetCanvasRectangle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_SetCanvasRectangle.Invoke(asset, new object[] { new Rect(viewport.x, viewport.y, viewport.size.x, viewport.size.y) }); if (asset.generateCollider) { // Create polygon contour if (SVGGraphics.paths != null && SVGGraphics.paths.Count > 0) { List <List <Vector2> > polygons = new List <List <Vector2> >(); for (int i = 0; i < SVGGraphics.paths.Count; i++) { Vector2[] points = SVGGraphics.paths[i].points; for (int j = 0; j < points.Length; j++) { points[j].x = points[j].x * SVGAssetImport.meshScale - offset.x; points[j].y = (points[j].y * SVGAssetImport.meshScale + offset.y) * -1f; } polygons.Add(new List <Vector2>(points)); } polygons = SVGGeom.MergePolygon(polygons); SVGPath[] paths = new SVGPath[polygons.Count]; for (int i = 0; i < polygons.Count; i++) { paths[i] = new SVGPath(polygons[i].ToArray()); } System.Reflection.MethodInfo _editor_SetColliderShape = typeof(SVGAsset).GetMethod("_editor_SetColliderShape", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (paths != null && paths.Length > 0) { _editor_SetColliderShape.Invoke(asset, new object[] { paths }); } else { _editor_SetColliderShape.Invoke(asset, new object[] { null }); } } } else { System.Reflection.MethodInfo _editor_SetColliderShape = typeof(SVGAsset).GetMethod("_editor_SetColliderShape", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_SetColliderShape.Invoke(asset, new object[] { null }); } System.Reflection.MethodInfo _editor_SetGradients = typeof(SVGAsset).GetMethod("_editor_SetGradients", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_SetGradients.Invoke(asset, new object[] { null }); if (hasGradients) { if (atlasData.gradientCache != null && atlasData.gradientCache.Count > 0) { int gradientsCount = SVGAssetImport.atlasData.gradientCache.Count; CCGradient[] gradients = new CCGradient[gradientsCount]; int i = 0; foreach (KeyValuePair <string, CCGradient> entry in SVGAssetImport.atlasData.gradientCache) { gradients[i++] = entry.Value; } _editor_SetGradients.Invoke(asset, new object[] { gradients }); } } System.Reflection.MethodInfo _editor_SetLayers = typeof(SVGAsset).GetMethod("_editor_SetLayers", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_SetLayers.Invoke(asset, new object[] { null }); if (asset.useLayers) { if (SVGGraphics.layers != null && SVGGraphics.layers.Count > 0) { _editor_SetLayers.Invoke(asset, new object[] { SVGGraphics.layers.ToArray() }); } } #if IGNORE_EXCEPTIONS } catch (System.Exception exception) { Debug.LogWarning("Asset: " + UnityEditor.AssetDatabase.GetAssetPath(asset) + " Failed to import\n" + exception.Message, asset); errors.Add(SVGError.CorruptedFile); } #endif if (_svgDocument != null) { _svgDocument.Clear(); _svgDocument = null; } Clear(); UnityEditor.EditorUtility.SetDirty(asset); _importingSVG = false; }
public static Mesh CreatePolygon(List <List <Vector2> > inputShapes, SVGPaintable paintable, SVGMatrix matrix, out Mesh antialiasingMesh) { antialiasingMesh = null; if (inputShapes == null || inputShapes.Count == 0) { return(null); } 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(null); } AddInputShape(simplifiedShapes); Rect bounds = GetRect(simplifiedShapes); switch (paintable.GetPaintType()) { case SVGPaintMethod.SolidGradientFill: { 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: { SVGLinearGradientBrush linearGradBrush = paintable.GetLinearGradientBrush(bounds, matrix); paintable.svgFill = linearGradBrush.fill; } break; case SVGPaintMethod.RadialGradientFill: { SVGRadialGradientBrush radialGradBrush = paintable.GetRadialGradientBrush(bounds, matrix); paintable.svgFill = radialGradBrush.fill; } break; case SVGPaintMethod.ConicalGradientFill: { SVGConicalGradientBrush conicalGradBrush = paintable.GetConicalGradientBrush(bounds, matrix); paintable.svgFill = conicalGradBrush.fill; } break; case SVGPaintMethod.PathDraw: { 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; } 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); } tesselation.Tessellate(LibTessDotNet.WindingRule.EvenOdd, LibTessDotNet.ElementType.Polygons, 3); Mesh mesh = new Mesh(); int meshVertexCount = tesselation.Vertices.Length; Vector3[] vertices = new Vector3[meshVertexCount]; Vector2[] uv = null; Vector2[] uv2 = null; for (int i = 0; i < meshVertexCount; i++) { vertices[i] = new Vector3(tesselation.Vertices[i].Position.X, tesselation.Vertices[i].Position.Y, 0f); } int numTriangles = tesselation.ElementCount; int[] triangles = new int[numTriangles * 3]; for (int i = 0; i < numTriangles; i++) { triangles[i * 3] = tesselation.Elements[i * 3]; triangles[i * 3 + 1] = tesselation.Elements[i * 3 + 1]; triangles[i * 3 + 2] = tesselation.Elements[i * 3 + 2]; } SVGFill svgFill = paintable.svgFill; Color32 fillColor = Color.white; if (svgFill.fillType != FILL_TYPE.GRADIENT && svgFill.gradientColors == null) { fillColor = svgFill.color; } antialiasingMesh = CreateAntialiasing(simplifiedShapes, fillColor, -SVGAssetImport.antialiasingWidth, false, SVGImporter.Utils.ClosePathRule.ALWAYS); Color32[] colors32 = new Color32[meshVertexCount]; for (int i = 0; i < meshVertexCount; i++) { colors32 [i].r = fillColor.r; colors32 [i].g = fillColor.g; colors32 [i].b = fillColor.b; colors32 [i].a = fillColor.a; } if (antialiasingMesh != null) { Vector3[] antialiasingVertices = antialiasingMesh.vertices; Vector2[] antialiasingUV = antialiasingMesh.uv; Vector2[] antialiasingUV2 = antialiasingMesh.uv2; WriteUVGradientCoordinates(ref antialiasingUV, antialiasingVertices, paintable, bounds); WriteUVGradientIndexType(ref antialiasingUV2, antialiasingVertices.Length, paintable); antialiasingMesh.uv = antialiasingUV; antialiasingMesh.uv2 = antialiasingUV2; } WriteUVGradientCoordinates(ref uv, vertices, paintable, bounds); WriteUVGradientIndexType(ref uv2, meshVertexCount, paintable); mesh.vertices = vertices; mesh.triangles = triangles; if (colors32 != null) { mesh.colors32 = colors32; } if (uv != null) { mesh.uv = uv; } if (uv2 != null) { mesh.uv2 = uv2; } return(mesh); }
public static void Create(ISVGElement svgElement, string defaultName = null, ClosePathRule closePathRule = ClosePathRule.ALWAYS) { if (svgElement == null) { return; } if (svgElement.paintable.visibility != SVGVisibility.Visible || svgElement.paintable.display == SVGDisplay.None) { return; } List <SVGShape> shapes = new List <SVGShape>(); List <List <Vector2> > inputPaths = svgElement.GetPath(); if (inputPaths.Count == 1) { if (svgElement.paintable.IsFill()) { List <List <Vector2> > path = inputPaths; if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { path = SVGGeom.ClipPolygon(new List <List <Vector2> >() { inputPaths[0] }, svgElement.paintable.clipPathList); } SVGShape[] addShapes = SVGGraphics.GetShapes(path, svgElement.paintable, svgElement.transformMatrix); if (addShapes != null && addShapes.Length > 0) { shapes.AddRange(addShapes); } } if (svgElement.paintable.IsStroke()) { List <List <Vector2> > path = SVGSimplePath.CreateStroke(inputPaths[0], svgElement.paintable, closePathRule); if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { path = SVGGeom.ClipPolygon(path, svgElement.paintable.clipPathList); } SVGShape[] addShapes = SVGGraphics.GetShapes(path, svgElement.paintable, svgElement.transformMatrix, true); if (addShapes != null && addShapes.Length > 0) { shapes.AddRange(addShapes); } } } else { if (svgElement.paintable.IsFill()) { List <List <Vector2> > fillPaths = inputPaths; if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { fillPaths = SVGGeom.ClipPolygon(inputPaths, svgElement.paintable.clipPathList); } SVGShape[] addShapes = SVGGraphics.GetShapes(fillPaths, svgElement.paintable, svgElement.transformMatrix); if (addShapes != null && addShapes.Length > 0) { shapes.AddRange(addShapes); } } if (svgElement.paintable.IsStroke()) { List <List <Vector2> > strokePath = SVGSimplePath.CreateStroke(inputPaths, svgElement.paintable, closePathRule); if (svgElement.paintable.clipPathList != null && svgElement.paintable.clipPathList.Count > 0) { strokePath = SVGGeom.ClipPolygon(strokePath, svgElement.paintable.clipPathList); } SVGShape[] addShapes = SVGGraphics.GetShapes(strokePath, svgElement.paintable, svgElement.transformMatrix, true); if (addShapes != null && addShapes.Length > 0) { shapes.AddRange(addShapes); } } } if (shapes.Count > 0) { string name = svgElement.attrList.GetValue("id"); if (string.IsNullOrEmpty(name)) { name = defaultName; } SVGLayer layer = new SVGLayer(); layer.shapes = shapes.ToArray(); layer.name = name; SVGGraphics.AddLayer(layer); } }
public void StartProcess(SVGAsset asset) { if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) { return; } if (errors == null) { errors = new List <SVGError>(); } else { errors.Clear(); } _importingSVG = true; UnityEditor.SerializedObject svgAsset = new UnityEditor.SerializedObject(asset); UnityEditor.SerializedProperty sharedMesh = svgAsset.FindProperty("_sharedMesh"); UnityEditor.SerializedProperty sharedShaders = svgAsset.FindProperty("_sharedShaders"); Clear(); SVGParser.Init(); SVGGraphics.Init(); atlasData = new SVGAtlasData(); SVGElement _rootSVGElement = null; #if IGNORE_EXCEPTIONS try { #else Debug.LogWarning("Exceptions are turned on!"); #endif // Create new Asset CreateEmptySVGDocument(); _rootSVGElement = this._svgDocument.rootElement; #if IGNORE_EXCEPTIONS } catch (System.Exception exception) { _rootSVGElement = null; errors.Add(SVGError.Syntax); Debug.LogError("SVG Document Exception: " + exception.Message, asset); } #endif if (_rootSVGElement == null) { Debug.LogError("SVG Document is corrupted! " + UnityEditor.AssetDatabase.GetAssetPath(asset), asset); _importingSVG = false; return; } SVGGraphics.depthTree = new SVGDepthTree(_rootSVGElement.paintable.viewport); #if IGNORE_EXCEPTIONS try { #endif _rootSVGElement.Render(); // Handle gradients bool hasGradients = (useGradients == SVGUseGradients.Always); // Create actual Mesh Shader[] outputShaders; SVGLayer[] outputLayers; Mesh mesh = SVGMesh.CombineMeshes(SVGGraphics.meshes, out outputLayers, out outputShaders, useGradients, format, compressDepth); if (mesh == null) { return; } if (outputShaders != null) { for (int i = 0; i < outputShaders.Length; i++) { if (outputShaders[i] == null) { continue; } if (outputShaders[i].name == SVGShader.GradientColorOpaque.name || outputShaders[i].name == SVGShader.GradientColorAlphaBlended.name) { hasGradients = true; break; } } } Vector3[] vertices = mesh.vertices; Vector2 offset; Bounds bounds = mesh.bounds; Rect viewport = _rootSVGElement.paintable.viewport; viewport.x *= SVGAssetImport.meshScale; viewport.y *= SVGAssetImport.meshScale; viewport.size *= SVGAssetImport.meshScale; if (asset.ignoreSVGCanvas) { offset = new Vector2(bounds.min.x + bounds.size.x * asset.pivotPoint.x, bounds.min.y + bounds.size.y * asset.pivotPoint.y); } else { offset = new Vector2(viewport.min.x + viewport.size.x * asset.pivotPoint.x, viewport.min.y + viewport.size.y * asset.pivotPoint.y); } // Apply pivot point and Flip Y Axis for (int i = 0; i < vertices.Length; i++) { vertices[i].x = vertices[i].x - offset.x; vertices[i].y = (vertices[i].y - offset.y) * -1f; } mesh.vertices = vertices; mesh.RecalculateBounds(); sharedMesh.objectReferenceValue = AddObjectToAsset <Mesh>(mesh, asset, HideFlags.HideInHierarchy); // Material sharedMaterial; if (outputShaders != null && outputShaders.Length > 0) { sharedShaders.arraySize = outputShaders.Length; if (hasGradients) { for (int i = 0; i < outputShaders.Length; i++) { sharedShaders.GetArrayElementAtIndex(i).stringValue = outputShaders[i].name; } } else { for (int i = 0; i < outputShaders.Length; i++) { if (outputShaders[i].name == SVGShader.GradientColorAlphaBlended.name) { outputShaders[i] = SVGShader.SolidColorAlphaBlended; } else if (outputShaders[i].name == SVGShader.GradientColorOpaque.name) { outputShaders[i] = SVGShader.SolidColorOpaque; } sharedShaders.GetArrayElementAtIndex(i).stringValue = outputShaders[i].name; } } } // Serialize the Asset svgAsset.ApplyModifiedProperties(); // Handle Canvas Rectangle System.Reflection.MethodInfo _editor_SetCanvasRectangle = typeof(SVGAsset).GetMethod("_editor_SetCanvasRectangle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_SetCanvasRectangle.Invoke(asset, new object[] { new Rect(viewport.x, viewport.y, viewport.size.x, viewport.size.y) }); if (asset.generateCollider) { // Create polygon contour if (SVGGraphics.paths != null && SVGGraphics.paths.Count > 0) { List <List <Vector2> > polygons = new List <List <Vector2> >(); for (int i = 0; i < SVGGraphics.paths.Count; i++) { Vector2[] points = SVGGraphics.paths[i].points; for (int j = 0; j < points.Length; j++) { points[j].x = points[j].x * SVGAssetImport.meshScale - offset.x; points[j].y = (points[j].y * SVGAssetImport.meshScale - offset.y) * -1f; } polygons.Add(new List <Vector2>(points)); } polygons = SVGGeom.MergePolygon(polygons); SVGPath[] paths = new SVGPath[polygons.Count]; for (int i = 0; i < polygons.Count; i++) { paths[i] = new SVGPath(polygons[i].ToArray()); } System.Reflection.MethodInfo _editor_SetColliderShape = typeof(SVGAsset).GetMethod("_editor_SetColliderShape", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (paths != null && paths.Length > 0) { _editor_SetColliderShape.Invoke(asset, new object[] { paths }); } else { _editor_SetColliderShape.Invoke(asset, new object[] { null }); } } } else { System.Reflection.MethodInfo _editor_SetColliderShape = typeof(SVGAsset).GetMethod("_editor_SetColliderShape", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); _editor_SetColliderShape.Invoke(asset, new object[] { null }); } if (hasGradients) { System.Reflection.MethodInfo _editor_SetGradients = typeof(SVGAsset).GetMethod("_editor_SetGradients", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (atlasData.gradients != null && atlasData.gradients.Count > 0) { _editor_SetGradients.Invoke(asset, new object[] { atlasData.gradients.ToArray() }); } else { _editor_SetGradients.Invoke(asset, new object[] { null }); } } #if IGNORE_EXCEPTIONS } catch (System.Exception exception) { Debug.LogWarning("Asset: " + UnityEditor.AssetDatabase.GetAssetPath(asset) + " Failed to import\n" + exception.Message, asset); errors.Add(SVGError.CorruptedFile); } #endif if (_svgDocument != null) { _svgDocument.Clear(); _svgDocument = null; } Clear(); UnityEditor.EditorUtility.SetDirty(asset); _importingSVG = false; }
public static bool CreatePolygon(List <List <Vector2> > inputShapes, SVGPaintable paintable, SVGMatrix matrix, out SVGLayer layer, bool isStroke = false) { layer = new SVGLayer(); 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: { 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: { SVGLinearGradientBrush linearGradBrush = paintable.GetLinearGradientBrush(bounds, matrix, viewport); paintable.svgFill = linearGradBrush.fill; } break; case SVGPaintMethod.RadialGradientFill: { SVGRadialGradientBrush radialGradBrush = paintable.GetRadialGradientBrush(bounds, matrix, viewport); paintable.svgFill = radialGradBrush.fill; } break; case SVGPaintMethod.ConicalGradientFill: { SVGConicalGradientBrush conicalGradBrush = paintable.GetConicalGradientBrush(bounds, matrix, viewport); paintable.svgFill = conicalGradBrush.fill; } break; case SVGPaintMethod.PathDraw: { 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 { 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; } 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; layer.vertices = new Vector2[meshVertexCount]; for (int i = 0; i < meshVertexCount; i++) { layer.vertices[i] = new Vector2(tesselation.Vertices[i].Position.X, tesselation.Vertices[i].Position.Y) * SVGAssetImport.meshScale; } int numTriangles = tesselation.ElementCount; layer.triangles = new int[numTriangles * 3]; 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]; } 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; if (layer.fill.transform != null) { 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); return(true); }