1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Xml;
- using System.Xml.Serialization;
- using FarseerPhysics.Collision.Shapes;
- using FarseerPhysics.Dynamics;
- using FarseerPhysics.Dynamics.Joints;
- using Microsoft.Xna.Framework;
- namespace FarseerPhysics.Common
- {
- public static class WorldSerializer
- {
- public static void Serialize(World world, string filename)
- {
- using (FileStream fs = new FileStream(filename, FileMode.Create))
- {
- new WorldXmlSerializer().Serialize(world, fs);
- }
- }
- public static void Deserialize(World world, string filename)
- {
- using (FileStream fs = new FileStream(filename, FileMode.Open))
- {
- new WorldXmlDeserializer().Deserialize(world, fs);
- }
- }
- public static World Deserialize(string filename)
- {
- using (FileStream fs = new FileStream(filename, FileMode.Open))
- {
- return new WorldXmlDeserializer().Deserialize(fs);
- }
- }
- }
- ///<summary>
- ///</summary>
- public class WorldXmlSerializer
- {
- private List<Body> _bodies = new List<Body>();
- private List<Fixture> _serializedFixtures = new List<Fixture>();
- private List<Shape> _serializedShapes = new List<Shape>();
- private XmlWriter _writer;
- private void SerializeShape(Shape shape)
- {
- _writer.WriteStartElement("Shape");
- _writer.WriteAttributeString("Type", shape.ShapeType.ToString());
- switch (shape.ShapeType)
- {
- case ShapeType.Circle:
- {
- CircleShape circle = (CircleShape)shape;
- _writer.WriteElementString("Radius", circle.Radius.ToString());
- WriteElement("Position", circle.Position);
- }
- break;
- case ShapeType.Polygon:
- {
- PolygonShape poly = (PolygonShape)shape;
- _writer.WriteStartElement("Vertices");
- foreach (Vector2 v in poly.Vertices)
- WriteElement("Vertex", v);
- _writer.WriteEndElement();
- WriteElement("Centroid", poly.MassData.Centroid);
- }
- break;
- case ShapeType.Edge:
- {
- EdgeShape poly = (EdgeShape)shape;
- WriteElement("Vertex1", poly.Vertex1);
- WriteElement("Vertex2", poly.Vertex2);
- }
- break;
- default:
- throw new Exception();
- }
- _writer.WriteEndElement();
- }
- private void SerializeFixture(Fixture fixture)
- {
- _writer.WriteStartElement("Fixture");
- _writer.WriteElementString("Shape", FindShapeIndex(fixture.Shape).ToString());
- _writer.WriteElementString("Density", fixture.Shape.Density.ToString());
- _writer.WriteStartElement("FilterData");
- _writer.WriteElementString("CategoryBits", ((int)fixture.CollisionCategories).ToString());
- _writer.WriteElementString("MaskBits", ((int)fixture.CollidesWith).ToString());
- _writer.WriteElementString("GroupIndex", fixture.CollisionGroup.ToString());
- _writer.WriteEndElement();
- _writer.WriteElementString("Friction", fixture.Friction.ToString());
- _writer.WriteElementString("IsSensor", fixture.IsSensor.ToString());
- _writer.WriteElementString("Restitution", fixture.Restitution.ToString());
- if (fixture.UserData != null)
- {
- _writer.WriteStartElement("UserData");
- WriteDynamicType(fixture.UserData.GetType(), fixture.UserData);
- _writer.WriteEndElement();
- }
- _writer.WriteEndElement();
- }
- private void SerializeBody(Body body)
- {
- _writer.WriteStartElement("Body");
- _writer.WriteAttributeString("Type", body.BodyType.ToString());
- _writer.WriteElementString("Active", body.Enabled.ToString());
- _writer.WriteElementString("AllowSleep", body.SleepingAllowed.ToString());
- _writer.WriteElementString("Angle", body.Rotation.ToString());
- _writer.WriteElementString("AngularDamping", body.AngularDamping.ToString());
- _writer.WriteElementString("AngularVelocity", body.AngularVelocity.ToString());
- _writer.WriteElementString("Awake", body.Awake.ToString());
- _writer.WriteElementString("Bullet", body.IsBullet.ToString());
- _writer.WriteElementString("FixedRotation", body.FixedRotation.ToString());
- _writer.WriteElementString("LinearDamping", body.LinearDamping.ToString());
- WriteElement("LinearVelocity", body.LinearVelocity);
- WriteElement("Position", body.Position);
- if (body.UserData != null)
- {
- _writer.WriteStartElement("UserData");
- WriteDynamicType(body.UserData.GetType(), body.UserData);
- _writer.WriteEndElement();
- }
- _writer.WriteStartElement("Fixtures");
- for (int i = 0; i < body.FixtureList.Count; i++)
- {
- _writer.WriteElementString("ID", FindFixtureIndex(body.FixtureList[i]).ToString());
- }
- _writer.WriteEndElement();
- _writer.WriteEndElement();
- }
- private void SerializeJoint(Joint joint)
- {
- if (joint.IsFixedType())
- return;
- _writer.WriteStartElement("Joint");
- _writer.WriteAttributeString("Type", joint.JointType.ToString());
- WriteElement("BodyA", FindBodyIndex(joint.BodyA));
- WriteElement("BodyB", FindBodyIndex(joint.BodyB));
- WriteElement("CollideConnected", joint.CollideConnected);
- WriteElement("Breakpoint", joint.Breakpoint);
- if (joint.UserData != null)
- {
- _writer.WriteStartElement("UserData");
- WriteDynamicType(joint.UserData.GetType(), joint.UserData);
- _writer.WriteEndElement();
- }
- switch (joint.JointType)
- {
- case JointType.Distance:
- {
- DistanceJoint djd = (DistanceJoint)joint;
- WriteElement("DampingRatio", djd.DampingRatio);
- WriteElement("FrequencyHz", djd.Frequency);
- WriteElement("Length", djd.Length);
- WriteElement("LocalAnchorA", djd.LocalAnchorA);
- WriteElement("LocalAnchorB", djd.LocalAnchorB);
- }
- break;
- case JointType.Friction:
- {
- FrictionJoint fjd = (FrictionJoint)joint;
- WriteElement("LocalAnchorA", fjd.LocalAnchorA);
- WriteElement("LocalAnchorB", fjd.LocalAnchorB);
- WriteElement("MaxForce", fjd.MaxForce);
- WriteElement("MaxTorque", fjd.MaxTorque);
- }
- break;
- case JointType.Gear:
- throw new Exception("Gear joint not supported by serialization");
- case JointType.Line:
- {
- LineJoint ljd = (LineJoint)joint;
- WriteElement("EnableMotor", ljd.MotorEnabled);
- WriteElement("LocalAnchorA", ljd.LocalAnchorA);
- WriteElement("LocalAnchorB", ljd.LocalAnchorB);
- WriteElement("MotorSpeed", ljd.MotorSpeed);
- WriteElement("DampingRatio", ljd.DampingRatio);
- WriteElement("MaxMotorTorque", ljd.MaxMotorTorque);
- WriteElement("FrequencyHz", ljd.Frequency);
- WriteElement("LocalXAxis", ljd.LocalXAxis);
- }
- break;
- case JointType.Prismatic:
- {
- PrismaticJoint pjd = (PrismaticJoint)joint;
- //NOTE: Does not conform with Box2DScene
- WriteElement("EnableLimit", pjd.LimitEnabled);
- WriteElement("EnableMotor", pjd.MotorEnabled);
- WriteElement("LocalAnchorA", pjd.LocalAnchorA);
- WriteElement("LocalAnchorB", pjd.LocalAnchorB);
- WriteElement("LocalXAxis1", pjd.LocalXAxis1);
- WriteElement("LowerTranslation", pjd.LowerLimit);
- WriteElement("UpperTranslation", pjd.UpperLimit);
- WriteElement("MaxMotorForce", pjd.MaxMotorForce);
- WriteElement("MotorSpeed", pjd.MotorSpeed);
- }
- break;
- case JointType.Pulley:
- {
- PulleyJoint pjd = (PulleyJoint)joint;
- WriteElement("GroundAnchorA", pjd.GroundAnchorA);
- WriteElement("GroundAnchorB", pjd.GroundAnchorB);
- WriteElement("LengthA", pjd.LengthA);
- WriteElement("LengthB", pjd.LengthB);
- WriteElement("LocalAnchorA", pjd.LocalAnchorA);
- WriteElement("LocalAnchorB", pjd.LocalAnchorB);
- WriteElement("MaxLengthA", pjd.MaxLengthA);
- WriteElement("MaxLengthB", pjd.MaxLengthB);
- WriteElement("Ratio", pjd.Ratio);
- }
- break;
- case JointType.Revolute:
- {
- RevoluteJoint rjd = (RevoluteJoint)joint;
- WriteElement("EnableLimit", rjd.LimitEnabled);
- WriteElement("EnableMotor", rjd.MotorEnabled);
- WriteElement("LocalAnchorA", rjd.LocalAnchorA);
- WriteElement("LocalAnchorB", rjd.LocalAnchorB);
- WriteElement("LowerAngle", rjd.LowerLimit);
- WriteElement("MaxMotorTorque", rjd.MaxMotorTorque);
- WriteElement("MotorSpeed", rjd.MotorSpeed);
- WriteElement("ReferenceAngle", rjd.ReferenceAngle);
- WriteElement("UpperAngle", rjd.UpperLimit);
- }
- break;
- case JointType.Weld:
- {
- WeldJoint wjd = (WeldJoint)joint;
- WriteElement("LocalAnchorA", wjd.LocalAnchorA);
- WriteElement("LocalAnchorB", wjd.LocalAnchorB);
- }
- break;
- //
- // Not part of Box2DScene
- //
- case JointType.Rope:
- {
- RopeJoint rjd = (RopeJoint)joint;
- WriteElement("LocalAnchorA", rjd.LocalAnchorA);
- WriteElement("LocalAnchorB", rjd.LocalAnchorB);
- WriteElement("MaxLength", rjd.MaxLength);
- }
- break;
- case JointType.Angle:
- {
- AngleJoint aj = (AngleJoint)joint;
- WriteElement("BiasFactor", aj.BiasFactor);
- WriteElement("MaxImpulse", aj.MaxImpulse);
- WriteElement("Softness", aj.Softness);
- WriteElement("TargetAngle", aj.TargetAngle);
- }
- break;
- case JointType.Slider:
- {
- SliderJoint sliderJoint = (SliderJoint)joint;
- WriteElement("DampingRatio", sliderJoint.DampingRatio);
- WriteElement("FrequencyHz", sliderJoint.Frequency);
- WriteElement("MaxLength", sliderJoint.MaxLength);
- WriteElement("MinLength", sliderJoint.MinLength);
- WriteElement("LocalAnchorA", sliderJoint.LocalAnchorA);
- WriteElement("LocalAnchorB", sliderJoint.LocalAnchorB);
- }
- break;
- default:
- throw new Exception("Joint not supported");
- }
- _writer.WriteEndElement();
- }
- private void WriteDynamicType(Type type, object val)
- {
- _writer.WriteElementString("Type", type.FullName);
- _writer.WriteStartElement("Value");
- XmlSerializer serializer = new XmlSerializer(type);
- XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
- xmlnsEmpty.Add("", "");
- serializer.Serialize(_writer, val, xmlnsEmpty);
- _writer.WriteEndElement();
- }
- private void WriteElement(string name, Vector2 vec)
- {
- _writer.WriteElementString(name, vec.X + " " + vec.Y);
- }
- private void WriteElement(string name, int val)
- {
- _writer.WriteElementString(name, val.ToString());
- }
- private void WriteElement(string name, bool val)
- {
- _writer.WriteElementString(name, val.ToString());
- }
- private void WriteElement(string name, float val)
- {
- _writer.WriteElementString(name, val.ToString());
- }
- public void Serialize(World world, Stream stream)
- {
- XmlWriterSettings settings = new XmlWriterSettings();
- settings.Indent = true;
- settings.NewLineOnAttributes = false;
- settings.OmitXmlDeclaration = true;
- _writer = XmlWriter.Create(stream, settings);
- _writer.WriteStartElement("World");
- _writer.WriteAttributeString("Version", "2");
- WriteElement("Gravity", world.Gravity);
- _writer.WriteStartElement("Shapes");
- for (int i = 0; i < world.BodyList.Count; i++)
- {
- Body body = world.BodyList[i];
- for (int j = 0; j < body.FixtureList.Count; j++)
- {
- Fixture fixture = body.FixtureList[j];
- bool alreadyThere = false;
- for (int k = 0; k < _serializedShapes.Count; k++)
- {
- Shape s2 = _serializedShapes[k];
- if (fixture.Shape.CompareTo(s2))
- {
- alreadyThere = true;
- break;
- }
- }
- if (!alreadyThere)
- {
- SerializeShape(fixture.Shape);
- _serializedShapes.Add(fixture.Shape);
- }
- }
- }
- _writer.WriteEndElement();
- _writer.WriteStartElement("Fixtures");
- for (int i = 0; i < world.BodyList.Count; i++)
- {
- Body body = world.BodyList[i];
- for (int j = 0; j < body.FixtureList.Count; j++)
- {
- Fixture fixture = body.FixtureList[j];
- bool alreadyThere = false;
- for (int k = 0; k < _serializedFixtures.Count; k++)
- {
- Fixture f2 = _serializedFixtures[k];
- if (fixture.CompareTo(f2))
- {
- alreadyThere = true;
- break;
- }
- }
- if (!alreadyThere)
- {
- SerializeFixture(fixture);
- _serializedFixtures.Add(fixture);
- }
- }
- }
- _writer.WriteEndElement();
- _writer.WriteStartElement("Bodies");
- for (int i = 0; i < world.BodyList.Count; i++)
- {
- Body body = world.BodyList[i];
- _bodies.Add(body);
- SerializeBody(body);
- }
- _writer.WriteEndElement();
- _writer.WriteStartElement("Joints");
- for (int i = 0; i < world.JointList.Count; i++)
- {
- Joint joint = world.JointList[i];
- SerializeJoint(joint);
- }
- _writer.WriteEndElement();
- _writer.WriteEndElement();
- _writer.Flush();
- _writer.Close();
- }
- private int FindBodyIndex(Body body)
- {
- for (int i = 0; i < _bodies.Count; ++i)
- if (_bodies[i] == body)
- return i;
- return -1;
- }
- private int FindFixtureIndex(Fixture fixture)
- {
- for (int i = 0; i < _serializedFixtures.Count; ++i)
- {
- if (_serializedFixtures[i].CompareTo(fixture))
- return i;
- }
- return -1;
- }
- private int FindShapeIndex(Shape shape)
- {
- for (int i = 0; i < _serializedShapes.Count; ++i)
- {
- if (_serializedShapes[i].CompareTo(shape))
- return i;
- }
- return -1;
- }
- }
- public class WorldXmlDeserializer
- {
- private List<Body> _bodies = new List<Body>();
- private List<Fixture> _fixtures = new List<Fixture>();
- private List<Joint> _joints = new List<Joint>();
- private List<Shape> _shapes = new List<Shape>();
- public World Deserialize(Stream stream)
- {
- World world = new World(Vector2.Zero);
- Deserialize(world, stream);
- return world;
- }
- public void Deserialize(World world, Stream stream)
- {
- world.Clear();
- XMLFragmentElement root = XMLFragmentParser.LoadFromStream(stream);
- if (root.Name.ToLower() != "world")
- throw new Exception();
- foreach (XMLFragmentElement main in root.Elements)
- {
- if (main.Name.ToLower() == "gravity")
- {
- world.Gravity = ReadVector(main);
- }
- }
- foreach (XMLFragmentElement shapeElement in root.Elements)
- {
- if (shapeElement.Name.ToLower() == "shapes")
- {
- foreach (XMLFragmentElement n in shapeElement.Elements)
- {
- if (n.Name.ToLower() != "shape")
- throw new Exception();
- ShapeType type = (ShapeType)Enum.Parse(typeof(ShapeType), n.Attributes[0].Value, true);
- switch (type)
- {
- case ShapeType.Circle:
- {
- CircleShape shape = new CircleShape();
- foreach (XMLFragmentElement sn in n.Elements)
- {
- switch (sn.Name.ToLower())
- {
- case "radius":
- shape.Radius = float.Parse(sn.Value);
- break;
- case "position":
- shape.Position = ReadVector(sn);
- break;
- default:
- throw new Exception();
- }
- }
- _shapes.Add(shape);
- }
- break;
- case ShapeType.Polygon:
- {
- PolygonShape shape = new PolygonShape();
- foreach (XMLFragmentElement sn in n.Elements)
- {
- switch (sn.Name.ToLower())
- {
- case "vertices":
- {
- List<Vector2> verts = new List<Vector2>();
- foreach (XMLFragmentElement vert in sn.Elements)
- verts.Add(ReadVector(vert));
- shape.Set(new Vertices(verts.ToArray()));
- }
- break;
- case "centroid":
- shape.MassData.Centroid = ReadVector(sn);
- break;
- }
- }
- _shapes.Add(shape);
- }
- break;
- case ShapeType.Edge:
- {
- EdgeShape shape = new EdgeShape();
- foreach (XMLFragmentElement sn in n.Elements)
- {
- switch (sn.Name.ToLower())
- {
- case "hasvertex0":
- shape.HasVertex0 = bool.Parse(sn.Value);
- break;
- case "hasvertex3":
- shape.HasVertex0 = bool.Parse(sn.Value);
- break;
- case "vertex0":
- shape.Vertex0 = ReadVector(sn);
- break;
- case "vertex1":
- shape.Vertex1 = ReadVector(sn);
- break;
- case "vertex2":
- shape.Vertex2 = ReadVector(sn);
- break;
- case "vertex3":
- shape.Vertex3 = ReadVector(sn);
- break;
- default:
- throw new Exception();
- }
- }
- _shapes.Add(shape);
- }
- break;
- }
- }
- }
- }
- foreach (XMLFragmentElement fixtureElement in root.Elements)
- {
- if (fixtureElement.Name.ToLower() == "fixtures")
- {
- foreach (XMLFragmentElement n in fixtureElement.Elements)
- {
- Fixture fixture = new Fixture();
- if (n.Name.ToLower() != "fixture")
- throw new Exception();
- foreach (XMLFragmentElement sn in n.Elements)
- {
- switch (sn.Name.ToLower())
- {
- case "shape":
- fixture.Shape = _shapes[int.Parse(sn.Value)];
- break;
- case "density":
- fixture.Shape.Density = float.Parse(sn.Value);
- break;
- case "filterdata":
- foreach (XMLFragmentElement ssn in sn.Elements)
- {
- switch (ssn.Name.ToLower())
- {
- case "categorybits":
- fixture._collisionCategories = (Category)int.Parse(ssn.Value);
- break;
- case "maskbits":
- fixture._collidesWith = (Category)int.Parse(ssn.Value);
- break;
- case "groupindex":
- fixture._collisionGroup = short.Parse(ssn.Value);
- break;
- }
- }
- break;
- case "friction":
- fixture.Friction = float.Parse(sn.Value);
- break;
- case "issensor":
- fixture.IsSensor = bool.Parse(sn.Value);
- break;
- case "restitution":
- fixture.Restitution = float.Parse(sn.Value);
- break;
- case "userdata":
- fixture.UserData = ReadSimpleType(sn, null, false);
- break;
- }
- }
- _fixtures.Add(fixture);
- }
- }
- }
- foreach (XMLFragmentElement bodyElement in root.Elements)
- {
- if (bodyElement.Name.ToLower() == "bodies")
- {
- foreach (XMLFragmentElement n in bodyElement.Elements)
- {
- Body body = new Body(world);
- if (n.Name.ToLower() != "body")
- throw new Exception();
- body.BodyType = (BodyType)Enum.Parse(typeof(BodyType), n.Attributes[0].Value, true);
- foreach (XMLFragmentElement sn in n.Elements)
- {
- switch (sn.Name.ToLower())
- {
- case "active":
- if (bool.Parse(sn.Value))
- body.Flags |= BodyFlags.Enabled;
- else
- body.Flags &= ~BodyFlags.Enabled;
- break;
- case "allowsleep":
- body.SleepingAllowed = bool.Parse(sn.Value);
- break;
- case "angle":
- {
- Vector2 position = body.Position;
- body.SetTransformIgnoreContacts(ref position, float.Parse(sn.Value));
- }
- break;
- case "angulardamping":
- body.AngularDamping = float.Parse(sn.Value);
- break;
- case "angularvelocity":
- body.AngularVelocity = float.Parse(sn.Value);
- break;
- case "awake":
- body.Awake = bool.Parse(sn.Value);
- break;
- case "bullet":
- body.IsBullet = bool.Parse(sn.Value);
- break;
- case "fixedrotation":
- body.FixedRotation = bool.Parse(sn.Value);
- break;
- case "lineardamping":
- body.LinearDamping = float.Parse(sn.Value);
- break;
- case "linearvelocity":
- body.LinearVelocity = ReadVector(sn);
- break;
- case "position":
- {
- float rotation = body.Rotation;
- Vector2 position = ReadVector(sn);
- body.SetTransformIgnoreContacts(ref position, rotation);
- }
- break;
- case "userdata":
- body.UserData = ReadSimpleType(sn, null, false);
- break;
- case "fixtures":
- {
- foreach (XMLFragmentElement v in sn.Elements)
- {
- Fixture blueprint = _fixtures[int.Parse(v.Value)];
- Fixture f = new Fixture(body, blueprint.Shape);
- f.Restitution = blueprint.Restitution;
- f.UserData = blueprint.UserData;
- f.Friction = blueprint.Friction;
- f.CollidesWith = blueprint.CollidesWith;
- f.CollisionCategories = blueprint.CollisionCategories;
- f.CollisionGroup = blueprint.CollisionGroup;
- }
- break;
- }
- }
- }
- _bodies.Add(body);
- }
- }
- }
- foreach (XMLFragmentElement jointElement in root.Elements)
- {
- if (jointElement.Name.ToLower() == "joints")
- {
- foreach (XMLFragmentElement n in jointElement.Elements)
- {
- Joint joint;
- if (n.Name.ToLower() != "joint")
- throw new Exception();
- JointType type = (JointType)Enum.Parse(typeof(JointType), n.Attributes[0].Value, true);
- int bodyAIndex = -1, bodyBIndex = -1;
- bool collideConnected = false;
- object userData = null;
- foreach (XMLFragmentElement sn in n.Elements)
- {
- switch (sn.Name.ToLower())
- {
- case "bodya":
- bodyAIndex = int.Parse(sn.Value);
- break;
- case "bodyb":
- bodyBIndex = int.Parse(sn.Value);
- break;
- case "collideconnected":
- collideConnected = bool.Parse(sn.Value);
- break;
- case "userdata":
- userData = ReadSimpleType(sn, null, false);
- break;
- }
- }
- Body bodyA = _bodies[bodyAIndex];
- Body bodyB = _bodies[bodyBIndex];
- switch (type)
- {
- case JointType.Distance:
- joint = new DistanceJoint();
- break;
- case JointType.Friction:
- joint = new FrictionJoint();
- break;
- case JointType.Line:
- joint = new LineJoint();
- break;
- case JointType.Prismatic:
- joint = new PrismaticJoint();
- break;
- case JointType.Pulley:
- joint = new PulleyJoint();
- break;
- case JointType.Revolute:
- joint = new RevoluteJoint();
- break;
- case JointType.Weld:
- joint = new WeldJoint();
- break;
- case JointType.Rope:
- joint = new RopeJoint();
- break;
- case JointType.Angle:
- joint = new AngleJoint();
- break;
- case JointType.Slider:
- joint = new SliderJoint();
- break;
- case JointType.Gear:
- throw new Exception("GearJoint is not supported.");
- default:
- throw new Exception("Invalid or unsupported joint.");
- }
- joint.CollideConnected = collideConnected;
- joint.UserData = userData;
- joint.BodyA = bodyA;
- joint.BodyB = bodyB;
- _joints.Add(joint);
- world.AddJoint(joint);
- foreach (XMLFragmentElement sn in n.Elements)
- {
- // check for specific nodes
- switch (type)
- {
- case JointType.Distance:
- {
- switch (sn.Name.ToLower())
- {
- case "dampingratio":
- ((DistanceJoint)joint).DampingRatio = float.Parse(sn.Value);
- break;
- case "frequencyhz":
- ((DistanceJoint)joint).Frequency = float.Parse(sn.Value);
- break;
- case "length":
- ((DistanceJoint)joint).Length = float.Parse(sn.Value);
- break;
- case "localanchora":
- ((DistanceJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((DistanceJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- }
- }
- break;
- case JointType.Friction:
- {
- switch (sn.Name.ToLower())
- {
- case "localanchora":
- ((FrictionJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((FrictionJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- case "maxforce":
- ((FrictionJoint)joint).MaxForce = float.Parse(sn.Value);
- break;
- case "maxtorque":
- ((FrictionJoint)joint).MaxTorque = float.Parse(sn.Value);
- break;
- }
- }
- break;
- case JointType.Line:
- {
- switch (sn.Name.ToLower())
- {
- case "enablemotor":
- ((LineJoint)joint).MotorEnabled = bool.Parse(sn.Value);
- break;
- case "localanchora":
- ((LineJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((LineJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- case "motorspeed":
- ((LineJoint)joint).MotorSpeed = float.Parse(sn.Value);
- break;
- case "dampingratio":
- ((LineJoint)joint).DampingRatio = float.Parse(sn.Value);
- break;
- case "maxmotortorque":
- ((LineJoint)joint).MaxMotorTorque = float.Parse(sn.Value);
- break;
- case "frequencyhz":
- ((LineJoint)joint).Frequency = float.Parse(sn.Value);
- break;
- case "localxaxis":
- ((LineJoint)joint).LocalXAxis = ReadVector(sn);
- break;
- }
- }
- break;
- case JointType.Prismatic:
- {
- switch (sn.Name.ToLower())
- {
- case "enablelimit":
- ((PrismaticJoint)joint).LimitEnabled = bool.Parse(sn.Value);
- break;
- case "enablemotor":
- ((PrismaticJoint)joint).MotorEnabled = bool.Parse(sn.Value);
- break;
- case "localanchora":
- ((PrismaticJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((PrismaticJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- case "local1axis1":
- ((PrismaticJoint)joint).LocalXAxis1 = ReadVector(sn);
- break;
- case "maxmotorforce":
- ((PrismaticJoint)joint).MaxMotorForce = float.Parse(sn.Value);
- break;
- case "motorspeed":
- ((PrismaticJoint)joint).MotorSpeed = float.Parse(sn.Value);
- break;
- case "lowertranslation":
- ((PrismaticJoint)joint).LowerLimit = float.Parse(sn.Value);
- break;
- case "uppertranslation":
- ((PrismaticJoint)joint).UpperLimit = float.Parse(sn.Value);
- break;
- case "referenceangle":
- ((PrismaticJoint)joint).ReferenceAngle = float.Parse(sn.Value);
- break;
- }
- }
- break;
- case JointType.Pulley:
- {
- switch (sn.Name.ToLower())
- {
- case "groundanchora":
- ((PulleyJoint)joint).GroundAnchorA = ReadVector(sn);
- break;
- case "groundanchorb":
- ((PulleyJoint)joint).GroundAnchorB = ReadVector(sn);
- break;
- case "lengtha":
- ((PulleyJoint)joint).LengthA = float.Parse(sn.Value);
- break;
- case "lengthb":
- ((PulleyJoint)joint).LengthB = float.Parse(sn.Value);
- break;
- case "localanchora":
- ((PulleyJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((PulleyJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- case "maxlengtha":
- ((PulleyJoint)joint).MaxLengthA = float.Parse(sn.Value);
- break;
- case "maxlengthb":
- ((PulleyJoint)joint).MaxLengthB = float.Parse(sn.Value);
- break;
- case "ratio":
- ((PulleyJoint)joint).Ratio = float.Parse(sn.Value);
- break;
- }
- }
- break;
- case JointType.Revolute:
- {
- switch (sn.Name.ToLower())
- {
- case "enablelimit":
- ((RevoluteJoint)joint).LimitEnabled = bool.Parse(sn.Value);
- break;
- case "enablemotor":
- ((RevoluteJoint)joint).MotorEnabled = bool.Parse(sn.Value);
- break;
- case "localanchora":
- ((RevoluteJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((RevoluteJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- case "maxmotortorque":
- ((RevoluteJoint)joint).MaxMotorTorque = float.Parse(sn.Value);
- break;
- case "motorspeed":
- ((RevoluteJoint)joint).MotorSpeed = float.Parse(sn.Value);
- break;
- case "lowerangle":
- ((RevoluteJoint)joint).LowerLimit = float.Parse(sn.Value);
- break;
- case "upperangle":
- ((RevoluteJoint)joint).UpperLimit = float.Parse(sn.Value);
- break;
- case "referenceangle":
- ((RevoluteJoint)joint).ReferenceAngle = float.Parse(sn.Value);
- break;
- }
- }
- break;
- case JointType.Weld:
- {
- switch (sn.Name.ToLower())
- {
- case "localanchora":
- ((WeldJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((WeldJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- }
- }
- break;
- case JointType.Rope:
- {
- switch (sn.Name.ToLower())
- {
- case "localanchora":
- ((RopeJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((RopeJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- case "maxlength":
- ((RopeJoint)joint).MaxLength = float.Parse(sn.Value);
- break;
- }
- }
- break;
- case JointType.Gear:
- throw new Exception("Gear joint is unsupported");
- case JointType.Angle:
- {
- switch (sn.Name.ToLower())
- {
- case "biasfactor":
- ((AngleJoint)joint).BiasFactor = float.Parse(sn.Value);
- break;
- case "maximpulse":
- ((AngleJoint)joint).MaxImpulse = float.Parse(sn.Value);
- break;
- case "softness":
- ((AngleJoint)joint).Softness = float.Parse(sn.Value);
- break;
- case "targetangle":
- ((AngleJoint)joint).TargetAngle = float.Parse(sn.Value);
- break;
- }
- }
- break;
- case JointType.Slider:
- {
- switch (sn.Name.ToLower())
- {
- case "dampingratio":
- ((SliderJoint)joint).DampingRatio = float.Parse(sn.Value);
- break;
- case "frequencyhz":
- ((SliderJoint)joint).Frequency = float.Parse(sn.Value);
- break;
- case "maxlength":
- ((SliderJoint)joint).MaxLength = float.Parse(sn.Value);
- break;
- case "minlength":
- ((SliderJoint)joint).MinLength = float.Parse(sn.Value);
- break;
- case "localanchora":
- ((SliderJoint)joint).LocalAnchorA = ReadVector(sn);
- break;
- case "localanchorb":
- ((SliderJoint)joint).LocalAnchorB = ReadVector(sn);
- break;
- }
- }
- break;
- }
- }
- }
- }
- }
- }
- private Vector2 ReadVector(XMLFragmentElement node)
- {
- string[] values = node.Value.Split(' ');
- return new Vector2(float.Parse(values[0]), float.Parse(values[1]));
- }
- private object ReadSimpleType(XMLFragmentElement node, Type type, bool outer)
- {
- if (type == null)
- return ReadSimpleType(node.Elements[1], Type.GetType(node.Elements[0].Value), outer);
- XmlSerializer serializer = new XmlSerializer(type);
- XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
- xmlnsEmpty.Add("", "");
- using (MemoryStream stream = new MemoryStream())
- {
- StreamWriter writer = new StreamWriter(stream);
- {
- writer.Write((outer) ? node.OuterXml : node.InnerXml);
- writer.Flush();
- stream.Position = 0;
- }
- XmlReaderSettings settings = new XmlReaderSettings();
- settings.ConformanceLevel = ConformanceLevel.Fragment;
- return serializer.Deserialize(XmlReader.Create(stream, settings));
- }
- }
- }
- #region XMLFragment
- public class XMLFragmentAttribute
- {
- public string Name { get; set; }
- public string Value { get; set; }
- }
- public class XMLFragmentElement
- {
- private List<XMLFragmentAttribute> _attributes = new List<XMLFragmentAttribute>();
- private List<XMLFragmentElement> _elements = new List<XMLFragmentElement>();
- public IList<XMLFragmentElement> Elements
- {
- get { return _elements; }
- }
- public IList<XMLFragmentAttribute> Attributes
- {
- get { return _attributes; }
- }
- public string Name { get; set; }
- public string Value { get; set; }
- public string OuterXml { get; set; }
- public string InnerXml { get; set; }
- }
- public class XMLFragmentException : Exception
- {
- public XMLFragmentException()
- {
- }
- public XMLFragmentException(string message)
- : base(message)
- {
- }
- public XMLFragmentException(string message, Exception inner)
- : base(message, inner)
- {
- }
- }
- public class FileBuffer
- {
- public FileBuffer(Stream stream)
- {
- using (StreamReader sr = new StreamReader(stream))
- Buffer = sr.ReadToEnd();
- Position = 0;
- }
- public string Buffer { get; set; }
- public int Position { get; set; }
- public int Length
- {
- get { return Buffer.Length; }
- }
- public char Next
- {
- get
- {
- char c = Buffer[Position];
- Position++;
- return c;
- }
- }
- public char Peek
- {
- get { return Buffer[Position]; }
- }
- public bool EndOfBuffer
- {
- get { return Position == Length; }
- }
- }
- public class XMLFragmentParser
- {
- private static List<char> _punctuation = new List<char> { '/', '<', '>', '=' };
- private FileBuffer _buffer;
- private XMLFragmentElement _rootNode;
- public XMLFragmentParser(Stream stream)
- {
- Load(stream);
- }
- public XMLFragmentParser(string fileName)
- {
- using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
- Load(fs);
- }
- public XMLFragmentElement RootNode
- {
- get { return _rootNode; }
- }
- public void Load(Stream stream)
- {
- _buffer = new FileBuffer(stream);
- }
- public static XMLFragmentElement LoadFromFile(string fileName)
- {
- XMLFragmentParser x = new XMLFragmentParser(fileName);
- x.Parse();
- return x.RootNode;
- }
- public static XMLFragmentElement LoadFromStream(Stream stream)
- {
- XMLFragmentParser x = new XMLFragmentParser(stream);
- x.Parse();
- return x.RootNode;
- }
- private string NextToken()
- {
- string str = "";
- bool _done = false;
- while (true)
- {
- char c = _buffer.Next;
- if (_punctuation.Contains(c))
- {
- if (str != "")
- {
- _buffer.Position--;
- break;
- }
- _done = true;
- }
- else if (char.IsWhiteSpace(c))
- {
- if (str != "")
- break;
- else
- continue;
- }
- str += c;
- if (_done)
- break;
- }
- str = TrimControl(str);
- // Trim quotes from start and end
- if (str[0] == '\"')
- str = str.Remove(0, 1);
- if (str[str.Length - 1] == '\"')
- str = str.Remove(str.Length - 1, 1);
- return str;
- }
- private string PeekToken()
- {
- int oldPos = _buffer.Position;
- string str = NextToken();
- _buffer.Position = oldPos;
- return str;
- }
- private string ReadUntil(char c)
- {
- string str = "";
- while (true)
- {
- char ch = _buffer.Next;
- if (ch == c)
- {
- _buffer.Position--;
- break;
- }
- str += ch;
- }
- // Trim quotes from start and end
- if (str[0] == '\"')
- str = str.Remove(0, 1);
- if (str[str.Length - 1] == '\"')
- str = str.Remove(str.Length - 1, 1);
- return str;
- }
- private string TrimControl(string str)
- {
- string newStr = str;
- // Trim control characters
- int i = 0;
- while (true)
- {
- if (i == newStr.Length)
- break;
- if (char.IsControl(newStr[i]))
- newStr = newStr.Remove(i, 1);
- else
- i++;
- }
- return newStr;
- }
- private string TrimTags(string outer)
- {
- int start = outer.IndexOf('>') + 1;
- int end = outer.LastIndexOf('<');
- return TrimControl(outer.Substring(start, end - start));
- }
- public XMLFragmentElement TryParseNode()
- {
- if (_buffer.EndOfBuffer)
- return null;
- int startOuterXml = _buffer.Position;
- string token = NextToken();
- if (token != "<")
- throw new XMLFragmentException("Expected \"<\", got " + token);
- XMLFragmentElement element = new XMLFragmentElement();
- element.Name = NextToken();
- while (true)
- {
- token = NextToken();
- if (token == ">")
- break;
- else if (token == "/") // quick-exit case
- {
- NextToken();
- element.OuterXml =
- TrimControl(_buffer.Buffer.Substring(startOuterXml, _buffer.Position - startOuterXml)).Trim();
- element.InnerXml = "";
- return element;
- }
- else
- {
- XMLFragmentAttribute attribute = new XMLFragmentAttribute();
- attribute.Name = token;
- if ((token = NextToken()) != "=")
- throw new XMLFragmentException("Expected \"=\", got " + token);
- attribute.Value = NextToken();
- element.Attributes.Add(attribute);
- }
- }
- while (true)
- {
- int oldPos = _buffer.Position; // for restoration below
- token = NextToken();
- if (token == "<")
- {
- token = PeekToken();
- if (token == "/") // finish element
- {
- NextToken(); // skip the / again
- token = NextToken();
- NextToken(); // skip >
- element.OuterXml =
- TrimControl(_buffer.Buffer.Substring(startOuterXml, _buffer.Position - startOuterXml)).Trim();
- element.InnerXml = TrimTags(element.OuterXml);
- if (token != element.Name)
- throw new XMLFragmentException("Mismatched element pairs: \"" + element.Name + "\" vs \"" +
- token + "\"");
- break;
- }
- else
- {
- _buffer.Position = oldPos;
- element.Elements.Add(TryParseNode());
- }
- }
- else
- {
- // value, probably
- _buffer.Position = oldPos;
- element.Value = ReadUntil('<');
- }
- }
- return element;
- }
- public void Parse()
- {
- _rootNode = TryParseNode();
- if (_rootNode == null)
- throw new XMLFragmentException("Unable to load root node");
- }
- }
- #endregion
- }
|