示例#1
0
 /// <summary>Creates a mirrored copy of the prototype object (Animated objects)</summary>
 /// <param name="Prototype">The prototype</param>
 /// <returns>The mirrored copy</returns>
 private static ObjectManager.UnifiedObject GetMirroredObject(ObjectManager.UnifiedObject Prototype)
 {
     if (Prototype is ObjectManager.StaticObject)
     {
         ObjectManager.StaticObject s = (ObjectManager.StaticObject)Prototype;
         return(GetMirroredStaticObject(s));
     }
     else if (Prototype is ObjectManager.AnimatedObjectCollection)
     {
         ObjectManager.AnimatedObjectCollection a      = (ObjectManager.AnimatedObjectCollection)Prototype;
         ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection();
         Result.Objects = new ObjectManager.AnimatedObject[a.Objects.Length];
         for (int i = 0; i < a.Objects.Length; i++)
         {
             Result.Objects[i] = a.Objects[i].Clone();
             for (int j = 0; j < a.Objects[i].States.Length; j++)
             {
                 Result.Objects[i].States[j].Object = GetMirroredStaticObject(a.Objects[i].States[j].Object);
             }
             Result.Objects[i].TranslateXDirection.X *= -1.0;
             Result.Objects[i].TranslateYDirection.X *= -1.0;
             Result.Objects[i].TranslateZDirection.X *= -1.0;
             Result.Objects[i].RotateXDirection.X    *= -1.0;
             Result.Objects[i].RotateYDirection.X    *= -1.0;
             Result.Objects[i].RotateZDirection.X    *= -1.0;
         }
         return(Result);
     }
     else
     {
         return(null);
     }
 }
		/// <summary>Creates a mirrored copy of the prototype object (Animated objects)</summary>
		/// <param name="Prototype">The prototype</param>
		/// <returns>The mirrored copy</returns>
		private static ObjectManager.UnifiedObject GetMirroredObject(ObjectManager.UnifiedObject Prototype)
		{
			if (Prototype is ObjectManager.StaticObject)
			{
				ObjectManager.StaticObject s = (ObjectManager.StaticObject)Prototype;
				return GetMirroredStaticObject(s);
			}
			else if (Prototype is ObjectManager.AnimatedObjectCollection)
			{
				ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)Prototype;
				ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection();
				Result.Objects = new ObjectManager.AnimatedObject[a.Objects.Length];
				for (int i = 0; i < a.Objects.Length; i++)
				{
					Result.Objects[i] = a.Objects[i].Clone();
					for (int j = 0; j < a.Objects[i].States.Length; j++)
					{
						Result.Objects[i].States[j].Object = GetMirroredStaticObject(a.Objects[i].States[j].Object);
					}
					Result.Objects[i].TranslateXDirection.X *= -1.0;
					Result.Objects[i].TranslateYDirection.X *= -1.0;
					Result.Objects[i].TranslateZDirection.X *= -1.0;
					Result.Objects[i].RotateXDirection.X *= -1.0;
					Result.Objects[i].RotateYDirection.X *= -1.0;
					Result.Objects[i].RotateZDirection.X *= -1.0;
				}
				return Result;
			}
			else
			{
				return null;
			}
		}
