Beispiel #1
0
        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 DrawJoint(Joint joint)
        {
            if (!joint.Enabled)
                return;

            Body b1 = joint.BodyA;
            Body b2 = joint.BodyB;
            Transform xf1;
            b1.GetTransform(out xf1);

            Vector2 x2 = Vector2.Zero;

            // WIP David
            if (!joint.IsFixedType())
            {
                Transform xf2;
                b2.GetTransform(out xf2);
                x2 = xf2.p;
            }

            Vector2 p1 = joint.WorldAnchorA;
            Vector2 p2 = joint.WorldAnchorB;
            Vector2 x1 = xf1.p;

            Color color = Color.FromArgb(255, 128, 205, 205);

            switch (joint.JointType)
            {
                case JointType.Distance:
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.Pulley:
                    PulleyJoint pulley = (PulleyJoint)joint;
                    Vector2 s1 = b1.GetWorldPoint(pulley.LocalAnchorA);
                    Vector2 s2 = b2.GetWorldPoint(pulley.LocalAnchorB);
                    DrawSegment(p1, p2, color);
                    DrawSegment(p1, s1, color);
                    DrawSegment(p2, s2, color);
                    break;
                case JointType.FixedMouse:
                    DrawPoint(p1, 0.5f, Color.FromArgb(255, 0, 255, 0));
                    DrawSegment(p1, p2, Color.FromArgb(255, 205, 205, 205));
                    break;
                case JointType.Revolute:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    DrawSegment(x2, p2, color);

                    DrawSolidCircle(p2, 0.1f, Vector2.Zero, Colors.Red);
                    DrawSolidCircle(p1, 0.1f, Vector2.Zero, Colors.Blue);
                    break;
                case JointType.FixedAngle:
                    //Should not draw anything.
                    break;
                case JointType.FixedRevolute:
                    DrawSegment(x1, p1, color);
                    DrawSolidCircle(p1, 0.1f, Vector2.Zero, Colors.Purple);
                    break;
                case JointType.FixedLine:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.FixedDistance:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.FixedPrismatic:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.Gear:
                    DrawSegment(x1, x2, color);
                    break;
                default:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    DrawSegment(x2, p2, color);
                    break;
            }
        }
        private void DrawJoint(Joint joint)
        {
            Body b1 = joint.BodyA;
            Body b2 = joint.BodyB;
            Transform xf1, xf2;
            b1.GetTransform(out xf1);

            Vector2 x2 = new Vector2();

            // WIP David
            if (!joint.IsFixedType())
            {
                b2.GetTransform(out xf2);
                x2 = xf2.Position;
            }
            Vector2 p2 = joint.WorldAnchorB;

            Vector2 x1 = xf1.Position;

            Vector2 p1 = joint.WorldAnchorA;

            Color color = new Color(0.5f, 0.8f, 0.8f);

            switch (joint.JointType)
            {
                case JointType.Distance:
                    DrawSegment(p1, p2, color);
                    break;

                case JointType.Pulley:
                    {
                        PulleyJoint pulley = (PulleyJoint) joint;
                        Vector2 s1 = pulley.GroundAnchorA;
                        Vector2 s2 = pulley.GroundAnchorB;
                        DrawSegment(s1, p1, color);
                        DrawSegment(s2, p2, color);
                        DrawSegment(s1, s2, color);
                    }
                    break;

                case JointType.FixedMouse:

                    FixedMouseJoint fixedMouseJoint = (FixedMouseJoint) joint;
                    p1 = fixedMouseJoint.Target;

                    DrawPoint(p2, 0.5f, new Color(0.0f, 1.0f, 0.0f));
                    DrawSegment(p1, p2, new Color(0.8f, 0.8f, 0.8f));
                    break;
                case JointType.Revolute:
                    //DrawSegment(x2, p1, color);
                    DrawSegment(p2, p1, color);
                    DrawSolidCircle(p2, 0.1f, new Vector2(), Color.Red);
                    DrawSolidCircle(p1, 0.1f, new Vector2(), Color.Blue);
                    break;
                case JointType.FixedRevolute:
                    DrawSolidCircle(p1, 0.1f, new Vector2(), Color.Pink);
                    break;
                case JointType.FixedLine:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.FixedDistance:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.FixedPrismatic:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.Gear:
                    DrawSegment(x1, x2, color);
                    //DrawSegment(x1, p1, color);
                    //DrawSegment(p1, p2, color);
                    break;
                default:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    DrawSegment(x2, p2, color);
                    break;
            }
        }
        private void DrawJoint(Joint joint)
        {
            Body b1 = joint.BodyA;
            Body b2 = joint.BodyB;
            Transform xf1, xf2;
            b1.GetTransform(out xf1);

            Vector2 x2 = new Vector2();

            // WIP David
            if (!joint.IsFixedType())
            {
                b2.GetTransform(out xf2);
                x2 = xf2.p;
            }
            Vector2 p2 = joint.WorldAnchorB;

            Vector2 x1 = xf1.p;

            Vector2 p1 = joint.WorldAnchorA;

            Color color = Color.FromArgb(255, 128, 205, 205);

            switch (joint.JointType)
            {
                case JointType.Distance:
                    DrawSegment(p1, p2, color);
                    break;

                case JointType.Pulley:
                    {
                        PulleyJoint pulley = (PulleyJoint)joint;
                        Vector2 s1 = pulley.GroundAnchorA;
                        Vector2 s2 = pulley.GroundAnchorB;
                        DrawSegment(s1, p1, color);
                        DrawSegment(s2, p2, color);
                        DrawSegment(s1, s2, color);
                    }
                    break;

                case JointType.FixedMouse:
                    DrawPoint(p1, 0.5f, Color.FromArgb(255, 0, 255, 0));
                    DrawSegment(p1, p2, Color.FromArgb(255, 205, 205, 205));
                    break;
                case JointType.Revolute:
                    //DrawSegment(x2, p1, color);
                    DrawSegment(p2, p1, color);
                    DrawSolidCircle(p2, 0.1f, new Vector2(), Colors.Red);
                    DrawSolidCircle(p1, 0.1f, new Vector2(), Colors.Blue);
                    break;
                case JointType.FixedRevolute:
                    DrawSolidCircle(p1, 0.1f, new Vector2(), Colors.Purple);
                    break;
                case JointType.FixedLine:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.FixedDistance:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.FixedPrismatic:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    break;
                case JointType.Gear:
                    DrawSegment(x1, x2, color);
                    //DrawSegment(x1, p1, color);
                    //DrawSegment(p1, p2, color);
                    break;
                default:
                    DrawSegment(x1, p1, color);
                    DrawSegment(p1, p2, color);
                    DrawSegment(x2, p2, color);
                    break;
            }
        }
        /// <summary>
        /// Destroy a joint. This may cause the connected bodies to begin colliding.
        /// Warning: This function is locked during callbacks.
        /// </summary>
        /// <param name="joint">The joint.</param>
        public void RemoveJoint(Joint joint)
        {
            Debug.Assert(!IsLocked);
            if (IsLocked)
            {
                return;
            }

            bool collideConnected = joint.CollideConnected;

            // Remove from the world list.
            JointList.Remove(joint);

            // Disconnect from island graph.
            Body bodyA = joint.BodyA;
            Body bodyB = joint.BodyB;

            // Wake up connected bodies.
            bodyA.Awake = true;

            // WIP David
            if (!joint.IsFixedType())
            {
                bodyB.Awake = true;
            }

            // Remove from body 1.
            if (joint.EdgeA.Prev != null)
            {
                joint.EdgeA.Prev.Next = joint.EdgeA.Next;
            }

            if (joint.EdgeA.Next != null)
            {
                joint.EdgeA.Next.Prev = joint.EdgeA.Prev;
            }

            if (joint.EdgeA == bodyA.JointList)
            {
                bodyA.JointList = joint.EdgeA.Next;
            }

            joint.EdgeA.Prev = null;
            joint.EdgeA.Next = null;

            // WIP David
            if (!joint.IsFixedType())
            {
                // Remove from body 2
                if (joint.EdgeB.Prev != null)
                {
                    joint.EdgeB.Prev.Next = joint.EdgeB.Next;
                }

                if (joint.EdgeB.Next != null)
                {
                    joint.EdgeB.Next.Prev = joint.EdgeB.Prev;
                }

                if (joint.EdgeB == bodyB.JointList)
                {
                    bodyB.JointList = joint.EdgeB.Next;
                }

                joint.EdgeB.Prev = null;
                joint.EdgeB.Next = null;
            }

            // WIP David
            if (!joint.IsFixedType())
            {
                // If the joint prevents collisions, then flag any contacts for filtering.
                if (collideConnected == false)
                {
                    ContactEdge edge = bodyB.ContactList;
                    while (edge != null)
                    {
                        if (edge.Other == bodyA)
                        {
                            // Flag the contact for filtering at the next time step (where either
                            // body is awake).
                            edge.Contact.FlagForFiltering();
                        }

                        edge = edge.Next;
                    }
                }
            }

            if (JointRemoved != null)
            {
                JointRemoved(joint);
            }
        }
        /// <summary>
        /// Create a joint to constrain bodies together. This may cause the connected bodies to cease colliding.
        /// Warning: This function is locked during callbacks.
        /// </summary>
        /// <param name="joint">The joint.</param>
        public void AddJoint(Joint joint)
        {
            Debug.Assert(!IsLocked);
            if (IsLocked)
            {
                return;
            }

            // Connect to the world list.
            JointList.Add(joint);

            // Connect to the bodies' doubly linked lists.
            joint.EdgeA.Joint = joint;
            joint.EdgeA.Other = joint.BodyB;
            joint.EdgeA.Prev = null;
            joint.EdgeA.Next = joint.BodyA.JointList;

            if (joint.BodyA.JointList != null)
                joint.BodyA.JointList.Prev = joint.EdgeA;

            joint.BodyA.JointList = joint.EdgeA;

            // WIP David
            if (!joint.IsFixedType())
            {
                joint.EdgeB.Joint = joint;
                joint.EdgeB.Other = joint.BodyA;
                joint.EdgeB.Prev = null;
                joint.EdgeB.Next = joint.BodyB.JointList;

                if (joint.BodyB.JointList != null)
                    joint.BodyB.JointList.Prev = joint.EdgeB;

                joint.BodyB.JointList = joint.EdgeB;
            }

            // WIP David
            if (!joint.IsFixedType())
            {
                Body bodyA = joint.BodyA;
                Body bodyB = joint.BodyB;

                // If the joint prevents collisions, then flag any contacts for filtering.
                if (joint.CollideConnected == false)
                {
                    ContactEdge edge = bodyB.ContactList;
                    while (edge != null)
                    {
                        if (edge.Other == bodyA)
                        {
                            // Flag the contact for filtering at the next time step (where either
                            // body is awake).
                            edge.Contact.FlagForFiltering();
                        }

                        edge = edge.Next;
                    }
                }
            }

            if (JointAdded != null)
                JointAdded(joint);

            // Note: creating a joint doesn't wake the bodies.
        }