protected void MaybeGeneratePathData()
 {
     PathObjectTypeContainer pathObjectTypes = WorldRoot.Instance.PathObjectTypes;
     if (pathObjectTypes.Count == 0)
         PathData = null;
     else if (WorldRoot.Instance.PathObjectTypes.AllObjectsDirty || locationDirty) {
         List<CollisionShape> meshShapes = WorldEditor.Instance.FindMeshCollisionShapes(meshName, displayObject.Entity);
         if (meshShapes.Count == 0)
             PathData = null;
         else {
             PathData = new PathData();
             float terrainHeight = WorldEditor.Instance.GetTerrainHeight(location.x, location.z) - location.y;
             for (int i=0; i<pathObjectTypes.Count; i++) {
                 PathObjectType type = pathObjectTypes.GetType(i);
                 try {
                     PathData.AddModelPathObject(WorldEditor.Instance.LogPathGeneration, type, name, location,
                         displayObject.SceneNode.FullTransform, meshShapes, terrainHeight);
                 }
                 catch (Exception e) {
                     MessageBox.Show(string.Format("An exception was raised when generating pathing information for " +
                             "model {0}, for path object type {1}.  The exception message was '{2}'.  Please run the World " +
                             "Editor again, with the command-line option --log_paths, save the world file to generate " +
                             "pathing information, and zip up the generated file " +
                             "PathGenerationLog.txt, found in the World Editor's bin directory, and send it to Multiverse, " +
                             "along with the {3} file so the problem can be identified and fixed.",
                             name, type.name, e.Message, meshName),
                         "Error Generating Path Information For Model " + name + "!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                 }
             }
         }
     }
 }
        protected void FromXml(XmlReader r)
        {
            bool adjustHeightFound = false;
            bool offsetFound = false;
            bool pRFound = false;
            // first parse name and mesh, which are attributes
            for (int i = 0; i < r.AttributeCount; i++)
            {
                r.MoveToAttribute(i);

                // set the field in this object based on the element we just read
                switch (r.Name)
                {
                    case "Name":
                        this.name = r.Value;
                        break;
                    case "Mesh":
                        this.meshName = r.Value;
                        break;
                    case "Sound":
                        string filename = r.Value;
                        if (!String.Equals(filename, ""))
                        {
                            ICommandFactory ret = new AddSoundCommandFactory(app, this, r.Value);
                            ICommand com = ret.CreateCommand();
                            com.Execute();
                        }
                        break;
                    case "TerrainOffset":
                        terrainOffset = float.Parse(r.Value);
                        offsetFound = true;
                        break;
                    case "AllowHeightAdjustment":
                        if (String.Equals(r.Value.ToLower(), "false"))
                        {
                            allowAdjustHeightOffTerrain = false;
                        }
                        break;
                    case "AcceptObjectPlacement":
                        acceptObjectPlacement = bool.Parse(r.Value);
                        break;
                    case "PerceptionRadius":
                        pRFound = true;
                        perceptionRadius = float.Parse(r.Value);
                        break;
                    case "CastShadows":
                        castShadows = bool.Parse(r.Value);
                        break;
                    case "ReceiveShadows":
                        receiveShadows = bool.Parse(r.Value);
                        break;
                    case "Azimuth":
                        azimuth = float.Parse(r.Value);
                        break;
                    case "Zenith":
                        zenith = float.Parse(r.Value);
                        break;
                    case "WorldViewSelect":
                        worldViewSelectable = bool.Parse(r.Value);
                        break;
                    case "Targetable":
                        targetable = bool.Parse(r.Value);
                        break;
                }
            }
            r.MoveToElement(); //Moves the reader back to the element node.

            // now parse the sub-elements
            while (r.Read())
            {
                // look for the start of an element
                if (r.NodeType == XmlNodeType.Element)
                {
                    // parse that element
                    // save the name of the element
                    string elementName = r.Name;
                    switch (elementName)
                    {
                        case "Position":
                            location = XmlHelperClass.ParseVectorAttributes(r);
                            break;
                        case "Scale":
                            scale = XmlHelperClass.ParseVectorAttributes(r);
                            break;
                        case "Rotation":
                            Vector3 rotation = XmlHelperClass.ParseVectorAttributes(r);
                            // force rotation to be between -180 and 180
                            while (rotation.y < -180)
                            {
                                rotation.y += 360;
                            }
                            while (rotation.y > 180)
                            {
                                rotation.y -= 360;
                            }
                            SetDirection(rotation.y, 90f);
                            break;
                        case "Orientation":
                            orientation = XmlHelperClass.ParseQuaternion(r);
                            break;
                        case "SubMeshes":
                            subMeshes = new SubMeshCollection(r);
                            if (!subMeshes.CheckValid(app, meshName))
                            {
                                app.AddPopupMessage(string.Format("Some submesh names in {0} changed.  Submesh display and material parameters for this object were reset.", meshName));

                                // if the check fails, then reset the subMeshes from the mesh
                                subMeshes = new SubMeshCollection(meshName);
                            }
                            break;
                        case "NameValuePairs":
                            nameValuePairs = new NameValueObject(r);
                            break;
                        case "ParticleEffect":
                            ParticleEffect particle = new ParticleEffect(r, this, app);
                            Add(particle);
                            break;
                        case "PathData":
                            pathData = new PathData(r);
                            locationDirty = pathData.Version != pathData.CodeVersion;
                            break;
                        case "Sound":
                            Sound sound = new Sound(r, this, app);
                            Add(sound);
                            break;
                    }
                }
                else if (r.NodeType == XmlNodeType.EndElement)
                {
                    break;
                }
            }
            if (!adjustHeightFound)
            {
                allowAdjustHeightOffTerrain = true;
            }
            if (!offsetFound)
            {
                terrainOffset = location.y - app.GetTerrainHeight(location.x, location.z);
            }
            if (!pRFound && nameValuePairs != null)
            {
                valueItem value = nameValuePairs.LookUp("perceptionRadius");
                if (value != null && ValidityHelperClass.isFloat(value.value))
                {
                    perceptionRadius = float.Parse(value.value);
                }
            }
            return;
        }