using System; using System.Text.RegularExpressions; using UnityEngine; public class MegaShapeSVG { private int splineindex; private char[] commaspace = new char[2] { ',', ' ' }; private const float CIRCLE_VECTOR_LENGTH = 0.5517862f; public void LoadXML(string svgdata, MegaShape shape, bool clear, int start) { MegaXMLReader megaXMLReader = new MegaXMLReader(); MegaXMLNode node = megaXMLReader.read(svgdata); if (!clear) { shape.splines.Clear(); } shape.selcurve = start; splineindex = start; ParseXML(node, shape); } public void ParseXML(MegaXMLNode node, MegaShape shape) { foreach (MegaXMLNode child in node.children) { switch (child.tagName) { case "circle": ParseCircle(child, shape); break; case "path": ParsePath(child, shape); break; case "ellipse": ParseEllipse(child, shape); break; case "rect": ParseRect(child, shape); break; case "polygon": ParsePolygon(child, shape); break; } ParseXML(child, shape); } } private MegaSpline GetSpline(MegaShape shape) { MegaSpline megaSpline; if (splineindex < shape.splines.Count) { megaSpline = shape.splines[splineindex]; } else { megaSpline = new MegaSpline(); shape.splines.Add(megaSpline); } splineindex++; return megaSpline; } private Vector3 SwapAxis(Vector3 val, MegaAxis axis) { float num = 0f; switch (axis) { case MegaAxis.X: num = val.x; val.x = val.y; val.y = num; break; case MegaAxis.Z: num = val.y; val.y = val.z; val.z = num; break; } return val; } private void AddKnot(MegaSpline spline, Vector3 p, Vector3 invec, Vector3 outvec, MegaAxis axis) { spline.AddKnot(SwapAxis(p, axis), SwapAxis(invec, axis), SwapAxis(outvec, axis)); } private void ParseCircle(MegaXMLNode node, MegaShape shape) { MegaSpline spline = GetSpline(shape); float num = 0f; float num2 = 0f; float num3 = 0f; for (int i = 0; i < node.values.Count; i++) { MegaXMLValue megaXMLValue = node.values[i]; switch (megaXMLValue.name) { case "cx": num = float.Parse(megaXMLValue.value); break; case "cy": num2 = float.Parse(megaXMLValue.value); break; case "r": num3 = float.Parse(megaXMLValue.value); break; } } float num4 = 0.5517862f * num3; spline.knots.Clear(); for (int j = 0; j < 4; j++) { float f = (float)Math.PI * 2f * (float)j / 4f; float num5 = Mathf.Sin(f); float num6 = Mathf.Cos(f); Vector3 vector = new Vector3(num6 * num3 + num, 0f, num5 * num3 + num2); Vector3 vector2 = new Vector3(num5 * num4, 0f, (0f - num6) * num4); AddKnot(spline, vector, vector + vector2, vector - vector2, shape.axis); } spline.closed = true; } private void ParseEllipse(MegaXMLNode node, MegaShape shape) { MegaSpline spline = GetSpline(shape); float num = 0f; float num2 = 0f; float value = 0f; float value2 = 0f; for (int i = 0; i < node.values.Count; i++) { MegaXMLValue megaXMLValue = node.values[i]; switch (megaXMLValue.name) { case "cx": num = float.Parse(megaXMLValue.value); break; case "cy": num2 = float.Parse(megaXMLValue.value); break; case "rx": value = float.Parse(megaXMLValue.value); break; case "ry": value2 = float.Parse(megaXMLValue.value); break; } } value2 = Mathf.Clamp(value2, 0f, float.MaxValue); value = Mathf.Clamp(value, 0f, float.MaxValue); float num3; float x; float y; if (value2 < value) { num3 = value; x = 1f; y = value2 / value; } else if (value < value2) { num3 = value2; x = value / value2; y = 1f; } else { num3 = value2; x = (y = 1f); } float num4 = 0.5517862f * num3; Vector3 b = new Vector3(x, y, 1f); for (int j = 0; j < 4; j++) { float f = (float)Math.PI * 2f * (float)j / 4f; float num5 = Mathf.Sin(f); float num6 = Mathf.Cos(f); Vector3 vector = new Vector3(num6 * num3 + num, 0f, num5 * num3 + num2); Vector3 vector2 = new Vector3(num5 * num4, 0f, (0f - num6) * num4); AddKnot(spline, Vector3.Scale(vector, b), Vector3.Scale(vector + vector2, b), Vector3.Scale(vector - vector2, b), shape.axis); } spline.closed = true; } private void ParseRect(MegaXMLNode node, MegaShape shape) { MegaSpline spline = GetSpline(shape); Vector3[] array = new Vector3[4]; float num = 0f; float num2 = 0f; float num3 = 0f; float num4 = 0f; for (int i = 0; i < node.values.Count; i++) { MegaXMLValue megaXMLValue = node.values[i]; switch (megaXMLValue.name) { case "x": num3 = float.Parse(megaXMLValue.value); break; case "y": num4 = float.Parse(megaXMLValue.value); break; case "width": num = float.Parse(megaXMLValue.value); break; case "height": num2 = float.Parse(megaXMLValue.value); break; case "transform": Debug.Log("SVG Transform not implemented yet"); break; } } array[0] = new Vector3(num3, 0f, num4); array[1] = new Vector3(num3, 0f, num4 + num2); array[2] = new Vector3(num3 + num, 0f, num4 + num2); array[3] = new Vector3(num3 + num, 0f, num4); spline.closed = true; spline.knots.Clear(); AddKnot(spline, array[0], array[0], array[0], shape.axis); AddKnot(spline, array[1], array[1], array[1], shape.axis); AddKnot(spline, array[2], array[2], array[2], shape.axis); AddKnot(spline, array[3], array[3], array[3], shape.axis); } private void ParsePolygon(MegaXMLNode node, MegaShape shape) { MegaSpline spline = GetSpline(shape); spline.knots.Clear(); spline.closed = true; char[] separator = new char[1] { ' ' }; for (int i = 0; i < node.values.Count; i++) { MegaXMLValue megaXMLValue = node.values[i]; string name = megaXMLValue.name; if (name != null && name == "points") { string[] array = megaXMLValue.value.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < array.Length; j++) { Vector3 vector = ParseV2Split(array[j], 0); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = megaKnot.p; megaKnot.outvec = megaKnot.p; spline.knots.Add(megaKnot); } } } if (spline.closed) { Vector3 vector2 = spline.knots[0].outvec - spline.knots[0].p; spline.knots[0].invec = spline.knots[0].p - vector2; } } private void ParsePath(MegaXMLNode node, MegaShape shape) { Vector3 vector = Vector3.zero; char[] separator = new char[2] { ',', ' ' }; MegaSpline megaSpline = null; for (int i = 0; i < node.values.Count; i++) { MegaXMLValue megaXMLValue = node.values[i]; string name = megaXMLValue.name; if (name == null || !(name == "d")) { continue; } string[] array = Regex.Split(megaXMLValue.value, "(?=[MmLlCcSsZzHhVv])"); for (int j = 0; j < array.Length; j++) { if (array[j].Length <= 0) { continue; } string text = array[j].Substring(1); if (text != null && text.Length > 0) { text = text.Replace("-", ",-"); while (text.Length > 0 && (text[0] == ',' || text[0] == ' ')) { text = text.Substring(1); } } switch (array[j][0]) { case 'Z': case 'z': if (megaSpline != null) { megaSpline.closed = true; int index = megaSpline.knots.Count - 1; megaSpline.knots[0].invec = megaSpline.knots[index].invec; megaSpline.knots.Remove(megaSpline.knots[index]); } break; case 'M': { megaSpline = GetSpline(shape); megaSpline.knots.Clear(); vector = ParseV2Split(text, 0); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = megaKnot.p; megaKnot.outvec = megaKnot.p; megaSpline.knots.Add(megaKnot); break; } case 'm': { megaSpline = GetSpline(shape); megaSpline.knots.Clear(); string[] array2 = text.Split(" "[0]); for (int num3 = 0; num3 < array2.Length - 1; num3++) { Vector3 vector4 = ParseV2Split(array2[num3], 0); vector.x += vector4.x; vector.y += vector4.y; MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = megaKnot.p; megaKnot.outvec = megaKnot.p; megaSpline.knots.Add(megaKnot); } break; } case 'l': { string[] array2 = text.Split(","[0]); for (int num4 = 0; num4 < array2.Length; num4 += 2) { vector += ParseV2(array2, num4); } megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); break; } case 'c': { string[] array2 = text.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int m = 0; m < array2.Length; m += 6) { Vector2 vector2 = vector + ParseV2(array2, m); Vector2 vector3 = vector + ParseV2(array2, m + 2); vector += ParseV2(array2, m + 4); megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector2.x, 0f, vector2.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector3.x, 0f, vector3.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); } break; } case 'L': { string[] array2 = text.Split(","[0]); for (int num6 = 0; num6 < array2.Length; num6 += 2) { vector = ParseV2(array2, num6); } megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); break; } case 'v': { string[] array2 = text.Split(","[0]); for (int num = 0; num < array2.Length; num++) { vector.y += float.Parse(array2[num]); } megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); break; } case 'V': { string[] array2 = text.Split(","[0]); for (int num7 = 0; num7 < array2.Length; num7++) { vector.y = float.Parse(array2[num7]); } megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); break; } case 'h': { string[] array2 = text.Split(","[0]); for (int num5 = 0; num5 < array2.Length; num5++) { vector.x += float.Parse(array2[num5]); } megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); break; } case 'H': { string[] array2 = text.Split(","[0]); for (int num2 = 0; num2 < array2.Length; num2++) { vector.x = float.Parse(array2[num2]); } megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); break; } case 'S': { string[] array2 = text.Split(","[0]); for (int n = 0; n < array2.Length; n += 4) { vector = ParseV2(array2, n + 2); Vector2 vector2 = ParseV2(array2, n); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector2.x, 0f, vector2.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); } break; } case 's': { string[] array2 = text.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int l = 0; l < array2.Length; l += 4) { Vector2 vector2 = vector + ParseV2(array2, l); vector += ParseV2(array2, l + 2); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector2.x, 0f, vector2.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); } break; } case 'C': { string[] array2 = text.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int k = 0; k < array2.Length; k += 6) { Vector2 vector2 = ParseV2(array2, k); Vector2 vector3 = ParseV2(array2, k + 2); vector = ParseV2(array2, k + 4); megaSpline.knots[megaSpline.knots.Count - 1].outvec = SwapAxis(new Vector3(vector2.x, 0f, vector2.y), shape.axis); MegaKnot megaKnot = new MegaKnot(); megaKnot.p = SwapAxis(new Vector3(vector.x, 0f, vector.y), shape.axis); megaKnot.invec = SwapAxis(new Vector3(vector3.x, 0f, vector3.y), shape.axis); megaKnot.outvec = megaKnot.p - (megaKnot.invec - megaKnot.p); megaSpline.knots.Add(megaKnot); } break; } } } } } public void importData(string svgdata, MegaShape shape, float scale, bool clear, int start) { LoadXML(svgdata, shape, clear, start); for (int i = start; i < splineindex; i++) { float num = shape.splines[i].Area(); if (num < 0f) { shape.splines[i].reverse = false; } else { shape.splines[i].reverse = true; } } shape.CoordAdjust(scale, new Vector3(-1f, 1f, 1f), start); shape.CalcLength(); } private Vector2 ParseV2Split(string str, int i) { return ParseV2(str.Split(commaspace, StringSplitOptions.RemoveEmptyEntries), i); } private Vector3 ParseV2(string[] str, int i) { Vector3 result = Vector2.zero; result.x = float.Parse(str[i]); result.y = float.Parse(str[i + 1]); return result; } public static string Export(MegaShape shape, int x, int y, float strokewidth, Color col) { string empty = string.Empty; Color32 color = col; empty += "\n"; empty += "\n"; empty += "\n"; empty = empty + "\n"; for (int i = 0; i < shape.splines.Count; i++) { MegaSpline megaSpline = shape.splines[i]; empty += "\n"; } }