示例#3
0
        internal static void Parse(string fileName, TrainManager.Train Train, ref ObjectManager.UnifiedObject[] CarObjects, ref ObjectManager.UnifiedObject[] BogieObjects)
        {
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the marker's XML file
            currentXML.Load(fileName);
            currentPath          = System.IO.Path.GetDirectoryName(fileName);
            CarObjectsReversed   = new bool[Train.Cars.Length];
            BogieObjectsReversed = new bool[Train.Cars.Length * 2];
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/Car");
                if (DocumentNodes == null || DocumentNodes.Count == 0)
                {
                    Interface.AddMessage(Interface.MessageType.Error, false, "No car nodes defined in XML file " + fileName);
                    //If we have no appropriate nodes specified, return false and fallback to loading the legacy Sound.cfg file
                    throw new Exception("Empty train.xml file");
                }
                //Use the index here for easy access to the car count
                for (int i = 0; i < DocumentNodes.Count; i++)
                {
                    if (i > Train.Cars.Length)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "WARNING: A total of " + DocumentNodes.Count + " cars were specified in XML file " + fileName + " whilst only " + Train.Cars.Length + " were specified in the train.dat file.");
                        break;
                    }
                    if (DocumentNodes[i].ChildNodes.OfType <XmlElement>().Any())
                    {
                        ParseCarNode(DocumentNodes[i], fileName, i, ref Train, ref CarObjects, ref BogieObjects);
                    }
                    else if (!String.IsNullOrEmpty(DocumentNodes[i].InnerText))
                    {
                        try
                        {
                            string      childFile = OpenBveApi.Path.CombineFile(currentPath, DocumentNodes[i].InnerText);
                            XmlDocument childXML  = new XmlDocument();
                            childXML.Load(childFile);
                            XmlNodeList childNodes = childXML.DocumentElement.SelectNodes("/openBVE/Car");
                            //We need to save and restore the current path to make relative paths within the child file work correctly
                            string savedPath = currentPath;
                            currentPath = System.IO.Path.GetDirectoryName(childFile);
                            ParseCarNode(childNodes[0], fileName, i, ref Train, ref CarObjects, ref BogieObjects);
                            currentPath = savedPath;
                        }
                        catch
                        {
                            Interface.AddMessage(Interface.MessageType.Error, false, "Failed to load the child Car XML file specified in " + DocumentNodes[i].InnerText);
                        }
                    }
                    if (i == DocumentNodes.Count && i < Train.Cars.Length)
                    {
                        //If this is the case, the number of motor cars is the primary thing which may get confused....
                        //Not a lot to be done about this until a full replacement is built for the train.dat file & we can dump it entirely
                        Interface.AddMessage(Interface.MessageType.Warning, false, "WARNING: The number of cars specified in the train.xml file does not match that in the train.dat- Some properties may be invalid.");
                    }
                }
                if (Train.Cars[Train.DriverCar].CameraRestrictionMode != Camera.RestrictionMode.NotSpecified)
                {
                    World.CameraRestriction = Train.Cars[Train.DriverCar].CameraRestrictionMode;
                    World.UpdateViewingDistances();
                }
                DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/NotchDescriptions");
                if (DocumentNodes != null && DocumentNodes.Count > 0)
                {
                    //Optional section
                    for (int i = 0; i < DocumentNodes.Count; i++)
                    {
                        if (DocumentNodes[i].ChildNodes.OfType <XmlElement>().Any())
                        {
                            foreach (XmlNode c in DocumentNodes[i].ChildNodes)
                            {
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "power":
                                    Train.PowerNotchDescriptions = c.InnerText.Split(';');
                                    for (int j = 0; j < Train.PowerNotchDescriptions.Length; j++)
                                    {
                                        Size s = Renderer.MeasureString(Fonts.NormalFont, Train.PowerNotchDescriptions[j]);
                                        if (s.Width > Train.MaxPowerNotchWidth)
                                        {
                                            Train.MaxPowerNotchWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "brake":
                                    Train.BrakeNotchDescriptions = c.InnerText.Split(';');
                                    for (int j = 0; j < Train.BrakeNotchDescriptions.Length; j++)
                                    {
                                        Size s = Renderer.MeasureString(Fonts.NormalFont, Train.BrakeNotchDescriptions[j]);
                                        if (s.Width > Train.MaxBrakeNotchWidth)
                                        {
                                            Train.MaxBrakeNotchWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "reverser":
                                    Train.ReverserDescriptions = c.InnerText.Split(';');
                                    for (int j = 0; j < Train.ReverserDescriptions.Length; j++)
                                    {
                                        Size s = Renderer.MeasureString(Fonts.NormalFont, Train.ReverserDescriptions[j]);
                                        if (s.Width > Train.MaxReverserWidth)
                                        {
                                            Train.MaxReverserWidth = s.Width;
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    if (CarObjects[i] != null)
                    {
                        if (CarObjectsReversed[i])
                        {
                            {
                                // reverse axle positions
                                double temp = Train.Cars[i].FrontAxle.Position;
                                Train.Cars[i].FrontAxle.Position = -Train.Cars[i].RearAxle.Position;
                                Train.Cars[i].RearAxle.Position  = -temp;
                            }
                            if (CarObjects[i] is ObjectManager.StaticObject)
                            {
                                ObjectManager.StaticObject obj = (ObjectManager.StaticObject)CarObjects[i];
                                obj.ApplyScale(-1.0, 1.0, -1.0);
                            }
                            else if (CarObjects[i] is ObjectManager.AnimatedObjectCollection)
                            {
                                ObjectManager.AnimatedObjectCollection obj = (ObjectManager.AnimatedObjectCollection)CarObjects[i];
                                for (int j = 0; j < obj.Objects.Length; j++)
                                {
                                    for (int h = 0; h < obj.Objects[j].States.Length; h++)
                                    {
                                        obj.Objects[j].States[h].Object.ApplyScale(-1.0, 1.0, -1.0);
                                        obj.Objects[j].States[h].Position.X *= -1.0;
                                        obj.Objects[j].States[h].Position.Z *= -1.0;
                                    }
                                    obj.Objects[j].TranslateXDirection.X *= -1.0;
                                    obj.Objects[j].TranslateXDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateYDirection.X *= -1.0;
                                    obj.Objects[j].TranslateYDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateZDirection.X *= -1.0;
                                    obj.Objects[j].TranslateZDirection.Z *= -1.0;
                                }
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                        }
                    }
                }

                //Check for bogie objects and reverse if necessary.....
                int bogieObjects = 0;
                for (int i = 0; i < Train.Cars.Length * 2; i++)
                {
                    bool IsOdd    = (i % 2 != 0);
                    int  CarIndex = i / 2;
                    if (BogieObjects[i] != null)
                    {
                        bogieObjects++;
                        if (BogieObjectsReversed[i])
                        {
                            {
                                // reverse axle positions
                                if (IsOdd)
                                {
                                    double temp = Train.Cars[CarIndex].FrontBogie.FrontAxle.Position;
                                    Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = -Train.Cars[CarIndex].FrontBogie.RearAxle.Position;
                                    Train.Cars[CarIndex].FrontBogie.RearAxle.Position  = -temp;
                                }
                                else
                                {
                                    double temp = Train.Cars[CarIndex].RearBogie.FrontAxle.Position;
                                    Train.Cars[CarIndex].RearBogie.FrontAxle.Position = -Train.Cars[CarIndex].RearBogie.RearAxle.Position;
                                    Train.Cars[CarIndex].RearBogie.RearAxle.Position  = -temp;
                                }
                            }
                            if (BogieObjects[i] is ObjectManager.StaticObject)
                            {
                                ObjectManager.StaticObject obj = (ObjectManager.StaticObject)BogieObjects[i];
                                obj.ApplyScale(-1.0, 1.0, -1.0);
                            }
                            else if (BogieObjects[i] is ObjectManager.AnimatedObjectCollection)
                            {
                                ObjectManager.AnimatedObjectCollection obj = (ObjectManager.AnimatedObjectCollection)BogieObjects[i];
                                for (int j = 0; j < obj.Objects.Length; j++)
                                {
                                    for (int h = 0; h < obj.Objects[j].States.Length; h++)
                                    {
                                        obj.Objects[j].States[h].Object.ApplyScale(-1.0, 1.0, -1.0);
                                        obj.Objects[j].States[h].Position.X *= -1.0;
                                        obj.Objects[j].States[h].Position.Z *= -1.0;
                                    }
                                    obj.Objects[j].TranslateXDirection.X *= -1.0;
                                    obj.Objects[j].TranslateXDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateYDirection.X *= -1.0;
                                    obj.Objects[j].TranslateYDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateZDirection.X *= -1.0;
                                    obj.Objects[j].TranslateZDirection.Z *= -1.0;
                                }
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                        }
                    }
                }
            }
        }
示例#4
0
        private static void ParseCarNode(XmlNode Node, string fileName, int Car, ref TrainManager.Train Train, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects)
        {
            string interiorFile = string.Empty;

            foreach (XmlNode c in Node.ChildNodes)
            {
                //Note: Don't use the short-circuiting operator, as otherwise we need another if
                switch (c.Name.ToLowerInvariant())
                {
                case "brake":
                    Train.Cars[Car].CarBrake.brakeType = BrakeType.Auxiliary;
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        ParseBrakeNode(c, fileName, Car, ref Train);
                    }
                    else if (!String.IsNullOrEmpty(c.InnerText))
                    {
                        try
                        {
                            string      childFile = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                            XmlDocument childXML  = new XmlDocument();
                            childXML.Load(childFile);
                            XmlNodeList childNodes = childXML.DocumentElement.SelectNodes("/openBVE/Brake");
                            //We need to save and restore the current path to make relative paths within the child file work correctly
                            string savedPath = currentPath;
                            currentPath = System.IO.Path.GetDirectoryName(childFile);
                            ParseBrakeNode(childNodes[0], fileName, Car, ref Train);
                            currentPath = savedPath;
                        }
                        catch
                        {
                            Interface.AddMessage(MessageType.Error, false, "Failed to load the child Brake XML file specified in " + c.InnerText);
                        }
                    }
                    break;

                case "length":
                    double l;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out l) | l <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid length defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Length = l;
                    break;

                case "width":
                    double w;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out w) | w <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid width defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Width = w;
                    break;

                case "height":
                    double h;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out h) | h <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid height defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Height = h;
                    break;

                case "motorcar":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].Specs.IsMotorCar         = true;
                        Train.Cars[Car].Specs.AccelerationCurves = new TrainManager.AccelerationCurve[AccelerationCurves.Length];
                        for (int i = 0; i < AccelerationCurves.Length; i++)
                        {
                            Train.Cars[Car].Specs.AccelerationCurves[i] = AccelerationCurves[i].Clone(AccelerationCurves[i].Multiplier);
                        }
                        switch (Train.Specs.ReadhesionDeviceType)
                        {
                        case TrainManager.ReadhesionDeviceType.TypeA:
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 8.0;
                            break;

                        case TrainManager.ReadhesionDeviceType.TypeB:
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 0.1;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.9935;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 4.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 1.125;
                            break;

                        case TrainManager.ReadhesionDeviceType.TypeC:

                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 0.1;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.965;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 2.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 1.5;
                            break;

                        case TrainManager.ReadhesionDeviceType.TypeD:
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 0.05;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.935;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 0.3;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 2.0;
                            break;

                        default:                                         // no readhesion device
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 99.0;
                            break;
                        }
                    }
                    else
                    {
                        Train.Cars[Car].Specs.AccelerationCurves = new TrainManager.AccelerationCurve[] { };
                        Train.Cars[Car].Specs.IsMotorCar         = false;
                        Train.Cars[Car].Specs.ReAdhesionDevice   = new TrainManager.CarReAdhesionDevice(Train.Cars[Car]);
                    }
                    break;

                case "mass":
                    double m;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out m) | m <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid mass defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Specs.MassEmpty   = m;
                    Train.Cars[Car].Specs.MassCurrent = m;
                    break;

                case "frontaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].FrontAxle.Position))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid front axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "rearaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].RearAxle.Position))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid rear axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "object":
                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (System.IO.File.Exists(f))
                    {
                        CarObjects[Car] = ObjectManager.LoadObject(f, System.Text.Encoding.Default, false, false, false);
                    }
                    break;

                case "reversed":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        CarObjectsReversed[Car] = true;
                    }
                    break;

                case "frontbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "rearbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2 + 1] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2 + 1] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "driverposition":
                    string[] splitText = c.InnerText.Split(',');
                    if (splitText.Length != 3)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position must have three arguments for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Driver = new Vector3();
                    double driverZ;
                    if (!NumberFormats.TryParseDoubleVb6(splitText[0], out Train.Cars[Car].Driver.X))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[1], out Train.Cars[Car].Driver.Y))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position Y was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[2], out driverZ))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    Train.Cars[Car].Driver.Z = 0.5 * Train.Cars[Car].Length + driverZ;
                    break;

                case "interiorview":
                    if (Train != TrainManager.PlayerTrain)
                    {
                        break;
                    }
                    Train.Cars[Car].HasInteriorView = true;
                    if (Car != Train.DriverCar)
                    {
                        Train.Cars[Car].CarSections             = new TrainManager.CarSection[1];
                        Train.Cars[Car].CarSections[0]          = new TrainManager.CarSection();
                        Train.Cars[Car].CarSections[0].Elements = new ObjectManager.AnimatedObject[] { };
                        Train.Cars[Car].CarSections[0].Overlay  = true;
                    }
                    string cv = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (!System.IO.File.Exists(cv))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Interior view file was invalid for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    interiorFile = cv;
                    break;
                }
            }
            //Driver position is measured from the front of the car
            //As there is no set order, this needs to be done after the loop
            if (interiorFile != String.Empty)
            {
                if (interiorFile.ToLowerInvariant().EndsWith(".cfg"))
                {
                    //Only supports panel2.cfg format
                    Panel2CfgParser.ParsePanel2Config(System.IO.Path.GetFileName(interiorFile), System.IO.Path.GetDirectoryName(interiorFile), Encoding.UTF8, Train, Car);
                    Train.Cars[Car].CameraRestrictionMode = Camera.RestrictionMode.On;
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".animated"))
                {
                    ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(interiorFile, Encoding.UTF8);
                    try
                    {
                        for (int i = 0; i < a.Objects.Length; i++)
                        {
                            a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                        }
                        Train.Cars[Car].CarSections[0].Elements = a.Objects;
                        Train.Cars[Car].CameraRestrictionMode   = Camera.RestrictionMode.NotAvailable;
                    }
                    catch
                    {
                        Program.RestartArguments = " ";
                        Loading.Cancel           = true;
                    }
                }
                else
                {
                    Interface.AddMessage(MessageType.Warning, false, "Interior view file is not supported for Car " + Car + " in XML file " + fileName);
                }
            }
        }
