Esempio n. 1
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.Specs.ReadhesionDeviceType;
            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;
                        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":
                    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))
                    {
                        CarObjects[Car] = ObjectManager.LoadObject(f, System.Text.Encoding.Default, false);
                    }
                    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))
                                {
                                    BogieObjects[Car * 2] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, false);
                                }
                                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))
                                {
                                    BogieObjects[Car * 2 + 1] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, false);
                                }
                                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), Encoding.UTF8, 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);
                }
            }
            //Assign readhesion device properties
            if (Train.Cars[Car].Specs.IsMotorCar)
            {
                switch (readhesionDevice)
                {
                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;
                }
            }
        }
Esempio n. 2
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);
                }
            }
        }
Esempio n. 3
0
        /// <summary>Attempts to load and parse the current train's panel configuration file.</summary>
        /// <param name="TrainPath">The absolute on-disk path to the train folder.</param>
        /// <param name="Encoding">The automatically detected or manually set encoding of the panel configuration file.</param>
        /// <param name="Train">The base train on which to apply the panel configuration.</param>
        internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Encoding, TrainManager.Train Train)
        {
            string File = OpenBveApi.Path.CombineFile(TrainPath, "panel.animated");

            if (System.IO.File.Exists(File))
            {
                Program.AppendToLogFile("Loading train panel: " + File);
                ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(File, Encoding, ObjectManager.ObjectLoadMode.DontAllowUnloadOfTextures);
                try
                {
                    for (int i = 0; i < a.Objects.Length; i++)
                    {
                        a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                    }
                    Train.Cars[Train.DriverCar].CarSections[0].Elements = a.Objects;
                    Train.Cars[Train.DriverCar].CameraRestrictionMode   = World.CameraRestrictionMode.NotAvailable;
                    World.CameraRestriction = World.CameraRestrictionMode.NotAvailable;
                    World.UpdateViewingDistances();
                }
                catch
                {
                    var currentError = Interface.GetInterfaceString("error_critical_file");
                    currentError = currentError.Replace("[file]", "panel.animated");
                    MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Program.RestartArguments = " ";
                    Loading.Cancel           = true;
                }
            }
            else
            {
                var Panel2 = false;
                try
                {
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg");
                    if (System.IO.File.Exists(File))
                    {
                        Program.AppendToLogFile("Loading train panel: " + File);
                        Panel2 = true;
                        Panel2CfgParser.ParsePanel2Config("panel2.cfg", TrainPath, Encoding, Train, Train.DriverCar);
                        Train.Cars[Train.DriverCar].CameraRestrictionMode = World.CameraRestrictionMode.On;
                        World.CameraRestriction = World.CameraRestrictionMode.On;
                    }
                    else
                    {
                        File = OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg");
                        if (System.IO.File.Exists(File))
                        {
                            Program.AppendToLogFile("Loading train panel: " + File);
                            PanelCfgParser.ParsePanelConfig(TrainPath, Encoding, Train);
                            Train.Cars[Train.DriverCar].CameraRestrictionMode = World.CameraRestrictionMode.On;
                            World.CameraRestriction = World.CameraRestrictionMode.On;
                        }
                        else
                        {
                            World.CameraRestriction = World.CameraRestrictionMode.NotAvailable;
                        }
                    }
                }
                catch
                {
                    var currentError = Interface.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", Panel2 == true ? "panel2.cfg" : "panel.cfg");
                    MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Program.RestartArguments = " ";
                    Loading.Cancel           = true;
                }
            }
        }
