Ejemplo n.º 1
0
			// --- constructors ---
			/// <summary>Creates a new sound source.</summary>
			/// <param name="buffer">The sound buffer.</param>
			/// <param name="radius">The effective sound radius.</param>
			/// <param name="pitch">The pitch change factor.</param>
			/// <param name="volume">The volume change factor.</param>
			/// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
			/// <param name="train">The train this sound source is attached to, or a null reference.</param>
			/// <param name="car">The car this sound source is attached to, or a null reference.</param>
			/// <param name="looped">Whether this sound source plays in a loop.</param>
			internal SoundSource(SoundBuffer buffer, double radius, double pitch, double volume, OpenBveApi.Math.Vector3 position, TrainManager.Train train, int car, bool looped) {
				this.Buffer = buffer;
				this.Radius = radius;
				this.Pitch = pitch;
				this.Volume = volume;
				this.Position = position;
				this.Train = train;
				this.Car = car;
				this.Looped = looped;
				this.State = SoundSourceState.PlayPending;
				this.OpenAlSourceName = 0;
				//Set the sound type to undefined to use Michelle's original processing
				if (train != null)
				{
					this.Type = SoundType.TrainCar;
				}
				else
				{
					this.Type = SoundType.Undefined;	
				}
				
			}
Ejemplo n.º 2
0
			/// <summary>Creates a new sound source.</summary>
			/// <param name="buffer">The sound buffer.</param>
			/// <param name="radius">The effective sound radius.</param>
			/// <param name="pitch">The pitch change factor.</param>
			/// <param name="volume">The volume change factor.</param>
			/// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
			/// <param name="train">The train this sound source is attached to, or a null reference.</param>
			/// <param name="type">The type of sound</param>
			/// <param name="car">The car this sound source is attached to, or a null reference.</param>
			/// <param name="looped">Whether this sound source plays in a loop.</param>
			internal SoundSource(SoundBuffer buffer, double radius, double pitch, double volume, OpenBveApi.Math.Vector3 position, TrainManager.Train train, SoundType type, int car, bool looped)
			{
				this.Buffer = buffer;
				this.Radius = radius;
				this.Pitch = pitch;
				this.Volume = volume;
				this.Position = position;
				this.Train = train;
				this.Car = car;
				this.Looped = looped;
				this.State = SoundSourceState.PlayPending;
				this.OpenAlSourceName = 0;
				//Set sound type manually
				this.Type = type;
			}
