AddMessage() static private method

static private AddMessage ( MessageType Type, bool FileNotFound, string Text ) : void
Type MessageType
FileNotFound bool
Text string
return void
示例#1
0
        /// <summary>Loads the available compatibility object database</summary>
        /// <param name="fileName">The database file</param>
        internal static void LoadCompatibilityObjects(string fileName)
        {
            if (!System.IO.File.Exists(fileName))
            {
                return;
            }
            string      d          = System.IO.Path.GetDirectoryName(fileName);
            XmlDocument currentXML = new XmlDocument();

            try
            {
                currentXML.Load(fileName);
            }
            catch
            {
                return;
            }

            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Compatibility/Object");
                //Check this file actually contains OpenBVE compatibility nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode n in DocumentNodes)
                    {
                        if (n.ChildNodes.OfType <XmlElement>().Any())
                        {
                            ReplacementObject o     = new ReplacementObject();
                            string[]          names = null;
                            foreach (XmlNode c in n.ChildNodes)
                            {
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "name":
                                    if (c.InnerText.IndexOf(';') == -1)
                                    {
                                        names = new string[]
                                        {
                                            c.InnerText
                                        };
                                    }
                                    else
                                    {
                                        names = c.InnerText.Split(';');
                                    }
                                    break;

                                case "path":
                                    string f = OpenBveApi.Path.CombineFile(d, c.InnerText.Trim());
                                    if (System.IO.File.Exists(f))
                                    {
                                        o.ReplacementPath = f;
                                    }
                                    break;

                                case "message":
                                    o.Message = c.InnerText.Trim();
                                    break;

                                default:
                                    Interface.AddMessage(MessageType.Warning, false, "Unexpected entry " + c.Name + " found in compatability object XML " + fileName);
                                    break;
                                }
                            }
                            if (names != null)
                            {
                                o.ObjectNames = names;
                                if (o.ReplacementPath != string.Empty)
                                {
                                    int i = AvailableReplacements.Length;
                                    Array.Resize(ref AvailableReplacements, i + 1);
                                    AvailableReplacements[i] = o;
                                }
                            }
                        }
                    }
                    DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Compatibility/Sound");
                    //Check this file actually contains OpenBVE compatibility nodes
                    if (DocumentNodes != null)
                    {
                        foreach (XmlNode n in DocumentNodes)
                        {
                            if (n.ChildNodes.OfType <XmlElement>().Any())
                            {
                                ReplacementObject o     = new ReplacementObject();
                                string[]          names = null;
                                foreach (XmlNode c in n.ChildNodes)
                                {
                                    switch (c.Name.ToLowerInvariant())
                                    {
                                    case "name":
                                        if (c.InnerText.IndexOf(';') == -1)
                                        {
                                            names = new string[]
                                            {
                                                c.InnerText
                                            };
                                        }
                                        else
                                        {
                                            names = c.InnerText.Split(';');
                                        }
                                        break;

                                    case "path":
                                        string f = OpenBveApi.Path.CombineFile(d, c.InnerText.Trim());
                                        if (System.IO.File.Exists(f))
                                        {
                                            o.ReplacementPath = f;
                                        }
                                        break;

                                    case "message":
                                        o.Message = c.InnerText.Trim();
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Warning, false,
                                                             "Unexpected entry " + c.Name + " found in compatability object XML " + fileName);
                                        break;
                                    }
                                }
                                if (names != null)
                                {
                                    o.ObjectNames = names;
                                    if (o.ReplacementPath != string.Empty)
                                    {
                                        int i = AvailableSounds.Length;
                                        Array.Resize(ref AvailableSounds, i + 1);
                                        AvailableSounds[i] = o;
                                    }
                                }
                            }
                        }
                    }
                    //Now try and load any object list XML files this references
                    DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Compatibility/ObjectList");

                    if (DocumentNodes != null)
                    {
                        foreach (XmlNode n in DocumentNodes)
                        {
                            if (n.ChildNodes.OfType <XmlElement>().Any())
                            {
                                foreach (XmlNode c in n.ChildNodes)
                                {
                                    switch (c.Name.ToLowerInvariant())
                                    {
                                    case "filename":
                                        var f = c.InnerText.Trim();
                                        if (!System.IO.File.Exists(f))
                                        {
                                            try
                                            {
                                                f = OpenBveApi.Path.CombineFile(d, f);
                                            }
                                            catch
                                            { }
                                        }
                                        LoadCompatibilityObjects(f);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Warning, false, "Unexpected entry " + c.Name + " found in compatability XML list " + fileName);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        internal static void ParseExtensionsConfig(string filePath, Encoding encoding, out UnifiedObject[] carObjects, out UnifiedObject[] bogieObjects, out double[] axleLocations, out TrainManager.Train train, bool loadObjects)
        {
            CultureInfo Culture = CultureInfo.InvariantCulture;

            carObjects    = new UnifiedObject[] { };
            bogieObjects  = new UnifiedObject[] { };
            axleLocations = new double[] { };
            train         = new TrainManager.Train();

            if (!System.IO.File.Exists(filePath))
            {
                return;
            }

            train.Cars = new TrainManager.Car[] { };
            bool[] carObjectsReversed   = new bool[train.Cars.Length];
            bool[] bogieObjectsReversed = new bool[train.Cars.Length * 2];
            bool[] carsDefined          = new bool[train.Cars.Length];
            bool[] bogiesDefined        = new bool[train.Cars.Length * 2];
            axleLocations = new double[train.Cars.Length * 2];

            string trainPath = System.IO.Path.GetDirectoryName(filePath);

            System.Globalization.CultureInfo culture     = System.Globalization.CultureInfo.InvariantCulture;
            TextEncoding.Encoding            newEncoding = TextEncoding.GetEncodingFromFile(filePath);
            if (newEncoding != TextEncoding.Encoding.Unknown)
            {
                switch (newEncoding)
                {
                case TextEncoding.Encoding.Utf7:
                    encoding = Encoding.UTF7;
                    break;

                case TextEncoding.Encoding.Utf8:
                    encoding = Encoding.UTF8;
                    break;

                case TextEncoding.Encoding.Utf16Le:
                    encoding = Encoding.Unicode;
                    break;

                case TextEncoding.Encoding.Utf16Be:
                    encoding = Encoding.BigEndianUnicode;
                    break;

                case TextEncoding.Encoding.Utf32Le:
                    encoding = Encoding.UTF32;
                    break;

                case TextEncoding.Encoding.Utf32Be:
                    encoding = Encoding.GetEncoding(12001);
                    break;

                case TextEncoding.Encoding.Shift_JIS:
                    encoding = Encoding.GetEncoding(932);
                    break;
                }
            }

            string[] lines = System.IO.File.ReadAllLines(filePath, encoding);
            for (int i = 0; i < lines.Length; i++)
            {
                int j = lines[i].IndexOf(';');
                if (j >= 0)
                {
                    lines[i] = lines[i].Substring(0, j).Trim();
                }
                else
                {
                    lines[i] = lines[i].Trim();
                }
            }

            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Length != 0)
                {
                    switch (lines[i].ToLowerInvariant())
                    {
                    case "[exterior]":
                        // exterior
                        i++;
                        while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            if (lines[i].Length != 0)
                            {
                                int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                if (j >= 0)
                                {
                                    string a = lines[i].Substring(0, j).TrimEnd();
                                    string b = lines[i].Substring(j + 1).TrimStart();
                                    int    n;
                                    if (int.TryParse(a, System.Globalization.NumberStyles.Integer, culture, out n))
                                    {
                                        if (n >= 0)
                                        {
                                            if (n >= train.Cars.Length)
                                            {
                                                Array.Resize(ref train.Cars, n + 1);
                                                Array.Resize(ref carObjects, n + 1);
                                                Array.Resize(ref bogieObjects, (n + 1) * 2);
                                                Array.Resize(ref carObjectsReversed, n + 1);
                                                Array.Resize(ref bogieObjectsReversed, (n + 1) * 2);
                                                Array.Resize(ref carsDefined, n + 1);
                                                Array.Resize(ref bogiesDefined, (n + 1) * 2);
                                            }
                                            if (Path.ContainsInvalidChars(b))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                            }
                                            else
                                            {
                                                string file = OpenBveApi.Path.CombineFile(trainPath, b);
                                                if (System.IO.File.Exists(file))
                                                {
                                                    if (loadObjects)
                                                    {
                                                        carObjects[n] = ObjectManager.LoadObject(file, encoding, false, false, false);
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(MessageType.Error, true, "The car object " + file + " does not exist at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "The car index " + a + " does not reference an existing car at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Invalid statement " + lines[i] + " encountered at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                }
                            }
                            i++;
                        }
                        i--;
                        break;

                    default:
                        if (lines[i].StartsWith("[car", StringComparison.OrdinalIgnoreCase) & lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            // car
                            string t = lines[i].Substring(4, lines[i].Length - 5);
                            int    n;
                            if (int.TryParse(t, System.Globalization.NumberStyles.Integer, culture, out n))
                            {
                                if (n >= 0)
                                {
                                    if (n >= train.Cars.Length)
                                    {
                                        Array.Resize(ref train.Cars, n + 1);
                                        Array.Resize(ref carObjects, n + 1);
                                        Array.Resize(ref bogieObjects, (n + 1) * 2);
                                        Array.Resize(ref carObjectsReversed, n + 1);
                                        Array.Resize(ref bogieObjectsReversed, (n + 1) * 2);
                                        Array.Resize(ref carsDefined, n + 1);
                                        Array.Resize(ref bogiesDefined, (n + 1) * 2);
                                        Array.Resize(ref axleLocations, (n + 1) * 2);
                                    }
                                    if (carsDefined[n])
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Car " + n.ToString(culture) + " has already been declared at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                    }
                                    carsDefined[n] = true;
                                    i++;
                                    while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                                    {
                                        if (lines[i].Length != 0)
                                        {
                                            int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                            if (j >= 0)
                                            {
                                                string a = lines[i].Substring(0, j).TrimEnd();
                                                string b = lines[i].Substring(j + 1).TrimStart();
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "object":
                                                    if (string.IsNullOrEmpty(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, true, "An empty car object was supplied at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                        break;
                                                    }
                                                    if (Path.ContainsInvalidChars(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                    }
                                                    else
                                                    {
                                                        string file = OpenBveApi.Path.CombineFile(trainPath, b);
                                                        if (System.IO.File.Exists(file))
                                                        {
                                                            if (loadObjects)
                                                            {
                                                                carObjects[n] = ObjectManager.LoadObject(file, encoding, false, false, false);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, "The car object " + file + " does not exist at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                        }
                                                    }
                                                    break;

                                                case "length":
                                                {
                                                    double m;
                                                    if (double.TryParse(b, System.Globalization.NumberStyles.Float, culture, out m))
                                                    {
                                                        if (m > 0.0)
                                                        {
                                                            train.Cars[n].Length = m;
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "Value is expected to be a positive floating-point number in " + a + " at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, "Value is expected to be a positive floating-point number in " + a + " at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                    }
                                                }
                                                break;

                                                case "reversed":
                                                    carObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase);
                                                    break;

                                                case "axles":
                                                    int k = b.IndexOf(',');
                                                    if (k >= 0)
                                                    {
                                                        string c = b.Substring(0, k).TrimEnd();
                                                        string d = b.Substring(k + 1).TrimStart();
                                                        double rear, front;
                                                        if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out rear))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "Rear is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + filePath);
                                                        }
                                                        else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out front))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "Front is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + filePath);
                                                        }
                                                        else if (rear >= front)
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "Rear is expected to be less than Front in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + filePath);
                                                        }
                                                        else
                                                        {
                                                            axleLocations[n]     = rear;
                                                            axleLocations[n + 1] = front;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + filePath);
                                                    }
                                                    break;

                                                default:
                                                    Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Invalid statement " + lines[i] + " encountered at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                            }
                                        }
                                        i++;
                                    }
                                    i--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The car index " + t + " does not reference an existing car at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                }
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(culture) + " in file " + filePath);
                            }
                        }
                        else if (lines[i].StartsWith("[bogie", StringComparison.OrdinalIgnoreCase) & lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            // car
                            string t = lines[i].Substring(6, lines[i].Length - 7);
                            int    n;
                            if (int.TryParse(t, System.Globalization.NumberStyles.Integer, culture, out n))
                            {
                                if (n >= train.Cars.Length * 2)
                                {
                                    Array.Resize(ref train.Cars, n / 2 + 1);
                                    Array.Resize(ref carObjects, n / 2 + 1);
                                    Array.Resize(ref bogieObjects, n + 2);
                                    Array.Resize(ref carObjectsReversed, n / 2 + 1);
                                    Array.Resize(ref bogieObjectsReversed, n + 2);
                                    Array.Resize(ref carsDefined, n / 2 + 1);
                                    Array.Resize(ref bogiesDefined, n + 2);
                                }

                                if (n > bogiesDefined.Length - 1)
                                {
                                    continue;
                                }
                                if (bogiesDefined[n])
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Bogie " + n.ToString(culture) + " has already been declared at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                }
                                bogiesDefined[n] = true;
                                //Assuming that there are two bogies per car
                                if (n >= 0 & n < train.Cars.Length * 2)
                                {
                                    i++;
                                    while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                                    {
                                        if (lines[i].Length != 0)
                                        {
                                            int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                            if (j >= 0)
                                            {
                                                string a = lines[i].Substring(0, j).TrimEnd();
                                                string b = lines[i].Substring(j + 1).TrimStart();
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "object":
                                                    if (Path.ContainsInvalidChars(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                    }
                                                    else
                                                    {
                                                        if (string.IsNullOrEmpty(b))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, "An empty bogie object was supplied at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                            break;
                                                        }
                                                        string file = OpenBveApi.Path.CombineFile(trainPath, b);
                                                        if (System.IO.File.Exists(file))
                                                        {
                                                            if (loadObjects)
                                                            {
                                                                bogieObjects[n] = ObjectManager.LoadObject(file, encoding, false, false, false);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, "The bogie object " + file + " does not exist at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                        }
                                                    }
                                                    break;

                                                case "length":
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "A defined length is not supported for bogies at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                }
                                                break;

                                                case "reversed":
                                                    bogieObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase);
                                                    break;

                                                case "axles":
                                                    //Axles aren't used in bogie positioning, just in rotation
                                                    break;

                                                default:
                                                    Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Invalid statement " + lines[i] + " encountered at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                            }
                                        }
                                        i++;
                                    }
                                    i--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The car index " + t + " does not reference an existing car at line " + (i + 1).ToString(culture) + " in file " + filePath);
                                }
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(culture) + " in file " + filePath);
                            }
                        }
                        else if (lines[i].StartsWith("[coupler", StringComparison.OrdinalIgnoreCase) & lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            i++;
                            while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                            {
                                /*
                                 * Coupler statments are currently not supported in Object Viewer
                                 */
                                i++;
                            }

                            i--;
                        }
                        else
                        {
                            // default
                            if (lines.Length == 1 && encoding.Equals(Encoding.Unicode))
                            {
                                /*
                                 * If only one line, there's a good possibility that our file is NOT Unicode at all
                                 * and that the misdetection has turned it into garbage
                                 *
                                 * Try again with ASCII instead
                                 */
                                ParseExtensionsConfig(filePath, Encoding.GetEncoding(1252), out carObjects, out bogieObjects, out axleLocations, out train, loadObjects);
                                return;
                            }
                            Interface.AddMessage(MessageType.Error, false, "Invalid statement " + lines[i] + " encountered at line " + (i + 1).ToString(culture) + " in file " + filePath);
                        }
                        break;
                    }
                }
            }

            // check for car objects and reverse if necessary
            int carObjectsCount = 0;

            for (int i = 0; i < train.Cars.Length; i++)
            {
                if (carObjects[i] != null)
                {
                    carObjectsCount++;
                    if (carObjectsReversed[i] && loadObjects)
                    {
                        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 bogieObjectsCount = 0;

            for (int i = 0; i < train.Cars.Length * 2; i++)
            {
                if (bogieObjects[i] != null)
                {
                    bogieObjectsCount++;
                    if (bogieObjectsReversed[i] && loadObjects)
                    {
                        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();
                        }
                    }
                }
            }

            if (carObjectsCount > 0 & carObjectsCount < train.Cars.Length)
            {
                Interface.AddMessage(MessageType.Warning, false, "An incomplete set of exterior objects was provided in file " + filePath);
            }

            if (bogieObjectsCount > 0 & bogieObjectsCount < train.Cars.Length * 2)
            {
                Interface.AddMessage(MessageType.Warning, false, "An incomplete set of bogie objects was provided in file " + filePath);
            }
        }
示例#3
0
        // --- functions ---

        /// <summary>Reports a problem to the host application.</summary>
        /// <param name="type">The type of problem that is reported.</param>
        /// <param name="text">The textual message that describes the problem.</param>
        public override void ReportProblem(OpenBveApi.Hosts.ProblemType type, string text)
        {
            Interface.AddMessage(MessageType.Error, false, text);
        }
示例#4
0
        /// <summary>Saves the current in-game black box log</summary>
        internal static void SaveLogs()
        {
            if (Interface.CurrentOptions.BlackBox == false)
            {
                return;
            }
            string BlackBoxFile = OpenBveApi.Path.CombineFile(Program.FileSystem.SettingsFolder, "logs.bin");

            try
            {
                using (System.IO.FileStream Stream = new System.IO.FileStream(BlackBoxFile, System.IO.FileMode.Create, System.IO.FileAccess.Write))
                {
                    //TODO: This code recreates the file every frame.....
                    //It should be possible to spin up a stream in a separate thread which then continously appends
                    using (System.IO.BinaryWriter Writer = new System.IO.BinaryWriter(Stream, System.Text.Encoding.UTF8))
                    {
                        byte[]      Identifier = new byte[] { 111, 112, 101, 110, 66, 86, 69, 95, 76, 79, 71, 83 };
                        const short Version    = 1;
                        Writer.Write(Identifier);
                        Writer.Write(Version);
                        Writer.Write(Game.LogRouteName);
                        Writer.Write(Game.LogTrainName);
                        Writer.Write(Game.LogDateTime.ToBinary());
                        Writer.Write((short)Interface.CurrentOptions.GameMode);
                        Writer.Write(Game.BlackBoxEntryCount);
                        for (int i = 0; i < Game.BlackBoxEntryCount; i++)
                        {
                            Writer.Write(Game.BlackBoxEntries[i].Time);
                            Writer.Write(Game.BlackBoxEntries[i].Position);
                            Writer.Write(Game.BlackBoxEntries[i].Speed);
                            Writer.Write(Game.BlackBoxEntries[i].Acceleration);
                            Writer.Write(Game.BlackBoxEntries[i].ReverserDriver);
                            Writer.Write(Game.BlackBoxEntries[i].ReverserSafety);
                            Writer.Write((short)Game.BlackBoxEntries[i].PowerDriver);
                            Writer.Write((short)Game.BlackBoxEntries[i].PowerSafety);
                            Writer.Write((short)Game.BlackBoxEntries[i].BrakeDriver);
                            Writer.Write((short)Game.BlackBoxEntries[i].BrakeSafety);
                            Writer.Write((short)Game.BlackBoxEntries[i].EventToken);
                        }

                        Writer.Write(Game.ScoreLogCount);
                        for (int i = 0; i < Game.ScoreLogCount; i++)
                        {
                            Writer.Write(Game.ScoreLogs[i].Time);
                            Writer.Write(Game.ScoreLogs[i].Position);
                            Writer.Write(Game.ScoreLogs[i].Value);
                            Writer.Write((short)Game.ScoreLogs[i].TextToken);
                        }

                        Writer.Write(Game.CurrentScore.Maximum);
                        Identifier = new byte[] { 95, 102, 105, 108, 101, 69, 78, 68 };
                        Writer.Write(Identifier);
                        Writer.Close();
                    }

                    Stream.Close();
                }
            }
            catch
            {
                Interface.CurrentOptions.BlackBox = false;
                Interface.AddMessage(MessageType.Error, false, "An unexpected error occurred whilst attempting to write to the black box log- Black box has been disabled.");
            }
        }
 internal static int UseTexture(int TextureIndex, UseMode Mode)
 {
     if (TextureIndex == -1)
     {
         return(0);
     }
     Textures[TextureIndex].CyclesSurvived = 0;
     if (Textures[TextureIndex].Loaded)
     {
         return(Textures[TextureIndex].OpenGlTextureIndex);
     }
     else if (Textures[TextureIndex].Data != null)
     {
         if (Textures[TextureIndex].IsRGBA)
         {
             LoadTextureRGBAforOpenGl(TextureIndex);
         }
         else
         {
             LoadTextureRGBforOpenGl(TextureIndex);
         }
         return(Textures[TextureIndex].OpenGlTextureIndex);
     }
     else
     {
         if (Renderer.LoadTexturesImmediately == Renderer.LoadTextureImmediatelyMode.Yes | Mode == UseMode.LoadImmediately || (Renderer.LoadTexturesImmediately != Renderer.LoadTextureImmediatelyMode.NotYet & Textures[TextureIndex].LoadImmediately & Mode != UseMode.QueryDimensions))
         {
             LoadTextureData(TextureIndex);
             if (Textures[TextureIndex].Loaded)
             {
                 return(Textures[TextureIndex].OpenGlTextureIndex);
             }
             else if (Textures[TextureIndex].Data != null)
             {
                 if (Textures[TextureIndex].IsRGBA)
                 {
                     LoadTextureRGBAforOpenGl(TextureIndex);
                 }
                 else
                 {
                     LoadTextureRGBforOpenGl(TextureIndex);
                 }
                 return(Textures[TextureIndex].OpenGlTextureIndex);
             }
             else
             {
                 return(0);
             }
         }
         else
         {
             if (Mode == UseMode.QueryDimensions & Textures[TextureIndex].FileName != null)
             {
                 try {
                     Bitmap b = (Bitmap)Image.FromFile(Textures[TextureIndex].FileName);
                     Textures[TextureIndex].ClipWidth  = b.Width;
                     Textures[TextureIndex].ClipHeight = b.Height;
                     b.Dispose();
                 } catch (Exception ex) {
                     Interface.AddMessage(Interface.MessageType.Error, false, "Internal error in TextureManager.cs::UseTexture: " + ex.Message);
                     throw;
                 }
             }
             Textures[TextureIndex].Queried = true;
             return(0);
         }
     }
 }
示例#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 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 = CameraRestrictionMode.NotAvailable;
                            Camera.CurrentRestriction = CameraRestrictionMode.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 = CameraRestrictionMode.On;
                            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 (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             = CameraRestrictionMode.NotAvailable;
                            Camera.CurrentRestriction = CameraRestrictionMode.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 = CameraRestrictionMode.On;
                    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, Train);
                        Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.On;
                        Camera.CurrentRestriction = CameraRestrictionMode.On;
                    }
                    else
                    {
                        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;
            }
        }
        /// <summary>Loads an object</summary>
        /// <param name="FileName">The file to load</param>
        /// <param name="Encoding">The text endcoding of the base file (Used if the encoding cannot be auto-detected)</param>
        /// <param name="PreserveVertices">Whether object should be optimized to remove duplicate vertices</param>
        /// <param name="ForceTextureRepeatX">Whether texture repeat is forced on the X-axis</param>
        /// <param name="ForceTextureRepeatY">Whether texture repeat is forced on the Y-axis</param>
        /// <returns>The new object, or a null reference if loading fails</returns>

        /*
         * Notes for refactoring:
         *   * Unused vertices must only be preserved in deformable objects (e.g. Crack and Form)
         *   * ForceTextureRepeatX / Y is only used for animated objects using the TextureShiftFunction
         *   * TODO / BUG: ForceTextureRepeat is only supported by the B3D / CSV parser
         *   * TODO / BUG: No detection of actual file contents, which will make all parsers barf
         */
        internal static UnifiedObject LoadObject(string FileName, Encoding Encoding, bool PreserveVertices, bool ForceTextureRepeatX, bool ForceTextureRepeatY)
        {
            if (String.IsNullOrEmpty(FileName))
            {
                return(null);
            }
#if !DEBUG
            try {
#endif
            if (!System.IO.Path.HasExtension(FileName))
            {
                while (true)
                {
                    var f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".x");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".csv");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".b3d");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".xml");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".l3dgrp");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".l3dobj");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                }
            }
            UnifiedObject Result;
            TextEncoding.Encoding newEncoding = TextEncoding.GetEncodingFromFile(FileName);
            if (newEncoding != TextEncoding.Encoding.Unknown)
            {
                switch (newEncoding)
                {
                case TextEncoding.Encoding.Utf7:
                    Encoding = System.Text.Encoding.UTF7;
                    break;

                case TextEncoding.Encoding.Utf8:
                    Encoding = System.Text.Encoding.UTF8;
                    break;

                case TextEncoding.Encoding.Utf16Le:
                    Encoding = System.Text.Encoding.Unicode;
                    break;

                case TextEncoding.Encoding.Utf16Be:
                    Encoding = System.Text.Encoding.BigEndianUnicode;
                    break;

                case TextEncoding.Encoding.Utf32Le:
                    Encoding = System.Text.Encoding.UTF32;
                    break;

                case TextEncoding.Encoding.Utf32Be:
                    Encoding = System.Text.Encoding.GetEncoding(12001);
                    break;

                case TextEncoding.Encoding.Shift_JIS:
                    Encoding = System.Text.Encoding.GetEncoding(932);
                    break;

                case TextEncoding.Encoding.Windows1252:
                    Encoding = System.Text.Encoding.GetEncoding(1252);
                    break;

                case TextEncoding.Encoding.Big5:
                    Encoding = System.Text.Encoding.GetEncoding(950);
                    break;

                case TextEncoding.Encoding.EUC_KR:
                    Encoding = System.Text.Encoding.GetEncoding(949);
                    break;
                }
            }
            string e = System.IO.Path.GetExtension(FileName);
            if (e == null)
            {
                Interface.AddMessage(MessageType.Error, false, "The file " + FileName + " does not have a recognised extension.");
                return(null);
            }
            switch (e.ToLowerInvariant())
            {
            case ".csv":
            case ".b3d":
                Result = CsvB3dObjectParser.ReadObject(FileName, Encoding);
                break;

            case ".x":
                if (Interface.CurrentOptions.CurrentXParser != Interface.XParsers.Original)
                {
                    try
                    {
                        if (Interface.CurrentOptions.CurrentXParser == Interface.XParsers.NewXParser)
                        {
                            Result = NewXParser.ReadObject(FileName, Encoding);
                        }
                        else
                        {
                            Result = AssimpXParser.ReadObject(FileName);
                        }
                    }
                    catch (Exception ex)
                    {
                        Interface.AddMessage(MessageType.Error, false, "The new X parser raised the following exception: " + ex);
                        Result = XObjectParser.ReadObject(FileName, Encoding);
                    }
                }
                else
                {
                    Result = XObjectParser.ReadObject(FileName, Encoding);
                }
                break;

            case ".animated":
                Result = AnimatedObjectParser.ReadObject(FileName, Encoding);
                break;

            case ".xml":
                Result = XMLParser.ReadObject(FileName, Encoding);
                break;

            case ".l3dgrp":
                Result = Ls3DGrpParser.ReadObject(FileName, Encoding, new Vector3());
                break;

            case ".l3dobj":
                Result = Ls3DObjectParser.ReadObject(FileName, new Vector3());
                break;

            case ".obj":
                if (Interface.CurrentOptions.CurrentObjParser == Interface.ObjParsers.Assimp)
                {
                    try
                    {
                        Result = AssimpObjParser.ReadObject(FileName);
                    }
                    catch (Exception ex)
                    {
                        Interface.AddMessage(MessageType.Error, false, "The new Obj parser raised the following exception: " + ex);
                        Result = WavefrontObjParser.ReadObject(FileName, Encoding);
                    }
                }
                else
                {
                    Result = WavefrontObjParser.ReadObject(FileName, Encoding);
                }
                break;

            case ".s":
                Result = MsTsShapeParser.ReadObject(FileName);
                break;

            default:
                Interface.AddMessage(MessageType.Error, false, "The file extension is not supported: " + FileName);
                return(null);
            }
            if (Result != null)
            {
                Result.OptimizeObject(PreserveVertices);
            }
            return(Result);