Esempio n. 4
0
        /// <summary>Attempts to load and parse the current train's panel configuration file.</summary>
        /// <param name="TrainPath">The absolute on-disk path to the train folder.</param>
        /// <param name="Encoding">The automatically detected or manually set encoding of the panel configuration file.</param>
        /// <param name="Train">The base train on which to apply the panel configuration.</param>
        internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Encoding, Train Train)
        {
            Train.Cars[Train.DriverCar].CarSections    = new CarSection[1];
            Train.Cars[Train.DriverCar].CarSections[0] = new CarSection
            {
                Groups = new ElementsGroup[1]
            };
            Train.Cars[Train.DriverCar].CarSections[0].Groups[0] = new ElementsGroup
            {
                Elements = new ObjectManager.AnimatedObject[] { },
                Overlay  = true
            };
            string File = OpenBveApi.Path.CombineFile(TrainPath, "panel.xml");

            if (!System.IO.File.Exists(File))
            {
                //Try animated variant too
                File = OpenBveApi.Path.CombineFile(TrainPath, "panel.animated.xml");
            }
            if (System.IO.File.Exists(File))
            {
                Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                try
                {
                    /*
                     * First load the XML. We use this to determine
                     * whether this is a 2D or a 3D animated panel
                     */
                    XDocument CurrentXML = XDocument.Load(File, LoadOptions.SetLineInfo);

                    // Check for null
                    if (CurrentXML.Root != null)
                    {
                        IEnumerable <XElement> DocumentElements = CurrentXML.Root.Elements("PanelAnimated");
                        if (DocumentElements.Any())
                        {
                            PanelAnimatedXmlParser.ParsePanelAnimatedXml(System.IO.Path.GetFileName(File), TrainPath, Train, Train.DriverCar);
                            Train.Cars[Train.DriverCar].CameraRestrictionMode = Camera.RestrictionMode.NotAvailable;
                            World.CameraRestriction = Camera.RestrictionMode.NotAvailable;
                        }

                        DocumentElements = CurrentXML.Root.Elements("Panel");
                        if (DocumentElements.Any())
                        {
                            PanelXmlParser.ParsePanelXml(System.IO.Path.GetFileName(File), TrainPath, Train, Train.DriverCar);
                            Train.Cars[Train.DriverCar].CameraRestrictionMode = Camera.RestrictionMode.On;
                            World.CameraRestriction = Camera.RestrictionMode.On;
                        }
                    }
                }
                catch
                {
                    var currentError = Translations.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", "panel.xml");
                    MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Program.RestartArguments = " ";
                    Loading.Cancel           = true;
                    return;
                }

                if (Train.Cars[Train.DriverCar].CarSections[0].Groups[0].Elements.Any())
                {
                    World.UpdateViewingDistances();
                    return;
                }
                Interface.AddMessage(MessageType.Error, false, "The panel.xml file " + File + " failed to load. Falling back to legacy panel.");
            }
            else
            {
                File = OpenBveApi.Path.CombineFile(TrainPath, "panel.animated");
                if (System.IO.File.Exists(File))
                {
                    Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                    if (System.IO.File.Exists(OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg")) || System.IO.File.Exists(OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg")))
                    {
                        Program.FileSystem.AppendToLogFile("INFO: This train contains both a 2D and a 3D panel. The 3D panel will always take precedence");
                    }
                    ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(File, Encoding);
                    if (a != null)
                    {
                        //HACK: If a == null , loading our animated object completely failed (Missing objects?). Fallback to trying the panel2.cfg
                        try
                        {
                            for (int i = 0; i < a.Objects.Length; i++)
                            {
                                a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                            }
                            Train.Cars[Train.DriverCar].CarSections[0].Groups[0].Elements = a.Objects;
                            Train.Cars[Train.DriverCar].CameraRestrictionMode             = Camera.RestrictionMode.NotAvailable;
                            World.CameraRestriction = Camera.RestrictionMode.NotAvailable;
                            World.UpdateViewingDistances();
                            return;
                        }
                        catch
                        {
                            var currentError = Translations.GetInterfaceString("errors_critical_file");
                            currentError = currentError.Replace("[file]", "panel.animated");
                            MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                            Program.RestartArguments = " ";
                            Loading.Cancel           = true;
                            return;
                        }
                    }
                    Interface.AddMessage(MessageType.Error, false, "The panel.animated file " + File + " failed to load. Falling back to 2D panel.");
                }
            }

            var Panel2 = false;

            try
            {
                File = OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg");
                if (System.IO.File.Exists(File))
                {
                    Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                    Panel2 = true;
                    Panel2CfgParser.ParsePanel2Config("panel2.cfg", TrainPath, Encoding, Train, Train.DriverCar);
                    Train.Cars[Train.DriverCar].CameraRestrictionMode = Camera.RestrictionMode.On;
                    World.CameraRestriction = Camera.RestrictionMode.On;
                }
                else
                {
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg");
                    if (System.IO.File.Exists(File))
                    {
                        Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                        PanelCfgParser.ParsePanelConfig(TrainPath, Encoding, Train);
                        Train.Cars[Train.DriverCar].CameraRestrictionMode = Camera.RestrictionMode.On;
                        World.CameraRestriction = Camera.RestrictionMode.On;
                    }
                    else
                    {
                        World.CameraRestriction = Camera.RestrictionMode.NotAvailable;
                    }
                }
            }
            catch
            {
                var currentError = Translations.GetInterfaceString("errors_critical_file");
                currentError = currentError.Replace("[file]", Panel2 ? "panel2.cfg" : "panel.cfg");
                MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                Program.RestartArguments = " ";
                Loading.Cancel           = true;
            }
        }
