| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451 |
- 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));
- }
- }
- }
- 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");
- }
- }
- }
|