#if !DEBUG
        }

        catch (Exception ex) {
            Interface.AddMessage(MessageType.Error, true, "An unexpected error occured (" + ex.Message + ") while attempting to load the file " + FileName);
            return(null);
        }
#endif
        }
示例#8
0
        //The XML Parser Class will allow loading of an object with more advanced
        //properties than are currently available with the CSV and B3D formats, whilst
        //not requiring backwards incompatible changes

        public static UnifiedObject ReadObject(string fileName, Encoding encoding)
        {
            //The current XML file to load
            XmlDocument  currentXML = new XmlDocument();
            StaticObject Object     = null;

            //Load the object's XML file
            currentXML.Load(fileName);
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openbve/object");
                //Check this file actually contains OpenBVE object nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode node in DocumentNodes)
                    {
                        string objectPath;
                        try
                        {
                            var fn        = System.IO.Path.GetDirectoryName(fileName);
                            var InnerNode = node.SelectSingleNode("filename").InnerText;
                            InnerNode  = InnerNode.Trim(new char[] { });
                            objectPath = OpenBveApi.Path.CombineFile(fn, InnerNode);
                        }
                        catch (Exception)
                        {
                            Interface.AddMessage(MessageType.Error, false,
                                                 "The XML does not contain a valid object path: " + fileName);
                            return(null);
                        }
                        if (objectPath != null && System.IO.File.Exists(objectPath))
                        {
                            UnifiedObject obj;
                            switch (System.IO.Path.GetExtension(objectPath).ToLowerInvariant())
                            {
                            case ".csv":
                            case ".b3d":
                                Program.CurrentHost.LoadObject(objectPath, encoding, out obj);
                                Object = (StaticObject)obj;
                                break;

                            case ".x":
                                Program.CurrentHost.LoadObject(objectPath, encoding, out obj);
                                Object = (StaticObject)obj;
                                break;

                            case ".animated":
                                //Not currently working.
                                //Object = AnimatedObjectParser.ReadObject(objectPath, encoding, LoadMode);
                                break;
                            }
                            try
                            {
                                var BoundingBoxUpper = node.SelectSingleNode("boundingboxupper").InnerText;
                                var BoundingBoxLower = node.SelectSingleNode("boundingboxlower").InnerText;
                                Object.Mesh.BoundingBox = new Vector3[2];
                                var splitStrings = BoundingBoxUpper.Split(',');
                                if (splitStrings.Length != 3)
                                {
                                    //Throw exception, as this isn't a valid 3D point
                                    throw new Exception();
                                }
                                Object.Mesh.BoundingBox[0].X = Double.Parse(splitStrings[0]);
                                Object.Mesh.BoundingBox[0].Y = Double.Parse(splitStrings[1]);
                                Object.Mesh.BoundingBox[0].Z = Double.Parse(splitStrings[2]);
                                splitStrings = BoundingBoxLower.Split(',');
                                if (splitStrings.Length != 3)
                                {
                                    //Throw exception, as this isn't a valid 3D point
                                    throw new Exception();
                                }
                                Object.Mesh.BoundingBox[1].X = Double.Parse(splitStrings[0]);
                                Object.Mesh.BoundingBox[1].Y = Double.Parse(splitStrings[1]);
                                Object.Mesh.BoundingBox[1].Y = Double.Parse(splitStrings[2]);
                            }
                            catch (Exception)
                            {
                                Interface.AddMessage(MessageType.Error, false,
                                                     "The XML contained an invalid bounding box entry: " + fileName);
                            }
                            var selectSingleNode = node.SelectSingleNode("author");
                            if (selectSingleNode != null)
                            {
                                //Attempt to load author information from XML
                                Object.Author = selectSingleNode.InnerText.Trim(new char[] { });
                            }
                            selectSingleNode = node.SelectSingleNode("copyright");
                            if (selectSingleNode != null)
                            {
                                //Attempt to load copyright information from XML
                                Object.Copyright = selectSingleNode.InnerText.Trim(new char[] { });
                            }
                            return(Object);
                        }
                        Interface.AddMessage(MessageType.Error, false,
                                             "The file extension is not supported: " + objectPath);
                        return(null);
                    }
                }
            }
            //We couldn't find any valid XML, so return a null object
            return(null);
        }
示例#9
0
        // parse animated object config
        /// <summary>Loads a collection of animated objects from a file.</summary>
        /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param>
        /// <param name="Encoding">The encoding the file is saved in. If the file uses a byte order mark, the encoding indicated by the byte order mark is used and the Encoding parameter is ignored.</param>
        /// <returns>The collection of animated objects.</returns>
        internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, Encoding Encoding)
        {
            System.Globalization.CultureInfo       Culture = System.Globalization.CultureInfo.InvariantCulture;
            ObjectManager.AnimatedObjectCollection Result  = new ObjectManager.AnimatedObjectCollection
            {
                Objects = new ObjectManager.AnimatedObject[4]
            };
            int ObjectCount = 0;

            // load file
            string[] Lines   = System.IO.File.ReadAllLines(FileName, Encoding);
            bool     rpnUsed = false;

            for (int i = 0; i < Lines.Length; i++)
            {
                int j = Lines[i].IndexOf(';');
                if (j >= 0)
                {
                    Lines[i] = Lines[i].Substring(0, j).Trim();
                }
                else
                {
                    Lines[i] = Lines[i].Trim();
                }
                if (Lines[i].IndexOf("functionrpn", StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    rpnUsed = true;
                }
            }
            if (rpnUsed)
            {
                Interface.AddMessage(MessageType.Error, false, "An animated object file contains RPN functions. These were never meant to be used directly, only for debugging. They won't be supported indefinately. Please get rid of them in file " + FileName);
            }
            for (int i = 0; i < Lines.Length; i++)
            {
                if (Lines[i].Length != 0)
                {
                    switch (Lines[i].ToLowerInvariant())
                    {
                    case "[include]":
                    {
                        i++;
                        Vector3         position = Vector3.Zero;
                        UnifiedObject[] obj      = new UnifiedObject[4];
                        int             objCount = 0;
                        while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal)))
                        {
                            if (Lines[i].Length != 0)
                            {
                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                if (j > 0)
                                {
                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                    switch (a.ToLowerInvariant())
                                    {
                                    case "position":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                position = new Vector3(x, y, z);
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "The attribute " + a + " is not supported at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        break;
                                    }
                                }
                                else
                                {
                                    string Folder = System.IO.Path.GetDirectoryName(FileName);
                                    if (Path.ContainsInvalidChars(Lines[i]))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, Lines[i] + " contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                    else
                                    {
                                        string file = OpenBveApi.Path.CombineFile(Folder, Lines[i]);
                                        if (System.IO.File.Exists(file))
                                        {
                                            if (obj.Length == objCount)
                                            {
                                                Array.Resize <UnifiedObject>(ref obj, obj.Length << 1);
                                            }
                                            obj[objCount] = ObjectManager.LoadObject(file, Encoding, false, false, false);
                                            objCount++;
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, true, "File " + file + " not found at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    }
                                }
                            }
                            i++;
                        }
                        i--;
                        for (int j = 0; j < objCount; j++)
                        {
                            if (obj[j] != null)
                            {
                                if (obj[j] is ObjectManager.StaticObject)
                                {
                                    ObjectManager.StaticObject s = (ObjectManager.StaticObject)obj[j];
                                    s.Dynamic = true;
                                    if (ObjectCount >= Result.Objects.Length)
                                    {
                                        Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                                    }
                                    ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                                    ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState(s, position);
                                    a.States = new ObjectManager.AnimatedObjectState[] { aos };
                                    Result.Objects[ObjectCount] = a;
                                    ObjectCount++;
                                }
                                else if (obj[j] is ObjectManager.AnimatedObjectCollection)
                                {
                                    ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)obj[j];
                                    for (int k = 0; k < a.Objects.Length; k++)
                                    {
                                        if (ObjectCount >= Result.Objects.Length)
                                        {
                                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                                        }
                                        for (int h = 0; h < a.Objects[k].States.Length; h++)
                                        {
                                            a.Objects[k].States[h].Position.X += position.X;
                                            a.Objects[k].States[h].Position.Y += position.Y;
                                            a.Objects[k].States[h].Position.Z += position.Z;
                                        }
                                        Result.Objects[ObjectCount] = a.Objects[k];
                                        ObjectCount++;
                                    }
                                }
                            }
                        }
                    }
                    break;

                    case "[object]":
                    {
                        i++;
                        if (Result.Objects.Length == ObjectCount)
                        {
                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                        }
                        Result.Objects[ObjectCount] = new ObjectManager.AnimatedObject
                        {
                            States                 = new ObjectManager.AnimatedObjectState[] {},
                            CurrentState           = -1,
                            TranslateXDirection    = Vector3.Right,
                            TranslateYDirection    = Vector3.Down,
                            TranslateZDirection    = Vector3.Forward,
                            RotateXDirection       = Vector3.Right,
                            RotateYDirection       = Vector3.Down,
                            RotateZDirection       = Vector3.Forward,
                            TextureShiftXDirection = new Vector2(1.0, 0.0),
                            TextureShiftYDirection = new Vector2(0.0, 1.0),
                            RefreshRate            = 0.0,
                            ObjectIndex            = -1
                        };
                        Vector3  Position          = Vector3.Zero;
                        bool     timetableUsed     = false;
                        string[] StateFiles        = null;
                        string   StateFunctionRpn  = null;
                        int      StateFunctionLine = -1;
                        while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal)))
                        {
                            if (Lines[i].Length != 0)
                            {
                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                if (j > 0)
                                {
                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                    switch (a.ToLowerInvariant())
                                    {
                                    case "position":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                Position = new Vector3(x, y, z);
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "states":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length >= 1)
                                        {
                                            string Folder = System.IO.Path.GetDirectoryName(FileName);
                                            StateFiles = new string[s.Length];
                                            for (int k = 0; k < s.Length; k++)
                                            {
                                                s[k] = s[k].Trim();
                                                if (s[k].Length == 0)
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "File" + k.ToString(Culture) + " is an empty string - did you mean something else? - in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    StateFiles[k] = null;
                                                }
                                                else if (Path.ContainsInvalidChars(s[k]))
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "File" + k.ToString(Culture) + " contains illegal characters in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    StateFiles[k] = null;
                                                }
                                                else
                                                {
                                                    StateFiles[k] = OpenBveApi.Path.CombineFile(Folder, s[k]);
                                                    if (!System.IO.File.Exists(StateFiles[k]))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, true, "File " + StateFiles[k] + " not found in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        StateFiles[k] = null;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "At least one argument is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            return(null);
                                        }
                                    } break;

                                    case "statefunction":
                                        try {
                                            StateFunctionLine = i;
                                            StateFunctionRpn  = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "statefunctionrpn":
                                    {
                                        StateFunctionLine = i;
                                        StateFunctionRpn  = b;
                                    } break;

                                    case "translatexdirection":
                                    case "translateydirection":
                                    case "translatezdirection":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "translatexdirection":
                                                    Result.Objects[ObjectCount].TranslateXDirection = new Vector3(x, y, z);
                                                    break;

                                                case "translateydirection":
                                                    Result.Objects[ObjectCount].TranslateYDirection = new Vector3(x, y, z);
                                                    break;

                                                case "translatezdirection":
                                                    Result.Objects[ObjectCount].TranslateZDirection = new Vector3(x, y, z);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "translatexfunction":
                                        try {
                                            Result.Objects[ObjectCount].TranslateXFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translateyfunction":
                                        try {
                                            Result.Objects[ObjectCount].TranslateYFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translatezfunction":
                                        try {
                                            Result.Objects[ObjectCount].TranslateZFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translatexfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TranslateXFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translateyfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TranslateYFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translatezfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TranslateZFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatexdirection":
                                    case "rotateydirection":
                                    case "rotatezdirection":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (x == 0.0 & y == 0.0 & z == 0.0)
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "The direction indicated by X, Y and Z is expected to be non-zero in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "rotatexdirection":
                                                    Result.Objects[ObjectCount].RotateXDirection = new Vector3(x, y, z);
                                                    break;

                                                case "rotateydirection":
                                                    Result.Objects[ObjectCount].RotateYDirection = new Vector3(x, y, z);
                                                    break;

                                                case "rotatezdirection":
                                                    Result.Objects[ObjectCount].RotateZDirection = new Vector3(x, y, z);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "rotatexfunction":
                                        try {
                                            Result.Objects[ObjectCount].RotateXFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotateyfunction":
                                        try {
                                            Result.Objects[ObjectCount].RotateYFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatezfunction":
                                        try {
                                            Result.Objects[ObjectCount].RotateZFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatexfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].RotateXFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotateyfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].RotateYFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatezfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].RotateZFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatexdamping":
                                    case "rotateydamping":
                                    case "rotatezdamping":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 2)
                                        {
                                            double nf, dr;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out nf))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "NaturalFrequency is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out dr))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "DampingRatio is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (nf <= 0.0)
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "NaturalFrequency is expected to be positive in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (dr <= 0.0)
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "DampingRatio is expected to be positive in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "rotatexdamping":
                                                    Result.Objects[ObjectCount].RotateXDamping = new Damping(nf, dr);
                                                    break;

                                                case "rotateydamping":
                                                    Result.Objects[ObjectCount].RotateYDamping = new Damping(nf, dr);
                                                    break;

                                                case "rotatezdamping":
                                                    Result.Objects[ObjectCount].RotateZDamping = new Damping(nf, dr);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Exactly 2 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "textureshiftxdirection":
                                    case "textureshiftydirection":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 2)
                                        {
                                            double x, y;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "textureshiftxdirection":
                                                    Result.Objects[ObjectCount].TextureShiftXDirection = new Vector2(x, y);
                                                    break;

                                                case "textureshiftydirection":
                                                    Result.Objects[ObjectCount].TextureShiftYDirection = new Vector2(x, y);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Exactly 2 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "textureshiftxfunction":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftXFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureshiftyfunction":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftYFunction = new FunctionScript(Program.CurrentHost, b, true);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureshiftxfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftXFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureshiftyfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftYFunction = new FunctionScript(Program.CurrentHost, b, false);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureoverride":
                                        switch (b.ToLowerInvariant())
                                        {
                                        case "none":
                                            break;

                                        case "timetable":
                                            if (!timetableUsed)
                                            {
                                                Timetable.AddObjectForCustomTimetable(Result.Objects[ObjectCount]);
                                                timetableUsed = true;
                                            }
                                            break;

                                        default:
                                            Interface.AddMessage(MessageType.Error, false, "Unrecognized value in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            break;
                                        }
                                        break;

                                    case "refreshrate":
                                    {
                                        double r;
                                        if (!double.TryParse(b, System.Globalization.NumberStyles.Float, Culture, out r))
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                        else if (r < 0.0)
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Value is expected to be non-negative in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                        else
                                        {
                                            Result.Objects[ObjectCount].RefreshRate = r;
                                        }
                                    } break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "The attribute " + a + " is not supported at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        break;
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    return(null);
                                }
                            }
                            i++;
                        }
                        i--;
                        if (StateFiles != null)
                        {
                            // create the object
                            if (timetableUsed)
                            {
                                if (StateFunctionRpn != null)
                                {
                                    StateFunctionRpn = "timetable 0 == " + StateFunctionRpn + " -1 ?";
                                }
                                else
                                {
                                    StateFunctionRpn = "timetable";
                                }
                            }
                            if (StateFunctionRpn != null)
                            {
                                try {
                                    Result.Objects[ObjectCount].StateFunction = new FunctionScript(Program.CurrentHost, StateFunctionRpn, false);
                                } catch (Exception ex) {
                                    Interface.AddMessage(MessageType.Error, false, ex.Message + " in StateFunction at line " + (StateFunctionLine + 1).ToString(Culture) + " in file " + FileName);
                                }
                            }
                            Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[StateFiles.Length];
                            bool ForceTextureRepeatX = Result.Objects[ObjectCount].TextureShiftXFunction != null & Result.Objects[ObjectCount].TextureShiftXDirection.X != 0.0 |
                                                       Result.Objects[ObjectCount].TextureShiftYFunction != null & Result.Objects[ObjectCount].TextureShiftYDirection.X != 0.0;
                            bool ForceTextureRepeatY = Result.Objects[ObjectCount].TextureShiftXFunction != null & Result.Objects[ObjectCount].TextureShiftXDirection.Y != 0.0 |
                                                       Result.Objects[ObjectCount].TextureShiftYFunction != null & Result.Objects[ObjectCount].TextureShiftYDirection.Y != 0.0;
                            for (int k = 0; k < StateFiles.Length; k++)
                            {
                                Result.Objects[ObjectCount].States[k].Position = Vector3.Zero;
                                if (StateFiles[k] != null)
                                {
                                    Result.Objects[ObjectCount].States[k].Object = ObjectManager.LoadStaticObject(StateFiles[k], Encoding, false, ForceTextureRepeatX, ForceTextureRepeatY);
                                    if (Result.Objects[ObjectCount].States[k].Object != null)
                                    {
                                        Result.Objects[ObjectCount].States[k].Position       = Position;
                                        Result.Objects[ObjectCount].States[k].Object.Dynamic = true;
                                        for (int l = 0; l < Result.Objects[ObjectCount].States[k].Object.Mesh.Materials.Length; l++)
                                        {
                                            if (ForceTextureRepeatX && ForceTextureRepeatY)
                                            {
                                                Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode = OpenGlTextureWrapMode.RepeatRepeat;
                                            }
                                            else if (ForceTextureRepeatX)
                                            {
                                                switch (Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode)
                                                {
                                                case OpenGlTextureWrapMode.ClampRepeat:
                                                    Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode = OpenGlTextureWrapMode.RepeatRepeat;
                                                    break;

                                                case OpenGlTextureWrapMode.ClampClamp:
                                                    Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode = OpenGlTextureWrapMode.RepeatClamp;
                                                    break;
                                                }
                                            }
                                            else if (ForceTextureRepeatY)
                                            {
                                                switch (Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode)
                                                {
                                                case OpenGlTextureWrapMode.RepeatClamp:
                                                    Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode = OpenGlTextureWrapMode.RepeatRepeat;
                                                    break;

                                                case OpenGlTextureWrapMode.ClampClamp:
                                                    Result.Objects[ObjectCount].States[k].Object.Mesh.Materials[l].WrapMode = OpenGlTextureWrapMode.ClampRepeat;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    Result.Objects[ObjectCount].States[k].Object = null;
                                }
                            }
                        }
                        else
                        {
                            Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[] { };
                        }
                        ObjectCount++;
                    }
                    break;

                    case "[sound]":
                    case "[statechangesound]":
                        //Only show the sound nag once per route, otherwise this could cause spam...
                        if (!Program.SoundError)
                        {
                            Interface.AddMessage(MessageType.Information, false, "Animated objects containing sounds are only supported in openBVE v1.5.2.4+");
                            Interface.AddMessage(MessageType.Information, false, "Object Viewer does not support sounds. Please use the main game to test these!");
                            Program.SoundError = true;
                        }
                        i++;
                        while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal)))
                        {
                            i++;
                        }
                        break;

                    default:
                        Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                        return(null);
                    }
                }
            }
            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, ObjectCount);
            return(Result);
        }
示例#10
0
        /// <summary>Parses a single XML node into a car sound</summary>
        /// <param name="node">The node to parse</param>
        /// <param name="Sound">The car sound</param>
        /// <param name="Position">The default position of this sound (May be overriden by the node)</param>
        /// <param name="Radius">The default radius of this sound (May be overriden by the node)</param>
        private static void ParseNode(XmlNode node, out TrainManager.CarSound Sound, Vector3 Position, double Radius)
        {
            string fileName = null;

            foreach (XmlNode c in node.ChildNodes)
            {
                switch (c.Name.ToLowerInvariant())
                {
                case "filename":
                    try
                    {
                        fileName = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                        if (!System.IO.File.Exists(fileName))
                        {
                            //Valid path, but the file does not exist
                            Interface.AddMessage(MessageType.Error, false, "The sound path " + c.InnerText + " in XML node " + node.Name + " does not exist.");
                            Sound = TrainManager.CarSound.Empty;
                            return;
                        }
                    }
                    catch
                    {
                        //Probably invalid filename characters
                        Interface.AddMessage(MessageType.Error, false, "The sound path " + c.InnerText + " in XML node " + node.Name + " is invalid.");
                        Sound = TrainManager.CarSound.Empty;
                        return;
                    }
                    break;

                case "position":
                    string[] Arguments = c.InnerText.Split(',');
                    double   x = 0.0, y = 0.0, z = 0.0;
                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], out x))
                    {
                        Interface.AddMessage(MessageType.Error, false, "Sound radius X " + Arguments[0] + " in XML node " + node.Name + " is invalid.");
                        x = 0.0;
                    }
                    if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[1], out y))
                    {
                        Interface.AddMessage(MessageType.Error, false, "Sound radius Y " + Arguments[1] + " in XML node " + node.Name + " is invalid.");
                        y = 0.0;
                    }
                    if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[2], out z))
                    {
                        Interface.AddMessage(MessageType.Error, false, "Sound radius Z " + Arguments[2] + " in XML node " + node.Name + " is invalid.");
                        z = 0.0;
                    }
                    Position = new Vector3(x, y, z);
                    break;

                case "radius":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Radius))
                    {
                        Interface.AddMessage(MessageType.Error, false, "The sound radius " + c.InnerText + " in XML node " + node.Name + " is invalid.");
                    }
                    break;
                }
            }
            if (fileName == null)
            {
                //No valid filename node specified
                Interface.AddMessage(MessageType.Error, false, "XML node " + node.Name + " does not point to a valid sound file.");
                Sound = TrainManager.CarSound.Empty;
                return;
            }
            Sound = new TrainManager.CarSound(fileName, Position, Radius);
        }