Esempio n. 5
0
        /// <summary>Attempts to load and parse the current train's panel configuration file.</summary>
        /// <param name="Train">The train</param>
        /// <param name="Encoding">The selected train encoding</param>
        internal void ParsePanelConfig(TrainBase Train, Encoding Encoding)
        {
            Train.Cars[Train.DriverCar].CarSections    = new CarSection[1];
            Train.Cars[Train.DriverCar].CarSections[0] = new CarSection(currentHost, ObjectType.Overlay, true);
            string File = Path.CombineFile(Train.TrainFolder, "panel.xml");

            if (!System.IO.File.Exists(File))
            {
                //Try animated variant too
                File = Path.CombineFile(Train.TrainFolder, "panel.animated.xml");
            }

            if (System.IO.File.Exists(File))
            {
                FileSystem.AppendToLogFile("Loading train panel: " + File);
                try
                {
                    /*
                     * First load the XML. We use this to determine
                     * whether this is a 2D or a 3D animated panel
                     */
                    XDocument CurrentXML = XDocument.Load(File, LoadOptions.SetLineInfo);

                    // Check for null
                    if (CurrentXML.Root != null)
                    {
                        IEnumerable <XElement> DocumentElements = CurrentXML.Root.Elements("PanelAnimated");
                        if (DocumentElements.Any())
                        {
                            PanelAnimatedXmlParser.ParsePanelAnimatedXml(System.IO.Path.GetFileName(File), Train, Train.DriverCar);
                            if (Train.Cars[Train.DriverCar].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                            {
                                Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.NotAvailable;
                            }
                            return;
                        }

                        DocumentElements = CurrentXML.Root.Elements("Panel");
                        if (DocumentElements.Any())
                        {
                            PanelXmlParser.ParsePanelXml(System.IO.Path.GetFileName(File), Train, Train.DriverCar);
                            Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.On;
                            Renderer.Camera.CurrentRestriction = CameraRestrictionMode.On;
                            return;
                        }
                    }
                }
                catch
                {
                    var currentError = Translations.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", "panel.xml");
                    currentHost.ReportProblem(ProblemType.InvalidData, currentError);
                    Cancel = true;
                    return;
                }

                currentHost.AddMessage(MessageType.Error, false, "The panel.xml file " + File + " failed to load. Falling back to legacy panel.");
            }
            else
            {
                File = Path.CombineFile(Train.TrainFolder, "panel.animated");
                if (System.IO.File.Exists(File))
                {
                    FileSystem.AppendToLogFile("Loading train panel: " + File);
                    if (System.IO.File.Exists(Path.CombineFile(Train.TrainFolder, "panel2.cfg")) || System.IO.File.Exists(Path.CombineFile(Train.TrainFolder, "panel.cfg")))
                    {
                        FileSystem.AppendToLogFile("INFO: This train contains both a 2D and a 3D panel. The 3D panel will always take precedence");
                    }

                    UnifiedObject currentObject;
                    currentHost.LoadObject(File, Encoding, out currentObject);
                    var a = currentObject as AnimatedObjectCollection;
                    if (a != null)
                    {
                        //HACK: If a == null , loading our animated object completely failed (Missing objects?). Fallback to trying the panel2.cfg
                        try
                        {
                            for (int i = 0; i < a.Objects.Length; i++)
                            {
                                currentHost.CreateDynamicObject(ref a.Objects[i].internalObject);
                            }

                            Train.Cars[Train.DriverCar].CarSections[0].Groups[0].Elements = a.Objects;
                            if (Train.Cars[Train.DriverCar].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                            {
                                Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.NotAvailable;
                                Renderer.Camera.CurrentRestriction = CameraRestrictionMode.NotAvailable;
                            }

                            return;
                        }
                        catch
                        {
                            var currentError = Translations.GetInterfaceString("errors_critical_file");
                            currentError = currentError.Replace("[file]", "panel.animated");
                            currentHost.ReportProblem(ProblemType.InvalidData, currentError);
                            Cancel = true;
                            return;
                        }
                    }

                    currentHost.AddMessage(MessageType.Error, false, "The panel.animated file " + File + " failed to load. Falling back to 2D panel.");
                }
            }

            var Panel2 = false;

            try
            {
                File = Path.CombineFile(Train.TrainFolder, "panel2.cfg");
                if (System.IO.File.Exists(File))
                {
                    FileSystem.AppendToLogFile("Loading train panel: " + File);
                    Panel2 = true;
                    Panel2CfgParser.ParsePanel2Config("panel2.cfg", Train.TrainFolder, Train.Cars[Train.DriverCar]);
                    Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.On;
                    Renderer.Camera.CurrentRestriction = CameraRestrictionMode.On;
                }
                else
                {
                    File = Path.CombineFile(Train.TrainFolder, "panel.cfg");
                    if (System.IO.File.Exists(File))
                    {
                        FileSystem.AppendToLogFile("Loading train panel: " + File);
                        PanelCfgParser.ParsePanelConfig(Train.TrainFolder, Encoding, Train.Cars[Train.DriverCar]);
                        Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.On;
                        Renderer.Camera.CurrentRestriction = CameraRestrictionMode.On;
                    }
                    else
                    {
                        Renderer.Camera.CurrentRestriction = CameraRestrictionMode.NotAvailable;
                    }
                }
            }
            catch
            {
                var currentError = Translations.GetInterfaceString("errors_critical_file");
                currentError = currentError.Replace("[file]", Panel2 ? "panel2.cfg" : "panel.cfg");
                currentHost.ReportProblem(ProblemType.InvalidData, currentError);
                Cancel = true;
            }
        }
Esempio n. 6
0
            /// <summary>Attempts to load and parse the current train's panel configuration file.</summary>
            /// <param name="TrainPath">The absolute on-disk path to the train folder.</param>
            /// <param name="Encoding">The selected train encoding</param>
            internal void ParsePanelConfig(string TrainPath, System.Text.Encoding Encoding)
            {
                Cars[DriverCar].CarSections    = new CarSection[1];
                Cars[DriverCar].CarSections[0] = new CarSection(Program.CurrentHost, ObjectType.Overlay);
                string File = OpenBveApi.Path.CombineFile(TrainPath, "panel.xml");

                if (!System.IO.File.Exists(File))
                {
                    //Try animated variant too
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel.animated.xml");
                }

                if (System.IO.File.Exists(File))
                {
                    Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                    try
                    {
                        /*
                         * First load the XML. We use this to determine
                         * whether this is a 2D or a 3D animated panel
                         */
                        XDocument CurrentXML = XDocument.Load(File, LoadOptions.SetLineInfo);

                        // Check for null
                        if (CurrentXML.Root != null)
                        {
                            IEnumerable <XElement> DocumentElements = CurrentXML.Root.Elements("PanelAnimated");
                            if (DocumentElements.Any())
                            {
                                PanelAnimatedXmlParser.ParsePanelAnimatedXml(System.IO.Path.GetFileName(File), TrainPath, this, DriverCar);
                                if (Cars[DriverCar].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                                {
                                    Cars[DriverCar].CameraRestrictionMode = CameraRestrictionMode.NotAvailable;
                                }
                            }

                            DocumentElements = CurrentXML.Root.Elements("Panel");
                            if (DocumentElements.Any())
                            {
                                PanelXmlParser.ParsePanelXml(System.IO.Path.GetFileName(File), TrainPath, this, DriverCar);
                                Cars[DriverCar].CameraRestrictionMode      = CameraRestrictionMode.On;
                                Program.Renderer.Camera.CurrentRestriction = CameraRestrictionMode.On;
                            }
                        }
                    }
                    catch
                    {
                        var currentError = Translations.GetInterfaceString("errors_critical_file");
                        currentError = currentError.Replace("[file]", "panel.xml");
                        MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                        Program.RestartArguments = " ";
                        Loading.Cancel           = true;
                        return;
                    }

                    if (Cars[DriverCar].CarSections[0].Groups[0].Elements.Any())
                    {
                        OpenBVEGame.RunInRenderThread(() =>
                        {
                            //Needs to be on the thread containing the openGL context
                            Program.Renderer.InitializeVisibility();
                        });
                        Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                        return;
                    }

                    Interface.AddMessage(MessageType.Error, false, "The panel.xml file " + File + " failed to load. Falling back to legacy panel.");
                }
                else
                {
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel.animated");
                    if (System.IO.File.Exists(File))
                    {
                        Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                        if (System.IO.File.Exists(OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg")) || System.IO.File.Exists(OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg")))
                        {
                            Program.FileSystem.AppendToLogFile("INFO: This train contains both a 2D and a 3D panel. The 3D panel will always take precedence");
                        }

                        UnifiedObject currentObject;
                        Program.CurrentHost.LoadObject(File, Encoding, out currentObject);
                        var a = currentObject as AnimatedObjectCollection;
                        if (a != null)
                        {
                            //HACK: If a == null , loading our animated object completely failed (Missing objects?). Fallback to trying the panel2.cfg
                            try
                            {
                                for (int i = 0; i < a.Objects.Length; i++)
                                {
                                    Program.CurrentHost.CreateDynamicObject(ref a.Objects[i].internalObject);
                                }

                                Cars[DriverCar].CarSections[0].Groups[0].Elements = a.Objects;
                                if (Cars[DriverCar].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                                {
                                    Cars[DriverCar].CameraRestrictionMode      = CameraRestrictionMode.NotAvailable;
                                    Program.Renderer.Camera.CurrentRestriction = CameraRestrictionMode.NotAvailable;
                                }

                                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                                return;
                            }
                            catch
                            {
                                var currentError = Translations.GetInterfaceString("errors_critical_file");
                                currentError = currentError.Replace("[file]", "panel.animated");
                                MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                                Program.RestartArguments = " ";
                                Loading.Cancel           = true;
                                return;
                            }
                        }

                        Interface.AddMessage(MessageType.Error, false, "The panel.animated file " + File + " failed to load. Falling back to 2D panel.");
                    }
                }

                var Panel2 = false;

                try
                {
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg");
                    if (System.IO.File.Exists(File))
                    {
                        Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                        Panel2 = true;
                        Panel2CfgParser.ParsePanel2Config("panel2.cfg", TrainPath, Cars[DriverCar]);
                        Cars[DriverCar].CameraRestrictionMode      = CameraRestrictionMode.On;
                        Program.Renderer.Camera.CurrentRestriction = CameraRestrictionMode.On;
                    }
                    else
                    {
                        File = OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg");
                        if (System.IO.File.Exists(File))
                        {
                            Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                            PanelCfgParser.ParsePanelConfig(TrainPath, Encoding, Cars[DriverCar]);
                            Cars[DriverCar].CameraRestrictionMode      = CameraRestrictionMode.On;
                            Program.Renderer.Camera.CurrentRestriction = CameraRestrictionMode.On;
                        }
                        else
                        {
                            Program.Renderer.Camera.CurrentRestriction = CameraRestrictionMode.NotAvailable;
                        }
                    }
                }
                catch
                {
                    var currentError = Translations.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", Panel2 ? "panel2.cfg" : "panel.cfg");
                    MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Program.RestartArguments = " ";
                    Loading.Cancel           = true;
                }
            }
Esempio n. 7
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);
                }
            }
        }