Ejemplo n.º 3
0
        internal static void Parse(string fileName, TrainManager.Train Train, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects, ref UnifiedObject[] CouplerObjects, ref bool[] interiorVisible)
        {
            //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);
            if (System.IO.File.Exists(OpenBveApi.Path.CombineFile(currentPath, "train.dat")))
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    if (Train.Cars[i].Specs.IsMotorCar)
                    {
                        AccelerationCurves = new BveAccelerationCurve[Train.Cars[i].Specs.AccelerationCurves.Length];
                        for (int j = 0; j < Train.Cars[i].Specs.AccelerationCurves.Length; j++)
                        {
                            BveAccelerationCurve c = (BveAccelerationCurve)Train.Cars[i].Specs.AccelerationCurves[j];
                            AccelerationCurves[j] = c.Clone(c.Multiplier);
                        }
                    }
                }
            }
            CarObjectsReversed   = new bool[Train.Cars.Length];
            BogieObjectsReversed = new bool[Train.Cars.Length * 2];
            interiorVisible      = new bool[Train.Cars.Length];
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/*[self::Car or self::Coupler]");
                if (DocumentNodes == null || DocumentNodes.Count == 0)
                {
                    Interface.AddMessage(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");
                }

                int carIndex = 0;
                //Use the index here for easy access to the car count
                for (int i = 0; i < DocumentNodes.Count; i++)
                {
                    if (carIndex > Train.Cars.Length)
                    {
                        Interface.AddMessage(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())
                    {
                        if (DocumentNodes[i].Name == "Car")
                        {
                            ParseCarNode(DocumentNodes[i], fileName, carIndex, ref Train, ref CarObjects, ref BogieObjects, ref interiorVisible[carIndex]);
                        }
                        else
                        {
                            if (carIndex - 1 > Train.Cars.Length - 2)
                            {
                                Interface.AddMessage(MessageType.Error, false, "Unexpected extra coupler encountered in XML file " + fileName);
                                continue;
                            }
                            foreach (XmlNode c in DocumentNodes[i].ChildNodes)
                            {
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "minimum":
                                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[carIndex - 1].Coupler.MinimumDistanceBetweenCars))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "MinimumDistanceBetweenCars is invalid for coupler " + carIndex + "in XML file " + fileName);
                                    }
                                    break;

                                case "maximum":
                                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[carIndex - 1].Coupler.MaximumDistanceBetweenCars))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "MaximumDistanceBetweenCars is invalid for coupler " + carIndex + "in XML file " + fileName);
                                    }
                                    break;

                                case "object":
                                    if (string.IsNullOrEmpty(c.InnerText))
                                    {
                                        Interface.AddMessage(MessageType.Warning, false, "Invalid object path for Coupler " + (carIndex - 1) + " in XML file " + fileName);
                                        break;
                                    }
                                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                                    if (System.IO.File.Exists(f))
                                    {
                                        Program.CurrentHost.LoadObject(f, System.Text.Encoding.Default, out CouplerObjects[carIndex - 1]);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    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, ref interiorVisible[carIndex]);
                            currentPath = savedPath;
                        }
                        catch
                        {
                            Interface.AddMessage(MessageType.Error, false, "Failed to load the child Car XML file specified in " + DocumentNodes[i].InnerText);
                        }
                    }
                    if (i == DocumentNodes.Count && carIndex < 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(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 (DocumentNodes[i].Name == "Car")
                    {
                        carIndex++;
                    }
                }
                if (Train.Cars[Train.DriverCar].CameraRestrictionMode != CameraRestrictionMode.NotSpecified)
                {
                    Program.Renderer.Camera.CurrentRestriction = Train.Cars[Train.DriverCar].CameraRestrictionMode;
                    Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                }
                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.Handles.Power.NotchDescriptions = c.InnerText.Split(new[] { ';' });
                                    for (int j = 0; j < Train.Handles.Power.NotchDescriptions.Length; j++)
                                    {
                                        Size s = Fonts.NormalFont.MeasureString(Train.Handles.Power.NotchDescriptions[j]);
                                        if (s.Width > Train.Handles.Power.MaxWidth)
                                        {
                                            Train.Handles.Power.MaxWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "brake":
                                    Train.Handles.Brake.NotchDescriptions = c.InnerText.Split(new[] { ';' });
                                    for (int j = 0; j < Train.Handles.Brake.NotchDescriptions.Length; j++)
                                    {
                                        Size s = Fonts.NormalFont.MeasureString(Train.Handles.Brake.NotchDescriptions[j]);
                                        if (s.Width > Train.Handles.Brake.MaxWidth)
                                        {
                                            Train.Handles.Brake.MaxWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "locobrake":
                                    if (Train.Handles.LocoBrake == null)
                                    {
                                        continue;
                                    }
                                    Train.Handles.LocoBrake.NotchDescriptions = c.InnerText.Split(new[] { ';' });
                                    for (int j = 0; j < Train.Handles.LocoBrake.NotchDescriptions.Length; j++)
                                    {
                                        Size s = Fonts.NormalFont.MeasureString(Train.Handles.LocoBrake.NotchDescriptions[j]);
                                        if (s.Width > Train.Handles.LocoBrake.MaxWidth)
                                        {
                                            Train.Handles.LocoBrake.MaxWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "reverser":
                                    Train.Handles.Reverser.NotchDescriptions = c.InnerText.Split(new[] { ';' });
                                    for (int j = 0; j < Train.Handles.Reverser.NotchDescriptions.Length; j++)
                                    {
                                        Size s = Fonts.NormalFont.MeasureString(Train.Handles.Reverser.NotchDescriptions[j]);
                                        if (s.Width > Train.Handles.Reverser.MaxWidth)
                                        {
                                            Train.Handles.Reverser.MaxWidth = 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 StaticObject)
                            {
                                StaticObject obj = (StaticObject)CarObjects[i];
                                obj.ApplyScale(-1.0, 1.0, -1.0);
                            }
                            else if (CarObjects[i] is AnimatedObjectCollection)
                            {
                                AnimatedObjectCollection obj = (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].Prototype.ApplyScale(-1.0, 1.0, -1.0);
                                        Matrix4D t = obj.Objects[j].States[h].Translation;
                                        t.Row3.X *= -1.0f;
                                        t.Row3.Z *= -1.0f;
                                        obj.Objects[j].States[h].Translation = t;
                                    }
                                    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 StaticObject)
                            {
                                StaticObject obj = (StaticObject)BogieObjects[i];
                                obj.ApplyScale(-1.0, 1.0, -1.0);
                            }
                            else if (BogieObjects[i] is AnimatedObjectCollection)
                            {
                                AnimatedObjectCollection obj = (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].Prototype.ApplyScale(-1.0, 1.0, -1.0);
                                        Matrix4D t = obj.Objects[j].States[h].Translation;
                                        t.Row3.X *= -1.0f;
                                        t.Row3.Z *= -1.0f;
                                        obj.Objects[j].States[h].Translation = t;
                                    }
                                    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();
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 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;

            TrainManager.ReadhesionDeviceType readhesionDevice = Train.Cars[0].Specs.ReAdhesionDevice.DeviceType;
            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 "camerarestriction":
                    Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.Restricted3D;
                    foreach (XmlNode cc in c.ChildNodes)
                    {
                        switch (cc.Name.ToLowerInvariant())
                        {
                        case "backwards":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.BottomLeft.Z))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid backwards camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "forwards":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.TopRight.Z))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid forwards camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "left":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.BottomLeft.X))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid left camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "right":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.TopRight.X))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid right camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "down":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.BottomLeft.Y))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid down camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "up":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.TopRight.Y))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid up camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;
                        }
                    }
                    break;

                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);
                        }
                    }
                    else
                    {
                        Train.Cars[Car].Specs.AccelerationCurves = new TrainManager.AccelerationCurve[] { };
                        Train.Cars[Car].Specs.IsMotorCar         = false;
                    }
                    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].EmptyMass = m;
                    Train.Cars[Car].CargoMass = 0;
                    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":
                    if (string.IsNullOrEmpty(c.InnerText))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid object path for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (System.IO.File.Exists(f))
                    {
                        Program.CurrentHost.LoadObject(f, System.Text.Encoding.Default, out CarObjects[Car]);
                    }
                    break;

                case "reversed":
                    int n;
                    NumberFormats.TryParseIntVb6(c.InnerText, out n);
                    if (n == 1 || c.InnerText.ToLowerInvariant() == "true")
                    {
                        CarObjectsReversed[Car] = true;
                    }
                    break;

                case "loadingsway":
                    int nm;
                    NumberFormats.TryParseIntVb6(c.InnerText, out nm);
                    if (nm == 1 || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].EnableLoadingSway = true;
                    }
                    else
                    {
                        Train.Cars[Car].EnableLoadingSway = false;
                    }
                    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":
                                if (string.IsNullOrEmpty(cc.InnerText))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie object path for Car " + Car + " in XML file " + fileName);
                                    break;
                                }
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    Program.CurrentHost.LoadObject(fb, System.Text.Encoding.Default, out BogieObjects[Car * 2]);
                                }
                                break;

                            case "reversed":
                                int nn;
                                NumberFormats.TryParseIntVb6(cc.InnerText, out nn);
                                if (cc.InnerText.ToLowerInvariant() == "true" || nn == 1)
                                {
                                    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":
                                if (string.IsNullOrEmpty(cc.InnerText))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie object path for Car " + Car + " in XML file " + fileName);
                                    break;
                                }
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    Program.CurrentHost.LoadObject(fb, System.Text.Encoding.Default, out BogieObjects[Car * 2 + 1]);
                                }
                                break;

                            case "reversed":
                                int nn;
                                NumberFormats.TryParseIntVb6(cc.InnerText, out nn);
                                if (cc.InnerText.ToLowerInvariant() == "true" || nn == 1)
                                {
                                    BogieObjectsReversed[Car * 2 + 1] = true;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "driverposition":
                    string[] splitText = c.InnerText.Split(new char[] { ',' });
                    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.IsPlayerTrain)
                    {
                        break;
                    }
                    Train.Cars[Car].HasInteriorView = true;
                    Train.Cars[Car].CarSections     = new TrainManager.CarSection[1];
                    Train.Cars[Car].CarSections[0]  = new TrainManager.CarSection
                    {
                        Groups = new TrainManager.ElementsGroup[1]
                    };
                    Train.Cars[Car].CarSections[0].Groups[0] = new TrainManager.ElementsGroup
                    {
                        Elements = new AnimatedObject[] { },
                        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;

                case "readhesiondevice":
                    switch (c.InnerText.ToLowerInvariant())
                    {
                    case "typea":
                    case "a":
                        readhesionDevice = TrainManager.ReadhesionDeviceType.TypeA;
                        break;

                    case "typeb":
                    case "b":
                        readhesionDevice = TrainManager.ReadhesionDeviceType.TypeB;
                        break;

                    case "typec":
                    case "c":
                        readhesionDevice = TrainManager.ReadhesionDeviceType.TypeC;
                        break;

                    case "typed":
                    case "d":
                        readhesionDevice = TrainManager.ReadhesionDeviceType.TypeD;
                        break;

                    default:
                        readhesionDevice = TrainManager.ReadhesionDeviceType.NotFitted;
                        break;
                    }
                    break;
                }
            }

            /*
             * As there is no set order for XML tags to be presented in, these must be
             * done after the end of the loop			 *
             */

            //Assign interior view
            if (interiorFile != String.Empty)
            {
                if (interiorFile.ToLowerInvariant().EndsWith(".xml"))
                {
                    XDocument CurrentXML = XDocument.Load(interiorFile, LoadOptions.SetLineInfo);

                    // Check for null
                    if (CurrentXML.Root == null)
                    {
                        // We couldn't find any valid XML, so return false
                        throw new System.IO.InvalidDataException();
                    }
                    IEnumerable <XElement> DocumentElements = CurrentXML.Root.Elements("PanelAnimated");
                    if (DocumentElements != null && DocumentElements.Count() != 0)
                    {
                        PanelAnimatedXmlParser.ParsePanelAnimatedXml(interiorFile, currentPath, Train, Car);
                        if (Train.Cars[Car].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                        {
                            Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.NotAvailable;
                        }
                        return;
                    }
                    DocumentElements = CurrentXML.Root.Elements("Panel");
                    if (DocumentElements != null && DocumentElements.Count() != 0)
                    {
                        PanelXmlParser.ParsePanelXml(interiorFile, currentPath, Train, Car);
                        Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.On;
                        return;
                    }
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".cfg"))
                {
                    //Only supports panel2.cfg format
                    Panel2CfgParser.ParsePanel2Config(System.IO.Path.GetFileName(interiorFile), System.IO.Path.GetDirectoryName(interiorFile), Train, Car);
                    Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.On;
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".animated"))
                {
                    UnifiedObject currentObject;
                    Program.CurrentHost.LoadObject(interiorFile, Encoding.UTF8, out currentObject);
                    var a = currentObject as AnimatedObjectCollection;
                    if (a != null)
                    {
                        try
                        {
                            for (int i = 0; i < a.Objects.Length; i++)
                            {
                                Program.CurrentHost.CreateDynamicObject(ref a.Objects[i].internalObject);
                            }
                            Train.Cars[Car].CarSections[0].Groups[0].Elements = a.Objects;
                            if (Train.Cars[Car].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                            {
                                Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.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);
                }
            }
            Train.Cars[Car].Specs.ReAdhesionDevice = new TrainManager.CarReAdhesionDevice(Train.Cars[Car], readhesionDevice);
        }
Ejemplo n.º 5
0
        internal static void Parse(string fileName, TrainManager.Train Train, ref UnifiedObject[] CarObjects, ref 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);
            if (System.IO.File.Exists(OpenBveApi.Path.CombineFile(currentPath, "train.dat")))
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    if (Train.Cars[i].Specs.IsMotorCar)
                    {
                        AccelerationCurves = new TrainManager.BveAccelerationCurve[Train.Cars[i].Specs.AccelerationCurves.Length];
                        for (int j = 0; j < Train.Cars[i].Specs.AccelerationCurves.Length; j++)
                        {
                            TrainManager.BveAccelerationCurve c = (TrainManager.BveAccelerationCurve)Train.Cars[i].Specs.AccelerationCurves[j];
                            AccelerationCurves[j] = c.Clone(c.Multiplier);
                        }
                    }
                }
            }
            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(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(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(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(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();
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 6
0
            internal override void Trigger(int Direction, EventTriggerType TriggerType, TrainManager.Train Train, int CarIndex)
            {
                if (TriggerType == EventTriggerType.RearCarRearAxle & Train != TrainManager.PlayerTrain)
                {
                    Train.Dispose();
                }
                else if (Train == TrainManager.PlayerTrain)
                {
                    Train.Derail(CarIndex, 0.0);
                }

                if (TriggerType == EventTriggerType.Camera)
                {
                    World.CameraAtWorldEnd = !World.CameraAtWorldEnd;
                }
            }
Ejemplo n.º 7
0
 /// <summary>The unconditional event trigger function</summary>
 /// <param name="Direction">The direction:
 ///  1 - Forwards
 /// -1 - Reverse</param>
 /// <param name="TriggerType">The trigger type (Car axle, camera follower etc.)</param>
 /// <param name="Train">The train, or a null reference</param>
 /// <param name="CarIndex">The car index, or a null reference</param>
 internal abstract void Trigger(int Direction, EventTriggerType TriggerType, TrainManager.Train Train, int CarIndex);
Ejemplo n.º 8
0
 internal StationAdjustAlarm(TrainManager.Train train)
 {
     this.baseTrain   = train;
     this.AdjustAlarm = new CarSound();
     this.Lit         = false;
 }
Ejemplo n.º 9
0
        private static void ParseBrakeNode(XmlNode Node, string fileName, int Car, ref TrainManager.Train Train)
        {
            double compressorRate = 5000.0, compressorMinimumPressure = 690000.0, compressorMaximumPressure = 780000.0;
            double auxiliaryReservoirChargeRate = 200000.0;
            double equalizingReservoirChargeRate = 200000.0, equalizingReservoirServiceRate = 50000.0, equalizingReservoirEmergencyRate = 250000.0;
            double brakePipeNormalPressure = 0.0, brakePipeChargeRate = 10000000.0, brakePipeServiceRate = 1500000.0, brakePipeEmergencyRate = 5000000.0;
            double straightAirPipeServiceRate = 300000.0, straightAirPipeEmergencyRate = 400000.0, straightAirPipeReleaseRate = 200000.0;
            double brakeCylinderServiceMaximumPressure = 440000.0, brakeCylinderEmergencyMaximumPressure = 440000.0, brakeCylinderEmergencyRate = 300000.0, brakeCylinderReleaseRate = 200000.0;

            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 "compressor":
                    Train.Cars[Car].CarBrake.brakeType = BrakeType.Main;                             //We have a compressor so must be a main brake type
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "rate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out compressorRate) | compressorRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid compression rate defined for Car " + Car + " in XML file " + fileName);
                                    compressorRate = 5000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "mainreservoir":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "minimumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out compressorMinimumPressure) | compressorMinimumPressure <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid main reservoir minumum pressure defined for Car " + Car + " in XML file " + fileName);
                                    compressorMinimumPressure = 690000.0;
                                }
                                break;

                            case "maximumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out compressorMaximumPressure) | compressorMaximumPressure <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid main reservoir maximum pressure defined for Car " + Car + " in XML file " + fileName);
                                    compressorMaximumPressure = 780000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "auxiliaryreservoir":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "chargerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out auxiliaryReservoirChargeRate) | auxiliaryReservoirChargeRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid auxiliary reservoir charge rate defined for Car " + Car + " in XML file " + fileName);
                                    auxiliaryReservoirChargeRate = 200000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "equalizingreservoir":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "chargerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out equalizingReservoirChargeRate) | equalizingReservoirChargeRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid equalizing reservoir charge rate defined for Car " + Car + " in XML file " + fileName);
                                    equalizingReservoirChargeRate = 50000.0;
                                }
                                break;

                            case "servicerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out equalizingReservoirServiceRate) | equalizingReservoirServiceRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid equalizing reservoir service rate defined for Car " + Car + " in XML file " + fileName);
                                    equalizingReservoirServiceRate = 50000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out equalizingReservoirEmergencyRate) | equalizingReservoirEmergencyRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid equalizing reservoir emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    equalizingReservoirEmergencyRate = 50000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "brakepipe":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "normalpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeNormalPressure) | brakePipeNormalPressure <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake pipe normal pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeNormalPressure = 0.0;
                                }
                                break;

                            case "chargerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeChargeRate) | brakePipeChargeRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake pipe charge rate defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeChargeRate = 10000000.0;
                                }
                                break;

                            case "servicerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeServiceRate) | brakePipeServiceRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake pipe service rate defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeServiceRate = 1500000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeEmergencyRate) | brakePipeEmergencyRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake pipe emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeEmergencyRate = 400000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "straightairpipe":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "servicerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out straightAirPipeServiceRate) | straightAirPipeServiceRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid straight air pipe service rate defined for Car " + Car + " in XML file " + fileName);
                                    straightAirPipeServiceRate = 300000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out straightAirPipeEmergencyRate) | straightAirPipeEmergencyRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid straight air pipe emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    straightAirPipeEmergencyRate = 400000.0;
                                }
                                break;

                            case "releaserate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out straightAirPipeReleaseRate) | straightAirPipeReleaseRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid straight air pipe emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    straightAirPipeReleaseRate = 200000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "brakecylinder":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "servicemaximumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderServiceMaximumPressure) | brakeCylinderServiceMaximumPressure <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake cylinder service pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderServiceMaximumPressure = 440000.0;
                                }
                                break;

                            case "emergencymaximumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderEmergencyMaximumPressure) | brakeCylinderEmergencyMaximumPressure <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake cylinder emergency pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderEmergencyMaximumPressure = 440000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderEmergencyRate) | brakeCylinderEmergencyRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake cylinder emergency pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderEmergencyRate = 300000.0;
                                }
                                break;

                            case "releaserate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderReleaseRate) | brakeCylinderReleaseRate <= 0.0)
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid brake cylinder emergency pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderReleaseRate = 200000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;
                }
            }
            Train.Cars[Car].CarBrake.airCompressor       = new Compressor(compressorRate);
            Train.Cars[Car].CarBrake.mainReservoir       = new MainReservoir(compressorMinimumPressure, compressorMaximumPressure, 0.01, (Train.Handles.Brake is TrainManager.AirBrakeHandle ? 0.25 : 0.075) / Train.Cars.Length);
            Train.Cars[Car].CarBrake.equalizingReservoir = new EqualizingReservoir(equalizingReservoirServiceRate, equalizingReservoirEmergencyRate, equalizingReservoirChargeRate);
            Train.Cars[Car].CarBrake.equalizingReservoir.NormalPressure = 1.005 * brakePipeNormalPressure;

            Train.Cars[Car].CarBrake.brakePipe = new BrakePipe(brakePipeNormalPressure, brakePipeChargeRate, brakePipeServiceRate, brakePipeEmergencyRate, Train.Cars[0].CarBrake is ElectricCommandBrake);
            {
                double r = 200000.0 / brakeCylinderEmergencyMaximumPressure - 1.0;
                if (r < 0.1)
                {
                    r = 0.1;
                }
                if (r > 1.0)
                {
                    r = 1.0;
                }
                Train.Cars[Car].CarBrake.auxiliaryReservoir = new AuxiliaryReservoir(0.975 * brakePipeNormalPressure, auxiliaryReservoirChargeRate, 0.5, r);
            }
            Train.Cars[Car].CarBrake.brakeCylinder   = new BrakeCylinder(brakeCylinderServiceMaximumPressure, brakeCylinderEmergencyMaximumPressure, Train.Handles.Brake is TrainManager.AirBrakeHandle ? brakeCylinderEmergencyRate : 0.3 * brakeCylinderEmergencyRate, brakeCylinderEmergencyRate, brakeCylinderReleaseRate);
            Train.Cars[Car].CarBrake.straightAirPipe = new StraightAirPipe(straightAirPipeServiceRate, straightAirPipeEmergencyRate, straightAirPipeReleaseRate);
        }
Ejemplo n.º 10
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 "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(Interface.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(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 = Camera.RestrictionMode.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   = Camera.RestrictionMode.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);
                }
            }
        }
Ejemplo n.º 11
0
 internal override void Trigger(int Direction, EventTriggerType TriggerType, TrainManager.Train Train, int CarIndex)
 {
     if (TriggerType == EventTriggerType.Camera)
     {
         if (Direction < 0)
         {
             Game.PreviousFog = this.PreviousFog;
             Game.NextFog     = this.CurrentFog;
         }
         else if (Direction > 0)
         {
             Game.PreviousFog = this.CurrentFog;
             Game.NextFog     = this.NextFog;
         }
     }
 }