示例#11
0
        /// <summary>Loads the specified plugin for the specified train.</summary>
        /// <param name="train">The train to attach the plugin to.</param>
        /// <param name="pluginFile">The file to the plugin.</param>
        /// <param name="trainFolder">The train folder.</param>
        /// <returns>Whether the plugin was loaded successfully.</returns>
        private static bool LoadPlugin(TrainManager.Train train, string pluginFile, string trainFolder)
        {
            string pluginTitle = System.IO.Path.GetFileName(pluginFile);

            if (!System.IO.File.Exists(pluginFile))
            {
                Interface.AddMessage(Interface.MessageType.Error, true, "The train plugin " + pluginTitle + " could not be found.");
                return(false);
            }

            /*
             * Unload plugin if already loaded.
             * */
            if (train.Plugin != null)
            {
                UnloadPlugin(train);
            }

            /*
             * Prepare initialization data for the plugin.
             * */
            BrakeTypes brakeType = (BrakeTypes)train.Cars[train.DriverCar].Specs.BrakeType;
            int        brakeNotches;
            int        powerNotches;
            bool       hasHoldBrake;

            if (brakeType == BrakeTypes.AutomaticAirBrake)
            {
                brakeNotches = 2;
                powerNotches = train.Handles.Power.MaximumNotch;
                hasHoldBrake = false;
            }
            else
            {
                brakeNotches = train.Handles.Brake.MaximumNotch + (train.Handles.HasHoldBrake ? 1 : 0);
                powerNotches = train.Handles.Power.MaximumNotch;
                hasHoldBrake = train.Handles.HasHoldBrake;
            }
            int                 cars  = train.Cars.Length;
            VehicleSpecs        specs = new VehicleSpecs(powerNotches, brakeType, brakeNotches, hasHoldBrake, cars);
            InitializationModes mode  = (InitializationModes)Game.TrainStart;

            /*
             * Check if the plugin is a .NET plugin.
             * */
            Assembly assembly;

            try {
                assembly = Assembly.LoadFile(pluginFile);
            } catch (BadImageFormatException) {
                assembly = null;
            } catch (Exception ex) {
                Interface.AddMessage(Interface.MessageType.Error, false, "The train plugin " + pluginTitle + " could not be loaded due to the following exception: " + ex.Message);
                return(false);
            }
            if (assembly != null)
            {
                Type[] types;
                try {
                    types = assembly.GetTypes();
                } catch (ReflectionTypeLoadException ex) {
                    foreach (Exception e in ex.LoaderExceptions)
                    {
                        Interface.AddMessage(Interface.MessageType.Error, false, "The train plugin " + pluginTitle + " raised an exception on loading: " + e.Message);
                    }
                    return(false);
                }
                foreach (Type type in types)
                {
                    if (typeof(IRuntime).IsAssignableFrom(type))
                    {
                        if (type.FullName == null)
                        {
                            //Should never happen, but static code inspection suggests that it's possible....
                            throw new InvalidOperationException();
                        }
                        IRuntime api = assembly.CreateInstance(type.FullName) as IRuntime;
                        train.Plugin = new NetPlugin(pluginFile, trainFolder, api, train);
                        if (train.Plugin.Load(specs, mode))
                        {
                            return(true);
                        }
                        else
                        {
                            train.Plugin = null;
                            return(false);
                        }
                    }
                }
                Interface.AddMessage(Interface.MessageType.Error, false, "The train plugin " + pluginTitle + " does not export a train interface and therefore cannot be used with openBVE.");
                return(false);
            }

            /*
             * Check if the plugin is a Win32 plugin.
             *
             */
            try {
                if (!CheckWin32Header(pluginFile))
                {
                    Interface.AddMessage(Interface.MessageType.Error, false, "The train plugin " + pluginTitle + " is of an unsupported binary format and therefore cannot be used with openBVE.");
                    return(false);
                }
            } catch (Exception ex) {
                Interface.AddMessage(Interface.MessageType.Error, false, "The train plugin " + pluginTitle + " could not be read due to the following reason: " + ex.Message);
                return(false);
            }
            if (!Program.CurrentlyRunningOnWindows | IntPtr.Size != 4)
            {
                Interface.AddMessage(Interface.MessageType.Warning, false, "The train plugin " + pluginTitle + " can only be used on 32-bit Microsoft Windows or compatible.");
                return(false);
            }
            if (Program.CurrentlyRunningOnWindows && !System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\AtsPluginProxy.dll"))
            {
                Interface.AddMessage(Interface.MessageType.Warning, false, "AtsPluginProxy.dll is missing or corrupt- Please reinstall.");
                return(false);
            }
            train.Plugin = new Win32Plugin(pluginFile, train);
            if (train.Plugin.Load(specs, mode))
            {
                return(true);
            }
            else
            {
                train.Plugin = null;
                Interface.AddMessage(Interface.MessageType.Error, false, "The train plugin " + pluginTitle + " does not export a train interface and therefore cannot be used with openBVE.");
                return(false);
            }
        }
示例#12
0
        internal static void Parse(string fileName, ref TrainManager.Car car, bool isDriverCar)
        {
            //3D center of the car
            Vector3 center = Vector3.Zero;
            //Positioned to the left of the car, but centered Y & Z
            Vector3 left = new Vector3(-1.3, 0.0, 0.0);
            //Positioned to the right of the car, but centered Y & Z
            Vector3 right = new Vector3(1.3, 0.0, 0.0);
            //Positioned at the front of the car, centered X and Y
            Vector3 front = new Vector3(0.0, 0.0, 0.5 * car.Length);
            //Positioned at the position of the panel / 3D cab (Remember that the panel is just an object in the world...)
            Vector3 panel = new Vector3(car.Driver.X, car.Driver.Y, car.Driver.Z + 1.0);



            //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 (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/CarSounds");
                if (DocumentNodes == null || DocumentNodes.Count == 0)
                {
                    Interface.AddMessage(MessageType.Error, false, "No car sound 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 sound.xml file");
                }
                foreach (XmlNode n in DocumentNodes)
                {
                    if (n.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode c in n.ChildNodes)
                        {
                            switch (c.Name.ToLowerInvariant())
                            {
                            case "ats":
                            case "plugin":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of plugin sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                ParseArrayNode(c, out car.Sounds.Plugin, center, SoundCfgParser.mediumRadius);
                                break;

                            case "brake":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of brake sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "releasehigh":
                                        //Release brakes from high pressure
                                        ParseNode(cc, out car.Sounds.AirHigh, center, SoundCfgParser.smallRadius);
                                        break;

                                    case "release":
                                        //Release brakes from normal pressure
                                        ParseNode(cc, out car.Sounds.Air, center, SoundCfgParser.smallRadius);
                                        break;

                                    case "releasefull":
                                        //Release brakes from full pressure
                                        ParseNode(cc, out car.Sounds.AirZero, center, SoundCfgParser.smallRadius);
                                        break;

                                    case "emergency":
                                        //Apply EB
                                        ParseNode(cc, out car.Sounds.EmrBrake, center, SoundCfgParser.smallRadius);
                                        break;

                                    case "application":
                                        //Standard application
                                        ParseNode(cc, out car.Sounds.Brake, center, SoundCfgParser.smallRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "brakehandle":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of brake handle sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "apply":
                                        ParseNode(cc, out car.Sounds.BrakeHandleApply, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "applyfast":
                                        ParseNode(cc, out car.Sounds.BrakeHandleApplyFast, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "release":
                                        ParseNode(cc, out car.Sounds.BrakeHandleRelease, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "releasefast":
                                        ParseNode(cc, out car.Sounds.BrakeHandleReleaseFast, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "min":
                                    case "minimum":
                                        ParseNode(cc, out car.Sounds.BrakeHandleMin, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "max":
                                    case "maximum":
                                        ParseNode(cc, out car.Sounds.BrakeHandleMax, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "breaker":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of breaker sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "on":
                                        ParseNode(cc, out car.Sounds.BreakerResume, panel, SoundCfgParser.smallRadius);
                                        break;

                                    case "off":
                                        ParseNode(cc, out car.Sounds.BreakerResumeOrInterrupt, panel, SoundCfgParser.smallRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "buzzer":
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                ParseNode(c, out car.Sounds.Adjust, panel, SoundCfgParser.tinyRadius);
                                break;

                            case "compressor":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of compressor sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (car.CarBrake.brakeType != BrakeType.Main)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "attack":
                                    case "start":
                                        //Compressor starting sound
                                        ParseNode(cc, out car.Sounds.CpStart, center, SoundCfgParser.mediumRadius);
                                        break;

                                    case "loop":
                                        //Compressor loop sound
                                        ParseNode(cc, out car.Sounds.CpLoop, center, SoundCfgParser.mediumRadius);
                                        break;

                                    case "release":
                                    case "stop":
                                    case "end":
                                        //Compressor end sound
                                        ParseNode(cc, out car.Sounds.CpEnd, center, SoundCfgParser.mediumRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "door":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of door sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "openleft":
                                    case "leftopen":
                                        ParseNode(cc, out car.Doors[0].OpenSound, left, SoundCfgParser.smallRadius);
                                        break;

                                    case "openright":
                                    case "rightopen":
                                        ParseNode(cc, out car.Doors[1].OpenSound, right, SoundCfgParser.smallRadius);
                                        break;

                                    case "closeleft":
                                    case "leftclose":
                                        ParseNode(cc, out car.Doors[0].CloseSound, left, SoundCfgParser.smallRadius);
                                        break;

                                    case "closeright":
                                    case "rightclose":
                                        ParseNode(cc, out car.Doors[1].CloseSound, right, SoundCfgParser.smallRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "flange":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of flange sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                ParseArrayNode(c, out car.Sounds.Flange, center, SoundCfgParser.mediumRadius);
                                break;

                            case "horn":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of horn sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "primary":
                                        //Primary horn
                                        ParseHornNode(cc, out car.Horns[0], front, SoundCfgParser.largeRadius);
                                        break;

                                    case "secondary":
                                        //Secondary horn
                                        ParseHornNode(cc, out car.Horns[1], front, SoundCfgParser.largeRadius);
                                        break;

                                    case "music":
                                        //Music horn
                                        ParseHornNode(cc, out car.Horns[2], front, SoundCfgParser.largeRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "loop":
                            case "noise":
                                ParseNode(c, out car.Sounds.Loop, center, SoundCfgParser.mediumRadius);
                                break;

                            case "mastercontroller":
                            case "powerhandle":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of power handle sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "up":
                                    case "increase":
                                        ParseNode(cc, out car.Sounds.MasterControllerUp, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "upfast":
                                    case "increasefast":
                                        ParseNode(cc, out car.Sounds.MasterControllerUpFast, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "down":
                                    case "decrease":
                                        ParseNode(cc, out car.Sounds.MasterControllerDown, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "downfast":
                                    case "decreasefast":
                                        ParseNode(cc, out car.Sounds.MasterControllerDownFast, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "min":
                                    case "minimum":
                                        ParseNode(cc, out car.Sounds.MasterControllerMin, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "max":
                                    case "maximum":
                                        ParseNode(cc, out car.Sounds.MasterControllerMax, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "motor":
                                if (!car.Specs.IsMotorCar)
                                {
                                    break;
                                }
                                ParseMotorSoundTableNode(c, ref car.Sounds.Motor.Tables, center, SoundCfgParser.mediumRadius);
                                break;

                            case "pilotlamp":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of pilot-lamp sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "on":
                                        ParseNode(cc, out car.Sounds.PilotLampOn, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "off":
                                        ParseNode(cc, out car.Sounds.PilotLampOff, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "pointfrontaxle":
                            case "switchfrontaxle":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of point front axle sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                ParseArrayNode(c, out car.FrontAxle.PointSounds, new Vector3(0.0, 0.0, car.FrontAxle.Position), SoundCfgParser.smallRadius);
                                break;

                            case "pointrearaxle":
                            case "switchrearaxle":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of point rear axle sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                ParseArrayNode(c, out car.RearAxle.PointSounds, new Vector3(0.0, 0.0, car.FrontAxle.Position), SoundCfgParser.smallRadius);
                                break;

                            case "reverser":
                            case "reverserhandle":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of reverser sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "on":
                                        ParseNode(cc, out car.Sounds.ReverserOn, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    case "off":
                                        ParseNode(cc, out car.Sounds.ReverserOff, panel, SoundCfgParser.tinyRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "run":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of run sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                ParseArrayNode(c, out car.Sounds.Run, center, SoundCfgParser.mediumRadius);
                                break;

                            case "shoe":
                            case "rub":
                                ParseNode(c, out car.Sounds.Rub, center, SoundCfgParser.mediumRadius);
                                break;

                            case "suspension":
                            case "spring":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of suspension sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "left":
                                        //Left suspension springs
                                        ParseNode(cc, out car.Sounds.SpringL, left, SoundCfgParser.smallRadius);
                                        break;

                                    case "right":
                                        //right suspension springs
                                        ParseNode(cc, out car.Sounds.SpringR, right, SoundCfgParser.smallRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "requeststop":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of request stop sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "stop":
                                        ParseNode(cc, out car.Sounds.RequestStop[0], center, SoundCfgParser.smallRadius);
                                        break;

                                    case "pass":
                                        ParseNode(cc, out car.Sounds.RequestStop[1], center, SoundCfgParser.smallRadius);
                                        break;

                                    case "ignored":
                                        ParseNode(cc, out car.Sounds.RequestStop[2], center, SoundCfgParser.smallRadius);
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, false, "Declaration " + cc.Name + " is unsupported in a " + c.Name + " node.");
                                        break;
                                    }
                                }
                                break;

                            case "touch":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false, "An empty list of touch sounds was defined in in XML file " + fileName);
                                    break;
                                }
                                if (!isDriverCar)
                                {
                                    break;
                                }
                                ParseArrayNode(c, out car.Sounds.Touch, center, SoundCfgParser.mediumRadius);
                                break;
                            }
                        }
                    }
                }
                car.Sounds.RunVolume    = new double[car.Sounds.Run.Length];
                car.Sounds.FlangeVolume = new double[car.Sounds.Flange.Length];
            }
        }
示例#13
0
        /// <summary>Loads a Loksim3D object from a file.</summary>
        /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param>
        /// <param name="LoadMode">The texture load mode.</param>
        /// <param name="Rotation">The rotation to be applied.</param>
        /// <returns>The object loaded.</returns>
        internal static ObjectManager.StaticObject ReadObject(string FileName, ObjectManager.ObjectLoadMode LoadMode, Vector3 Rotation)
        {
            string      BaseDir    = System.IO.Path.GetDirectoryName(FileName);
            XmlDocument currentXML = new XmlDocument();

            //Initialise the object
            ObjectManager.StaticObject Object = new ObjectManager.StaticObject
            {
                Mesh =
                {
                    Faces     = new World.MeshFace[]     { },
                    Materials = new World.MeshMaterial[] { },
                    Vertices  = new World.Vertex[]       { }
                }
            };
            MeshBuilder Builder = new MeshBuilder();

            Vector3[] Normals         = new Vector3[4];
            bool      PropertiesFound = false;

            World.Vertex[] tempVertices       = new World.Vertex[0];
            Vector3[]      tempNormals        = new Vector3[0];
            Color24        transparentColor   = new Color24();
            string         tday               = null;
            string         transtex           = null;
            string         tnight             = null;
            bool           TransparencyUsed   = false;
            bool           TransparentTypSet  = false;
            bool           FirstPxTransparent = false;
            Color24        FirstPxColor       = new Color24();
            bool           Face2              = false;
            int            TextureWidth       = 0;
            int            TextureHeight      = 0;

            if (File.Exists(FileName))
            {
                try
                {
                    currentXML.Load(FileName);
                }
                catch
                {
                    return(null);
                }
            }
            else
            {
                Interface.AddMessage(Interface.MessageType.Error, false, "Loksim3D object " + FileName + " does not exist.");
                return(null);
            }
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/OBJECT");
                //Check this file actually contains Loksim3D object nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode outerNode in DocumentNodes)
                    {
                        if (outerNode.ChildNodes.OfType <XmlElement>().Any())
                        {
                            foreach (XmlNode node in outerNode.ChildNodes)
                            {
                                //I think there should only be one properties node??
                                //Need better format documentation
                                if (node.Name == "Props" && PropertiesFound == false)
                                {
                                    if (node.Attributes != null)
                                    {
                                        //Our node has child nodes, therefore this properties node should be valid
                                        //Needs better validation
                                        PropertiesFound = true;
                                        foreach (XmlAttribute attribute in node.Attributes)
                                        {
                                            switch (attribute.Name)
                                            {
                                            //Sets the texture
                                            //Loksim3D objects only support daytime textures
                                            case "Texture":
                                                tday = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory);
                                                if (!File.Exists(tday))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Warning, true, "Ls3d Texture file " + attribute.Value + " not found.");
                                                    break;
                                                }
                                                try
                                                {
                                                    using (Bitmap TextureInformation = new Bitmap(tday))
                                                    {
                                                        TextureWidth  = TextureInformation.Width;
                                                        TextureHeight = TextureInformation.Height;
                                                        Color color = TextureInformation.GetPixel(0, 0);
                                                        FirstPxColor = new Color24(color.R, color.G, color.B);
                                                    }
                                                }
                                                catch
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, true,
                                                                         "An error occured loading daytime texture " + tday +
                                                                         " in file " + FileName);
                                                    tday = null;
                                                }
                                                break;

                                            //Defines whether the texture uses transparency
                                            //May be omitted
                                            case "Transparent":
                                                if (TransparentTypSet)
                                                {
                                                    //Appears to be ignored with TransparentTyp set
                                                    continue;
                                                }
                                                if (attribute.Value == "TRUE")
                                                {
                                                    TransparencyUsed = true;
                                                    transparentColor = new Color24(0, 0, 0);
                                                }
                                                break;

                                            case "TransTexture":
                                                if (string.IsNullOrEmpty(attribute.Value))
                                                {
                                                    //Empty....
                                                    continue;
                                                }
                                                transtex = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory);
                                                if (!File.Exists(transtex))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, true, "AlphaTexture " + transtex + " could not be found in file " + FileName);
                                                    transtex = null;
                                                }
                                                break;

                                            //Sets the transparency type
                                            case "TransparentTyp":
                                                TransparentTypSet = true;
                                                switch (attribute.Value)
                                                {
                                                case "0":
                                                    //Transparency is disabled
                                                    TransparencyUsed = false;
                                                    break;

                                                case "1":
                                                    //Transparency is solid black
                                                    TransparencyUsed   = true;
                                                    transparentColor   = new Color24(0, 0, 0);
                                                    FirstPxTransparent = false;
                                                    break;

                                                case "2":
                                                    //Transparency is the color at Pixel 1,1
                                                    TransparencyUsed   = true;
                                                    FirstPxTransparent = true;
                                                    break;

                                                case "3":
                                                case "4":
                                                    //This is used when transparency is used with an alpha bitmap
                                                    TransparencyUsed   = false;
                                                    FirstPxTransparent = false;
                                                    break;

                                                default:
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Unrecognised transparency type " + attribute.Value + " detected in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    break;
                                                }
                                                break;

                                            //Sets whether the rears of the faces are to be drawn
                                            case "Drawrueckseiten":
                                                if (attribute.Value == "TRUE" || string.IsNullOrEmpty(attribute.Value))
                                                {
                                                    Face2 = true;
                                                }
                                                else
                                                {
                                                    Face2 = false;
                                                }
                                                break;

                                                /*
                                                 * MISSING PROPERTIES:
                                                 * AutoRotate - Rotate with tracks?? LS3D presumably uses a 3D world system.
                                                 * Beleuchtet- Translates as illuminated. Presume something to do with lighting? - What emissive color?
                                                 * FileAuthor
                                                 * FileInfo
                                                 * FilePicture
                                                 */
                                            }
                                        }
                                    }
                                }
                                //The point command is eqivilant to a vertex
                                else if (node.Name == "Point" && node.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            //Vertex
                                            double vx = 0.0, vy = 0.0, vz = 0.0;
                                            //Normals
                                            double nx = 0.0, ny = 0.0, nz = 0.0;
                                            foreach (XmlAttribute attribute in childNode.Attributes)
                                            {
                                                switch (attribute.Name)
                                                {
                                                //Sets the vertex normals
                                                case "Normal":
                                                    string[] NormalPoints = attribute.Value.Split(';');
                                                    if (!double.TryParse(NormalPoints[0], out nx))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument nX in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(NormalPoints[1], out ny))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument nY in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(NormalPoints[2], out nz))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument nZ in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    break;

                                                //Sets the vertex 3D co-ordinates
                                                case "Vekt":
                                                    string[] VertexPoints = attribute.Value.Split(';');
                                                    if (!double.TryParse(VertexPoints[0], out vx))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument vX in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(VertexPoints[1], out vy))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument yY in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(VertexPoints[2], out vz))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument vZ in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    break;
                                                }
                                            }
                                            World.Normalize(ref nx, ref ny, ref nz);
                                            //Resize temp arrays
                                            Array.Resize <World.Vertex>(ref tempVertices, tempVertices.Length + 1);
                                            Array.Resize <Vector3>(ref tempNormals, tempNormals.Length + 1);
                                            //Add vertex and normals to temp array
                                            tempVertices[tempVertices.Length - 1].Coordinates = new Vector3(vx, vy, vz);
                                            tempNormals[tempNormals.Length - 1] = new Vector3((float)nx, (float)ny, (float)nz);
                                            Array.Resize <World.Vertex>(ref Builder.Vertices, Builder.Vertices.Length + 1);
                                            while (Builder.Vertices.Length >= Normals.Length)
                                            {
                                                Array.Resize <Vector3>(ref Normals, Normals.Length << 1);
                                            }
                                            Builder.Vertices[Builder.Vertices.Length - 1].Coordinates = new Vector3(vx, vy, vz);
                                            Normals[Builder.Vertices.Length - 1] = new Vector3((float)nx, (float)ny, (float)nz);
                                        }
                                    }
                                }
                                //The Flaeche command creates a face
                                else if (node.Name == "Flaeche" && node.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            //Defines the verticies in this face
                                            //**NOTE**: A vertex may appear in multiple faces with different texture co-ordinates
                                            if (childNode.Attributes["Points"] != null)
                                            {
                                                string[] Verticies = childNode.Attributes["Points"].Value.Split(';');
                                                int      f         = Builder.Faces.Length;
                                                //Add 1 to the length of the face array
                                                Array.Resize <World.MeshFace>(ref Builder.Faces, f + 1);
                                                Builder.Faces[f] = new World.MeshFace();
                                                //Create the vertex array for the face
                                                Builder.Faces[f].Vertices = new World.MeshFaceVertex[Verticies.Length];
                                                while (Builder.Vertices.Length > Normals.Length)
                                                {
                                                    Array.Resize <Vector3>(ref Normals,
                                                                           Normals.Length << 1);
                                                }
                                                //Run through the vertices list and grab from the temp array

                                                int smallestX = TextureWidth;
                                                int smallestY = TextureHeight;
                                                for (int j = 0; j < Verticies.Length; j++)
                                                {
                                                    //This is the position of the vertex in the temp array
                                                    int currentVertex;
                                                    if (!int.TryParse(Verticies[j], out currentVertex))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, Verticies[j] + " does not parse to a valid Vertex in " + node.Name + " in Loksim3D object file " + FileName);
                                                        continue;
                                                    }
                                                    //Add one to the actual vertex array
                                                    Array.Resize <World.Vertex>(ref Builder.Vertices, Builder.Vertices.Length + 1);
                                                    //Set coordinates
                                                    Builder.Vertices[Builder.Vertices.Length - 1].Coordinates = tempVertices[currentVertex].Coordinates;
                                                    //Set the vertex index
                                                    Builder.Faces[f].Vertices[j].Index = (ushort)(Builder.Vertices.Length - 1);
                                                    //Set the normals
                                                    Builder.Faces[f].Vertices[j].Normal = tempNormals[currentVertex];
                                                    //Now deal with the texture
                                                    //Texture mapping points are in pixels X,Y and are relative to the face in question rather than the vertex
                                                    if (childNode.Attributes["Texture"] != null)
                                                    {
                                                        string[] TextureCoords = childNode.Attributes["Texture"].Value.Split(';');
                                                        Vector2  currentCoords;
                                                        float    OpenBVEWidth;
                                                        float    OpenBVEHeight;
                                                        string[] splitCoords = TextureCoords[j].Split(',');
                                                        if (!float.TryParse(splitCoords[0], out OpenBVEWidth))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Invalid texture width specified in " + node.Name + " in Loksim3D object file " + FileName);
                                                            continue;
                                                        }
                                                        if (!float.TryParse(splitCoords[1], out OpenBVEHeight))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Invalid texture height specified in " + node.Name + " in Loksim3D object file " + FileName);
                                                            continue;
                                                        }
                                                        if (OpenBVEWidth <= smallestX && OpenBVEHeight <= smallestY)
                                                        {
                                                            //Clamp texture width and height
                                                            smallestX = (int)OpenBVEWidth;
                                                            smallestY = (int)OpenBVEHeight;
                                                        }
                                                        if (TextureWidth != 0 && TextureHeight != 0)
                                                        {
                                                            //Calculate openBVE co-ords
                                                            currentCoords.X = (OpenBVEWidth / TextureWidth);
                                                            currentCoords.Y = (OpenBVEHeight / TextureHeight);
                                                        }
                                                        else
                                                        {
                                                            //Invalid, so just return zero
                                                            currentCoords.X = 0;
                                                            currentCoords.Y = 0;
                                                        }
                                                        Builder.Vertices[Builder.Vertices.Length - 1].TextureCoordinates = currentCoords;
                                                    }
                                                }
                                                if (Face2)
                                                {
                                                    //Add face2 flag if required
                                                    Builder.Faces[f].Flags = (byte)World.MeshFace.Face2Mask;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //Apply rotation

                /*
                 * NOTES:
                 * No rotation order is specified
                 * The rotation string in a .l3dgrp file is ordered Y, Z, X    ??? Can't find a good reason for this ???
                 * Rotations must still be performed in X,Y,Z order to produce correct results
                 */

                if (Rotation.Z != 0.0)
                {
                    //Convert to radians
                    Rotation.Z *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 1, 0, 0, Rotation.Z);
                }


                if (Rotation.X != 0.0)
                {
                    //This is actually the Y-Axis rotation
                    //Convert to radians
                    Rotation.X *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 0, 1, 0, Rotation.X);
                }
                if (Rotation.Y != 0.0)
                {
                    //This is actually the X-Axis rotation
                    //Convert to radians
                    Rotation.Y *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 0, 0, 1, Rotation.Y);
                }


                //These files appear to only have one texture defined
                //Therefore import later- May have to change
                if (File.Exists(tday))
                {
                    for (int j = 0; j < Builder.Materials.Length; j++)
                    {
                        Builder.Materials[j].DaytimeTexture      = tday;
                        Builder.Materials[j].TransparencyTexture = transtex;
                        Builder.Materials[j].NighttimeTexture    = tnight;
                    }
                }
                if (TransparencyUsed == true)
                {
                    for (int j = 0; j < Builder.Materials.Length; j++)
                    {
                        Builder.Materials[j].TransparentColor     = FirstPxTransparent ? FirstPxColor : transparentColor;
                        Builder.Materials[j].TransparentColorUsed = true;
                    }
                }
            }
            ApplyMeshBuilder(ref Object, Builder, LoadMode, false, false);
            World.CreateNormals(ref Object.Mesh);
            return(Object);
        }