Esempio n. 8
0
        /// <summary>Attempts to load and parse the current train's panel configuration file.</summary>
        /// <param name="TrainPath">The absolute on-disk path to the train folder.</param>
        /// <param name="Encoding">The automatically detected or manually set encoding of the panel configuration file.</param>
        /// <param name="Train">The base train on which to apply the panel configuration.</param>
        internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Encoding, Train Train)
        {
            Train.Cars[Train.DriverCar].CarSections    = new CarSection[1];
            Train.Cars[Train.DriverCar].CarSections[0] = new CarSection
            {
                Elements = new ObjectManager.AnimatedObject[] { },
                Overlay  = true
            };
            string File = OpenBveApi.Path.CombineFile(TrainPath, "panel.animated");

            if (System.IO.File.Exists(File))
            {
                Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                if (System.IO.File.Exists(OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg")) || System.IO.File.Exists(OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg")))
                {
                    Program.FileSystem.AppendToLogFile("INFO: This train contains both a 2D and a 3D panel. The 3D panel will always take precedence");
                }
                ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(File, Encoding);
                if (a != null)
                {
                    //HACK: If a == null , loading our animated object completely failed (Missing objects?). Fallback to trying the panel2.cfg
                    try
                    {
                        for (int i = 0; i < a.Objects.Length; i++)
                        {
                            a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                        }
                        Train.Cars[Train.DriverCar].CarSections[0].Elements = a.Objects;
                        Train.Cars[Train.DriverCar].CameraRestrictionMode   = Camera.RestrictionMode.NotAvailable;
                        World.CameraRestriction = Camera.RestrictionMode.NotAvailable;
                        World.UpdateViewingDistances();
                        return;
                    }
                    catch
                    {
                        var currentError = Translations.GetInterfaceString("errors_critical_file");
                        currentError = currentError.Replace("[file]", "panel.animated");
                        MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                        Program.RestartArguments = " ";
                        Loading.Cancel           = true;
                        return;
                    }
                }
                Interface.AddMessage(MessageType.Error, false, "The panel.animated file " + File + " failed to load. Falling back to 2D panel.");
            }

            var Panel2 = false;

            try
            {
                File = OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg");
                if (System.IO.File.Exists(File))
                {
                    Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                    Panel2 = true;
                    Panel2CfgParser.ParsePanel2Config("panel2.cfg", TrainPath, Encoding, Train, Train.DriverCar);
                    Train.Cars[Train.DriverCar].CameraRestrictionMode = Camera.RestrictionMode.On;
                    World.CameraRestriction = Camera.RestrictionMode.On;
                }
                else
                {
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg");
                    if (System.IO.File.Exists(File))
                    {
                        Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                        PanelCfgParser.ParsePanelConfig(TrainPath, Encoding, Train);
                        Train.Cars[Train.DriverCar].CameraRestrictionMode = Camera.RestrictionMode.On;
                        World.CameraRestriction = Camera.RestrictionMode.On;
                    }
                    else
                    {
                        World.CameraRestriction = Camera.RestrictionMode.NotAvailable;
                    }
                }
            }
            catch
            {
                var currentError = Translations.GetInterfaceString("errors_critical_file");
                currentError = currentError.Replace("[file]", Panel2 == true ? "panel2.cfg" : "panel.cfg");
                MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                Program.RestartArguments = " ";
                Loading.Cancel           = true;
            }
        }