示例#5
0
        private static void ParsePanelAnimatedNode(XElement Element, string FileName, string TrainPath, TrainManager.Train Train, int Car, TrainManager.CarSection CarSection, int GroupIndex)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;

            int    currentSectionElement   = 0;
            int    numberOfSectionElements = Element.Elements().Count();
            double invfac = numberOfSectionElements == 0 ? Loading.TrainProgressCurrentWeight : Loading.TrainProgressCurrentWeight / (double)numberOfSectionElements;

            foreach (XElement SectionElement in Element.Elements())
            {
                Loading.TrainProgress = Loading.TrainProgressCurrentSum + invfac * (double)currentSectionElement;
                if ((currentSectionElement & 4) == 0)
                {
                    System.Threading.Thread.Sleep(1);
                    if (Loading.Cancel)
                    {
                        return;
                    }
                }

                string Section = SectionElement.Name.LocalName;

                switch (SectionElement.Name.LocalName.ToLowerInvariant())
                {
                case "group":
                    if (GroupIndex == 0)
                    {
                        int n = 0;

                        foreach (XElement KeyNode in SectionElement.Elements())
                        {
                            string Key        = KeyNode.Name.LocalName;
                            string Value      = KeyNode.Value;
                            int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                            switch (Key.ToLowerInvariant())
                            {
                            case "number":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out n))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;
                            }
                        }

                        if (n + 1 >= CarSection.Groups.Length)
                        {
                            Array.Resize(ref CarSection.Groups, n + 2);
                            CarSection.Groups[n + 1] = new TrainManager.ElementsGroup
                            {
                                Elements = new ObjectManager.AnimatedObject[] { },
                                Overlay  = true
                            };
                        }

                        ParsePanelAnimatedNode(SectionElement, FileName, TrainPath, Train, Car, CarSection, n + 1);
                    }
                    break;

                case "touch":
                    if (GroupIndex > 0)
                    {
                        Vector3 Position             = Vector3.Zero;
                        Vector3 Size                 = Vector3.Zero;
                        int     JumpScreen           = GroupIndex - 1;
                        int     SoundIndex           = -1;
                        Translations.Command Command = Translations.Command.None;
                        int CommandOption            = 0;

                        foreach (XElement KeyNode in SectionElement.Elements())
                        {
                            string Key        = KeyNode.Name.LocalName;
                            string Value      = KeyNode.Value;
                            int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                            switch (Key.ToLowerInvariant())
                            {
                            case "position":
                            {
                                string[] s = Value.Split(',');
                                if (s.Length == 3)
                                {
                                    if (s[0].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[0], out Position.X))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "X is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[1].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[1], out Position.Y))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[2].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[2], out Position.Z))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Three arguments are expected in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                            }
                            break;

                            case "size":
                            {
                                string[] s = Value.Split(',');
                                if (s.Length == 3)
                                {
                                    if (s[0].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[0], out Size.X))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "X is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[1].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[1], out Size.Y))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[2].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[2], out Size.Z))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Three arguments are expected in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                            }
                            break;

                            case "jumpscreen":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out JumpScreen))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;

                            case "soundindex":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out SoundIndex))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;

                            case "command":
                            {
                                int i;
                                for (i = 0; i < Translations.CommandInfos.Length; i++)
                                {
                                    if (string.Compare(Value, Translations.CommandInfos[i].Name, StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        break;
                                    }
                                }
                                if (i == Translations.CommandInfos.Length || Translations.CommandInfos[i].Type != Translations.CommandType.Digital)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                else
                                {
                                    Command = Translations.CommandInfos[i].Command;
                                }
                            }
                            break;

                            case "commandoption":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out CommandOption))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;
                            }
                        }
                        CreateTouchElement(CarSection.Groups[GroupIndex], Position, Size, JumpScreen, SoundIndex, Command, CommandOption);
                    }
                    break;

                case "include":
                {
                    foreach (XElement KeyNode in SectionElement.Elements())
                    {
                        string Key        = KeyNode.Name.LocalName;
                        string Value      = KeyNode.Value;
                        int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                        switch (Key.ToLowerInvariant())
                        {
                        case "filename":
                        {
                            string File = OpenBveApi.Path.CombineFile(TrainPath, Value);
                            if (System.IO.File.Exists(File))
                            {
                                System.Text.Encoding e = TextEncoding.GetSystemEncodingFromFile(File);
                                ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(File, e);
                                if (a != null)
                                {
                                    for (int i = 0; i < a.Objects.Length; i++)
                                    {
                                        a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                                    }
                                    CarSection.Groups[GroupIndex].Elements = a.Objects;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                            }
                        }
                        break;
                        }
                    }
                }
                break;
                }
            }
        }