示例#14
0
        // parse extensions config
        internal static void ParseExtensionsConfig(string TrainPath, System.Text.Encoding Encoding, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects, TrainManager.Train Train, bool LoadObjects)
        {
            bool[] CarObjectsReversed   = new bool[Train.Cars.Length];
            bool[] BogieObjectsReversed = new bool[Train.Cars.Length * 2];

            bool[] CarsDefined   = new bool[Train.Cars.Length];
            bool[] BogiesDefined = new bool[Train.Cars.Length * 2];
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string FileName = OpenBveApi.Path.CombineFile(TrainPath, "extensions.cfg");

            if (System.IO.File.Exists(FileName))
            {
                TextEncoding.Encoding newEncoding = TextEncoding.GetEncodingFromFile(FileName);
                if (newEncoding != TextEncoding.Encoding.Unknown)
                {
                    switch (newEncoding)
                    {
                    case TextEncoding.Encoding.Utf7:
                        Encoding = System.Text.Encoding.UTF7;
                        break;

                    case TextEncoding.Encoding.Utf8:
                        Encoding = System.Text.Encoding.UTF8;
                        break;

                    case TextEncoding.Encoding.Utf16Le:
                        Encoding = System.Text.Encoding.Unicode;
                        break;

                    case TextEncoding.Encoding.Utf16Be:
                        Encoding = System.Text.Encoding.BigEndianUnicode;
                        break;

                    case TextEncoding.Encoding.Utf32Le:
                        Encoding = System.Text.Encoding.UTF32;
                        break;

                    case TextEncoding.Encoding.Utf32Be:
                        Encoding = System.Text.Encoding.GetEncoding(12001);
                        break;

                    case TextEncoding.Encoding.Shift_JIS:
                        Encoding = System.Text.Encoding.GetEncoding(932);
                        break;
                    }
                }

                string[] Lines = System.IO.File.ReadAllLines(FileName, Encoding);
                for (int i = 0; i < Lines.Length; i++)
                {
                    int j = Lines[i].IndexOf(';');
                    if (j >= 0)
                    {
                        Lines[i] = Lines[i].Substring(0, j).Trim();
                    }
                    else
                    {
                        Lines[i] = Lines[i].Trim();
                    }
                }
                for (int i = 0; i < Lines.Length; i++)
                {
                    if (Lines[i].Length != 0)
                    {
                        switch (Lines[i].ToLowerInvariant())
                        {
                        case "[exterior]":
                            // exterior
                            i++;
                            while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal))
                            {
                                if (Lines[i].Length != 0)
                                {
                                    int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                    if (j >= 0)
                                    {
                                        string a = Lines[i].Substring(0, j).TrimEnd();
                                        string b = Lines[i].Substring(j + 1).TrimStart();
                                        int    n;
                                        if (int.TryParse(a, System.Globalization.NumberStyles.Integer, Culture, out n))
                                        {
                                            if (n >= 0 & n < Train.Cars.Length)
                                            {
                                                if (Path.ContainsInvalidChars(b))
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                }
                                                else
                                                {
                                                    string File = OpenBveApi.Path.CombineFile(TrainPath, b);
                                                    if (System.IO.File.Exists(File))
                                                    {
                                                        if (LoadObjects)
                                                        {
                                                            CarObjects[n] = ObjectManager.LoadObject(File, Encoding, false);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(MessageType.Error, true, "The car object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "The car index " + a + " does not reference an existing car at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                }
                                i++;
                            }
                            i--;
                            break;

                        default:
                            if (Lines[i].StartsWith("[car", StringComparison.OrdinalIgnoreCase) & Lines[i].EndsWith("]", StringComparison.Ordinal))
                            {
                                // car
                                string t = Lines[i].Substring(4, Lines[i].Length - 5);
                                int    n; if (int.TryParse(t, System.Globalization.NumberStyles.Integer, Culture, out n))
                                {
                                    if (n >= 0 & n < Train.Cars.Length)
                                    {
                                        if (CarsDefined[n])
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Car " + n.ToString(Culture) + " has already been declared at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                        CarsDefined[n] = true;
                                        bool DefinedLength = false;
                                        bool DefinedAxles  = false;
                                        i++;
                                        while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal))
                                        {
                                            if (Lines[i].Length != 0)
                                            {
                                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                                if (j >= 0)
                                                {
                                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                                    switch (a.ToLowerInvariant())
                                                    {
                                                    case "object":
                                                        if (string.IsNullOrEmpty(b))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, "An empty car object was supplied at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            break;
                                                        }
                                                        if (Path.ContainsInvalidChars(b))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                        else
                                                        {
                                                            string File = OpenBveApi.Path.CombineFile(TrainPath, b);
                                                            if (System.IO.File.Exists(File))
                                                            {
                                                                if (LoadObjects)
                                                                {
                                                                    CarObjects[n] = ObjectManager.LoadObject(File, Encoding, false);
                                                                }
                                                            }
                                                            else
                                                            {
                                                                Interface.AddMessage(MessageType.Error, true, "The car object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                        }
                                                        break;

                                                    case "length":
                                                    {
                                                        double m;
                                                        if (double.TryParse(b, System.Globalization.NumberStyles.Float, Culture, out m))
                                                        {
                                                            if (m > 0.0)
                                                            {
                                                                Train.Cars[n].Length = m;
                                                                Train.Cars[n].BeaconReceiverPosition = 0.5 * m;
                                                                DefinedLength = true;
                                                            }
                                                            else
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Value is expected to be a positive floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "Value is expected to be a positive floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                    }
                                                    break;

                                                    case "axles":
                                                    {
                                                        int k = b.IndexOf(',');
                                                        if (k >= 0)
                                                        {
                                                            string c = b.Substring(0, k).TrimEnd();
                                                            string d = b.Substring(k + 1).TrimStart();
                                                            double rear, front;
                                                            if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out rear))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Rear is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out front))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Front is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else if (rear >= front)
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Rear is expected to be less than Front in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else
                                                            {
                                                                Train.Cars[n].RearAxle.Position  = rear;
                                                                Train.Cars[n].FrontAxle.Position = front;
                                                                DefinedAxles = true;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                    }
                                                    break;

                                                    case "reversed":
                                                        CarObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase);
                                                        break;

                                                    default:
                                                        Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                }
                                            }
                                            i++;
                                        }
                                        i--;
                                        if (DefinedLength & !DefinedAxles)
                                        {
                                            double AxleDistance = 0.4 * Train.Cars[n].Length;
                                            Train.Cars[n].RearAxle.Position  = -AxleDistance;
                                            Train.Cars[n].FrontAxle.Position = AxleDistance;
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The car index " + t + " does not reference an existing car at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                }
                            }
                            else if (Lines[i].StartsWith("[coupler", StringComparison.OrdinalIgnoreCase) & Lines[i].EndsWith("]", StringComparison.Ordinal))
                            {
                                // coupler
                                string t = Lines[i].Substring(8, Lines[i].Length - 9);
                                int    n; if (int.TryParse(t, System.Globalization.NumberStyles.Integer, Culture, out n))
                                {
                                    if (n >= 0 & n < Train.Couplers.Length)
                                    {
                                        i++; while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal))
                                        {
                                            if (Lines[i].Length != 0)
                                            {
                                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                                if (j >= 0)
                                                {
                                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                                    switch (a.ToLowerInvariant())
                                                    {
                                                    case "distances":
                                                    {
                                                        int k = b.IndexOf(',');
                                                        if (k >= 0)
                                                        {
                                                            string c = b.Substring(0, k).TrimEnd();
                                                            string d = b.Substring(k + 1).TrimStart();
                                                            double min, max;
                                                            if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out min))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Minimum is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out max))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Maximum is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else if (min > max)
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Minimum is expected to be less than Maximum in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else
                                                            {
                                                                Train.Couplers[n].MinimumDistanceBetweenCars = min;
                                                                Train.Couplers[n].MaximumDistanceBetweenCars = max;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                    } break;

                                                    default:
                                                        Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                }
                                            }
                                            i++;
                                        }
                                        i--;
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The coupler index " + t + " does not reference an existing coupler at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The coupler index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                }
                            }
                            else if (Lines[i].StartsWith("[bogie", StringComparison.OrdinalIgnoreCase) & Lines[i].EndsWith("]", StringComparison.Ordinal))
                            {
                                // car
                                string t = Lines[i].Substring(6, Lines[i].Length - 7);
                                int    n; if (int.TryParse(t, System.Globalization.NumberStyles.Integer, Culture, out n))
                                {
                                    if (n > BogiesDefined.Length - 1)
                                    {
                                        continue;
                                    }
                                    if (BogiesDefined[n])
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Bogie " + n.ToString(Culture) + " has already been declared at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                    BogiesDefined[n] = true;
                                    //Assuming that there are two bogies per car
                                    bool IsOdd    = (n % 2 != 0);
                                    int  CarIndex = n / 2;
                                    if (n >= 0 & n < Train.Cars.Length * 2)
                                    {
                                        bool DefinedAxles = false;
                                        i++;
                                        while (i < Lines.Length && !Lines[i].StartsWith("[", StringComparison.Ordinal) & !Lines[i].EndsWith("]", StringComparison.Ordinal))
                                        {
                                            if (Lines[i].Length != 0)
                                            {
                                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                                if (j >= 0)
                                                {
                                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                                    switch (a.ToLowerInvariant())
                                                    {
                                                    case "object":
                                                        if (Path.ContainsInvalidChars(b))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                        else
                                                        {
                                                            if (string.IsNullOrEmpty(b))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, true, "An empty bogie object was supplied at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                                break;
                                                            }
                                                            string File = OpenBveApi.Path.CombineFile(TrainPath, b);
                                                            if (System.IO.File.Exists(File))
                                                            {
                                                                if (LoadObjects)
                                                                {
                                                                    BogieObjects[n] = ObjectManager.LoadObject(File, Encoding, false);
                                                                }
                                                            }
                                                            else
                                                            {
                                                                Interface.AddMessage(MessageType.Error, true, "The bogie object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                        }
                                                        break;

                                                    case "length":
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, "A defined length is not supported for bogies at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    }
                                                    break;

                                                    case "axles":
                                                    {
                                                        int k = b.IndexOf(',');
                                                        if (k >= 0)
                                                        {
                                                            string c = b.Substring(0, k).TrimEnd();
                                                            string d = b.Substring(k + 1).TrimStart();
                                                            double rear, front;
                                                            if (!double.TryParse(c, System.Globalization.NumberStyles.Float, Culture, out rear))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Rear is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else if (!double.TryParse(d, System.Globalization.NumberStyles.Float, Culture, out front))
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Front is expected to be a floating-point number in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else if (rear >= front)
                                                            {
                                                                Interface.AddMessage(MessageType.Error, false, "Rear is expected to be less than Front in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                            }
                                                            else
                                                            {
                                                                if (IsOdd)
                                                                {
                                                                    Train.Cars[CarIndex].FrontBogie.RearAxle.Position  = rear;
                                                                    Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = front;
                                                                }
                                                                else
                                                                {
                                                                    Train.Cars[CarIndex].RearBogie.RearAxle.Position  = rear;
                                                                    Train.Cars[CarIndex].RearBogie.FrontAxle.Position = front;
                                                                }
                                                                DefinedAxles = true;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                    }
                                                    break;

                                                    case "reversed":
                                                        BogieObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase);
                                                        break;

                                                    default:
                                                        Interface.AddMessage(MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                }
                                            }
                                            i++;
                                        }
                                        i--;
                                        if (!DefinedAxles)
                                        {
                                            if (IsOdd)
                                            {
                                                double AxleDistance = 0.4 * Train.Cars[CarIndex].FrontBogie.Length;
                                                Train.Cars[CarIndex].FrontBogie.RearAxle.Position  = -AxleDistance;
                                                Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = AxleDistance;
                                            }
                                            else
                                            {
                                                double AxleDistance = 0.4 * Train.Cars[CarIndex].RearBogie.Length;
                                                Train.Cars[CarIndex].RearBogie.RearAxle.Position  = -AxleDistance;
                                                Train.Cars[CarIndex].RearBogie.FrontAxle.Position = AxleDistance;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The car index " + t + " does not reference an existing car at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                }
                            }
                            else
                            {
                                // default
                                if (Lines.Length == 1 && Encoding.Equals(Encoding.Unicode))
                                {
                                    /*
                                     * If only one line, there's a good possibility that our file is NOT Unicode at all
                                     * and that the misdetection has turned it into garbage
                                     *
                                     * Try again with ASCII instead
                                     */
                                    ParseExtensionsConfig(TrainPath, Encoding.GetEncoding(1252), ref CarObjects, ref BogieObjects, Train, LoadObjects);
                                    return;
                                }
                                Interface.AddMessage(MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                            }
                            break;
                        }
                    }
                }

                // check for car objects and reverse if necessary
                int carObjects = 0;
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    if (CarObjects[i] != null)
                    {
                        carObjects++;
                        if (CarObjectsReversed[i] && LoadObjects)
                        {
                            {
                                // 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 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++)
                                    {
                                        if (obj.Objects[j].States[h].Object == null)
                                        {
                                            continue;                                             //object failed to load?
                                        }
                                        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] && LoadObjects)
                        {
                            {
                                // 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 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++)
                                    {
                                        if (obj.Objects[j].States[h].Object == null)
                                        {
                                            continue;                                             //object failed to load?
                                        }
                                        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();
                            }
                        }
                    }
                }

                if (carObjects > 0 & carObjects < Train.Cars.Length)
                {
                    Interface.AddMessage(MessageType.Warning, false, "An incomplete set of exterior objects was provided in file " + FileName);
                }

                if (bogieObjects > 0 & bogieObjects < Train.Cars.Length * 2)
                {
                    Interface.AddMessage(MessageType.Warning, false, "An incomplete set of bogie objects was provided in file " + FileName);
                }
            }
        }
示例#15
0
 /// <summary>Parses a string into OpenBVE's internal time representation (Seconds since midnight on the first day)</summary>
 /// <param name="Expression">The time in string format</param>
 /// <param name="Value">The number of seconds since midnight on the first day this represents, updated via 'out'</param>
 /// <returns>True if the parse succeeds, false if it does not</returns>
 internal static bool TryParseTime(string Expression, out double Value)
 {
     Expression = Expression.TrimInside();
     if (Expression.Length != 0)
     {
         CultureInfo Culture = CultureInfo.InvariantCulture;
         int         i       = Expression.IndexOf('.');
         if (i == -1)
         {
             i = Expression.IndexOf(':');
         }
         if (i >= 1)
         {
             int h; if (int.TryParse(Expression.Substring(0, i), NumberStyles.Integer, Culture, out h))
             {
                 int n = Expression.Length - i - 1;
                 if (n == 1 | n == 2)
                 {
                     uint m; if (uint.TryParse(Expression.Substring(i + 1, n), NumberStyles.None, Culture, out m))
                     {
                         Value = 3600.0 * (double)h + 60.0 * (double)m;
                         return(true);
                     }
                 }
                 else if (n >= 3)
                 {
                     if (n > 4)
                     {
                         Interface.AddMessage(MessageType.Warning, false, "A maximum of 4 digits of precision are supported in TIME values");
                         n = 4;
                     }
                     uint m; if (uint.TryParse(Expression.Substring(i + 1, 2), NumberStyles.None, Culture, out m))
                     {
                         uint   s;
                         string ss = Expression.Substring(i + 3, n - 2);
                         if (Interface.CurrentOptions.EnableBveTsHacks)
                         {
                             /*
                              * Handles values in the following format:
                              * HH.MM.SS
                              */
                             if (ss.StartsWith("."))
                             {
                                 ss = ss.Substring(1, ss.Length - 1);
                             }
                         }
                         if (uint.TryParse(ss, NumberStyles.None, Culture, out s))
                         {
                             Value = 3600.0 * (double)h + 60.0 * (double)m + (double)s;
                             return(true);
                         }
                     }
                 }
             }
         }
         else if (i == -1)
         {
             int h; if (int.TryParse(Expression, NumberStyles.Integer, Culture, out h))
             {
                 Value = 3600.0 * (double)h;
                 return(true);
             }
         }
     }
     Value = 0.0;
     return(false);
 }
        private static void CheckRouteSpecificFixes(string FileName, ref RouteData Data, ref Expression[] Expressions)
        {
            if (Interface.CurrentOptions.EnableBveTsHacks == false)
            {
                return;
            }
            FileInfo f = new FileInfo(FileName);

            switch (f.Length)
            {
            case 63652:
                //Jundiai-Francisco Morato.rw
                if (Game.RouteComment == "Jundiai-Francisco Morato\nExtensão Operacional Linha A\nCPTM - Cia. Paulista de Trens Metropolitanos")
                {
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Jundiai - Francisco Morato routefile detected- Applying fix to line endings.");
                    Data.LineEndingFix = true;
                }
                break;

            case 67729:
                //kurra_fine1.csv
                if (Game.RouteComment == "Kurrajong Line, 1963\r\nLocal\r\n2 Cars\r\nRichmond - Kurrajong\r\n\r\n(C) 2001 Spot")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Richmond- Kurrajong routefile detected- Applying fix to yaw / roll.");
                }
                break;

            case 70625:
                //FVES3.rw
                if (Game.RouteComment == "Linie S3 der FVE\nFarge - Vegesack\nHöchstgeschwindigkeit\nder Strecke 80Km/h\nvon Hans-Martin Finken")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Linie S3 (FVE) routefile detected- Applying fix to yaw / roll.");
                }
                break;

            case 73262:
                //kurrajong.csv
                if (Game.RouteComment == "Kurrajong Line, 1953\r\nLocal\r\n2 Cars\r\nRichmond - Kurrajong\r\n\r\n(C) 2001 Spot")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Richmond- Kurrajong routefile detected- Applying fix to yaw / roll.");
                }
                break;

            case 75400:
                //camden_17.csv
                if (Game.RouteComment == "Camden Line, 1963\r\nLocal\r\n2 Cars\r\nCampbelltown - Camden\r\n\r\n(C) 2001 Spot")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Campbelltown- Camden routefile detected- Applying fix to yaw / roll.");
                }
                break;

            case 86723:
                //Zwolle-Vlissingen.rw
                if (Game.RouteComment == "Zwolle - Vlissingen \n(Part Two of Groningen-Vlissingen)\nEarly Evening Express")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Zwolle - Vlissingen routefile detected- Applying fix to yaw / roll.");
                }
                break;

            case 101882:
            case 101930:
            case 102150:
            case 102405:
            case 102493:
            case 102575:
                //Sanbie-663-bve4.csv
                if (Game.RouteComment == "Linea Santhià-Biella completa Km 26.724. Partenza ore 13:22 Arrivo 13:51 Non ferma a Brianco. \r\n Line Santhià-Biella  Departure: Santhià  Arrival: Biella km 26.724. The train doesn't stops at Brianco.")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Sanbie routefile detected- Applying fix to yaw / roll.");
                }
                //Sanbie-663-nonstop-bve4.csv
                //Sanbie-663-rain-nonstop-bve4.csv
                if (Game.RouteComment == "Linea Santhià-Biella completa Km 26.724. Partenza ore 07:37 Arrivo 07:58 Non fa fermate intermedie. \r\n Line Santhià-Biella  Departure: Santhià Arrival: Biella km 26.724. Non stop train.")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Sanbie routefile detected- Applying fix to yaw / roll.");
                }
                //Sanbie-773-bve4.csv
                if (Game.RouteComment == "Linea Santhià-Biella completa Km 26.724. Partenza ore 13:22 Arrivo 13:51 Non ferma a Brianco. \r\n Line Santhià-Biella  Departure: Santhià  Arrival: Biella km 26.724. The train doesn't stops at Brianco.Variant of Peter Shotz")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Sanbie routefile detected- Applying fix to yaw / roll.");
                }
                //Sanbie-773-nonstop-bve4.csv
                if (Game.RouteComment == "Linea Santhià-Biella completa Km 26.724. Partenza ore 07:37 Arrivo 07:58 Non fa fermate intermedie. \r\n Line Santhià-Biella  Departure: Santhià Arrival: Biella km 26.724. Non stop train. variant of Peter Shotz.")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Sanbie routefile detected- Applying fix to yaw / roll.");
                }
                //Sanbie-773-rain-nonstop-bve4.csv
                if (Game.RouteComment == "Linea Santhià-Biella completa Km 26.724. Partenza ore 07:37 Arrivo 07:58 Non fa fermate intermedie. \r\n Line Santhià-Biella  Departure: Santhià Arrival: Biella km 26.724. Non stop train. variant of Peter Shotz. Rain.")
                {
                    Data.IgnorePitchRoll = true;
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Sanbie routefile detected- Applying fix to yaw / roll.");
                }
                break;

            case 14297:
                //目蒲線普.csv
                //Trackwork on exit to second station is broken without this
                if (Game.RouteComment == "東急目蒲線\r\n奥沢-多摩川園\r\nver1.01\r\n\r\n(C)2004 こば")
                {
                    if (Expressions[596].Text == ".rail 1;7.5:0")
                    {
                        Expressions[596].Text = ".rail 1;7.5;0";
                    }

                    if (Expressions[600].Text == ".rail 1;5.5:0")
                    {
                        Expressions[600].Text = ".rail 1;5.5;0";
                    }
                }
                break;
            }
        }
示例#17
0
        /// <summary>Loads a Loksim3D GruppenObject</summary>
        /// <param name="FileName">The filename to load</param>
        /// <param name="Encoding">The text encoding of the containing file (Currently ignored, REMOVE??)</param>
        /// <param name="Rotation">A three-dimemsional vector describing the rotation to be applied</param>
        /// <returns>A new animated object collection, containing the GruppenObject's meshes etc.</returns>
        internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, Encoding Encoding, Vector3 Rotation)
        {
            XmlDocument currentXML = new XmlDocument();

            ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection();
            Result.Objects = new ObjectManager.AnimatedObject[0];
            try
            {
                currentXML.Load(FileName);
            }
            catch (Exception ex)
            {
                //The XML is not strictly valid
                string[] Lines = File.ReadAllLines(FileName);
                using (var stringReader = new StringReader(Lines[0]))
                {
                    var settings = new XmlReaderSettings {
                        ConformanceLevel = ConformanceLevel.Fragment
                    };
                    using (var xmlReader = XmlReader.Create(stringReader, settings))
                    {
                        if (xmlReader.Read())
                        {
                            //Attempt to find the text encoding and re-read the file
                            var result = xmlReader.GetAttribute("encoding");
                            if (result != null)
                            {
                                var e = System.Text.Encoding.GetEncoding(result);
                                Lines = File.ReadAllLines(FileName, e);
                                //Turf out the old encoding, as our string array should now be UTF-8
                                Lines[0] = "<?xml version=\"1.0\"?>";
                            }
                        }
                    }
                }
                for (int i = 0; i < Lines.Length; i++)
                {
                    while (Lines[i].IndexOf("\"\"", StringComparison.InvariantCulture) != -1)
                    {
                        //Loksim parser tolerates multiple quotes, strict XML does not
                        Lines[i] = Lines[i].Replace("\"\"", "\"");
                    }
                    while (Lines[i].IndexOf("  ", StringComparison.InvariantCulture) != -1)
                    {
                        //Replace double-spaces with singles
                        Lines[i] = Lines[i].Replace("  ", " ");
                    }
                }
                bool tryLoad = false;
                try
                {
                    //Horrible hack: Write out our string array to a new memory stream, then load from this stream
                    //Why can't XmlDocument.Load() just take a string array......
                    using (var stream = new MemoryStream())
                    {
                        var sw = new StreamWriter(stream);
                        foreach (var line in Lines)
                        {
                            sw.Write(line);
                            sw.Flush();
                        }
                        sw.Flush();
                        stream.Position = 0;
                        currentXML.Load(stream);
                        tryLoad = true;
                    }
                }
                catch
                {
                    //Generic catch-all clause
                }
                if (!tryLoad)
                {
                    //Pass out the *original* XML error, not anything generated when we've tried to correct it
                    Interface.AddMessage(MessageType.Error, false, "Error parsing Loksim3D XML: " + ex.Message);
                    return(null);
                }
            }

            string BaseDir = System.IO.Path.GetDirectoryName(FileName);

            GruppenObject[] CurrentObjects = new GruppenObject[0];
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                UnifiedObject[] obj           = new UnifiedObject[0];
                XmlNodeList     DocumentNodes = currentXML.DocumentElement.SelectNodes("/GRUPPENOBJECT");
                if (DocumentNodes != null)
                {
                    foreach (XmlNode outerNode in DocumentNodes)
                    {
                        if (outerNode.ChildNodes.OfType <XmlElement>().Any())
                        {
                            foreach (XmlNode node in outerNode.ChildNodes)
                            {
                                if (node.Name == "Object" && node.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            GruppenObject Object = new GruppenObject
                                            {
                                                Rotation = Rotation
                                            };
                                            foreach (XmlAttribute attribute in childNode.Attributes)
                                            {
                                                switch (attribute.Name)
                                                {
                                                case "Name":
                                                    string ObjectFile = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory);
                                                    if (!File.Exists(ObjectFile))
                                                    {
                                                        Object.Name = null;
                                                        Interface.AddMessage(MessageType.Warning, true, "Ls3d Object file " + attribute.Value + " not found.");
                                                    }
                                                    else
                                                    {
                                                        Object.Name = ObjectFile;
                                                    }
                                                    break;

                                                case "Position":
                                                    string[] SplitPosition = attribute.Value.Split(';');
                                                    double.TryParse(SplitPosition[0], out Object.Position.X);
                                                    double.TryParse(SplitPosition[1], out Object.Position.Y);
                                                    double.TryParse(SplitPosition[2], out Object.Position.Z);
                                                    break;

                                                case "Rotation":
                                                    string[] SplitRotation = attribute.Value.Split(';');
                                                    Vector3  r;
                                                    double.TryParse(SplitRotation[0], out r.X);
                                                    double.TryParse(SplitRotation[1], out r.Y);
                                                    double.TryParse(SplitRotation[2], out r.Z);
                                                    Object.Rotation += r;
                                                    break;

                                                case "ShowOn":
                                                    //Defines when the object should be shown
                                                    Object.FunctionScript = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(GetAnimatedFunction(attribute.Value, false));
                                                    break;

                                                case "HideOn":
                                                    //Defines when the object should be hidden
                                                    Object.FunctionScript = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(GetAnimatedFunction(attribute.Value, true));
                                                    break;

                                                case "FixedDynamicVisibility":
                                                    if (attribute.Value.ToLowerInvariant() == "true")
                                                    {
                                                        Object.FixedDynamicVisibility = true;
                                                    }
                                                    else
                                                    {
                                                        Object.FixedDynamicVisibility = false;
                                                    }
                                                    break;

                                                case "DynamicVisibility":
                                                    if (Object.FixedDynamicVisibility)
                                                    {
                                                        Object.FunctionScript = FunctionScriptNotation.GetPostfixNotationFromInfixNotation(GetDynamicFunction(attribute.Value));
                                                    }
                                                    break;
                                                }
                                            }
                                            if (Object.Name != null)
                                            {
                                                Array.Resize <GruppenObject>(ref CurrentObjects, CurrentObjects.Length + 1);
                                                CurrentObjects[CurrentObjects.Length - 1] = Object;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    //We've loaded the XML references, now load the objects into memory

                    //Single mesh object, containing all static components of the LS3D object
                    //If we use multiples, the Z-sorting throws a wobbly
                    ObjectManager.StaticObject staticObject = null;
                    for (int i = 0; i < CurrentObjects.Length; i++)
                    {
                        if (CurrentObjects[i] == null || string.IsNullOrEmpty(CurrentObjects[i].Name))
                        {
                            continue;
                        }
                        ObjectManager.StaticObject             Object         = null;
                        ObjectManager.AnimatedObjectCollection AnimatedObject = null;
                        try
                        {
                            if (CurrentObjects[i].Name.ToLowerInvariant().EndsWith(".l3dgrp"))
                            {
                                AnimatedObject = ReadObject(CurrentObjects[i].Name, Encoding, CurrentObjects[i].Rotation);
                            }
                            else if (CurrentObjects[i].Name.ToLowerInvariant().EndsWith(".l3dobj"))
                            {
                                //Object = (ObjectManager.StaticObject)ObjectManager.LoadObject(CurrentObjects[i].Name, Encoding, false, false, CurrentObjects[i].Rotation);
                            }
                            else
                            {
                                throw new Exception("Format " + System.IO.Path.GetExtension(CurrentObjects[i].Name) + " is not currently supported by the Loksim3D object parser");
                            }
                        }
                        catch (Exception ex)
                        {
                            Interface.AddMessage(MessageType.Error, false, ex.Message);
                        }
                        if (Object != null)
                        {
                            if (!string.IsNullOrEmpty(CurrentObjects[i].FunctionScript))
                            {
                                //If the function script is not empty, this is a new animated object bit
                                Array.Resize <UnifiedObject>(ref obj, obj.Length + 1);
                                obj[obj.Length - 1] = Object;
                                int aL = Result.Objects.Length;
                                Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, aL + 1);
                                ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                                ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState(Object, CurrentObjects[i].Position);
                                a.States           = new ObjectManager.AnimatedObjectState[] { aos };
                                Result.Objects[aL] = a;
                                Result.Objects[aL].StateFunction = new FunctionScript(Program.CurrentHost, CurrentObjects[i].FunctionScript + " 1 == --", false);
                            }
                            else
                            {
                                //Otherwise, join to the main static mesh & update co-ords
                                for (int j = 0; j < Object.Mesh.Vertices.Length; j++)
                                {
                                    Object.Mesh.Vertices[j].Coordinates += CurrentObjects[i].Position;
                                }
                                staticObject.JoinObjects(Object);
                            }
                        }
                        else if (AnimatedObject != null)
                        {
                            int rl = Result.Objects.Length;
                            int l  = AnimatedObject.Objects.Length;
                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + l);
                            for (int o = rl; o < rl + l; o++)
                            {
                                if (AnimatedObject.Objects[o - rl] != null)
                                {
                                    Result.Objects[o] = AnimatedObject.Objects[o - rl].Clone();
                                    for (int si = 0; si < Result.Objects[o].States.Length; si++)
                                    {
                                        Result.Objects[o].States[si].Position += CurrentObjects[i].Position;
                                    }
                                }
                                else
                                {
                                    Result.Objects[o]        = new ObjectManager.AnimatedObject();
                                    Result.Objects[o].States = new ObjectManager.AnimatedObjectState[0];
                                }
                            }
                        }
                    }
                    if (staticObject != null)
                    {
                        Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + 1);
                        ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                        ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState(staticObject, Vector3.Zero);
                        a.States = new ObjectManager.AnimatedObjectState[] { aos };
                        Result.Objects[Result.Objects.Length - 1] = a;
                    }
                }
                return(Result);
            }
            //Didn't find an acceptable XML object
            //Probably will cause things to throw an absolute wobbly somewhere....
            return(null);
        }
示例#18
0
        /// <summary>This function processes the list of expressions for $Char, $Rnd, $If and $Sub directives, and evaluates them into the final expressions dataset</summary>
        private static void PreprocessChrRndSub(string FileName, bool IsRW, System.Text.Encoding Encoding, ref Expression[] Expressions)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string[] Subs    = new string[16];
            int      openIfs = 0;

            for (int i = 0; i < Expressions.Length; i++)
            {
                string Epilog = " at line " + Expressions[i].Line.ToString(Culture) + ", column " + Expressions[i].Column.ToString(Culture) + " in file " + Expressions[i].File;
                bool   continueWithNextExpression = false;
                for (int j = Expressions[i].Text.Length - 1; j >= 0; j--)
                {
                    if (Expressions[i].Text[j] == '$')
                    {
                        int k;
                        for (k = j + 1; k < Expressions[i].Text.Length; k++)
                        {
                            if (Expressions[i].Text[k] == '(')
                            {
                                break;
                            }
                            else if (Expressions[i].Text[k] == '/' | Expressions[i].Text[k] == '\\')
                            {
                                k = Expressions[i].Text.Length + 1;
                                break;
                            }
                        }
                        if (k <= Expressions[i].Text.Length)
                        {
                            string t = Expressions[i].Text.Substring(j, k - j).TrimEnd();
                            int    l = 1, h;
                            for (h = k + 1; h < Expressions[i].Text.Length; h++)
                            {
                                switch (Expressions[i].Text[h])
                                {
                                case '(':
                                    l++;
                                    break;

                                case ')':
                                    l--;
                                    if (l < 0)
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Invalid parenthesis structure in " + t + Epilog);
                                    }
                                    break;
                                }
                                if (l <= 0)
                                {
                                    break;
                                }
                            }
                            if (continueWithNextExpression)
                            {
                                break;
                            }
                            if (l != 0)
                            {
                                Interface.AddMessage(MessageType.Error, false, "Invalid parenthesis structure in " + t + Epilog);
                                break;
                            }
                            string s = Expressions[i].Text.Substring(k + 1, h - k - 1).Trim();
                            switch (t.ToLowerInvariant())
                            {
                            case "$if":
                                if (j != 0)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The $If directive must not appear within another statement" + Epilog);
                                }
                                else
                                {
                                    double num;
                                    if (double.TryParse(s, System.Globalization.NumberStyles.Float, Culture, out num))
                                    {
                                        openIfs++;
                                        Expressions[i].Text = string.Empty;
                                        if (num == 0.0)
                                        {
                                            /*
                                             * Blank every expression until the matching $Else or $EndIf
                                             * */
                                            i++;
                                            int level = 1;
                                            while (i < Expressions.Length)
                                            {
                                                if (Expressions[i].Text.StartsWith("$if", StringComparison.OrdinalIgnoreCase))
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                    level++;
                                                }
                                                else if (Expressions[i].Text.StartsWith("$else", StringComparison.OrdinalIgnoreCase))
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                    if (level == 1)
                                                    {
                                                        level--;
                                                        break;
                                                    }
                                                }
                                                else if (Expressions[i].Text.StartsWith("$endif", StringComparison.OrdinalIgnoreCase))
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                    level--;
                                                    if (level == 0)
                                                    {
                                                        openIfs--;
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                }
                                                i++;
                                            }
                                            if (level != 0)
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "$EndIf missing at the end of the file" + Epilog);
                                            }
                                        }
                                        continueWithNextExpression = true;
                                        break;
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The $If condition does not evaluate to a number" + Epilog);
                                    }
                                }
                                continueWithNextExpression = true;
                                break;

                            case "$else":
                                /*
                                 * Blank every expression until the matching $EndIf
                                 * */
                                Expressions[i].Text = string.Empty;
                                if (openIfs != 0)
                                {
                                    i++;
                                    int level = 1;
                                    while (i < Expressions.Length)
                                    {
                                        if (Expressions[i].Text.StartsWith("$if", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Expressions[i].Text = string.Empty;
                                            level++;
                                        }
                                        else if (Expressions[i].Text.StartsWith("$else", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Expressions[i].Text = string.Empty;
                                            if (level == 1)
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Duplicate $Else encountered" + Epilog);
                                            }
                                        }
                                        else if (Expressions[i].Text.StartsWith("$endif", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Expressions[i].Text = string.Empty;
                                            level--;
                                            if (level == 0)
                                            {
                                                openIfs--;
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            Expressions[i].Text = string.Empty;
                                        }
                                        i++;
                                    }
                                    if (level != 0)
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "$EndIf missing at the end of the file" + Epilog);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "$Else without matching $If encountered" + Epilog);
                                }
                                continueWithNextExpression = true;
                                break;

                            case "$endif":
                                Expressions[i].Text = string.Empty;
                                if (openIfs != 0)
                                {
                                    openIfs--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "$EndIf without matching $If encountered" + Epilog);
                                }
                                continueWithNextExpression = true;
                                break;

                            case "$include":
                                if (j != 0)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "The $Include directive must not appear within another statement" + Epilog);
                                    continueWithNextExpression = true;
                                    break;
                                }
                                string[] args = s.Split(';');
                                for (int ia = 0; ia < args.Length; ia++)
                                {
                                    args[ia] = args[ia].Trim();
                                }
                                int      count        = (args.Length + 1) / 2;
                                string[] files        = new string[count];
                                double[] weights      = new double[count];
                                double[] offsets      = new double[count];
                                double   weightsTotal = 0.0;
                                for (int ia = 0; ia < count; ia++)
                                {
                                    string file;
                                    double offset;
                                    int    colon = args[2 * ia].IndexOf(':');
                                    if (colon >= 0)
                                    {
                                        file = args[2 * ia].Substring(0, colon).TrimEnd();
                                        string value = args[2 * ia].Substring(colon + 1).TrimStart();
                                        if (!double.TryParse(value, NumberStyles.Float, Culture, out offset))
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "The track position offset " + value + " is invalid in " + t + Epilog);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        file   = args[2 * ia];
                                        offset = 0.0;
                                    }
                                    files[ia]   = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), file);
                                    offsets[ia] = offset;
                                    if (!System.IO.File.Exists(files[ia]))
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "The file " + file + " could not be found in " + t + Epilog);
                                        for (int ta = i; ta < Expressions.Length - 1; ta++)
                                        {
                                            Expressions[ta] = Expressions[ta + 1];
                                        }
                                        Array.Resize <Expression>(ref Expressions, Expressions.Length - 1);
                                        i--;
                                        break;
                                    }
                                    if (2 * ia + 1 < args.Length)
                                    {
                                        if (!NumberFormats.TryParseDoubleVb6(args[2 * ia + 1], out weights[ia]))
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "A weight is invalid in " + t + Epilog);
                                            break;
                                        }
                                        if (weights[ia] <= 0.0)
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "A weight is not positive in " + t + Epilog);
                                            break;
                                        }
                                        weightsTotal += weights[ia];
                                    }
                                    else
                                    {
                                        weights[ia]   = 1.0;
                                        weightsTotal += 1.0;
                                    }
                                }
                                if (count == 0)
                                {
                                    continueWithNextExpression = true;
                                    Interface.AddMessage(MessageType.Error, false, "No file was specified in " + t + Epilog);
                                    break;
                                }
                                if (!continueWithNextExpression)
                                {
                                    double number      = Program.RandomNumberGenerator.NextDouble() * weightsTotal;
                                    double value       = 0.0;
                                    int    chosenIndex = 0;
                                    for (int ia = 0; ia < count; ia++)
                                    {
                                        value += weights[ia];
                                        if (value > number)
                                        {
                                            chosenIndex = ia;
                                            break;
                                        }
                                    }
                                    Expression[] expr;
                                    //Get the text encoding of our $Include file
                                    System.Text.Encoding includeEncoding = TextEncoding.GetSystemEncodingFromFile(files[chosenIndex]);
                                    if (!includeEncoding.Equals(Encoding) && includeEncoding.WindowsCodePage != Encoding.WindowsCodePage)
                                    {
                                        //If the encodings do not match, add a warning
                                        //This is not critical, but it's a bad idea to mix and match character encodings within a routefile, as the auto-detection may sometimes be wrong
                                        Interface.AddMessage(MessageType.Warning, false, "The text encoding of the $Include file " + files[chosenIndex] + " does not match that of the base routefile.");
                                    }
                                    string[] lines = System.IO.File.ReadAllLines(files[chosenIndex], includeEncoding);
                                    PreprocessSplitIntoExpressions(files[chosenIndex], IsRW, lines, out expr, false, offsets[chosenIndex] + Expressions[i].TrackPositionOffset);
                                    int length = Expressions.Length;
                                    if (expr.Length == 0)
                                    {
                                        for (int ia = i; ia < Expressions.Length - 1; ia++)
                                        {
                                            Expressions[ia] = Expressions[ia + 1];
                                        }
                                        Array.Resize <Expression>(ref Expressions, length - 1);
                                    }
                                    else
                                    {
                                        Array.Resize <Expression>(ref Expressions, length + expr.Length - 1);
                                        for (int ia = Expressions.Length - 1; ia >= i + expr.Length; ia--)
                                        {
                                            Expressions[ia] = Expressions[ia - expr.Length + 1];
                                        }
                                        for (int ia = 0; ia < expr.Length; ia++)
                                        {
                                            Expressions[i + ia] = expr[ia];
                                        }
                                    }
                                    i--;
                                    continueWithNextExpression = true;
                                }
                                break;

                            case "$chr":
                            case "$chruni":
                            {
                                int x;
                                if (NumberFormats.TryParseIntVb6(s, out x))
                                {
                                    if (x < 0)
                                    {
                                        //Must be non-negative
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index must be a non-negative character in " + t + Epilog);
                                    }
                                    else
                                    {
                                        Expressions[i].Text = Expressions[i].Text.Substring(0, j) + char.ConvertFromUtf32(x) + Expressions[i].Text.Substring(h + 1);
                                    }
                                }
                                else
                                {
                                    continueWithNextExpression = true;
                                    Interface.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                }
                            } break;

                            case "$chrascii":
                            {
                                int x;
                                if (NumberFormats.TryParseIntVb6(s, out x))
                                {
                                    if (x < 0 || x > 128)
                                    {
                                        //Standard ASCII characters from 0-128
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index does not correspond to a valid ASCII character in " + t + Epilog);
                                    }
                                    else
                                    {
                                        Expressions[i].Text = Expressions[i].Text.Substring(0, j) + char.ConvertFromUtf32(x) + Expressions[i].Text.Substring(h + 1);
                                    }
                                }
                                else
                                {
                                    continueWithNextExpression = true;
                                    Interface.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                }
                            }
                            break;

                            case "$rnd":
                            {
                                int m = s.IndexOf(";", StringComparison.Ordinal);
                                if (m >= 0)
                                {
                                    string s1 = s.Substring(0, m).TrimEnd();
                                    string s2 = s.Substring(m + 1).TrimStart();
                                    int    x; if (NumberFormats.TryParseIntVb6(s1, out x))
                                    {
                                        int y; if (NumberFormats.TryParseIntVb6(s2, out y))
                                        {
                                            int z = x + (int)Math.Floor(Program.RandomNumberGenerator.NextDouble() * (double)(y - x + 1));
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + z.ToString(Culture) + Expressions[i].Text.Substring(h + 1);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "Index2 is invalid in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index1 is invalid in " + t + Epilog);
                                    }
                                }
                                else
                                {
                                    continueWithNextExpression = true;
                                    Interface.AddMessage(MessageType.Error, false, "Two arguments are expected in " + t + Epilog);
                                }
                            } break;

                            case "$sub":
                            {
                                l = 0;
                                bool f = false;
                                int  m;
                                for (m = h + 1; m < Expressions[i].Text.Length; m++)
                                {
                                    switch (Expressions[i].Text[m])
                                    {
                                    case '(': l++; break;

                                    case ')': l--; break;

                                    case '=': if (l == 0)
                                        {
                                            f = true;
                                        }
                                        break;

                                    default:
                                        if (!char.IsWhiteSpace(Expressions[i].Text[m]))
                                        {
                                            l = -1;
                                        }
                                        break;
                                    }
                                    if (f | l < 0)
                                    {
                                        break;
                                    }
                                }
                                if (f)
                                {
                                    l = 0;
                                    int n;
                                    for (n = m + 1; n < Expressions[i].Text.Length; n++)
                                    {
                                        switch (Expressions[i].Text[n])
                                        {
                                        case '(': l++; break;

                                        case ')': l--; break;
                                        }
                                        if (l < 0)
                                        {
                                            break;
                                        }
                                    }
                                    int x;
                                    if (NumberFormats.TryParseIntVb6(s, out x))
                                    {
                                        if (x >= 0)
                                        {
                                            while (x >= Subs.Length)
                                            {
                                                Array.Resize <string>(ref Subs, Subs.Length << 1);
                                            }
                                            Subs[x]             = Expressions[i].Text.Substring(m + 1, n - m - 1).Trim();
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + Expressions[i].Text.Substring(n);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "Index is expected to be non-negative in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                    }
                                }
                                else
                                {
                                    int x;
                                    if (NumberFormats.TryParseIntVb6(s, out x))
                                    {
                                        if (x >= 0 & x < Subs.Length && Subs[x] != null)
                                        {
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + Subs[x] + Expressions[i].Text.Substring(h + 1);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "Index is out of range in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                    }
                                }
                            }
                            break;
                            }
                        }
                    }
                    if (continueWithNextExpression)
                    {
                        break;
                    }
                }
            }
            // handle comments introduced via chr, rnd, sub
            {
                int length = Expressions.Length;
                for (int i = 0; i < length; i++)
                {
                    Expressions[i].Text = Expressions[i].Text.Trim();
                    if (Expressions[i].Text.Length != 0)
                    {
                        if (Expressions[i].Text[0] == ';')
                        {
                            for (int j = i; j < length - 1; j++)
                            {
                                Expressions[j] = Expressions[j + 1];
                            }
                            length--;
                            i--;
                        }
                    }
                    else
                    {
                        for (int j = i; j < length - 1; j++)
                        {
                            Expressions[j] = Expressions[j + 1];
                        }
                        length--;
                        i--;
                    }
                }
                if (length != Expressions.Length)
                {
                    Array.Resize <Expression>(ref Expressions, length);
                }
            }
        }
        internal static StaticObject LoadStaticObject(string FileName, System.Text.Encoding Encoding, bool PreserveVertices, bool ForceTextureRepeatX, bool ForceTextureRepeatY)
        {
            if (String.IsNullOrEmpty(FileName))
            {
                return(null);
            }
#if !DEBUG
            try {
#endif
            if (!System.IO.Path.HasExtension(FileName))
            {
                while (true)
                {
                    string f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".x");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".csv");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                        break;
                    }
                    f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), System.IO.Path.GetFileName(FileName) + ".b3d");
                    if (System.IO.File.Exists(f))
                    {
                        FileName = f;
                    }
                    break;
                }
            }
            StaticObject Result;
            string e = System.IO.Path.GetExtension(FileName);
            if (e == null)
            {
                Interface.AddMessage(MessageType.Error, false, "The file " + FileName + " does not have a recognised extension.");
                return(null);
            }
            switch (e.ToLowerInvariant())
            {
            case ".csv":
            case ".b3d":
                Result = CsvB3dObjectParser.ReadObject(FileName, Encoding);
                break;

            case ".x":
                if (Interface.CurrentOptions.CurrentXParser != Interface.XParsers.Original)
                {
                    try
                    {
                        if (Interface.CurrentOptions.CurrentXParser == Interface.XParsers.NewXParser)
                        {
                            Result = NewXParser.ReadObject(FileName, Encoding);
                        }
                        else
                        {
                            Result = AssimpXParser.ReadObject(FileName);
                        }
                    }
                    catch (Exception ex)
                    {
                        Interface.AddMessage(MessageType.Error, false, "The new X parser raised the following exception: " + ex);
                        Result = XObjectParser.ReadObject(FileName, Encoding);
                    }
                }
                else
                {
                    Result = XObjectParser.ReadObject(FileName, Encoding);
                }
                break;

            case ".animated":
            case ".s":
                Interface.AddMessage(MessageType.Error, false, "Tried to load an animated object even though only static objects are allowed: " + FileName);
                return(null);

            case ".obj":
                if (Interface.CurrentOptions.CurrentObjParser == Interface.ObjParsers.Assimp)
                {
                    try
                    {
                        Result = AssimpObjParser.ReadObject(FileName);
                    }
                    catch (Exception ex)
                    {
                        Interface.AddMessage(MessageType.Error, false, "The new Obj parser raised the following exception: " + ex);
                        Result = WavefrontObjParser.ReadObject(FileName, Encoding);
                    }
                }
                else
                {
                    Result = WavefrontObjParser.ReadObject(FileName, Encoding);
                }
                break;

            /*
             * This will require implementing a specific static object load function- Leave alone for the moment
             *
             * case ".xml":
             * Result = XMLParser.ReadObject(FileName, Encoding, ForceTextureRepeatX, ForceTextureRepeatY);
             * break;
             */
            default:
                Interface.AddMessage(MessageType.Error, false, "The file extension is not supported: " + FileName);
                return(null);
            }
            if (Result != null)
            {
                Result.OptimizeObject(PreserveVertices);
            }
            return(Result);

