123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- using UnityEngine;
- using System;
- using System.Collections.Generic;
- #if !UNITY_FLASH && !UNITY_METRO && !UNITY_WP8
- using System.Text.RegularExpressions;
- #endif
- // Part of MegaShape?
- public class MegaShapeSVG
- {
- public void LoadXML(string svgdata, MegaShape shape, bool clear, int start)
- {
- MegaXMLReader xml = new MegaXMLReader();
- MegaXMLNode node = xml.read(svgdata);
- if ( !clear )
- shape.splines.Clear();
- shape.selcurve = start;
- splineindex = start;
- ParseXML(node, shape);
- }
- int splineindex = 0;
- public void ParseXML(MegaXMLNode node, MegaShape shape)
- {
- foreach ( MegaXMLNode n in node.children )
- {
- switch ( n.tagName )
- {
- case "circle": ParseCircle(n, shape); break;
- case "path": ParsePath(n, shape); break;
- case "ellipse": ParseEllipse(n, shape); break;
- case "rect": ParseRect(n, shape); break;
- case "polygon": ParsePolygon(n, shape); break;
- default: break;
- }
- ParseXML(n, shape);
- }
- }
- MegaSpline GetSpline(MegaShape shape)
- {
- MegaSpline spline;
- if ( splineindex < shape.splines.Count )
- spline = shape.splines[splineindex];
- else
- {
- spline = new MegaSpline();
- shape.splines.Add(spline);
- }
- splineindex++;
- return spline;
- }
- Vector3 SwapAxis(Vector3 val, MegaAxis axis)
- {
- float v = 0.0f;
- switch ( axis )
- {
- case MegaAxis.X:
- v = val.x;
- val.x = val.y;
- val.y = v;
- break;
- case MegaAxis.Y:
- break;
- case MegaAxis.Z:
- v = val.y;
- val.y = val.z;
- val.z = v;
- break;
- }
- return val;
- }
- void AddKnot(MegaSpline spline, Vector3 p, Vector3 invec, Vector3 outvec, MegaAxis axis)
- {
- spline.AddKnot(SwapAxis(p, axis), SwapAxis(invec, axis), SwapAxis(outvec, axis));
- }
- void ParseCircle(MegaXMLNode node, MegaShape shape)
- {
- MegaSpline spline = GetSpline(shape);
- float cx = 0.0f;
- float cy = 0.0f;
- float r = 0.0f;
- for ( int i = 0; i < node.values.Count; i++ )
- {
- MegaXMLValue val = node.values[i];
- switch ( val.name )
- {
- case "cx": cx = float.Parse(val.value); break;
- case "cy": cy = float.Parse(val.value); break;
- case "r": r = float.Parse(val.value); break;
- }
- }
- float vector = CIRCLE_VECTOR_LENGTH * r;
- spline.knots.Clear();
- for ( int ix = 0; ix < 4; ++ix )
- {
- float angle = (Mathf.PI * 2.0f) * (float)ix / (float)4;
- float sinfac = Mathf.Sin(angle);
- float cosfac = Mathf.Cos(angle);
- Vector3 p = new Vector3((cosfac * r) + cx, 0.0f, (sinfac * r) + cy);
- Vector3 rotvec = new Vector3(sinfac * vector, 0.0f, -cosfac * vector);
- //spline.AddKnot(p, p + rotvec, p - rotvec);
- AddKnot(spline, p, p + rotvec, p - rotvec, shape.axis);
- }
- spline.closed = true;
- }
- void ParseEllipse(MegaXMLNode node, MegaShape shape)
- {
- MegaSpline spline = GetSpline(shape);
- float cx = 0.0f;
- float cy = 0.0f;
- float rx = 0.0f;
- float ry = 0.0f;
- for ( int i = 0; i < node.values.Count; i++ )
- {
- MegaXMLValue val = node.values[i];
- switch ( val.name )
- {
- case "cx": cx = float.Parse(val.value); break;
- case "cy": cy = float.Parse(val.value); break;
- case "rx": rx = float.Parse(val.value); break;
- case "ry": ry = float.Parse(val.value); break;
- }
- }
- ry = Mathf.Clamp(ry, 0.0f, float.MaxValue);
- rx = Mathf.Clamp(rx, 0.0f, float.MaxValue);
- float radius, xmult, ymult;
- if ( ry < rx )
- {
- radius = rx;
- xmult = 1.0f;
- ymult = ry / rx;
- }
- else
- {
- if ( rx < ry )
- {
- radius = ry;
- xmult = rx / ry;
- ymult = 1.0f;
- }
- else
- {
- radius = ry;
- xmult = ymult = 1.0f;
- }
- }
- float vector = CIRCLE_VECTOR_LENGTH * radius;
- Vector3 mult = new Vector3(xmult, ymult, 1.0f);
- for ( int ix = 0; ix < 4; ++ix )
- {
- float angle = 6.2831853f * (float)ix / 4.0f;
- float sinfac = Mathf.Sin(angle);
- float cosfac = Mathf.Cos(angle);
- Vector3 p = new Vector3(cosfac * radius + cx, 0.0f, sinfac * radius + cy);
- Vector3 rotvec = new Vector3(sinfac * vector, 0.0f, -cosfac * vector);
- //spline.AddKnot(Vector3.Scale(p, mult), Vector3.Scale((p + rotvec), mult), Vector3.Scale((p - rotvec), mult)); //, tm);
- AddKnot(spline, Vector3.Scale(p, mult), Vector3.Scale((p + rotvec), mult), Vector3.Scale((p - rotvec), mult), shape.axis); //, tm);
- }
- spline.closed = true;
- }
- void ParseRect(MegaXMLNode node, MegaShape shape)
- {
- MegaSpline spline = GetSpline(shape);
- Vector3[] ppoints = new Vector3[4];
- float w = 0.0f;
- float h = 0.0f;
- float x = 0.0f;
- float y = 0.0f;
- for ( int i = 0; i < node.values.Count; i++ )
- {
- MegaXMLValue val = node.values[i];
- switch ( val.name )
- {
- case "x": x = float.Parse(val.value); break;
- case "y": y = float.Parse(val.value); break;
- case "width": w = float.Parse(val.value); break;
- case "height": h = float.Parse(val.value); break;
- case "transform": Debug.Log("SVG Transform not implemented yet");
- break;
- }
- }
- ppoints[0] = new Vector3(x, 0.0f, y);
- ppoints[1] = new Vector3(x, 0.0f, y + h);
- ppoints[2] = new Vector3(x + w, 0.0f, y + h);
- ppoints[3] = new Vector3(x + w, 0.0f, y);
- spline.closed = true;
- spline.knots.Clear();
- //spline.AddKnot(ppoints[0], ppoints[0], ppoints[0]);
- //spline.AddKnot(ppoints[1], ppoints[1], ppoints[1]);
- //spline.AddKnot(ppoints[2], ppoints[2], ppoints[2]);
- //spline.AddKnot(ppoints[3], ppoints[3], ppoints[3]);
- AddKnot(spline, ppoints[0], ppoints[0], ppoints[0], shape.axis);
- AddKnot(spline, ppoints[1], ppoints[1], ppoints[1], shape.axis);
- AddKnot(spline, ppoints[2], ppoints[2], ppoints[2], shape.axis);
- AddKnot(spline, ppoints[3], ppoints[3], ppoints[3], shape.axis);
- }
- void ParsePolygon(MegaXMLNode node, MegaShape shape)
- {
- MegaSpline spline = GetSpline(shape);
- spline.knots.Clear();
- spline.closed = true;
- char[] charSeparators = new char[] { ' ' };
- for ( int i = 0; i < node.values.Count; i++ )
- {
- MegaXMLValue val = node.values[i];
- switch ( val.name )
- {
- case "points":
- string[] coordinates = val.value.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
- for ( int j = 0; j < coordinates.Length; j++ )
- {
- Vector3 p = ParseV2Split(coordinates[j], 0);
- MegaKnot k = new MegaKnot();
- k.p = SwapAxis(new Vector3(p.x, 0.0f, p.y), shape.axis);
- k.invec = k.p;
- k.outvec = k.p;
- spline.knots.Add(k);
- }
- break;
- }
- }
- if ( spline.closed )
- {
- Vector3 delta1 = spline.knots[0].outvec - spline.knots[0].p;
- spline.knots[0].invec = spline.knots[0].p - delta1;
- }
- }
- char[] commaspace = new char[] { ',', ' ' };
- void ParsePath(MegaXMLNode node, MegaShape shape)
- {
- Vector3 cp = Vector3.zero;
- Vector2 cP1;
- Vector2 cP2;
- char[] charSeparators = new char[] { ',', ' ' };
- MegaSpline spline = null;
- MegaKnot k;
- string[] coord;
- for ( int i = 0; i < node.values.Count; i++ )
- {
- MegaXMLValue val = node.values[i];
- //Debug.Log("val name " + val.name);
- switch ( val.name )
- {
- case "d":
- #if UNITY_FLASH || UNITY_METRO || UNITY_WP8
- string[] coordinates = null; //string.Split(val.value, @"(?=[MmLlCcSsZzHhVv])");
- #else
- string[] coordinates = Regex.Split(val.value, @"(?=[MmLlCcSsZzHhVv])");
- #endif
- for ( int j = 0; j < coordinates.Length; j++ )
- {
- if ( coordinates[j].Length > 0 )
- {
- string v = coordinates[j].Substring(1);
- if ( v != null && v.Length > 0 )
- {
- v = v.Replace("-", ",-");
- while ( v.Length > 0 && (v[0] == ',' || v[0] == ' ') )
- v = v.Substring(1);
- }
- switch ( coordinates[j][0] )
- {
- case 'Z':
- case 'z':
- if ( spline != null )
- {
- spline.closed = true;
- #if false
- Vector3 delta1 = spline.knots[0].outvec - spline.knots[0].p;
- spline.knots[0].invec = spline.knots[0].p - delta1;
- if ( spline.knots[0].p == spline.knots[spline.knots.Count - 1].p )
- spline.knots.Remove(spline.knots[spline.knots.Count - 1]);
- #else
- int kc = spline.knots.Count - 1;
- spline.knots[0].invec = spline.knots[kc].invec;
- spline.knots.Remove(spline.knots[kc]);
- #endif
- }
- break;
- case 'M':
- spline = GetSpline(shape);
- spline.knots.Clear();
- cp = ParseV2Split(v, 0);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = k.p;
- k.outvec = k.p;
- spline.knots.Add(k);
- break;
- case 'm':
- spline = GetSpline(shape);
- spline.knots.Clear();
- //Debug.Log("v: " + v);
- coord = v.Split(" "[0]);
- //Debug.Log("m coords " + coord.Length);
- //Debug.Log("v2 " + coord[0]);
- for ( int k0 = 0; k0 < coord.Length - 1; k0 = k0 + 1 )
- {
- //Debug.Log("v2 " + coord[k0]);
- Vector3 cp1 = ParseV2Split(coord[k0], 0);
- //Debug.Log("cp1 " + cp1);
- cp.x += cp1.x; //ParseV2Split(coord[k0], 0); // ParseV2(coord, k0);
- cp.y += cp1.y;
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = k.p;
- k.outvec = k.p;
- spline.knots.Add(k);
- }
- #if false
- Vector3 cp1 = ParseV2Split(v, 0);
- cp.x += cp1.x;
- cp.y += cp1.y;
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = k.p;
- k.outvec = k.p;
- spline.knots.Add(k);
- #endif
- break;
- case 'l':
- coord = v.Split(","[0]);
- for ( int k0 = 0; k0 < coord.Length; k0 = k0 + 2 )
- cp += ParseV2(coord, k0);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- break;
- case 'c':
- coord = v.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
- for ( int k2 = 0; k2 < coord.Length; k2 += 6 )
- {
- cP1 = cp + ParseV2(coord, k2);
- cP2 = cp + ParseV2(coord, k2 + 2);
- cp += ParseV2(coord, k2 + 4);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cP1.x, 0.0f, cP1.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cP2.x, 0.0f, cP2.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- }
- break;
- case 'L':
- coord = v.Split(","[0]);
- for ( int k3 = 0; k3 < coord.Length; k3 = k3 + 2 )
- cp = ParseV2(coord, k3);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- break;
- case 'v':
- //Debug.Log("v: " + v);
- coord = v.Split(","[0]);
- for ( int k4 = 0; k4 < coord.Length; k4++ )
- cp.y += float.Parse(coord[k4]);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- break;
- case 'V':
- coord = v.Split(","[0]);
- for ( int k9 = 0; k9 < coord.Length; k9++ )
- cp.y = float.Parse(coord[k9]);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- break;
- case 'h':
- coord = v.Split(","[0]);
- for ( int k5 = 0; k5 < coord.Length; k5++ )
- cp.x += float.Parse(coord[k5]);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- break;
- case 'H':
- coord = v.Split(","[0]);
- for ( int k6 = 0; k6 < coord.Length; k6++ )
- cp.x = float.Parse(coord[k6]);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- break;
- case 'S':
- coord = v.Split(","[0]);
- for ( int k7 = 0; k7 < coord.Length; k7 = k7 + 4 )
- {
- cp = ParseV2(coord, k7 + 2);
- cP1 = ParseV2(coord, k7);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cP1.x, 0.0f, cP1.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- }
- break;
- case 's':
- coord = v.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
- for ( int k7 = 0; k7 < coord.Length; k7 = k7 + 4 )
- {
- cP1 = cp + ParseV2(coord, k7);
- cp += ParseV2(coord, k7 + 2);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cP1.x, 0.0f, cP1.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- }
- break;
- case 'C':
- coord = v.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
- for ( int k2 = 0; k2 < coord.Length; k2 += 6 )
- {
- cP1 = ParseV2(coord, k2);
- cP2 = ParseV2(coord, k2 + 2);
- cp = ParseV2(coord, k2 + 4);
- spline.knots[spline.knots.Count - 1].outvec = SwapAxis(new Vector3(cP1.x, 0.0f, cP1.y), shape.axis);
- k = new MegaKnot();
- k.p = SwapAxis(new Vector3(cp.x, 0.0f, cp.y), shape.axis);
- k.invec = SwapAxis(new Vector3(cP2.x, 0.0f, cP2.y), shape.axis);
- k.outvec = k.p - (k.invec - k.p);
- spline.knots.Add(k);
- }
- break;
- default:
- break;
- }
- }
- }
- 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 area = shape.splines[i].Area();
- if ( area < 0.0f )
- shape.splines[i].reverse = false;
- else
- shape.splines[i].reverse = true;
- }
- //shape.Centre(0.01f, new Vector3(-1.0f, 1.0f, 1.0f));
- shape.Centre(scale, new Vector3(-1.0f, 1.0f, 1.0f), start);
- shape.CalcLength(); //10);
- }
- const float CIRCLE_VECTOR_LENGTH = 0.5517861843f;
- Vector2 ParseV2Split(string str, int i)
- {
- return ParseV2(str.Split(commaspace, StringSplitOptions.RemoveEmptyEntries), i);
- }
- Vector3 ParseV2(string[] str, int i)
- {
- Vector3 p = Vector2.zero;
- p.x = float.Parse(str[i]);
- p.y = float.Parse(str[i + 1]);
- return p;
- }
- static public string Export(MegaShape shape, int x, int y, float strokewidth, Color col)
- {
- string file = "";
- Color32 c = col;
- file += "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
- file += "<!-- MegaShapes SVG Exporter v1.0 -->\n";
- file += "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
- file += "<svg version=\"1.1\" id=\"" + shape.name + "\" x=\"0px\" y=\"0px\" width=\"640.0px\" height=\"480.0px\">\n";
- for ( int i = 0; i < shape.splines.Count; i++ )
- {
- MegaSpline spline = shape.splines[i];
- file += "<path d=\"";
- MegaKnot k1;
- MegaKnot k = spline.knots[0];
- k1 = k;
- file += "M" + k.p[x] + "," + -k.p[y];
- //Vector3 cp = k.p;
- for ( int j = 1; j < spline.knots.Count; j++ )
- {
- k = spline.knots[j];
- Vector3 po = k1.outvec; // - cp; // - k1.p;
- Vector3 pi = k.invec; // - cp; // - k.p;
- Vector3 kp = k.p; // - cp;
- kp[y] = -kp[y];
- po[y] = -po[y];
- pi[y] = -pi[y];
- file += "C" + po[x] + "," + po[y];
- file += " " + pi[x] + "," + pi[y];
- file += " " + kp[x] + "," + kp[y];
- k1 = k;
- }
- if ( spline.closed )
- {
- file += "z\"";
- }
- file += " fill=\"none\"";
- file += " stroke=\"#" + c.r.ToString("x") + c.g.ToString("x") + c.b.ToString("x") + "\"";
- file += " stroke-width=\"" + strokewidth + "\"";
- file += "/>\n";
- }
- file += "</svg>\n";
- return file;
- }
- }
|