/// <summary> /// Create a Sprite icon of a SVG image. /// </summary> /// <param name="svgContent">String containing svg content.</param> /// <remarks> /// Standard header and footer will be included if not found in svgContent /// </remarks> public static Sprite GetSprite(string svgContent) { string svg; if (svgContent.StartsWith("<?xml version = \"1.0\" encoding=\"UTF - 8\"?>")) { svg = svgContent; } else { svg = svgIconHeader + svgContent; } if (!svg.EndsWith(svgIconFooter)) { svg = svg + svgIconFooter; } // Parse the SVG SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(new System.IO.StringReader(svg)); int width = Mathf.CeilToInt(sceneInfo.SceneViewport.width); int height = Mathf.CeilToInt(sceneInfo.SceneViewport.height); if ((width > 64) || (height > 64)) { Debug.LogWarning("SVG icon of unusual size!"); } List <VectorUtils.Geometry> iconGeometry = VectorUtils.TessellateScene(sceneInfo.Scene, tessellationOptions); Sprite sprite = VectorUtils.BuildSprite(iconGeometry, 100f, VectorUtils.Alignment.Center, Vector2.zero, 128, true); return(sprite); }
private void ComputeTessellationOptions(SVGParser.SceneInfo sceneInfo, int targetResolution, float multiplier, out float stepDist, out float maxCord, out float maxTangent) { // These tessellation options were found by trial and error to find values that made // visual sense with a variety of SVG assets. // "Pixels per Unit" doesn't make sense for UI Toolkit since it will be displayed in // a pixels space. We adjust the magic values below accordingly. #if UNITY_2019_3_OR_NEWER float ppu = (SvgType == SVGType.UIToolkit) ? 1.0f : SvgPixelsPerUnit; #else float ppu = SvgPixelsPerUnit; #endif var bbox = VectorUtils.ApproximateSceneNodeBounds(sceneInfo.Scene.Root); float maxDim = Mathf.Max(bbox.width, bbox.height) / ppu; // The scene ratio gives a rough estimate of coverage % of the vector scene on the screen. // Higher values should result in a more dense tessellation. float sceneRatio = maxDim / (targetResolution * multiplier); stepDist = float.MaxValue; // No need for uniform step distance #if UNITY_2019_3_OR_NEWER if (SvgType == SVGType.UIToolkit) { maxCord = Mathf.Max(0.01f, 2.0f * sceneRatio); maxTangent = Mathf.Max(0.1f, 3.0f * sceneRatio); } else #endif { maxCord = Mathf.Max(0.01f, 75.0f * sceneRatio); maxTangent = Mathf.Max(0.1f, 100.0f * sceneRatio); } }
/// <summary> /// Create a Texture2D icon of a SVG image. /// </summary> /// <param name="svg">String containing svg content.</param> public static Texture2D GetIcon(string svg) { // Parse the SVG SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(new System.IO.StringReader(svg)); int width = Mathf.CeilToInt(sceneInfo.SceneViewport.width); int height = Mathf.CeilToInt(sceneInfo.SceneViewport.height); if ((width > 64) || (height > 64)) { Debug.LogWarning("SVG icon of unusual size!"); } VectorUtils.TessellationOptions tessellationOptions = new VectorUtils.TessellationOptions() { StepDistance = 0.05f, MaxCordDeviation = float.MaxValue, MaxTanAngleDeviation = Mathf.PI / 2.0f, SamplingStepSize = 0.01f }; List <VectorUtils.Geometry> iconGeometry = VectorUtils.TessellateScene(sceneInfo.Scene, tessellationOptions); Sprite sprite = VectorUtils.BuildSprite(iconGeometry, 1f, VectorUtils.Alignment.Center, Vector2.zero, 128, true); Texture2D iconTexture = VectorUtils.RenderSpriteToTexture2D(sprite, width, height, renderMaterial); return(iconTexture); }
/// <summary> /// Create a Texture2D icon of a SVG image (editor only version). /// </summary> /// <param name="svg">String containing svg content.</param> /// <param name="renderUtil">PreviewRenderUtility to use for drawing</param> public static Texture2D GetIcon(string svg, PreviewRenderUtility renderUtil) { // Parse the SVG SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(new System.IO.StringReader(svg)); int width = Mathf.CeilToInt(sceneInfo.SceneViewport.width); int height = Mathf.CeilToInt(sceneInfo.SceneViewport.height); if ((width > 64) || (height > 64)) { Debug.LogWarning("SVG icon of unusual size!"); } // Save the render state and get a temporary render texture RenderTexture activeTexture = RenderTexture.active; renderUtil.camera.targetTexture = RenderTexture.GetTemporary(width, height, 8, RenderTextureFormat.ARGB32); renderUtil.camera.backgroundColor = Color.clear; // Generate the mesh Mesh iconMesh = new Mesh(); VectorUtils.TessellationOptions tessellationOptions = new VectorUtils.TessellationOptions() { StepDistance = 0.05f, MaxCordDeviation = float.MaxValue, MaxTanAngleDeviation = Mathf.PI / 2.0f, SamplingStepSize = 0.01f }; List <VectorUtils.Geometry> iconGeometry = VectorUtils.TessellateScene(sceneInfo.Scene, tessellationOptions); VectorUtils.FillMesh(iconMesh, iconGeometry, 1f); // Activate the render texture and draw the mesh into it RenderTexture.active = renderUtil.camera.targetTexture; float cameraSize = renderUtil.camera.orthographicSize; Vector3 cameraPosition = renderUtil.camera.transform.position; renderUtil.camera.orthographicSize = sceneInfo.SceneViewport.height / 2; renderUtil.camera.transform.position = new Vector3(sceneInfo.SceneViewport.center.x, sceneInfo.SceneViewport.center.y, -1); // HACK until FillMesh() flpYAxis is fixed renderUtil.camera.transform.Rotate(0, 0, 180f); renderUtil.DrawMesh(iconMesh, Matrix4x4.identity, renderMaterial, 0); renderUtil.camera.Render(); renderUtil.camera.transform.Rotate(0, 0, 180f); renderUtil.camera.orthographicSize = cameraSize; renderUtil.camera.transform.position = cameraPosition; Texture2D iconTexture = new Texture2D(width, height); iconTexture.ReadPixels(new Rect(0, 0, width, height), 0, 0); iconTexture.Apply(); // Restore the render state and release the temporary render texture RenderTexture.active = activeTexture; RenderTexture.ReleaseTemporary(renderUtil.camera.targetTexture); return(iconTexture); }
/// <summary> /// Parse SVG into VectorShape list. /// </summary> public static List <VectorShape> ReadSVG(System.IO.TextReader svg) { List <VectorShape> shapes = new List <VectorShape>(); SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(svg); //Debug.Log(sceneInfo.SceneViewport); Matrix2D rootTransform = Matrix2D.Scale(new Vector2(0.01f, -0.01f)) * sceneInfo.Scene.Root.Transform; RecurseSVGNodes(sceneInfo.Scene.Root, rootTransform, shapes); return(shapes); }
private void ComputeTessellationOptions(SVGParser.SceneInfo sceneInfo, int targetResolution, float multiplier, out float stepDist, out float maxCord, out float maxTangent) { var bbox = VectorUtils.ApproximateSceneNodeBounds(sceneInfo.Scene.Root); float maxDim = Mathf.Max(bbox.width, bbox.height) / SvgPixelsPerUnit; // The scene ratio gives a rough estimate of coverage % of the vector scene on the screen. // Higher values should result in a more dense tessellation. float sceneRatio = maxDim / (targetResolution * multiplier); stepDist = float.MaxValue; // No need for uniform step distance maxCord = Mathf.Max(0.01f, 75.0f * sceneRatio); maxTangent = Mathf.Max(0.1f, 100.0f * sceneRatio); }
public void SetAppearance() { worldController = WorldController.GetWorldController; citizen = GetComponent <Citizen>(); skinTone = worldController.skinTones[Random.Range(0, worldController.skinTones.Length)]; skinTone = ChangeColorBrightness(skinTone); string svg = @"<svg xmlns=""http://www.w3.org/2000/svg"" viewBox=""0 0 30.11 27.39""> <g><path id=""Body"" d=""M30.81,17.36c0,7.43-6.63,13.45-14.81,13.45s-14.81-6-14.81-13.45a12.56,12.56,0,0,1,.36-3C3,8.4,8.94,3.92,16,3.92,24.18,3.92,30.81,9.94,30.81,17.36Z"" transform=""translate(-0.94 -3.67)"" fill=""#fff"" stroke=""#000"" stroke-miterlimit=""10"" stroke-width=""0.5""/></g>"; Hand(0); Hand(1); int hairChance = Random.Range(0, citizen.gender ? 100 : 55); SVGParser.SceneInfo sceneInfo = default; if (hairChance < 70) { SetHair(ref svg, ref sceneInfo); } else { svg += "</svg>"; sceneInfo = SVGParser.ImportSVG(new StringReader(svg)); } var shape = sceneInfo.NodeIDs["Body"].Shapes[0]; shape.Fill = new SolidFill() { Color = skinTone }; var tessOptions = new VectorUtils.TessellationOptions() { StepDistance = 100f, MaxCordDeviation = 0.5f, MaxTanAngleDeviation = 0.1f, SamplingStepSize = 0.01f }; var geoms = VectorUtils.TessellateScene(sceneInfo.Scene, tessOptions); var sprite = VectorUtils.BuildSprite(geoms, 26, VectorUtils.Alignment.Center, Vector2.zero, 128, true); GetComponent <SpriteRenderer>().sprite = sprite; }
public bool ImportSVG(TextReader textReader, ViewportOptions viewportOptions, float dpi = 0, float pixelsPerUnit = 1, int windowWidth = 0, int windowHeight = 0) { bool ret = false; try { _scene = SVGParser.ImportSVG(textReader, viewportOptions, dpi, pixelsPerUnit, windowWidth, windowHeight); ret = true; } catch (System.Exception e) { Debug.LogError(e); } return(ret); }
void ApplySVGPath() { string svgPath = "Assets/RouteData/drawsvg.svg"; SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(new StreamReader(svgPath)); Shape path = sceneInfo.NodeIDs["e1_polyline"].Shapes[0]; Debug.Log(path); BezierContour[] cs = path.Contours; BezierContour c = cs[0]; //Debug.Log(c); BezierPathSegment[] ss = c.Segments; Debug.Log($"SVGRoute segments count: {ss.Length}"); for (int i = 0; i < ss.Length; i++) { BezierPathSegment s = ss[i]; Debug.Log($"SVGRoute Segment points: {s.P0} -> {s.P1} -> {s.P2}"); var debug1 = GameObject.Find($"SVGTarget{(i * 3) + 1}"); var debug2 = GameObject.Find($"SVGTarget{(i * 3) + 2}"); var debug3 = GameObject.Find($"SVGTarget{(i * 3) + 3}"); debug1.transform.localPosition = s.P0; debug2.transform.localPosition = s.P1; debug3.transform.localPosition = s.P2; Debug.Log(debug3); } // debug1.transform.position = new Vector3(s.P0.x, 0.1f, s.P0.y); // //(s.P0.x / 10) - 10f, 0.1f, (s.P0.y / 10) + 4.3f); // debug2.transform.position = new Vector3(s.P1.x, 0.1f, s.P1.y); // debug3.transform.position = new Vector3(s.P2.x, 0.1f, s.P2.y); var debug0 = GameObject.Find("SVGTarget0"); debug0.transform.localPosition = Vector3.zero; //path. //var fill = shape.Fill as SolidFill; //fill.Color = Color.red; // ... //var geoms = VectorUtils.TessellateScene(sceneInfo.Scene, tessOptions); //var sprite = VectorUtils.BuildSprite(geoms, 100.0f, VectorUtils.Alignment.Center, Vector2.zero, 128, true); }
void SetHair(ref string svg, ref SVGParser.SceneInfo sceneInfo) { if (citizen.age >= 55) { hairColour = Color.grey; } else { hairColour = worldController.hairColours[Random.Range(0, worldController.hairColours.Length)]; } hairColour = ChangeColorBrightness(hairColour); //string hairSvg = // @"<svg xmlns=""http://www.w3.org/2000/svg"" viewBox=""0 0 30.21 14.6"">"; int style = 0; if (!citizen.gender) { RandomHairStyle(ref svg, out style); } svg += @"<g><path id=""Hair1"" d=""M30.82,16.71c.29,7.6-6.42,14-14.57,14.1-8.33.12-15.34-6.33-15-14.1"" transform=""translate(-1 -2.6)"" fill=""#fff"" stroke=""#040000"" stroke-linecap=""round"" stroke-miterlimit=""10"" stroke-width=""0.5""/></g> <g><path id=""Hair2"" d=""M1.12,16.71a29.34,29.34,0,0,0,14.88,4,29.25,29.25,0,0,0,14.75-4"" transform=""translate(-1 -2.6)"" fill=""#fff"" stroke=""#000"" stroke-linecap=""round"" stroke-miterlimit=""10"" stroke-width=""0.5""/></g> </svg>"; sceneInfo = SVGParser.ImportSVG(new StringReader(svg)); var hairShape = sceneInfo.NodeIDs["Hair1"].Shapes[0]; hairShape.Fill = new SolidFill() { Color = hairColour }; hairShape = sceneInfo.NodeIDs["Hair2"].Shapes[0]; hairShape.Fill = new SolidFill() { Color = skinTone }; if (!citizen.gender) { switch (style) { case 0: hairShape = sceneInfo.NodeIDs["PonyTail"].Shapes[0]; hairShape.Fill = new SolidFill() { Color = hairColour }; hairShape = sceneInfo.NodeIDs["PonyTail2"].Shapes[0]; hairShape.Fill = new SolidFill() { Color = hairColour }; break; case 1: hairShape = sceneInfo.NodeIDs["PonyTail"].Shapes[0]; hairShape.Fill = new SolidFill() { Color = hairColour }; break; } } //var tessOptions = new VectorUtils.TessellationOptions() //{ // StepDistance = 100f, // MaxCordDeviation = 0.5f, // MaxTanAngleDeviation = 0.1f, // SamplingStepSize = 0.01f //}; //var geoms = VectorUtils.TessellateScene(hairSceneInfo.Scene, tessOptions); //var sprite = VectorUtils.BuildSprite(geoms, 26, VectorUtils.Alignment.Center, Vector2.zero, 128, true); //GameObject go = new GameObject("Hair"); //go.transform.SetParent(transform); //transform.GetChild(0).gameObject.SetActive(true); //go.AddComponent<SpriteRenderer>(); //go.transform.localPosition = new Vector3(0, citizen.gender ? -.25f : -.355f, 0); //SpriteRenderer sr = go.GetComponent<SpriteRenderer>(); //sr.sprite = sprite; //sr.sortingLayerID = GetComponent<SpriteRenderer>().sortingLayerID; //sr.sortingOrder = GetComponent<SpriteRenderer>().sortingOrder; }
void Start() { // Prepare the vector path, add it to the vector scene. m_Path = new Shape() { Contours = new BezierContour[] { new BezierContour() { Segments = new BezierPathSegment[2] }, new BezierContour() { Segments = new BezierPathSegment[2] } }, PathProps = new PathProperties() { Stroke = new Stroke() { Color = Color.white, HalfThickness = 0.1f } } }; m_Scene = new Scene() { Root = new SceneNode() { Shapes = new List <Shape> { //m_Path } } }; m_Options = new VectorUtils.TessellationOptions() { StepDistance = 1000.0f, MaxCordDeviation = 0.05f, MaxTanAngleDeviation = 0.05f, SamplingStepSize = 0.01f }; // Instantiate a new mesh, it will be filled with data in Update() m_Mesh = new Mesh(); GetComponent <MeshFilter>().mesh = m_Mesh; // ======================================================================= string path = string.Format(@"D:\WriteByHand\svgs\{0}.svg", 20986); string svg = SVGHelper.readSVG(path); SVGParser.SceneInfo scene_info = SVGParser.ImportSVG(new StringReader(svg)); Scene scene = scene_info.Scene; SceneNode word = scene.Root.Children[1]; // 前半為背景(無 Clipper),後半為寫字筆劃(有 Clipper) List <SceneNode> bg_and_stroke = word.Children; int double_stroke_number = bg_and_stroke.Count; int stroke_number = double_stroke_number / 2; // 筆劃第一筆 SceneNode test_node = bg_and_stroke[stroke_number]; List <Shape> test_shapes = test_node.Shapes; SceneNode test_clipper_node = (test_node.Clipper == null) ? null : test_node.Clipper; List <Shape> test_clippers = new List <Shape>(); if (test_clipper_node != null) { test_clippers = test_clipper_node.Children[0].Shapes; if (test_clippers != null) { print("test_clippers len:" + test_clippers.Count); Shape test_clipper_shape = test_clippers[0]; } else { print("test_clippers is null"); } } else { print("test_clipper_node is null"); } Shape test_stroke = test_shapes[0]; BezierContour[] bezierContours = test_stroke.Contours; BezierPathSegment[] bezierPathSegments = bezierContours[0].Segments; BezierPathSegment point1 = bezierPathSegments[0]; BezierPathSegment point2 = bezierPathSegments[bezierPathSegments.Length - 1]; #region Word scene // 遮罩嘗試 display_scene = new Scene() { Root = new SceneNode() { Children = new List <SceneNode>() { #region One stroke new SceneNode() { Shapes = new List <Shape>() { #region Piece of stroke new Shape() { Contours = new BezierContour[] { new BezierContour() { Segments = new BezierPathSegment[] { point1, point2 } }, //new BezierContour() { // Segments = new BezierPathSegment[2] //} }, PathProps = new PathProperties() { Stroke = new Stroke() { Color = Color.white, HalfThickness = 10f } } } #endregion Piece of stroke end }, Clipper = new SceneNode() { Shapes = new List <Shape>() { #region Piece of clipper test_clippers[0] #endregion Piece of clipper end } } } #endregion One stroke end } } }; #endregion Word scene end StartCoroutine(nextStroke(bg_and_stroke)); }
void Start() { //string svg = // @"<svg width=""283.9"" height=""283.9"" xmlns=""http://www.w3.org/2000/svg""> // <line x1=""170.3"" y1=""226.99"" x2=""177.38"" y2=""198.64"" fill=""none"" stroke=""#888"" stroke-width=""1""/> // <line x1=""205.73"" y1=""198.64"" x2=""212.81"" y2=""226.99"" fill=""none"" stroke=""#888"" stroke-width=""1""/> // <line x1=""212.81"" y1=""226.99"" x2=""219.9"" y2=""255.33"" fill=""none"" stroke=""#888"" stroke-width=""1""/> // <line x1=""248.25"" y1=""255.33"" x2=""255.33"" y2=""226.99"" fill=""none"" stroke=""#888"" stroke-width=""1""/> // <path d=""M170.08,226.77c7.09-28.34,35.43-28.34,42.52,0s35.43,28.35,42.52,0"" transform=""translate(0.22 0.22)"" fill=""none"" stroke=""red"" stroke-width=""1.2""/> // <circle cx=""170.3"" cy=""226.99"" r=""1.2"" fill=""blue"" stroke-width=""0.6""/> // <circle cx=""212.81"" cy=""226.99"" r=""1.2"" fill=""blue"" stroke-width=""0.6""/> // <circle cx=""255.33"" cy=""226.99"" r=""1.2"" fill=""blue"" stroke-width=""0.6""/> // <circle cx=""177.38"" cy=""198.64"" r=""1"" fill=""black"" /> // <circle cx=""205.73"" cy=""198.64"" r=""1"" fill=""black"" /> // <circle cx=""248.25"" cy=""255.33"" r=""1"" fill=""black"" /> // <circle cx=""219.9"" cy=""255.33"" r=""1"" fill=""black"" /> // </svg>"; var tessOptions = new VectorUtils.TessellationOptions() { StepDistance = 100.0f, MaxCordDeviation = 0.5f, MaxTanAngleDeviation = 0.1f, SamplingStepSize = 0.01f }; //Pfad zur Datei string svgFilePath = Application.dataPath + "/Resources/testObject_layerTest-10-10.svg"; StreamReader sr = new StreamReader(svgFilePath); string svgText = sr.ReadToEnd(); print(svgText); sr.Close(); sr.Dispose(); var sceneInfo = SVGParser.ImportSVG(new StringReader(svgText)); int NrOfLayers = sceneInfo.Scene.Root.Children.Count; m_Sprites = new Sprite[NrOfLayers]; SVGParser.SceneInfo[] m_SIArray = new SVGParser.SceneInfo[NrOfLayers]; List <VectorUtils.Geometry>[] m_Geoms = new List <VectorUtils.Geometry> [NrOfLayers]; for (int i = 0; i < NrOfLayers; i++) { m_SIArray[i] = SVGParser.ImportSVG(new StringReader(svgText)); int removed = 0; for (int c = 0; c < NrOfLayers; c++) { if (c != i) { //print("at " + i + " removing index " + c); m_SIArray[i].Scene.Root.Children.Remove(m_SIArray[i].Scene.Root.Children[c - removed]); removed++; } } var fullBounds = VectorUtils.SceneNodeBounds(sceneInfo.Scene.Root); var localBounds = VectorUtils.SceneNodeBounds(sceneInfo.Scene.Root.Children[i]); var pivot = localBounds.position - fullBounds.position; var localSceneBounds = VectorUtils.SceneNodeBounds(m_SIArray[i].Scene.Root); Vector2 position = new Vector2(fullBounds.position.x, fullBounds.position.y); // position = new Vector2(fullBounds.center.x / fullBounds.width - (localBounds.position.x) / fullBounds.width, fullBounds.center.y / fullBounds.height - localBounds.position.y / fullBounds.height); //position = new Vector2((fullBounds.center.x - localBounds.position.x )/ fullBounds.width, 0); //position = new Vector2((fullBounds.position.x-localBounds.position.x-pivot.x) / fullBounds.width , 0); position = new Vector2(0, 0); print("FullBounds: " + fullBounds + " localBounds:" + localBounds);// + " localSceneBounds:"+ localSceneBounds); //print(i + ": " + position+" / pivot: "+pivot); //print(position.x * fullBounds.width + " , " + position.y * fullBounds.height); m_Geoms[i] = VectorUtils.TessellateScene(m_SIArray[i].Scene, tessOptions); m_Sprites[i] = VectorUtils.BuildSprite(m_Geoms[i], 1000.0f, VectorUtils.Alignment.TopLeft, position, 128, true); GameObject go = new GameObject(); SpriteRenderer s = go.AddComponent <SpriteRenderer>(); go.transform.parent = transform; // go.transform.position = new Vector3((localSceneBounds.x - fullBounds.width/2f)/1000f, (fullBounds.y + fullBounds.height/2f - localSceneBounds.y) /1000f , 0); go.transform.position = new Vector3((localBounds.x) / 1000f, (fullBounds.y - localBounds.y) / 1000f, 0); s.sprite = m_Sprites[i]; //var test = typeof(VectorUtils.TessellateScene); //var methods = test.GetMethods(); //// test code: generate better shape //bool m_BetterGeneratePhysicsShape = true; //if (m_BetterGeneratePhysicsShape) //{ // var test = typeof(VectorUtils); // var methods = test.GetMethods(); // foreach (MethodInfo mf in methods) // { // Debug.Log(mf.Name); // } // var physicsShapes = VectorUtils.TraceNodeHierarchyShapes(sceneInfo.Scene.Root, tessOptions); // var rect = sceneInfo.SceneViewport; // foreach (var vertices in physicsShapes) // { // if (rect == Rect.zero) // { // rect = VectorUtils.Bounds(vertices); // VectorUtils.RealignVerticesInBounds(vertices, rect, flip: true); // } // else // { // VectorUtils.FlipVerticesInBounds(vertices, rect); // VectorUtils.ClampVerticesInBounds(vertices, rect); // } // } // m_Sprites[i].OverridePhysicsShape(physicsShapes); //} //// test code end go.AddComponent <PolygonCollider2D>(); //PrefabUtility.SaveAsPrefabAsset(go, svgFilePath.Replace(".svg", "_2" + i.ToString() + ".prefab")); } //AssetImportContext ctx; //ctx.AddObjectToAsset(); //var geoms = VectorUtils.TessellateScene(sceneInfo.Scene, tessOptions); //// Build a sprite with the tessellated geometry. //var sprite = VectorUtils.BuildSprite(geoms, 1000.0f, VectorUtils.Alignment.TopLeft, Vector2.zero, 128, true); //GetComponent<SpriteRenderer>().sprite = sprite; //GenerateSpriteAsset(ctx, sprite, name); }
/// <summary> /// Create a Texture2D icon of a SVG image (editor only version). /// </summary> /// <param name="svg">String containing svg content.</param> /// <param name="renderUtil">PreviewRenderUtility to use for drawing</param> /// <remarks> /// Standard header and footer will be included if not found in svgContent /// </remarks> public static Texture2D GetIcon(string svgContent, PreviewRenderUtility renderUtil) { string svg; if (svgContent.StartsWith("<?xml version = \"1.0\" encoding=\"UTF - 8\"?>")) { svg = svgContent; } else { svg = svgIconHeader + svgContent; } if (!svg.EndsWith(svgIconFooter)) { svg = svg + svgIconFooter; } // Parse the SVG SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(new System.IO.StringReader(svg)); int width = Mathf.CeilToInt(sceneInfo.SceneViewport.width); int height = Mathf.CeilToInt(sceneInfo.SceneViewport.height); if ((width > 64) || (height > 64)) { Debug.LogWarning("SVG icon of unusual size!"); } // Save the render state and get a temporary render texture RenderTexture activeTexture = RenderTexture.active; renderUtil.camera.targetTexture = RenderTexture.GetTemporary(width * 2, height * 2, 8, RenderTextureFormat.ARGB32); renderUtil.camera.backgroundColor = Color.clear; // Generate the mesh Mesh iconMesh = new Mesh(); List <VectorUtils.Geometry> iconGeometry = VectorUtils.TessellateScene(sceneInfo.Scene, tessellationOptions); VectorUtils.FillMesh(iconMesh, iconGeometry, 1f); // Activate the render texture and draw the mesh into it RenderTexture.active = renderUtil.camera.targetTexture; float cameraSize = renderUtil.camera.orthographicSize; Vector3 cameraPosition = renderUtil.camera.transform.position; renderUtil.camera.orthographicSize = sceneInfo.SceneViewport.height / 2; renderUtil.camera.transform.position = new Vector3(sceneInfo.SceneViewport.center.x, sceneInfo.SceneViewport.center.y, -1); // HACK until FillMesh() flpYAxis is fixed renderUtil.camera.transform.Rotate(0, 0, 180f); renderUtil.DrawMesh(iconMesh, Matrix4x4.identity, renderMaterial, 0); renderUtil.camera.Render(); renderUtil.camera.transform.Rotate(0, 0, 180f); renderUtil.camera.orthographicSize = cameraSize; renderUtil.camera.transform.position = cameraPosition; Texture2D iconTexture = new Texture2D(width * 2, height * 2); iconTexture.ReadPixels(new Rect(0, 0, width * 2, height * 2), 0, 0); iconTexture.Apply(); // Restore the render state and release the temporary objects RenderTexture.active = activeTexture; RenderTexture.ReleaseTemporary(renderUtil.camera.targetTexture); UnityEngine.Object.DestroyImmediate(iconMesh); return(iconTexture); }
// Start is called before the first frame update void Start() { string path = string.Format(@"D:\WriteByHand\svgs\{0}.svg", 20986); string svg = SVGHelper.readSVG(path); SVGParser.SceneInfo scene_info = SVGParser.ImportSVG(new StringReader(svg)); scene = scene_info.Scene; // svg 本體 SceneNode node = scene.Root; List <SceneNode> layer1 = node.Children; // node0:背景米字;node1:字的筆劃 SceneNode node0 = layer1[0], node1 = layer1[1]; // 背景米字 //List<SceneNode> layer2 = node0.Children; //print("layer2:" + layer2.Count); // 字的筆劃 List <SceneNode> layer3 = node1.Children; //print("layer3:" + layer3.Count); //int n = 0; //foreach (SceneNode scene_node in layer3) //{ // print(string.Format("=== Node {0} ===", ++n)); // List<Shape> shapes = scene_node.Shapes; // length = 1 // Shape shape = shapes[0]; // length = 1 // BezierContour[] contours = shape.Contours; // length = 1 // BezierPathSegment[] segments = contours[0].Segments; // 每一筆劃的區段數量不同 // int num = 0; // foreach(BezierPathSegment bezierPathSegment in segments) // { // print(string.Format("= segment {0} =", ++num)); // print(bezierPathSegment.P0); // print(bezierPathSegment.P1); // print(bezierPathSegment.P2); // break; // } // SceneNode clipper = (scene_node.Clipper == null) ? null : scene_node.Clipper; // if(clipper != null) // { // List<SceneNode> clippers = clipper.Children; // length = 1 // SceneNode mask = clippers[0]; // List<Shape> m_shapes = mask.Shapes; // length = 1 // Shape m_shape = m_shapes[0]; // BezierContour[] m_contours = m_shape.Contours; // length = 1 // //print("m_contours len:" + m_contours.Length); // BezierPathSegment[] m_segments = m_contours[0].Segments; // 每一筆劃的區段數量不同 // //print("m_segments len:" + m_segments.Length); // int number = 0; // foreach (BezierPathSegment m_bezierPathSegment in m_segments) // { // print(string.Format("= clipper segment {0} =", ++number)); // print(m_bezierPathSegment.P0); // print(m_bezierPathSegment.P1); // print(m_bezierPathSegment.P2); // break; // } // } // else // { // print("clipper is null"); // } //} n_scene = new Scene() { Root = new SceneNode() { // node.Children 正常的字 // node1.Children 上下相反的字 //Children = node.Children Children = new List <SceneNode>() { new SceneNode() { Children = node1.Children } } } }; //foreach (SceneNode sceneNode in layer3) //{ // n_scene.Root.Children.Add(sceneNode); //} sceneDisplay(n_scene, render); //StartCoroutine(nextStroke(layer3)); }
/// <summary> /// Imports a vector texture /// </summary> /// <param name="file">The file to import from</param> /// <param name="size">The size of the texture</param> /// <param name="type"></param> /// <returns>The vector texture imported as a Sprite</returns> public static Sprite ImportVector(FileInfo file, int size, SpriteImportType type) { StreamReader reader = null; StringReader sr = null; try { reader = new StreamReader(file.OpenRead()); sr = new StringReader(reader.ReadToEnd()); SVGParser.SceneInfo scene = SVGParser.ImportSVG(sr); VectorUtils.TessellationOptions tessOptions = new VectorUtils.TessellationOptions() { StepDistance = 100.0f, MaxCordDeviation = 0.5f, MaxTanAngleDeviation = 0.1f, SamplingStepSize = 0.01f }; List <VectorUtils.Geometry> geoms = VectorUtils.TessellateScene(scene.Scene, tessOptions); Sprite tempSprite = VectorUtils.BuildSprite(geoms, size, VectorUtils.Alignment.Center, Vector2.zero, 64, false); Shader shader = null; switch (type) { case SpriteImportType.svggradient: shader = Shader.Find("Unlit/VectorGradient"); break; case SpriteImportType.svg: default: shader = Shader.Find("Unlit/Vector"); break; } Texture2D tex = VectorUtils.RenderSpriteToTexture2D(tempSprite, size, size, new Material(shader)); //tex.alphaIsTransparency = true; Sprite sprite = Sprite.Create(tex, new Rect(Vector2.zero, new Vector2(tex.width, tex.height)), new Vector2(0.5f, 0.5f), size * 2); return(sprite); } catch (Exception e) { MonoBehaviour.print(e.Message + "\nFile: " + file.Name + "\n" + e.StackTrace); } finally { if (reader != null) { reader.Close(); } if (sr != null) { sr.Close(); } } return(null); }