#if !DEBUG
        }

        catch (Exception ex) {
            Interface.AddMessage(MessageType.Error, true, "An unexpected error occured (" + ex.Message + ") while attempting to load the file " + FileName);
            return(null);
        }
#endif
        }
示例#20
0
        private static void PreprocessSortByTrackPosition(bool IsRW, double[] UnitFactors, ref Expression[] Expressions)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            PositionedExpression[]           p       = new PositionedExpression[Expressions.Length];
            int    n           = 0;
            double a           = -1.0;
            bool   NumberCheck = !IsRW;

            for (int i = 0; i < Expressions.Length; i++)
            {
                if (IsRW)
                {
                    // only check for track positions in the railway section for RW routes
                    if (Expressions[i].Text.StartsWith("[", StringComparison.Ordinal) & Expressions[i].Text.EndsWith("]", StringComparison.Ordinal))
                    {
                        string s = Expressions[i].Text.Substring(1, Expressions[i].Text.Length - 2).Trim();
                        if (string.Compare(s, "Railway", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            NumberCheck = true;
                        }
                        else
                        {
                            NumberCheck = false;
                        }
                    }
                }
                double x;
                if (NumberCheck && NumberFormats.TryParseDouble(Expressions[i].Text, UnitFactors, out x))
                {
                    x += Expressions[i].TrackPositionOffset;
                    if (x >= 0.0)
                    {
                        if (Interface.CurrentOptions.EnableBveTsHacks)
                        {
                            switch (System.IO.Path.GetFileName(Expressions[i].File.ToLowerInvariant()))
                            {
                            case "balloch - dumbarton central special nighttime run.csv":
                            case "balloch - dumbarton central summer 2004 morning run.csv":
                                if (x != 0 || a != 4125)
                                {
                                    //Misplaced comma in the middle of the line causes this to be interpreted as a track position
                                    a = x;
                                }
                                break;

                            default:
                                a = x;
                                break;
                            }
                        }
                        else
                        {
                            a = x;
                        }
                    }
                    else
                    {
                        Interface.AddMessage(MessageType.Error, false, "Negative track position encountered at line " + Expressions[i].Line.ToString(Culture) + ", column " + Expressions[i].Column.ToString(Culture) + " in file " + Expressions[i].File);
                    }
                }
                else
                {
                    p[n].TrackPosition = a;
                    p[n].Expression    = Expressions[i];
                    int j = n;
                    n++;
                    while (j > 0)
                    {
                        if (p[j].TrackPosition < p[j - 1].TrackPosition)
                        {
                            PositionedExpression t = p[j];
                            p[j]     = p[j - 1];
                            p[j - 1] = t;
                            j--;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            a = -1.0;
            Expression[] e = new Expression[Expressions.Length];
            int          m = 0;

            for (int i = 0; i < n; i++)
            {
                if (p[i].TrackPosition != a)
                {
                    a    = p[i].TrackPosition;
                    e[m] = new Expression
                    {
                        Text   = (a / UnitFactors[UnitFactors.Length - 1]).ToString(Culture),
                        Line   = -1,
                        Column = -1
                    };
                    m++;
                }
                e[m] = p[i].Expression;
                m++;
            }
            Array.Resize <Expression>(ref e, m);
            Expressions = e;
        }
示例#21
0
文件: Program.cs 项目: hyusan/OpenBVE
        private static void Main(string[] args)
        {
            // Add handler for UI thread exceptions
            Application.ThreadException += (CrashHandler.UIThreadException);

            // Force all WinForms errors to go through handler
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

            // This handler is for catching non-UI thread exceptions
            AppDomain.CurrentDomain.UnhandledException += (CrashHandler.CurrentDomain_UnhandledException);


            //Determine the current CPU architecture-
            //ARM will generally only support OpenGL-ES
            PortableExecutableKinds peKind;

            typeof(object).Module.GetPEKind(out peKind, out CurrentCPUArchitecture);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //--- determine the running environment ---
            //I wonder if disabling this hack will stop the craashing on Linux....
            CurrentlyRunningOnMono = Type.GetType("Mono.Runtime") != null;
            //Doesn't appear to, but Mono have fixed the button appearance bug
            CurrentlyRunningOnWindows = Environment.OSVersion.Platform == PlatformID.Win32S | Environment.OSVersion.Platform == PlatformID.Win32Windows | Environment.OSVersion.Platform == PlatformID.Win32NT;
            Joysticks   = new JoystickManager();
            CurrentHost = new Host();
            try {
                FileSystem = FileSystem.FromCommandLineArgs(args);
                FileSystem.CreateFileSystem();
            } catch (Exception ex) {
                MessageBox.Show(Translations.GetInterfaceString("errors_filesystem_invalid") + Environment.NewLine + Environment.NewLine + ex.Message, Translations.GetInterfaceString("program_title"), MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return;
            }

            //Platform specific startup checks
            if (CurrentlyRunningOnMono && !CurrentlyRunningOnWindows)
            {
                // --- Check if we're running as root, and prompt not to ---
                if (getuid() == 0)
                {
                    MessageBox.Show(
                        "You are currently running as the root user." + System.Environment.NewLine +
                        "This is a bad idea, please dont!", Translations.GetInterfaceString("program_title"), MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
            }
            else
            {
                if (!System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "OpenAL32.dll")))
                {
                    MessageBox.Show(
                        "OpenAL was not found on your system, and will now be installed." + System.Environment.NewLine + System.Environment.NewLine +
                        "Please follow the install prompts.", Translations.GetInterfaceString("program_title"), MessageBoxButtons.OK, MessageBoxIcon.Hand);

                    ProcessStartInfo info = new ProcessStartInfo(Path.Combine(FileSystem.DataFolder, "Dependencies\\Win32\\oalinst.exe"));
                    info.UseShellExecute = true;
                    if (Environment.OSVersion.Version.Major >= 6)
                    {
                        info.Verb = "runas";
                    }
                    try
                    {
                        Process p = Process.Start(info);
                        if (p != null)
                        {
                            p.WaitForExit();
                        }
                        else
                        {
                            //For unknown reasons, the process failed to trigger, but did not raise an exception itself
                            //Throw one
                            throw new Win32Exception();
                        }
                    }
                    catch (Win32Exception)
                    {
                        MessageBox.Show(
                            "An error occured during OpenAL installation....", Translations.GetInterfaceString("program_title"), MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    }
                }
            }


            // --- load options and controls ---
            Interface.LoadOptions();
            //Switch between SDL2 and native backends; use native backend by default
            var options = new ToolkitOptions();

            if (Interface.CurrentOptions.PreferNativeBackend)
            {
                options.Backend = PlatformBackend.PreferNative;
            }
            Toolkit.Init(options);
            // --- load language ---
            {
                string folder = Program.FileSystem.GetDataFolder("Languages");
                Translations.LoadLanguageFiles(folder);
            }
            Interface.LoadControls(null, out Interface.CurrentControls);
            {
                string folder = Program.FileSystem.GetDataFolder("Controls");
                string file   = OpenBveApi.Path.CombineFile(folder, "Default keyboard assignment.controls");
                Interface.Control[] controls;
                Interface.LoadControls(file, out controls);
                Interface.AddControls(ref Interface.CurrentControls, controls);
            }
            InputDevicePlugin.LoadPlugins(Program.FileSystem);

            // --- check the command-line arguments for route and train ---
            formMain.MainDialogResult result = new formMain.MainDialogResult();
            CommandLine.ParseArguments(args, ref result);
            // --- check whether route and train exist ---
            if (result.RouteFile != null)
            {
                if (!System.IO.File.Exists(result.RouteFile))
                {
                    result.RouteFile = null;
                }
            }
            if (result.TrainFolder != null)
            {
                if (!System.IO.Directory.Exists(result.TrainFolder))
                {
                    result.TrainFolder = null;
                }
            }
            // --- if a route was provided but no train, try to use the route default ---
            if (result.RouteFile != null & result.TrainFolder == null)
            {
                bool isRW = string.Equals(System.IO.Path.GetExtension(result.RouteFile), ".rw", StringComparison.OrdinalIgnoreCase);
                CsvRwRouteParser.ParseRoute(result.RouteFile, isRW, result.RouteEncoding, null, null, null, true);
                if (!string.IsNullOrEmpty(Game.TrainName))
                {
                    string folder = System.IO.Path.GetDirectoryName(result.RouteFile);
                    while (true)
                    {
                        string trainFolder = OpenBveApi.Path.CombineDirectory(folder, "Train");
                        if (System.IO.Directory.Exists(trainFolder))
                        {
                            folder = OpenBveApi.Path.CombineDirectory(trainFolder, Game.TrainName);
                            if (System.IO.Directory.Exists(folder))
                            {
                                string file = OpenBveApi.Path.CombineFile(folder, "train.dat");
                                if (System.IO.File.Exists(file))
                                {
                                    result.TrainFolder   = folder;
                                    result.TrainEncoding = System.Text.Encoding.UTF8;
                                    for (int j = 0; j < Interface.CurrentOptions.TrainEncodings.Length; j++)
                                    {
                                        if (string.Compare(Interface.CurrentOptions.TrainEncodings[j].Value, result.TrainFolder, StringComparison.InvariantCultureIgnoreCase) == 0)
                                        {
                                            result.TrainEncoding = System.Text.Encoding.GetEncoding(Interface.CurrentOptions.TrainEncodings[j].Codepage);
                                            break;
                                        }
                                    }
                                }
                            }
                            break;
                        }
                        if (folder == null)
                        {
                            continue;
                        }
                        System.IO.DirectoryInfo info = System.IO.Directory.GetParent(folder);
                        if (info != null)
                        {
                            folder = info.FullName;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                Game.Reset(false);
            }
            // --- show the main menu if necessary ---
            if (result.RouteFile == null | result.TrainFolder == null)
            {
                Joysticks.RefreshJoysticks();

                // end HACK //
                result = formMain.ShowMainDialog(result);
            }
            else
            {
                result.Start = true;
                //Apply translations
                Translations.SetInGameLanguage(Translations.CurrentLanguageCode);
            }
            // --- start the actual program ---
            if (result.Start)
            {
                if (Initialize())
                {
                                        #if !DEBUG
                    try {
                                                #endif
                    MainLoop.StartLoopEx(result);
                                                #if !DEBUG
                }
                catch (Exception ex) {
                    bool found = false;
                    for (int i = 0; i < TrainManager.Trains.Length; i++)
                    {
                        if (TrainManager.Trains[i] != null && TrainManager.Trains[i].Plugin != null)
                        {
                            if (TrainManager.Trains[i].Plugin.LastException != null)
                            {
                                CrashHandler.LoadingCrash(ex.Message, true);
                                MessageBox.Show("The train plugin " + TrainManager.Trains[i].Plugin.PluginTitle + " caused a runtime exception: " + TrainManager.Trains[i].Plugin.LastException.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                                found            = true;
                                RestartArguments = "";
                                break;
                            }
                        }
                    }
                    if (!found)
                    {
                        if (ex is System.DllNotFoundException)
                        {
                            Interface.AddMessage(MessageType.Critical, false, "The required system library " + ex.Message + " was not found on the system.");
                            switch (ex.Message)
                            {
                            case "libopenal.so.1":
                                MessageBox.Show("openAL was not found on this system. \n Please install libopenal1 via your distribtion's package management system.", Translations.GetInterfaceString("program_title"), MessageBoxButtons.OK, MessageBoxIcon.Hand);
                                break;

                            default:
                                MessageBox.Show("The required system library " + ex.Message + " was not found on this system.", Translations.GetInterfaceString("program_title"), MessageBoxButtons.OK, MessageBoxIcon.Hand);
                                break;
                            }
                        }
                        else
                        {
                            Interface.AddMessage(MessageType.Critical, false, "The route and train loader encountered the following critical error: " + ex.Message);
                            CrashHandler.LoadingCrash(ex + Environment.StackTrace, false);
                        }
                        RestartArguments = "";
                    }
                }
#endif
                }
                Deinitialize();
            }
            // --- restart the program if necessary ---
            if (RestartArguments != null)
            {
                string arguments;
                if (FileSystem.RestartArguments.Length != 0 & RestartArguments.Length != 0)
                {
                    arguments = FileSystem.RestartArguments + " " + RestartArguments;
                }
                else
                {
                    arguments = FileSystem.RestartArguments + RestartArguments;
                }
                try {
                    System.Diagnostics.Process.Start(System.IO.File.Exists(FileSystem.RestartProcess) ? FileSystem.RestartProcess : Application.ExecutablePath, arguments);
                } catch (Exception ex) {
                    MessageBox.Show(ex.Message + "\n\nProcess = " + FileSystem.RestartProcess + "\nArguments = " + arguments, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
示例#22
0
        private static void PreprocessSplitIntoExpressions(string FileName, bool IsRW, string[] Lines, out Expression[] Expressions, bool AllowRwRouteDescription, double trackPositionOffset)
        {
            Expressions = new Expression[4096];
            int e = 0;

            // full-line rw comments
            if (IsRW)
            {
                for (int i = 0; i < Lines.Length; i++)
                {
                    int Level = 0;
                    for (int j = 0; j < Lines[i].Length; j++)
                    {
                        switch (Lines[i][j])
                        {
                        case '(':
                            Level++;
                            break;

                        case ')':
                            Level--;
                            break;

                        case ';':
                            if (Level == 0)
                            {
                                Lines[i] = Lines[i].Substring(0, j).TrimEnd();
                                j        = Lines[i].Length;
                            }
                            break;

                        case '=':
                            if (Level == 0)
                            {
                                j = Lines[i].Length;
                            }
                            break;
                        }
                    }
                }
            }
            // parse
            for (int i = 0; i < Lines.Length; i++)
            {
                //Remove empty null characters
                //Found these in a couple of older routes, harmless but generate errors
                //Possibly caused by BVE-RR (DOS version)
                Lines[i] = Lines[i].Replace("\0", "");
                if (IsRW & AllowRwRouteDescription)
                {
                    // ignore rw route description
                    if (
                        Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].IndexOf("]", StringComparison.Ordinal) > 0 |
                        Lines[i].StartsWith("$")
                        )
                    {
                        AllowRwRouteDescription = false;
                        Game.RouteComment       = Game.RouteComment.Trim();
                    }
                    else
                    {
                        if (Game.RouteComment.Length != 0)
                        {
                            Game.RouteComment += "\n";
                        }
                        Game.RouteComment += Lines[i];
                        continue;
                    }
                }
                {
                    // count expressions
                    int n = 0; int Level = 0;
                    for (int j = 0; j < Lines[i].Length; j++)
                    {
                        switch (Lines[i][j])
                        {
                        case '(':
                            Level++;
                            break;

                        case ')':
                            Level--;
                            break;

                        case ',':
                            if (!IsRW & Level == 0)
                            {
                                n++;
                            }
                            break;

                        case '@':
                            if (IsRW & Level == 0)
                            {
                                n++;
                            }
                            break;
                        }
                    }
                    // create expressions
                    int m = e + n + 1;
                    while (m >= Expressions.Length)
                    {
                        Array.Resize <Expression>(ref Expressions, Expressions.Length << 1);
                    }
                    Level = 0;
                    int a = 0, c = 0;
                    for (int j = 0; j < Lines[i].Length; j++)
                    {
                        switch (Lines[i][j])
                        {
                        case '(':
                            Level++;
                            break;

                        case ')':
                            if (Interface.CurrentOptions.EnableBveTsHacks)
                            {
                                if (Level > 0)
                                {
                                    //Don't decrease the level below zero, as this messes up when extra closing brackets are encountered
                                    Level--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid additional closing parenthesis encountered at line " + i + " character " + j + " in file " + FileName);
                                }
                            }
                            else
                            {
                                Level--;
                            }
                            break;

                        case ',':
                            if (Level == 0 & !IsRW)
                            {
                                string t = Lines[i].Substring(a, j - a).Trim();
                                if (t.Length > 0 && !t.StartsWith(";"))
                                {
                                    Expressions[e] = new Expression
                                    {
                                        File   = FileName,
                                        Text   = t,
                                        Line   = i + 1,
                                        Column = c + 1,
                                        TrackPositionOffset = trackPositionOffset
                                    };
                                    e++;
                                }
                                a = j + 1;
                                c++;
                            }
                            break;

                        case '@':
                            if (Level == 1 & IsRW & Interface.CurrentOptions.EnableBveTsHacks)
                            {
                                //BVE2 doesn't care if a bracket is unclosed, fixes various routefiles
                                Level--;
                            }
                            else if (Level == 2 && IsRW & Interface.CurrentOptions.EnableBveTsHacks)
                            {
                                int k = j;
                                while (k > 0)
                                {
                                    k--;
                                    if (Lines[i][k] == '(')
                                    {
                                        //Opening bracket has been used instead of closing bracket, again BVE2 ignores this
                                        Level -= 2;
                                        break;
                                    }
                                    if (!char.IsWhiteSpace(Lines[i][k]))
                                    {
                                        //Bracket not found, and this isn't whitespace either, so break out
                                        break;
                                    }
                                }
                            }
                            if (Level == 0 & IsRW)
                            {
                                string t = Lines[i].Substring(a, j - a).Trim();
                                if (t.Length > 0 && !t.StartsWith(";"))
                                {
                                    Expressions[e] = new Expression
                                    {
                                        File   = FileName,
                                        Text   = t,
                                        Line   = i + 1,
                                        Column = c + 1,
                                        TrackPositionOffset = trackPositionOffset
                                    };
                                    e++;
                                }
                                a = j + 1;
                                c++;
                            }
                            break;
                        }
                    }
                    if (Lines[i].Length - a > 0)
                    {
                        string t = Lines[i].Substring(a).Trim();
                        if (t.Length > 0 && !t.StartsWith(";"))
                        {
                            Expressions[e] = new Expression
                            {
                                File   = FileName,
                                Text   = t,
                                Line   = i + 1,
                                Column = c + 1,
                                TrackPositionOffset = trackPositionOffset
                            };
                            e++;
                        }
                    }
                }
            }
            Array.Resize <Expression>(ref Expressions, e);
        }
        //Parses an XML background definition
        public static BackgroundManager.BackgroundHandle ReadBackgroundXML(string fileName)
        {
            List <BackgroundManager.StaticBackground> Backgrounds = new List <BackgroundManager.StaticBackground>();
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the object's XML file
            currentXML.Load(fileName);
            string Path = System.IO.Path.GetDirectoryName(fileName);

            double[] UnitOfLength = { 1.0 };
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Background");
                //Check this file actually contains OpenBVE light definition nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode n in DocumentNodes)
                    {
                        if (n.ChildNodes.OfType <XmlElement>().Any())
                        {
                            double DisplayTime = -1;
                            //The time to transition between backgrounds in seconds
                            double TransitionTime = 0.8;
                            //The texture to use (if static)
                            Textures.Texture t = null;
                            //The object to use (if object based)
                            ObjectManager.StaticObject o = null;
                            //The transition mode between backgrounds
                            BackgroundManager.BackgroundTransitionMode mode = BackgroundManager.BackgroundTransitionMode.FadeIn;
                            //The number of times the texture is repeated around the viewing frustrum (if appropriate)
                            double repetitions = 6;
                            foreach (XmlNode c in n.ChildNodes)
                            {
                                string[] Arguments = c.InnerText.Split(',');
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "mode":
                                    switch (c.InnerText.ToLowerInvariant())
                                    {
                                    case "fadein":
                                        mode = BackgroundManager.BackgroundTransitionMode.FadeIn;
                                        break;

                                    case "fadeout":
                                        mode = BackgroundManager.BackgroundTransitionMode.FadeOut;
                                        break;

                                    case "none":
                                        mode = BackgroundManager.BackgroundTransitionMode.None;
                                        break;

                                    default:
                                        Interface.AddMessage(Interface.MessageType.Error, true, c.InnerText + "is not a valid background fade mode in file " + fileName);
                                        break;
                                    }
                                    break;

                                case "object":
                                    string f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(fileName), c.InnerText);
                                    if (!System.IO.File.Exists(f))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in file " + fileName);
                                    }
                                    else
                                    {
                                        ObjectManager.UnifiedObject b = ObjectManager.LoadObject(f, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                        o = (ObjectManager.StaticObject)b;
                                    }
                                    break;

                                case "repetitions":
                                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out repetitions))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, c.InnerText + " does not parse to a valid number of repetitions in " + fileName);
                                    }
                                    break;

                                case "texture":
                                    var file = OpenBveApi.Path.CombineFile(Path, c.InnerText);
                                    if (!System.IO.File.Exists(file))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, "The background texture file " + c.InnerText + " does not exist in " + fileName);
                                    }
                                    else
                                    {
                                        Textures.RegisterTexture(file, out t);
                                    }
                                    break;

                                case "time":
                                    if (!Interface.TryParseTime(Arguments[0].Trim(), out DisplayTime))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, c.InnerText + " does not parse to a valid time in file " + fileName);
                                    }
                                    break;

                                case "transitiontime":
                                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out TransitionTime))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, c.InnerText + " is not a valid background transition time in " + fileName);
                                    }
                                    break;
                                }
                            }
                            //Create background if texture is not null
                            if (t != null && o == null)
                            {
                                Backgrounds.Add(new BackgroundManager.StaticBackground(t, repetitions, false, TransitionTime, mode, DisplayTime));
                            }
                            if (t == null && o != null)
                            {
                                //All other parameters are ignored if an object has been defined
                                //TODO: Error message stating they have been ignored
                                return(new BackgroundManager.BackgroundObject(o));
                            }
                        }
                    }
                    if (Backgrounds.Count == 1)
                    {
                        return(Backgrounds[0]);
                    }
                    if (Backgrounds.Count > 1)
                    {
                        //Sort list- Not worried about when they start or end, so use simple LINQ
                        Backgrounds = Backgrounds.OrderBy(o => o.Time).ToList();
                        //If more than 2 backgrounds, convert to array and return a new dynamic background
                        return(new BackgroundManager.DynamicBackground(Backgrounds.ToArray()));
                    }
                }
            }
            //We couldn't find any valid XML, so return false
            throw new InvalidDataException();
        }