示例#6
0
        private static void ParseCarNode(XmlNode Node, string fileName, int Car, ref TrainManager.Train Train, ref ObjectManager.UnifiedObject[] CarObjects, ref ObjectManager.UnifiedObject[] BogieObjects)
        {
            double driverZ      = 0.0;
            string interiorFile = string.Empty;

            foreach (XmlNode c in Node.ChildNodes)
            {
                //Note: Don't use the short-circuiting operator, as otherwise we need another if
                switch (c.Name.ToLowerInvariant())
                {
                case "length":
                    double l;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out l) | l <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid length defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Length = l;
                    break;

                case "width":
                    double w;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out w) | w <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid width defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Width = w;
                    break;

                case "height":
                    double h;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out h) | h <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid height defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Height = h;
                    break;

                case "motorcar":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].Specs.IsMotorCar = true;
                    }
                    else
                    {
                        Train.Cars[Car].Specs.IsMotorCar = false;
                    }
                    break;

                case "mass":
                    double m;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out m) | m <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid mass defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Specs.MassEmpty   = m;
                    Train.Cars[Car].Specs.MassCurrent = m;
                    break;

                case "frontaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].FrontAxle.Position))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid front axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "rearaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].RearAxle.Position))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid rear axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "object":
                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (System.IO.File.Exists(f))
                    {
                        CarObjects[Car] = ObjectManager.LoadObject(f, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                    }
                    break;

                case "reversed":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        CarObjectsReversed[Car] = true;
                    }
                    break;

                case "frontbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid front bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid front bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "rearbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid rear bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid rear bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2 + 1] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2 + 1] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "driverposition":
                    string[] splitText = c.InnerText.Split(',');
                    if (splitText.Length != 3)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position must have three arguments for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Driver = new Vector3();
                    if (!NumberFormats.TryParseDoubleVb6(splitText[0], out Train.Cars[Car].Driver.X))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[1], out Train.Cars[Car].Driver.Y))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position Y was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[2], out driverZ))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    Train.Cars[Car].Driver.Z = 0.5 * Train.Cars[Car].Length + driverZ;
                    break;

                case "interiorview":
                    if (Train != TrainManager.PlayerTrain)
                    {
                        break;
                    }
                    Train.Cars[Car].HasInteriorView = true;
                    if (Car != Train.DriverCar)
                    {
                        Train.Cars[Car].CarSections             = new TrainManager.CarSection[1];
                        Train.Cars[Car].CarSections[0]          = new TrainManager.CarSection();
                        Train.Cars[Car].CarSections[0].Elements = new ObjectManager.AnimatedObject[] { };
                        Train.Cars[Car].CarSections[0].Overlay  = true;
                    }
                    string cv = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (!System.IO.File.Exists(cv))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Interior view file was invalid for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    interiorFile = cv;
                    break;
                }
            }
            //Driver position is measured from the front of the car
            //As there is no set order, this needs to be done after the loop
            if (interiorFile != String.Empty)
            {
                if (interiorFile.ToLowerInvariant().EndsWith(".cfg"))
                {
                    //Only supports panel2.cfg format
                    Panel2CfgParser.ParsePanel2Config(System.IO.Path.GetFileName(interiorFile), System.IO.Path.GetDirectoryName(interiorFile), Encoding.UTF8, Train, Car);
                    Train.Cars[Car].CameraRestrictionMode = World.CameraRestrictionMode.On;
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".animated"))
                {
                    ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(interiorFile, Encoding.UTF8, ObjectManager.ObjectLoadMode.DontAllowUnloadOfTextures);
                    try
                    {
                        for (int i = 0; i < a.Objects.Length; i++)
                        {
                            a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                        }
                        Train.Cars[Car].CarSections[0].Elements = a.Objects;
                        Train.Cars[Car].CameraRestrictionMode   = World.CameraRestrictionMode.NotAvailable;
                    }
                    catch
                    {
                        Program.RestartArguments = " ";
                        Loading.Cancel           = true;
                    }
                }
                else
                {
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Interior view file is not supported for Car " + Car + " in XML file " + fileName);
                }
            }
        }