示例#24
0
        private static void ParseExtensionsConfig(string filePath, Encoding encoding, out UnifiedObject[] carObjects, out UnifiedObject[] bogieObjects, out UnifiedObject[] couplerObjects, out double[] axleLocations, out double[] couplerDistances, out TrainManager.Train train, bool loadObjects)
        {
            CultureInfo culture = CultureInfo.InvariantCulture;

            carObjects       = new UnifiedObject[0];
            bogieObjects     = new UnifiedObject[0];
            couplerObjects   = new UnifiedObject[0];
            axleLocations    = new double[0];
            couplerDistances = new double[0];
            train            = new TrainManager.Train {
                Cars = new CarBase[0]
            };

            if (!File.Exists(filePath))
            {
                return;
            }

            bool[] carObjectsReversed   = new bool[0];
            bool[] bogieObjectsReversed = new bool[0];
            bool[] carsDefined          = new bool[0];
            bool[] bogiesDefined        = new bool[0];
            bool[] couplerDefined       = new bool[0];

            string trainPath = System.IO.Path.GetDirectoryName(filePath);

            if (encoding == null)
            {
                encoding = TextEncoding.GetSystemEncodingFromFile(trainPath);
            }

            string[] lines = File.ReadAllLines(filePath, encoding);
            for (int i = 0; i < lines.Length; i++)
            {
                int j = lines[i].IndexOf(';');
                if (j >= 0)
                {
                    lines[i] = lines[i].Substring(0, j).Trim(new char[] { });
                }
                else
                {
                    lines[i] = lines[i].Trim(new char[] { });
                }
            }

            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Length != 0)
                {
                    switch (lines[i].ToLowerInvariant())
                    {
                    case "[exterior]":
                        // exterior
                        i++;
                        while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            if (lines[i].Length != 0)
                            {
                                int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                if (j >= 0)
                                {
                                    // ReSharper disable RedundantExplicitParamsArrayCreation
                                    string a = lines[i].Substring(0, j).TrimEnd(new char[] { });
                                    string b = lines[i].Substring(j + 1).TrimStart(new char[] { });
                                    // ReSharper restore RedundantExplicitParamsArrayCreation

                                    int n;
                                    if (int.TryParse(a, NumberStyles.Integer, culture, out n))
                                    {
                                        if (n >= 0)
                                        {
                                            if (n >= train.Cars.Length)
                                            {
                                                Array.Resize(ref train.Cars, n + 1);
                                                train.Cars[n] = new CarBase(train, n);
                                                Array.Resize(ref carObjects, n + 1);
                                                Array.Resize(ref bogieObjects, (n + 1) * 2);
                                                Array.Resize(ref couplerObjects, n);
                                                Array.Resize(ref carObjectsReversed, n + 1);
                                                Array.Resize(ref bogieObjectsReversed, (n + 1) * 2);
                                                Array.Resize(ref carsDefined, n + 1);
                                                Array.Resize(ref bogiesDefined, (n + 1) * 2);
                                                Array.Resize(ref couplerDefined, n);
                                                Array.Resize(ref axleLocations, (n + 1) * 2);
                                                Array.Resize(ref couplerDistances, n);
                                            }
                                            if (Path.ContainsInvalidChars(b))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, $"File contains illegal characters at line {(i + 1).ToString(culture)} in file {filePath}");
                                            }
                                            else
                                            {
                                                string file = Path.CombineFile(trainPath, b);
                                                if (File.Exists(file))
                                                {
                                                    if (loadObjects)
                                                    {
                                                        Program.CurrentHost.LoadObject(file, encoding, out carObjects[n]);
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(MessageType.Error, true, $"The car object {file} does not exist at line {(i + 1).ToString(culture)} in file {filePath}");
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, $"The car index {a} does not reference an existing car at line {(i + 1).ToString(culture)} in file {filePath}");
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, $"The car index is expected to be an integer at line {(i + 1).ToString(culture)} in file {filePath}");
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, $"Invalid statement {lines[i]} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                }
                            }
                            i++;
                        }
                        i--;
                        break;

                    default:
                        if (lines[i].StartsWith("[car", StringComparison.OrdinalIgnoreCase) & lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            // car
                            string t = lines[i].Substring(4, lines[i].Length - 5);
                            int    n;
                            if (int.TryParse(t, NumberStyles.Integer, culture, out n))
                            {
                                if (n >= 0)
                                {
                                    if (n >= train.Cars.Length)
                                    {
                                        Array.Resize(ref train.Cars, n + 1);
                                        train.Cars[n] = new CarBase(train, n);
                                        Array.Resize(ref carObjects, n + 1);
                                        Array.Resize(ref bogieObjects, (n + 1) * 2);
                                        Array.Resize(ref carObjectsReversed, n + 1);
                                        Array.Resize(ref bogieObjectsReversed, (n + 1) * 2);
                                        Array.Resize(ref couplerObjects, n);
                                        Array.Resize(ref carsDefined, n + 1);
                                        Array.Resize(ref bogiesDefined, (n + 1) * 2);
                                        Array.Resize(ref couplerDefined, n);
                                        Array.Resize(ref axleLocations, (n + 1) * 2);
                                        Array.Resize(ref couplerDistances, n);
                                    }
                                    if (carsDefined[n])
                                    {
                                        Interface.AddMessage(MessageType.Error, false, $"Car {n.ToString(culture)} has already been declared at line {(i + 1).ToString(culture)} in file {filePath}");
                                    }
                                    carsDefined[n] = true;
                                    i++;
                                    while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                                    {
                                        if (lines[i].Length != 0)
                                        {
                                            int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                            if (j >= 0)
                                            {
                                                // ReSharper disable RedundantExplicitParamsArrayCreation
                                                string a = lines[i].Substring(0, j).TrimEnd(new char[] { });
                                                string b = lines[i].Substring(j + 1).TrimStart(new char[] { });
                                                // ReSharper restore RedundantExplicitParamsArrayCreation

                                                switch (a.ToLowerInvariant())
                                                {
                                                case "object":
                                                    if (string.IsNullOrEmpty(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, true, $"An empty car object was supplied at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        break;
                                                    }
                                                    if (Path.ContainsInvalidChars(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, $"File contains illegal characters at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    }
                                                    else
                                                    {
                                                        string file = Path.CombineFile(trainPath, b);
                                                        if (File.Exists(file))
                                                        {
                                                            if (loadObjects)
                                                            {
                                                                Program.CurrentHost.LoadObject(file, encoding, out carObjects[n]);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, $"The car object {file} does not exist at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                    }
                                                    break;

                                                case "length":
                                                {
                                                    double m;
                                                    if (double.TryParse(b, NumberStyles.Float, culture, out m))
                                                    {
                                                        if (m > 0.0)
                                                        {
                                                            train.Cars[n].Length = m;
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Value is expected to be a positive floating-point number in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, $"Value is expected to be a positive floating-point number in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    }
                                                }
                                                break;

                                                case "reversed":
                                                    carObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase);
                                                    break;

                                                case "axles":
                                                    int k = b.IndexOf(',');
                                                    if (k >= 0)
                                                    {
                                                        // ReSharper disable RedundantExplicitParamsArrayCreation
                                                        string c = b.Substring(0, k).TrimEnd(new char[] { });
                                                        string d = b.Substring(k + 1).TrimStart(new char[] { });
                                                        // ReSharper restore RedundantExplicitParamsArrayCreation

                                                        double rear, front;
                                                        if (!double.TryParse(c, NumberStyles.Float, culture, out rear))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Rear is expected to be a floating-point number in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                        else if (!double.TryParse(d, NumberStyles.Float, culture, out front))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Front is expected to be a floating-point number in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                        else if (rear >= front)
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Rear is expected to be less than Front in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                        else
                                                        {
                                                            if (n == 0)
                                                            {
                                                                axleLocations[n]     = rear;
                                                                axleLocations[n + 1] = front;
                                                            }
                                                            else
                                                            {
                                                                axleLocations[n * 2]     = rear;
                                                                axleLocations[n * 2 + 1] = front;
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, $"An argument-separating comma is expected in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    }
                                                    break;

                                                default:
                                                    Interface.AddMessage(MessageType.Warning, false, $"Unsupported key-value pair {a} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(MessageType.Error, false, $"Invalid statement {lines[i]} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                            }
                                        }
                                        i++;
                                    }
                                    i--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, $"The car index {t} does not reference an existing car at line {(i + 1).ToString(culture)} in file {filePath}");
                                }
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, $"The car index is expected to be an integer at line {(i + 1).ToString(culture)} in file {filePath}");
                            }
                        }
                        else if (lines[i].StartsWith("[bogie", StringComparison.OrdinalIgnoreCase) & lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            // bogie
                            string t = lines[i].Substring(6, lines[i].Length - 7);
                            int    n;
                            if (int.TryParse(t, NumberStyles.Integer, culture, out n))
                            {
                                if (n >= train.Cars.Length * 2)
                                {
                                    Array.Resize(ref train.Cars, n / 2 + 1);
                                    if (n == 0)
                                    {
                                        train.Cars[0] = new CarBase(train, 0);
                                        Array.Resize(ref axleLocations, 2);
                                    }
                                    else
                                    {
                                        train.Cars[n / 2] = new CarBase(train, n / 2);
                                        Array.Resize(ref axleLocations, (n / 2 + 1) * 2);
                                    }

                                    Array.Resize(ref carObjects, n / 2 + 1);
                                    Array.Resize(ref bogieObjects, n + 2);
                                    Array.Resize(ref couplerObjects, n / 2);
                                    Array.Resize(ref carObjectsReversed, n / 2 + 1);
                                    Array.Resize(ref bogieObjectsReversed, n + 2);
                                    Array.Resize(ref carsDefined, n / 2 + 1);
                                    Array.Resize(ref bogiesDefined, n + 2);
                                    Array.Resize(ref couplerDefined, n / 2);
                                    Array.Resize(ref couplerDistances, n / 2);
                                }

                                if (n > bogiesDefined.Length - 1)
                                {
                                    continue;
                                }
                                if (bogiesDefined[n])
                                {
                                    Interface.AddMessage(MessageType.Error, false, $"Bogie {n.ToString(culture)} has already been declared at line {(i + 1).ToString(culture)} in file {filePath}");
                                }
                                bogiesDefined[n] = true;
                                //Assuming that there are two bogies per car
                                if (n >= 0 & n < train.Cars.Length * 2)
                                {
                                    i++;
                                    while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                                    {
                                        if (lines[i].Length != 0)
                                        {
                                            int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                            if (j >= 0)
                                            {
                                                // ReSharper disable RedundantExplicitParamsArrayCreation
                                                string a = lines[i].Substring(0, j).TrimEnd(new char[] { });
                                                string b = lines[i].Substring(j + 1).TrimStart(new char[] { });
                                                // ReSharper restore RedundantExplicitParamsArrayCreation

                                                switch (a.ToLowerInvariant())
                                                {
                                                case "object":
                                                    if (Path.ContainsInvalidChars(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, $"File contains illegal characters at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    }
                                                    else
                                                    {
                                                        if (string.IsNullOrEmpty(b))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, $"An empty bogie object was supplied at line {(i + 1).ToString(culture)} in file {filePath}");
                                                            break;
                                                        }
                                                        string file = Path.CombineFile(trainPath, b);
                                                        if (File.Exists(file))
                                                        {
                                                            if (loadObjects)
                                                            {
                                                                Program.CurrentHost.LoadObject(file, encoding, out bogieObjects[n]);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, $"The bogie object {file} does not exist at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                    }
                                                    break;

                                                case "length":
                                                {
                                                    Interface.AddMessage(MessageType.Error, false, $"A defined length is not supported for bogies at line {(i + 1).ToString(culture)} in file {filePath}");
                                                }
                                                break;

                                                case "reversed":
                                                    bogieObjectsReversed[n] = b.Equals("true", StringComparison.OrdinalIgnoreCase);
                                                    break;

                                                case "axles":
                                                    //Axles aren't used in bogie positioning, just in rotation
                                                    break;

                                                default:
                                                    Interface.AddMessage(MessageType.Warning, false, $"Unsupported key-value pair {a} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(MessageType.Error, false, $"Invalid statement {lines[i]} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                            }
                                        }
                                        i++;
                                    }
                                    i--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, $"The bogie index {t} does not reference an existing bogie at line {(i + 1).ToString(culture)} in file {filePath}");
                                }
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, $"The bogie index is expected to be an integer at line {(i + 1).ToString(culture)} in file {filePath}");
                            }
                        }
                        else if (lines[i].StartsWith("[coupler", StringComparison.OrdinalIgnoreCase) & lines[i].EndsWith("]", StringComparison.Ordinal))
                        {
                            // coupler
                            string t = lines[i].Substring(8, lines[i].Length - 9);
                            int    n;
                            if (int.TryParse(t, NumberStyles.Integer, culture, out n))
                            {
                                if (n >= 0)
                                {
                                    if (n >= train.Cars.Length - 1)
                                    {
                                        Array.Resize(ref train.Cars, n + 2);
                                        train.Cars[n + 1] = new CarBase(train, n + 1);
                                        Array.Resize(ref carObjects, n + 2);
                                        Array.Resize(ref bogieObjects, (n + 2) * 2);
                                        Array.Resize(ref carObjectsReversed, n + 2);
                                        Array.Resize(ref bogieObjectsReversed, (n + 2) * 2);
                                        Array.Resize(ref couplerObjects, n + 1);
                                        Array.Resize(ref carsDefined, n + 2);
                                        Array.Resize(ref bogiesDefined, (n + 2) * 2);
                                        Array.Resize(ref couplerDefined, n + 1);
                                        Array.Resize(ref axleLocations, (n + 2) * 2);
                                        Array.Resize(ref couplerDistances, n + 1);
                                    }
                                    if (couplerDefined[n])
                                    {
                                        Interface.AddMessage(MessageType.Error, false, $"Coupler {n.ToString(culture)} has already been declared at line {(i + 1).ToString(culture)} in file {filePath}");
                                    }
                                    couplerDefined[n] = true;
                                    i++;
                                    while (i < lines.Length && !lines[i].StartsWith("[", StringComparison.Ordinal) & !lines[i].EndsWith("]", StringComparison.Ordinal))
                                    {
                                        if (lines[i].Length != 0)
                                        {
                                            int j = lines[i].IndexOf("=", StringComparison.Ordinal);
                                            if (j >= 0)
                                            {
                                                // ReSharper disable RedundantExplicitParamsArrayCreation
                                                string a = lines[i].Substring(0, j).TrimEnd(new char[] { });
                                                string b = lines[i].Substring(j + 1).TrimStart(new char[] { });
                                                // ReSharper restore RedundantExplicitParamsArrayCreation

                                                switch (a.ToLowerInvariant())
                                                {
                                                case "distances":
                                                {
                                                    int k = b.IndexOf(',');
                                                    if (k >= 0)
                                                    {
                                                        // ReSharper disable RedundantExplicitParamsArrayCreation
                                                        string c = b.Substring(0, k).TrimEnd(new char[] { });
                                                        string d = b.Substring(k + 1).TrimStart(new char[] { });
                                                        // ReSharper restore RedundantExplicitParamsArrayCreation

                                                        double min, max;
                                                        if (!double.TryParse(c, NumberStyles.Float, culture, out min))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Minimum is expected to be a floating-point number in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                        else if (!double.TryParse(d, NumberStyles.Float, culture, out max))
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Maximum is expected to be a floating-point number in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                        else if (min > max)
                                                        {
                                                            Interface.AddMessage(MessageType.Error, false, $"Minimum is expected to be less than Maximum in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                        else
                                                        {
                                                            couplerDistances[n] = 0.5 * (min + max);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, $"An argument-separating comma is expected in {a} at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    }
                                                }
                                                break;

                                                case "object":
                                                    if (string.IsNullOrEmpty(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, true, $"An empty coupler object was supplied at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        break;
                                                    }
                                                    if (Path.ContainsInvalidChars(b))
                                                    {
                                                        Interface.AddMessage(MessageType.Error, false, $"File contains illegal characters at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    }
                                                    else
                                                    {
                                                        string file = Path.CombineFile(trainPath, b);
                                                        if (File.Exists(file))
                                                        {
                                                            if (loadObjects)
                                                            {
                                                                Program.CurrentHost.LoadObject(file, encoding, out couplerObjects[n]);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(MessageType.Error, true, $"The coupler object {file} does not exist at line {(i + 1).ToString(culture)} in file {filePath}");
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    Interface.AddMessage(MessageType.Warning, false, $"Unsupported key-value pair {a} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(MessageType.Error, false, $"Invalid statement {lines[i]} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                                            }
                                        }
                                        i++;
                                    }
                                    i--;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, $"The coupler index {t} does not reference an existing coupler at line {(i + 1).ToString(culture)} in file {filePath}");
                                }
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, $"The coupler index is expected to be an integer at line {(i + 1).ToString(culture)} in file {filePath}");
                            }
                        }
                        else
                        {
                            // default
                            if (lines.Length == 1 && encoding.Equals(Encoding.Unicode))
                            {
                                /*
                                 * If only one line, there's a good possibility that our file is NOT Unicode at all
                                 * and that the misdetection has turned it into garbage
                                 *
                                 * Try again with ASCII instead
                                 */
                                ParseExtensionsConfig(filePath, Encoding.GetEncoding(1252), out carObjects, out bogieObjects, out couplerObjects, out axleLocations, out couplerDistances, out train, loadObjects);
                                return;
                            }
                            Interface.AddMessage(MessageType.Error, false, $"Invalid statement {lines[i]} encountered at line {(i + 1).ToString(culture)} in file {filePath}");
                        }
                        break;
                    }
                }
            }

            // check for car objects and reverse if necessary
            int carObjectsCount = 0;

            for (int i = 0; i < train.Cars.Length; i++)
            {
                if (carObjects[i] != null)
                {
                    carObjectsCount++;
                    if (carObjectsReversed[i] && loadObjects)
                    {
                        if (carObjects[i] is StaticObject)
                        {
                            StaticObject obj = (StaticObject)carObjects[i].Clone();
                            obj.ApplyScale(-1.0, 1.0, -1.0);
                            carObjects[i] = obj;
                        }
                        else if (carObjects[i] is AnimatedObjectCollection)
                        {
                            AnimatedObjectCollection obj = (AnimatedObjectCollection)carObjects[i].Clone();
                            obj.Reverse();
                            carObjects[i] = obj;
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }
            }

            //Check for bogie objects and reverse if necessary.....
            int bogieObjectsCount = 0;

            for (int i = 0; i < train.Cars.Length * 2; i++)
            {
                if (bogieObjects[i] != null)
                {
                    bogieObjectsCount++;
                    if (bogieObjectsReversed[i] && loadObjects)
                    {
                        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];
                            obj.Reverse();
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }
            }

            if (carObjectsCount > 0 & carObjectsCount < train.Cars.Length)
            {
                Interface.AddMessage(MessageType.Warning, false, $"An incomplete set of exterior objects was provided in file {filePath}");
            }

            if (bogieObjectsCount > 0 & bogieObjectsCount < train.Cars.Length * 2)
            {
                Interface.AddMessage(MessageType.Warning, false, $"An incomplete set of bogie objects was provided in file {filePath}");
            }
        }
示例#25
0
 // load texture rgba
 private static void LoadTextureRGBAforData(Bitmap Bitmap, World.ColorRGB TransparentColor, byte TransparentColorUsed, int TextureIndex)
 {
     try {
         // load bytes
         int Width, Height, Stride; byte[] Data;
         {
             if (Textures[TextureIndex].ClipWidth == 0)
             {
                 Textures[TextureIndex].ClipWidth = Bitmap.Width;
             }
             if (Textures[TextureIndex].ClipHeight == 0)
             {
                 Textures[TextureIndex].ClipHeight = Bitmap.Height;
             }
             Width  = Textures[TextureIndex].ClipWidth;
             Height = Textures[TextureIndex].ClipHeight;
             Bitmap    c   = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
             Graphics  g   = Graphics.FromImage(c);
             Rectangle dst = new Rectangle(0, 0, Width, Height);
             Rectangle src = new Rectangle(Textures[TextureIndex].ClipLeft, Textures[TextureIndex].ClipTop, Textures[TextureIndex].ClipWidth, Textures[TextureIndex].ClipHeight);
             g.DrawImage(Bitmap, dst, src, GraphicsUnit.Pixel);
             g.Dispose();
             BitmapData d = c.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, c.PixelFormat);
             Stride = d.Stride;
             Data   = new byte[Stride * Height];
             System.Runtime.InteropServices.Marshal.Copy(d.Scan0, Data, 0, Stride * Height);
             c.UnlockBits(d);
             c.Dispose();
         }
         // load mode
         if (Textures[TextureIndex].LoadMode == TextureLoadMode.Bve4SignalGlow)
         {
             // bve 4 signal glow
             int  p = 0, pn = Stride - 4 * Width;
             byte tr, tg, tb;
             if (TransparentColorUsed != 0)
             {
                 tr = TransparentColor.R;
                 tg = TransparentColor.G;
                 tb = TransparentColor.B;
             }
             else
             {
                 tr = 0; tg = 0; tb = 0;
             }
             // invert lightness
             byte[] Temp = new byte[Stride * Height];
             for (int y = 0; y < Height; y++)
             {
                 for (int x = 0; x < Width; x++)
                 {
                     if (Data[p] == tb & Data[p + 1] == tg & Data[p + 2] == tr)
                     {
                         Temp[p]     = 0;
                         Temp[p + 1] = 0;
                         Temp[p + 2] = 0;
                     }
                     else if (Data[p] != 255 | Data[p + 1] != 255 | Data[p + 2] != 255)
                     {
                         int b = Data[p], g = Data[p + 1], r = Data[p + 2];
                         InvertLightness(ref r, ref g, ref b);
                         int l = r >= g & r >= b ? r : g >= b ? g : b;
                         Temp[p]     = (byte)(l * b / 255);
                         Temp[p + 1] = (byte)(l * g / 255);
                         Temp[p + 2] = (byte)(l * r / 255);
                     }
                     else
                     {
                         Temp[p]     = Data[p];
                         Temp[p + 1] = Data[p + 1];
                         Temp[p + 2] = Data[p + 2];
                     }
                     p += 4;
                 }
                 p += pn;
             }
             p = 0;
             // blur the image and multiply by lightness
             int s = 4;
             int n = Stride - (2 * s + 1 << 2);
             for (int y = 0; y < Height; y++)
             {
                 for (int x = 0; x < Width; x++)
                 {
                     int q = p - s * (Stride + 4);
                     int r = 0, g = 0, b = 0, c = 0;
                     for (int yr = y - s; yr <= y + s; yr++)
                     {
                         if (yr >= 0 & yr < Height)
                         {
                             for (int xr = x - s; xr <= x + s; xr++)
                             {
                                 if (xr >= 0 & xr < Width)
                                 {
                                     b += (int)Temp[q];
                                     g += (int)Temp[q + 1];
                                     r += (int)Temp[q + 2];
                                     c++;
                                 }
                                 q += 4;
                             }
                             q += n;
                         }
                         else
                         {
                             q += Stride;
                         }
                     }
                     if (c == 0)
                     {
                         Data[p]     = 0;
                         Data[p + 1] = 0;
                         Data[p + 2] = 0;
                         Data[p + 3] = 255;
                     }
                     else
                     {
                         r /= c; g /= c; b /= c;
                         int l = r >= g & r >= b ? r : g >= b ? g : b;
                         Data[p]     = (byte)(l * b / 255);
                         Data[p + 1] = (byte)(l * g / 255);
                         Data[p + 2] = (byte)(l * r / 255);
                         Data[p + 3] = 255;
                     }
                     p += 4;
                 }
                 p += pn;
             }
             Textures[TextureIndex].Transparency    = TextureTransparencyMode.None;
             Textures[TextureIndex].DontAllowUnload = true;
         }
         else if (TransparentColorUsed != 0)
         {
             // transparent color
             int  p = 0, pn = Stride - 4 * Width;
             byte tr   = TransparentColor.R;
             byte tg   = TransparentColor.G;
             byte tb   = TransparentColor.B;
             bool used = false;
             // check if alpha is actually used
             int y;
             for (y = 0; y < Height; y++)
             {
                 int x; for (x = 0; x < Width; x++)
                 {
                     if (Data[p + 3] != 255)
                     {
                         break;
                     }
                     p += 4;
                 }
                 if (x < Width)
                 {
                     break;
                 }
                 p += pn;
             }
             if (y == Height)
             {
                 Textures[TextureIndex].Transparency = TextureTransparencyMode.TransparentColor;
             }
             // duplicate color data from adjacent pixels
             p = 0; pn = Stride - 4 * Width;
             for (y = 0; y < Height; y++)
             {
                 for (int x = 0; x < Width; x++)
                 {
                     if (Data[p] == tb & Data[p + 1] == tg & Data[p + 2] == tr)
                     {
                         used = true;
                         if (x == 0)
                         {
                             int q = p;
                             int v; for (v = y; v < Height; v++)
                             {
                                 int u; for (u = v == y ? x + 1 : 0; u < Width; u++)
                                 {
                                     if (Data[q] != tb | Data[q + 1] != tg | Data[q + 2] != tr)
                                     {
                                         Data[p]     = Data[q];
                                         Data[p + 1] = Data[q + 1];
                                         Data[p + 2] = Data[q + 2];
                                         Data[p + 3] = 0;
                                         break;
                                     }
                                     q += 4;
                                 }
                                 if (u < Width)
                                 {
                                     break;
                                 }
                                 else
                                 {
                                     q += pn;
                                 }
                             }
                             if (v == Height)
                             {
                                 if (y == 0)
                                 {
                                     Data[p]     = 128;
                                     Data[p + 1] = 128;
                                     Data[p + 2] = 128;
                                     Data[p + 3] = 0;
                                 }
                                 else
                                 {
                                     Data[p]     = Data[p - Stride];
                                     Data[p + 1] = Data[p - Stride + 1];
                                     Data[p + 2] = Data[p - Stride + 2];
                                     Data[p + 3] = 0;
                                 }
                             }
                         }
                         else
                         {
                             Data[p]     = Data[p - 4];
                             Data[p + 1] = Data[p - 3];
                             Data[p + 2] = Data[p - 2];
                             Data[p + 3] = 0;
                         }
                     }
                     p += 4;
                 }
                 p += pn;
             }
             // transparent color is not actually used
             if (!used & Textures[TextureIndex].Transparency == TextureTransparencyMode.TransparentColor)
             {
                 Textures[TextureIndex].Transparency = TextureTransparencyMode.None;
             }
         }
         else if (Textures[TextureIndex].Transparency == TextureTransparencyMode.Alpha)
         {
             // check if alpha is actually used
             int p = 0, pn = Stride - 4 * Width;
             int y; for (y = 0; y < Height; y++)
             {
                 int x; for (x = 0; x < Width; x++)
                 {
                     if (Data[p + 3] != 255)
                     {
                         break;
                     }
                     p += 4;
                 }
                 if (x < Width)
                 {
                     break;
                 }
                 p += pn;
             }
             if (y == Height)
             {
                 Textures[TextureIndex].Transparency = TextureTransparencyMode.None;
             }
         }
         // non-power of two
         int TargetWidth  = Interface.RoundToPowerOfTwo(Width);
         int TargetHeight = Interface.RoundToPowerOfTwo(Height);
         if (TargetWidth != Width | TargetHeight != Height)
         {
             Bitmap     b = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
             BitmapData d = b.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, b.PixelFormat);
             System.Runtime.InteropServices.Marshal.Copy(Data, 0, d.Scan0, d.Stride * d.Height);
             b.UnlockBits(d);
             Bitmap   c = new Bitmap(TargetWidth, TargetHeight, PixelFormat.Format32bppArgb);
             Graphics g = Graphics.FromImage(c);
             g.DrawImage(b, 0, 0, TargetWidth, TargetHeight);
             g.Dispose();
             b.Dispose();
             d      = c.LockBits(new Rectangle(0, 0, TargetWidth, TargetHeight), ImageLockMode.ReadOnly, c.PixelFormat);
             Stride = d.Stride;
             Data   = new byte[Stride * TargetHeight];
             System.Runtime.InteropServices.Marshal.Copy(d.Scan0, Data, 0, Stride * TargetHeight);
             c.UnlockBits(d);
             c.Dispose();
         }
         Textures[TextureIndex].Width  = TargetWidth;
         Textures[TextureIndex].Height = TargetHeight;
         Textures[TextureIndex].Data   = Data;
     } catch (Exception ex) {
         Interface.AddMessage(Interface.MessageType.Error, false, "Internal error in TextureManager.cs::LoadTextureRGBAForData: " + ex.Message);
         throw;
     }
 }
示例#26
0
        //Parses an XML dynamic lighting definition
        public static bool ReadLightingXML(string fileName)
        {
            //Prep
            Program.Renderer.Lighting.LightDefinitions = new LightDefinition[0];
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the object's XML file
            try
            {
                currentXML.Load(fileName);
            }
            catch
            {
                return(false);
            }

            bool defined = false;

            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Brightness");
                //Check this file actually contains OpenBVE light definition nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode n in DocumentNodes)
                    {
                        LightDefinition currentLight = new LightDefinition();
                        if (n.ChildNodes.OfType <XmlElement>().Any())
                        {
                            bool   tf = false, al = false, dl = false, ld = false, cb = false;
                            string ts = null;
                            foreach (XmlNode c in n.ChildNodes)
                            {
                                string[] Arguments = c.InnerText.Split(new char[] { ',' });
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "cablighting":
                                    double b;
                                    if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out b))
                                    {
                                        cb = true;
                                    }
                                    if (b > 255 || b < 0)
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " is not a valid brightness value in file " + fileName);
                                        currentLight.CabBrightness = 255;
                                        break;
                                    }
                                    currentLight.CabBrightness = b;
                                    break;

                                case "time":
                                    double t;
                                    if (Interface.TryParseTime(Arguments[0].Trim(new char[] { }), out t))
                                    {
                                        currentLight.Time = (int)t;
                                        tf = true;
                                        //Keep back for error report later
                                        ts = Arguments[0];
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid time in file " + fileName);
                                    }
                                    break;

                                case "ambientlight":
                                    if (Arguments.Length == 3)
                                    {
                                        double R, G, B;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out R) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out G) && NumberFormats.TryParseDoubleVb6(Arguments[2].Trim(new char[] { }), out B))
                                        {
                                            currentLight.AmbientColor = new Color24((byte)R, (byte)G, (byte)B);
                                            al = true;
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid color in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        if (Arguments.Length == 1)
                                        {
                                            if (Color24.TryParseHexColor(Arguments[0], out currentLight.DiffuseColor))
                                            {
                                                al = true;
                                                break;
                                            }
                                        }
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not contain three arguments in file " + fileName);
                                    }
                                    break;

                                case "directionallight":
                                    if (Arguments.Length == 3)
                                    {
                                        double R, G, B;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out R) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out G) && NumberFormats.TryParseDoubleVb6(Arguments[2].Trim(new char[] { }), out B))
                                        {
                                            currentLight.DiffuseColor = new Color24((byte)R, (byte)G, (byte)B);
                                            dl = true;
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid color in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        if (Arguments.Length == 1)
                                        {
                                            if (Color24.TryParseHexColor(Arguments[0], out currentLight.DiffuseColor))
                                            {
                                                dl = true;
                                                break;
                                            }
                                        }
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not contain three arguments in file " + fileName);
                                    }
                                    break;

                                case "cartesianlightdirection":
                                case "lightdirection":
                                    if (Arguments.Length == 3)
                                    {
                                        double X, Y, Z;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out X) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out Y) && NumberFormats.TryParseDoubleVb6(Arguments[2].Trim(new char[] { }), out Z))
                                        {
                                            currentLight.LightPosition = new Vector3(X, Y, Z);
                                            ld = true;
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid direction in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not contain three arguments in file " + fileName);
                                    }
                                    break;

                                case "sphericallightdirection":
                                    if (Arguments.Length == 2)
                                    {
                                        double theta, phi;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out theta) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out phi))
                                        {
                                            currentLight.LightPosition = new Vector3(Math.Cos(theta) * Math.Sin(phi), -Math.Sin(theta), Math.Cos(theta) * Math.Cos(phi));
                                            ld = true;
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid direction in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not contain two arguments in file " + fileName);
                                    }
                                    break;
                                }
                            }
                            //We want to be able to add a completely default light element,  but not one that's not been defined in the XML properly
                            if (tf || al || ld || dl || cb)
                            {
                                //HACK: No way to break out of the first loop and continue with the second, so we've got to use a variable
                                bool Break = false;
                                int  l     = Program.Renderer.Lighting.LightDefinitions.Length;
                                for (int i = 0; i > l; i++)
                                {
                                    if (Program.Renderer.Lighting.LightDefinitions[i].Time == currentLight.Time)
                                    {
                                        Break = true;
                                        if (ts == null)
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Multiple undefined times were encountered in file " + fileName);
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Duplicate time found: " + ts + " in file " + fileName);
                                        }
                                        break;
                                    }
                                }
                                if (Break)
                                {
                                    continue;
                                }
                                //We've got there, so now figure out where to add the new light into our list of light definitions
                                int t = 0;
                                if (l == 1)
                                {
                                    t = currentLight.Time > Program.Renderer.Lighting.LightDefinitions[0].Time ? 1 : 0;
                                }
                                else if (l > 1)
                                {
                                    for (int i = 1; i < l; i++)
                                    {
                                        t = i + 1;
                                        if (currentLight.Time > Program.Renderer.Lighting.LightDefinitions[i - 1].Time && currentLight.Time < Program.Renderer.Lighting.LightDefinitions[i].Time)
                                        {
                                            break;
                                        }
                                    }
                                }
                                //Resize array
                                defined = true;
                                Array.Resize(ref Program.Renderer.Lighting.LightDefinitions, l + 1);
                                if (t == l)
                                {
                                    //Straight insert at the end of the array
                                    Program.Renderer.Lighting.LightDefinitions[l] = currentLight;
                                }
                                else
                                {
                                    for (int u = t; u < l; u++)
                                    {
                                        //Otherwise, shift all elements to compensate
                                        Program.Renderer.Lighting.LightDefinitions[u + 1] = Program.Renderer.Lighting.LightDefinitions[u];
                                    }
                                    Program.Renderer.Lighting.LightDefinitions[t] = currentLight;
                                }
                            }
                        }
                    }
                }
            }
            //We couldn't find any valid XML, so return false
            return(defined);
        }
示例#27
0
        private void button1_Click(object sender, EventArgs e)
        {
            InterpolationMode previousInterpolationMode = Interface.CurrentOptions.Interpolation;
            int previousAntialasingLevel = Interface.CurrentOptions.AntiAliasingLevel;
            int previousAnsiotropicLevel = Interface.CurrentOptions.AnisotropicFilteringLevel;

            //Interpolation mode
            switch (InterpolationMode.SelectedIndex)
            {
            case 0:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.NearestNeighbor;
                break;

            case 1:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.Bilinear;
                break;

            case 2:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.NearestNeighborMipmapped;
                break;

            case 3:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.BilinearMipmapped;
                break;

            case 4:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.TrilinearMipmapped;
                break;

            case 5:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.AnisotropicFiltering;
                break;
            }
            //Ansiotropic filtering level
            Interface.CurrentOptions.AnisotropicFilteringLevel = (int)AnsiotropicLevel.Value;
            //Antialiasing level
            Interface.CurrentOptions.AntiAliasingLevel = (int)AntialiasingLevel.Value;
            if (Interface.CurrentOptions.AntiAliasingLevel != previousAntialasingLevel)
            {
                Program.currentGraphicsMode = new GraphicsMode(new ColorFormat(8, 8, 8, 8), 24, 8, Interface.CurrentOptions.AntiAliasingLevel);
            }
            //Transparency quality
            switch (TransparencyQuality.SelectedIndex)
            {
            case 0:
                Interface.CurrentOptions.TransparencyMode = TransparencyMode.Performance;
                break;

            default:
                Interface.CurrentOptions.TransparencyMode = TransparencyMode.Quality;
                break;
            }
            //Set width and height
            if (Program.Renderer.Screen.Width != width.Value || Program.Renderer.Screen.Height != height.Value)
            {
                if (width.Value >= 300)
                {
                    Program.Renderer.Screen.Width   = (int)width.Value;
                    Program.currentGameWindow.Width = (int)width.Value;
                }
                if (height.Value >= 300)
                {
                    Program.Renderer.Screen.Height   = (int)height.Value;
                    Program.currentGameWindow.Height = (int)height.Value;
                }
                Program.Renderer.UpdateViewport();
            }
            //Check if interpolation mode or ansiotropic filtering level has changed, and trigger a reload
            if (previousInterpolationMode != Interface.CurrentOptions.Interpolation || previousAnsiotropicLevel != Interface.CurrentOptions.AnisotropicFilteringLevel)
            {
                Program.ReducedMode      = false;
                Program.LightingRelative = -1.0;
                Game.Reset();
                Program.Renderer.TextureManager.UnloadAllTextures();
                Interface.ClearMessages();
                for (int i = 0; i < Program.Files.Length; i++)
                {
#if !DEBUG
                    try {
#endif
                    UnifiedObject o;
                    Program.CurrentHost.LoadObject(Program.Files[i], System.Text.Encoding.UTF8, out o);
                    Program.Renderer.CreateObject(o, Vector3.Zero,
                                                  new Transformation(), new Transformation(), true, 0.0, 0.0, 25.0, 0.0);
#if !DEBUG
                }
                catch (Exception ex) {
                    Interface.AddMessage(MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Program.Files[i] + ".");
                }
#endif
                }
                Program.Renderer.InitializeVisibility();
                Program.Renderer.UpdateVisibility(0.0, true);
                ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
            }
            Interface.CurrentOptions.CurrentXParser   = (XParsers)comboBoxNewXParser.SelectedIndex;
            Interface.CurrentOptions.CurrentObjParser = (ObjParsers)comboBoxNewObjParser.SelectedIndex;
            for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
            {
                if (Program.CurrentHost.Plugins[i].Object != null)
                {
                    Program.CurrentHost.Plugins[i].Object.SetObjectParser(Interface.CurrentOptions.CurrentXParser);
                    Program.CurrentHost.Plugins[i].Object.SetObjectParser(Interface.CurrentOptions.CurrentObjParser);
                }
            }
            Options.SaveOptions();
            this.Close();
        }
示例#28
0
        internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, System.Text.Encoding Encoding,
                                                                          ObjectManager.ObjectLoadMode LoadMode)
        {
            XmlDocument currentXML = new XmlDocument();

            //May need to be changed to use de-DE
            System.Globalization.CultureInfo       Culture = System.Globalization.CultureInfo.InvariantCulture;
            ObjectManager.AnimatedObjectCollection Result  = new ObjectManager.AnimatedObjectCollection();
            Result.Objects = new ObjectManager.AnimatedObject[0];
            try
            {
                currentXML.Load(FileName);
            }
            catch (Exception ex)
            {
                //The XML is not strictly valid
                string[] Lines = File.ReadAllLines(FileName);
                using (var stringReader = new StringReader(Lines[0]))
                {
                    var settings = new XmlReaderSettings {
                        ConformanceLevel = ConformanceLevel.Fragment
                    };
                    using (var xmlReader = XmlReader.Create(stringReader, settings))
                    {
                        if (xmlReader.Read())
                        {
                            //Attempt to find the text encoding and re-read the file
                            var result = xmlReader.GetAttribute("encoding");
                            var e      = System.Text.Encoding.GetEncoding(result);
                            Lines = File.ReadAllLines(FileName, e);
                            //Turf out the old encoding, as our string array should now be UTF-8
                            Lines[0] = "<?xml version=\"1.0\"?>";
                        }
                    }
                }
                for (int i = 0; i < Lines.Length; i++)
                {
                    while (Lines[i].IndexOf("\"\"") != -1)
                    {
                        //Loksim parser tolerates multiple quotes, strict XML does not
                        Lines[i] = Lines[i].Replace("\"\"", "\"");
                    }
                    while (Lines[i].IndexOf("  ") != -1)
                    {
                        //Replace double-spaces with singles
                        Lines[i] = Lines[i].Replace("  ", " ");
                    }
                }
                bool tryLoad = false;
                try
                {
                    //Horrible hack: Write out our string array to a new memory stream, then load from this stream
                    //Why can't XmlDocument.Load() just take a string array......
                    using (var stream = new MemoryStream())
                    {
                        var sw = new StreamWriter(stream);
                        foreach (var line in Lines)
                        {
                            sw.Write(line);
                            sw.Flush();
                        }
                        sw.Flush();
                        stream.Position = 0;
                        currentXML.Load(stream);
                        tryLoad = true;
                    }
                }
                catch
                {
                    //Generic catch-all clause
                }
                if (!tryLoad)
                {
                    //Pass out the *original* XML error, not anything generated when we've tried to correct it
                    Interface.AddMessage(Interface.MessageType.Error, false, "Error parsing Loksim3D XML: " + ex.Message);
                    return(null);
                }
            }

            string BaseDir = System.IO.Path.GetDirectoryName(FileName);

            GruppenObject[] CurrentObjects = new GruppenObject[0];
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                ObjectManager.UnifiedObject[] obj = new OpenBve.ObjectManager.UnifiedObject[0];
                XmlNodeList DocumentNodes         = currentXML.DocumentElement.SelectNodes("/GRUPPENOBJECT");
                if (DocumentNodes != null)
                {
                    foreach (XmlNode outerNode in DocumentNodes)
                    {
                        if (outerNode.HasChildNodes)
                        {
                            foreach (XmlNode node in outerNode.ChildNodes)
                            {
                                if (node.Name == "Object" && node.HasChildNodes)
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            GruppenObject Object = new GruppenObject();
                                            foreach (XmlAttribute attribute in childNode.Attributes)
                                            {
                                                switch (attribute.Name)
                                                {
                                                case "Name":
                                                    string ObjectFile = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory);
                                                    if (!File.Exists(ObjectFile))
                                                    {
                                                        Object.Name = null;
                                                        Interface.AddMessage(Interface.MessageType.Warning, true, "Ls3d Object file " + attribute.Value + " not found.");
                                                    }
                                                    else
                                                    {
                                                        Object.Name = ObjectFile;
                                                    }
                                                    break;

                                                case "Position":
                                                    string[] SplitPosition = attribute.Value.Split(';');
                                                    double.TryParse(SplitPosition[0], out Object.Position.X);
                                                    double.TryParse(SplitPosition[1], out Object.Position.Y);
                                                    double.TryParse(SplitPosition[2], out Object.Position.Z);
                                                    break;

                                                case "Rotation":
                                                    string[] SplitRotation = attribute.Value.Split(';');

                                                    double.TryParse(SplitRotation[0], out Object.Rotation.X);
                                                    double.TryParse(SplitRotation[1], out Object.Rotation.Y);
                                                    double.TryParse(SplitRotation[2], out Object.Rotation.Z);
                                                    break;

                                                case "ShowOn":
                                                    //Defines when the object should be shown
                                                    Object.FunctionScript = FunctionScripts.GetPostfixNotationFromInfixNotation(GetAnimatedFunction(attribute.Value, false));
                                                    break;

                                                case "HideOn":
                                                    //Defines when the object should be hidden
                                                    Object.FunctionScript = FunctionScripts.GetPostfixNotationFromInfixNotation(GetAnimatedFunction(attribute.Value, true));
                                                    break;
                                                }
                                            }
                                            if (Object.Name != null)
                                            {
                                                Array.Resize <GruppenObject>(ref CurrentObjects, CurrentObjects.Length + 1);
                                                CurrentObjects[CurrentObjects.Length - 1] = Object;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    //We've loaded the XML references, now load the objects into memory
                    for (int i = 0; i < CurrentObjects.Length; i++)
                    {
                        if (CurrentObjects[i] == null || string.IsNullOrEmpty(CurrentObjects[i].Name))
                        {
                            continue;
                        }
                        var Object = Ls3DObjectParser.ReadObject(CurrentObjects[i].Name, LoadMode, CurrentObjects[i].Rotation);
                        if (Object != null)
                        {
                            Array.Resize <ObjectManager.UnifiedObject>(ref obj, obj.Length + 1);
                            obj[obj.Length - 1] = Object;

                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + 1);
                            Object.Dynamic = true;
                            ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                            ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState
                            {
                                Object   = Object,
                                Position = CurrentObjects[i].Position,
                            };
                            a.States          = new ObjectManager.AnimatedObjectState[] { aos };
                            Result.Objects[i] = a;
                            if (!string.IsNullOrEmpty(CurrentObjects[i].FunctionScript))
                            {
                                Result.Objects[i].StateFunction =
                                    FunctionScripts.GetFunctionScriptFromPostfixNotation(CurrentObjects[i].FunctionScript + " 1 == --");
                            }
                        }
                    }
                }
                return(Result);
            }
            //Didn't find an acceptable XML object
            //Probably will cause things to throw an absolute wobbly somewhere....
            return(null);
        }
示例#29
0
 public override void AddMessage(MessageType type, bool FileNotFound, string text)
 {
     Interface.AddMessage(type, FileNotFound, text);
 }
示例#30
0
        /// <summary>Locates the absolute on-disk path of the object to be loaded, or an available compatible replacement if not found</summary>
        /// <param name="fileName">The object's file-name</param>
        /// <param name="objectPath">The path to the objects directory for this route</param>
        internal static bool LocateObject(ref string fileName, string objectPath)
        {
            string n;

            try
            {
                //Catch completely malformed path references
                n = OpenBveApi.Path.CombineFile(objectPath, fileName);
            }
            catch
            {
                return(false);
            }
            if (System.IO.File.Exists(n))
            {
                fileName = n;
                //The object exists, and does not require a compatibility object
                return(true);
            }

            if (Interface.CurrentOptions.EnableBveTsHacks)
            {
                string fn;
                //The Midland Suburban Line has a malformed object zip, so let's try again....
                if (fileName.StartsWith("Midland Suburban Line", StringComparison.InvariantCultureIgnoreCase))
                {
                    fn = "Midland Suburban Line Objects" + fileName.Substring(21);
                    try
                    {
                        //Catch completely malformed path references
                        n = OpenBveApi.Path.CombineFile(objectPath, fn);
                    }
                    catch
                    {
                        return(false);
                    }
                    if (System.IO.File.Exists(n))
                    {
                        fileName = n;
                        //The object exists, and does not require a compatibility object
                        return(true);
                    }
                }
                //The Midland Suburban Line expects BRSema4Sigs to be placed in it's object folder, but we've probably got them elsewhere
                if (fileName.StartsWith(@"Midland Suburban Line\BrSema4Sigs", StringComparison.InvariantCultureIgnoreCase))
                {
                    fn = "BrSema4Sigs" + fileName.Substring(33);
                    try
                    {
                        //Catch completely malformed path references
                        n = OpenBveApi.Path.CombineFile(objectPath, fn);
                    }
                    catch
                    {
                        return(false);
                    }
                    if (System.IO.File.Exists(n))
                    {
                        fileName = n;
                        //The object exists, and does not require a compatibility object
                        return(true);
                    }
                }
            }
            //We haven't found the object on-disk, so check the compatibility objects to see if a replacement is available
            for (int i = 0; i < CompatibilityObjects.AvailableReplacements.Length; i++)
            {
                if (CompatibilityObjects.AvailableReplacements[i].ObjectNames.Length == 0)
                {
                    continue;
                }
                for (int j = 0; j < CompatibilityObjects.AvailableReplacements[i].ObjectNames.Length; j++)
                {
                    if (CompatibilityObjects.AvailableReplacements[i].ObjectNames[j].ToLowerInvariant() == fileName.ToLowerInvariant())
                    {
                        //Available replacement found
                        fileName = CompatibilityObjects.AvailableReplacements[i].ReplacementPath;
                        if (!string.IsNullOrEmpty(CompatibilityObjects.AvailableReplacements[i].Message))
                        {
                            Interface.AddMessage(MessageType.Warning, false, CompatibilityObjects.AvailableReplacements[i].Message);
                        }
                        CompatibilityObjectsUsed++;
                        return(true);
                    }
                }
            }
            return(false);
        }