Exemplo n.º 1
0
        // load
        private void formLoading_Load(object sender, EventArgs e)
        {
            this.MinimumSize = this.Size;
            try
            {
                string f = Interface.GetCombinedFileName(Program.FileSystem.GetDataFolder("Menu"), "banner.png");
                pictureboxBanner.Image = Image.FromFile(f);
            }
            catch { }
            labelRoute.Text                  = Interface.GetInterfaceString("loading_loading_route");
            labelTrain.Text                  = Interface.GetInterfaceString("loading_loading_train");
            labelAlmostTitle.Text            = Interface.GetInterfaceString("loading_almost");
            labelFilesNotFoundCaption.Text   = Interface.GetInterfaceString("loading_almost_filesnotfound");
            buttonIssues.Text                = Interface.GetInterfaceString("loading_almost_show");
            labelProblemsTitle.Text          = Interface.GetInterfaceString("loading_problems");
            listviewProblems.Columns[0].Text = Interface.GetInterfaceString("loading_problems_type");
            listviewProblems.Columns[1].Text = Interface.GetInterfaceString("loading_problems_description");
            buttonSave.Text                  = Interface.GetInterfaceString("loading_save");
            buttonIgnore.Text                = Interface.GetInterfaceString("loading_ignore");
            buttonCancel.Text                = Interface.GetInterfaceString("loading_cancel");

            /*
             * For some reasons, the Ignore and Save Report buttons do not show
             * up later on Mac OS X if initially set to invisible.
             * */
            if (Program.CurrentPlatform != Program.Platform.Mac)
            {
                buttonIgnore.Visible = false;
                buttonSave.Visible   = false;
            }
        }
        /// <summary>Loads the default plugin for the specified train.</summary>
        /// <param name="train">The train to attach the plugin to.</param>
        /// <param name="trainFolder">The train folder.</param>
        /// <returns>Whether the plugin was loaded successfully.</returns>
        internal static bool LoadDefaultPlugin(TrainManager.Train train, string trainFolder)
        {
            string file    = Interface.GetCombinedFileName(Program.FileSystem.GetDataFolder("Plugins"), "OpenbveAts.dll");
            bool   success = LoadPlugin(train, file, trainFolder);

            if (success)
            {
                train.Plugin.IsDefault = true;
                SoundCfgParser.LoadDefaultPluginSounds(train, trainFolder);
            }
            return(success);
        }
        /// <summary>Loads a custom plugin for the specified train.</summary>
        /// <param name="train">The train to attach the plugin to.</param>
        /// <param name="trainFolder">The absolute path to the train folder.</param>
        /// <param name="encoding">The encoding to be used.</param>
        /// <returns>Whether the plugin was loaded successfully.</returns>
        internal static bool LoadCustomPlugin(TrainManager.Train train, string trainFolder, System.Text.Encoding encoding)
        {
            string config = Interface.GetCombinedFileName(trainFolder, "ats.cfg");

            if (!System.IO.File.Exists(config))
            {
                return(false);
            }
            string[] lines = System.IO.File.ReadAllLines(config, encoding);
            if (lines.Length == 0)
            {
                return(false);
            }
            string file  = Interface.GetCombinedFileName(trainFolder, lines[0]);
            string title = System.IO.Path.GetFileName(file);

            if (!System.IO.File.Exists(file))
            {
                Interface.AddMessage(Interface.MessageType.Error, true, "The train plugin " + title + " could not be found in " + config);
                return(false);
            }
            return(LoadPlugin(train, file, trainFolder));
        }
Exemplo n.º 4
0
        // show messages
        private void ShowMessages()
        {
            listviewProblems.SmallImageList = new ImageList();
            string Folder = Program.FileSystem.GetDataFolder("Menu");

            try
            {
                listviewProblems.SmallImageList.Images.Add("information", Image.FromFile(Interface.GetCombinedFileName(Folder, "icon_information.png")));
            }
            catch { }
            try
            {
                listviewProblems.SmallImageList.Images.Add("warning", Image.FromFile(Interface.GetCombinedFileName(Folder, "icon_warning.png")));
            }
            catch { }
            try
            {
                listviewProblems.SmallImageList.Images.Add("error", Image.FromFile(Interface.GetCombinedFileName(Folder, "icon_error.png")));
            }
            catch { }
            try
            {
                listviewProblems.SmallImageList.Images.Add("critical", Image.FromFile(Interface.GetCombinedFileName(Folder, "icon_critical.png")));
            }
            catch { }

            /*
             * Show critical errors
             * */
            for (int i = 0; i < Interface.MessageCount; i++)
            {
                if (Interface.Messages[i].Type == Interface.MessageType.Critical)
                {
                    ListViewItem a = listviewProblems.Items.Add("Critical", "critical");
                    a.SubItems.Add(Interface.Messages[i].Text);
                }
            }

            /*
             * Show informational messages
             * */
            for (int i = 0; i < Interface.MessageCount; i++)
            {
                if (Interface.Messages[i].Type == Interface.MessageType.Information)
                {
                    ListViewItem a = listviewProblems.Items.Add("Information", "information");
                    a.SubItems.Add(Interface.Messages[i].Text);
                }
            }

            /*
             * Show errors
             * */
            for (int i = 0; i < Interface.MessageCount; i++)
            {
                if (Interface.Messages[i].Type == Interface.MessageType.Error)
                {
                    ListViewItem a = listviewProblems.Items.Add("Error", "error");
                    a.SubItems.Add(Interface.Messages[i].Text);
                }
            }

            /*
             * Show warnings
             * */
            for (int i = 0; i < Interface.MessageCount; i++)
            {
                if (Interface.Messages[i].Type == Interface.MessageType.Warning)
                {
                    ListViewItem a = listviewProblems.Items.Add("Warning", "warning");
                    a.SubItems.Add(Interface.Messages[i].Text);
                }
            }
            listviewProblems.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
        }
Exemplo n.º 5
0
        // start
        private static void Start(string[] Args)
        {
            // initialize sdl video
            if (Sdl.SDL_Init(Sdl.SDL_INIT_VIDEO) != 0)
            {
                MessageBox.Show("SDL failed to initialize the video subsystem.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return;
            }
            if (Sdl.SDL_Init(Sdl.SDL_INIT_JOYSTICK) != 0)
            {
                MessageBox.Show("SDL failed to initialize the joystick subsystem.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return;
            }
            // initialize sdl joysticks
            {
                int n = Sdl.SDL_NumJoysticks();
                Interface.CurrentJoysticks = new Interface.Joystick[n];
                for (int i = 0; i < n; i++)
                {
                    Interface.CurrentJoysticks[i].SdlHandle = Sdl.SDL_JoystickOpen(i);
                    if (CurrentPlatform == Platform.Windows)
                    {
                        string s = Sdl.SDL_JoystickName(i);
                        /* string returned is ascii packed in utf-16 (2 chars per codepoint) */
                        System.Text.StringBuilder t = new System.Text.StringBuilder(s.Length << 1);
                        for (int k = 0; k < s.Length; k++)
                        {
                            int a = (int)s[k];
                            t.Append(char.ConvertFromUtf32(a & 0xFF) + char.ConvertFromUtf32(a >> 8));
                        }
                        Interface.CurrentJoysticks[i].Name = t.ToString();
                    }
                    else
                    {
                        Interface.CurrentJoysticks[i].Name = Sdl.SDL_JoystickName(i);
                    }
                }
            }
            // load options and controls
            Interface.LoadOptions();
            Interface.LoadControls(null, out Interface.CurrentControls);
            {
                string f = Interface.GetCombinedFileName(Program.FileSystem.GetDataFolder("Controls"), "Default keyboard assignment.controls");
                Interface.Control[] c;
                Interface.LoadControls(f, out c);
                Interface.AddControls(ref Interface.CurrentControls, c);
            }
            // command line arguments
            formMain.MainDialogResult Result = new formMain.MainDialogResult();
            for (int i = 0; i < Args.Length; i++)
            {
                if (Args[i].StartsWith("/route=", StringComparison.OrdinalIgnoreCase))
                {
                    Result.RouteFile     = Args[i].Substring(7);
                    Result.RouteEncoding = System.Text.Encoding.UTF8;
                    for (int j = 0; j < Interface.CurrentOptions.RouteEncodings.Length; j++)
                    {
                        if (string.Compare(Interface.CurrentOptions.RouteEncodings[j].Value, Result.RouteFile, StringComparison.InvariantCultureIgnoreCase) == 0)
                        {
                            Result.RouteEncoding = System.Text.Encoding.GetEncoding(Interface.CurrentOptions.RouteEncodings[j].Codepage);
                            break;
                        }
                    }
                }
                else if (Args[i].StartsWith("/train=", StringComparison.OrdinalIgnoreCase))
                {
                    Result.TrainFolder   = Args[i].Substring(7);
                    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;
                        }
                    }
                }
            }
            // train provided
            if (Result.TrainFolder != null)
            {
                if (System.IO.Directory.Exists(Result.TrainFolder))
                {
                    string File = Interface.GetCombinedFileName(Result.TrainFolder, "train.dat");
                    if (System.IO.File.Exists(File))
                    {
                        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);
                            }
                        }
                    }
                    else
                    {
                        Result.TrainFolder = null;
                    }
                }
                else
                {
                    Result.TrainFolder = null;
                }
            }
            // route provided
            if (Result.RouteFile != null)
            {
                if (!System.IO.File.Exists(Result.RouteFile))
                {
                    Result.RouteFile = null;
                }
            }
            // route provided but no train
            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 (Game.TrainName != null && Game.TrainName.Length != 0)
                {
                    string Folder = System.IO.Path.GetDirectoryName(Result.RouteFile);
                    while (true)
                    {
                        string TrainFolder = Interface.GetCombinedFolderName(Folder, "Train");
                        if (System.IO.Directory.Exists(TrainFolder))
                        {
                            Folder = Interface.GetCombinedFolderName(TrainFolder, Game.TrainName);
                            if (System.IO.Directory.Exists(Folder))
                            {
                                string File = Interface.GetCombinedFileName(Folder, "train.dat");
                                if (System.IO.File.Exists(File))
                                {
                                    // associated train found
                                    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;
                        }
                        else
                        {
                            System.IO.DirectoryInfo Info = System.IO.Directory.GetParent(Folder);
                            if (Info != null)
                            {
                                Folder = Info.FullName;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
                Game.Reset(false);
            }
            // show main menu if applicable
            if (Result.RouteFile == null | Result.TrainFolder == null)
            {
                Result = formMain.ShowMainDialog();
                if (!Result.Start)
                {
                    return;
                }
            }
            // screen
            int Width  = Interface.CurrentOptions.FullscreenMode ? Interface.CurrentOptions.FullscreenWidth : Interface.CurrentOptions.WindowWidth;
            int Height = Interface.CurrentOptions.FullscreenMode ? Interface.CurrentOptions.FullscreenHeight : Interface.CurrentOptions.WindowHeight;

            if (Width < 16)
            {
                Width = 16;
            }
            if (Height < 16)
            {
                Height = 16;
            }
            Renderer.ScreenWidth  = Width;
            Renderer.ScreenHeight = Height;
            World.AspectRatio     = (double)Renderer.ScreenWidth / (double)Renderer.ScreenHeight;
            const double degree = 0.0174532925199433;

            World.VerticalViewingAngle         = 45.0 * degree;
            World.HorizontalViewingAngle       = 2.0 * Math.Atan(Math.Tan(0.5 * World.VerticalViewingAngle) * World.AspectRatio);
            World.OriginalVerticalViewingAngle = World.VerticalViewingAngle;
            World.ExtraViewingDistance         = 50.0;
            World.ForwardViewingDistance       = (double)Interface.CurrentOptions.ViewingDistance;
            World.BackwardViewingDistance      = 0.0;
            World.BackgroundImageDistance      = (double)Interface.CurrentOptions.ViewingDistance;
            // load route and train
            SoundManager.Initialize();
            if (!Loading.Load(Result.RouteFile, Result.RouteEncoding, Result.TrainFolder, Result.TrainEncoding))
            {
                return;
            }
            Game.LogRouteName = System.IO.Path.GetFileName(Result.RouteFile);
            Game.LogTrainName = System.IO.Path.GetFileName(Result.TrainFolder);
            Game.LogDateTime  = DateTime.Now;
            // initialize sdl window
            Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_DOUBLEBUFFER, 1);
            Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_DEPTH_SIZE, 24);
            Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_RED_SIZE, 8);
            Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_GREEN_SIZE, 8);
            Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_BLUE_SIZE, 8);
            Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_SWAP_CONTROL, Interface.CurrentOptions.VerticalSynchronization ? 1 : 0);
            Sdl.SDL_ShowCursor(Sdl.SDL_DISABLE);
            SdlWindowCreated = true;
            int Bits = Interface.CurrentOptions.FullscreenMode ? Interface.CurrentOptions.FullscreenBits : 32;

            // --- window caption and icon ---
            Sdl.SDL_WM_SetCaption(Application.ProductName, null);
            {
                string bitmapFile = OpenBveApi.Path.CombineFile(Program.FileSystem.DataFolder, "icon.bmp");
                IntPtr bitmap     = Sdl.SDL_LoadBMP(bitmapFile);
                if (bitmap != null)
                {
                    string maskFile = OpenBveApi.Path.CombineFile(Program.FileSystem.DataFolder, "mask.bin");
                    byte[] mask     = System.IO.File.ReadAllBytes(maskFile);
                    Sdl.SDL_WM_SetIcon(bitmap, mask);
                }
            }
            // create window
            int    fullscreen = Interface.CurrentOptions.FullscreenMode ? Sdl.SDL_FULLSCREEN : 0;
            IntPtr video      = Sdl.SDL_SetVideoMode(Width, Height, Bits, Sdl.SDL_OPENGL | Sdl.SDL_DOUBLEBUF | fullscreen);

            if (video != IntPtr.Zero)
            {
                // anisotropic filtering
                string[] Extensions = Gl.glGetString(Gl.GL_EXTENSIONS).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                Interface.CurrentOptions.AnisotropicFilteringMaximum = 0;
                for (int i = 0; i < Extensions.Length; i++)
                {
                    if (string.Compare(Extensions[i], "GL_EXT_texture_filter_anisotropic", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        float n; Gl.glGetFloatv(Gl.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, out n);
                        Interface.CurrentOptions.AnisotropicFilteringMaximum = (int)Math.Round((double)n);
                        break;
                    }
                }
                if (Interface.CurrentOptions.AnisotropicFilteringMaximum <= 0)
                {
                    Interface.CurrentOptions.AnisotropicFilteringMaximum = 0;
                    Interface.CurrentOptions.AnisotropicFilteringLevel   = 0;
                }
                else if (Interface.CurrentOptions.AnisotropicFilteringLevel == 0 & Interface.CurrentOptions.AnisotropicFilteringMaximum > 0)
                {
                    Interface.CurrentOptions.AnisotropicFilteringLevel = Interface.CurrentOptions.AnisotropicFilteringMaximum;
                }
                else if (Interface.CurrentOptions.AnisotropicFilteringLevel > Interface.CurrentOptions.AnisotropicFilteringMaximum)
                {
                    Interface.CurrentOptions.AnisotropicFilteringLevel = Interface.CurrentOptions.AnisotropicFilteringMaximum;
                }
                // module initialization
                Fonts.Initialize();
                Renderer.Initialize();
                Renderer.InitializeLighting();
                Sdl.SDL_GL_SwapBuffers();
                Timetable.CreateTimetable();
                // camera
                MainLoop.UpdateViewport(MainLoop.ViewPortChangeMode.NoChange);
                MainLoop.InitializeMotionBlur();
                // start loop
                MainLoop.StartLoop();
            }
            else
            {
                // failed
                MessageBox.Show("SDL failed to create the window.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }
        // parse extensions config
        internal static void ParseExtensionsConfig(string TrainPath, System.Text.Encoding Encoding, out ObjectManager.UnifiedObject[] CarObjects, TrainManager.Train Train)
        {
            CarObjects = new ObjectManager.UnifiedObject[Train.Cars.Length];
            bool[] CarObjectsReversed = new bool[Train.Cars.Length];
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string FileName = Interface.GetCombinedFileName(TrainPath, "extensions.cfg");

            if (System.IO.File.Exists(FileName))
            {
                // load file
                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 (Interface.ContainsInvalidPathChars(b))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                }
                                                else
                                                {
                                                    string File = Interface.GetCombinedFileName(TrainPath, b);
                                                    if (System.IO.File.Exists(File))
                                                    {
                                                        CarObjects[n] = ObjectManager.LoadObject(File, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                    }
                                                    else
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, true, "The car object " + File + " does not exist at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                Interface.AddMessage(Interface.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(Interface.MessageType.Error, false, "The car index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(Interface.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)
                                    {
                                        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 (Interface.ContainsInvalidPathChars(b))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "File contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                        else
                                                        {
                                                            string File = Interface.GetCombinedFileName(TrainPath, b);
                                                            if (System.IO.File.Exists(File))
                                                            {
                                                                CarObjects[n] = ObjectManager.LoadObject(File, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                            }
                                                            else
                                                            {
                                                                Interface.AddMessage(Interface.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(Interface.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(Interface.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(Interface.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(Interface.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(Interface.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].RearAxlePosition  = rear;
                                                                Train.Cars[n].FrontAxlePosition = front;
                                                                DefinedAxles = true;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            Interface.AddMessage(Interface.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(Interface.MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(Interface.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].RearAxlePosition  = -AxleDistance;
                                            Train.Cars[n].FrontAxlePosition = AxleDistance;
                                        }
                                    }
                                    else
                                    {
                                        Interface.AddMessage(Interface.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(Interface.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(Interface.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(Interface.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(Interface.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(Interface.MessageType.Error, false, "An argument-separating comma is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        }
                                                    }
                                                    break;

                                                    default:
                                                        Interface.AddMessage(Interface.MessageType.Warning, false, "Unsupported key-value pair " + a + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                }
                                            }
                                            i++;
                                        }
                                        i--;
                                    }
                                    else
                                    {
                                        Interface.AddMessage(Interface.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(Interface.MessageType.Error, false, "The coupler index is expected to be an integer at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                }
                            }
                            else
                            {
                                // default
                                Interface.AddMessage(Interface.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])
                        {
                            {
                                // reverse axle positions
                                double temp = Train.Cars[i].FrontAxlePosition;
                                Train.Cars[i].FrontAxlePosition = -Train.Cars[i].RearAxlePosition;
                                Train.Cars[i].RearAxlePosition  = -temp;
                            }
                            if (CarObjects[i] is ObjectManager.StaticObject)
                            {
                                ObjectManager.StaticObject obj = (ObjectManager.StaticObject)CarObjects[i];
                                CsvB3dObjectParser.ApplyScale(obj, -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++)
                                    {
                                        CsvB3dObjectParser.ApplyScale(obj.Objects[j].States[h].Object, -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(Interface.MessageType.Warning, false, "An incomplete set of exterior objects was provided in file " + FileName);
                }
            }
        }
Exemplo n.º 7
0
        private static void LoadEverythingThreaded()
        {
            string RailwayFolder = GetRailwayFolder(CurrentRouteFile);

            if (RailwayFolder == null)
            {
                Interface.AddMessage(Interface.MessageType.Critical, false, "The Railway and Train folders could not be found in any of the route file's parent directories. Please check your folder structure.");
                return;
            }
            string ObjectFolder = Interface.GetCombinedFolderName(RailwayFolder, "Object");
            string SoundFolder  = Interface.GetCombinedFolderName(RailwayFolder, "Sound");

            // reset
            Game.Reset(true);
            Game.MinimalisticSimulation = true;
            // screen
            World.CameraTrackFollower          = new TrackManager.TrackFollower();
            World.CameraTrackFollower.Train    = null;
            World.CameraTrackFollower.CarIndex = -1;
            World.CameraMode = World.CameraViewMode.Interior;
            // load route
            bool IsRW = string.Equals(System.IO.Path.GetExtension(CurrentRouteFile), ".rw", StringComparison.OrdinalIgnoreCase);

            CsvRwRouteParser.ParseRoute(CurrentRouteFile, IsRW, CurrentRouteEncoding, CurrentTrainFolder, ObjectFolder, SoundFolder, false);
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Game.CalculateSeaLevelConstants();
            if (Game.BogusPretrainInstructions.Length != 0)
            {
                double t = Game.BogusPretrainInstructions[0].Time;
                double p = Game.BogusPretrainInstructions[0].TrackPosition;
                for (int i = 1; i < Game.BogusPretrainInstructions.Length; i++)
                {
                    if (Game.BogusPretrainInstructions[i].Time > t)
                    {
                        t = Game.BogusPretrainInstructions[i].Time;
                    }
                    else
                    {
                        t += 1.0;
                        Game.BogusPretrainInstructions[i].Time = t;
                    }
                    if (Game.BogusPretrainInstructions[i].TrackPosition > p)
                    {
                        p = Game.BogusPretrainInstructions[i].TrackPosition;
                    }
                    else
                    {
                        p += 1.0;
                        Game.BogusPretrainInstructions[i].TrackPosition = p;
                    }
                }
            }
            RouteProgress = 1.0;
            // initialize trains
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            TrainManager.Trains = new TrainManager.Train[Game.PrecedingTrainTimeDeltas.Length + 1 + (Game.BogusPretrainInstructions.Length != 0 ? 1 : 0)];
            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                TrainManager.Trains[k]            = new TrainManager.Train();
                TrainManager.Trains[k].TrainIndex = k;
                if (k == TrainManager.Trains.Length - 1 & Game.BogusPretrainInstructions.Length != 0)
                {
                    TrainManager.Trains[k].State = TrainManager.TrainState.Bogus;
                }
                else
                {
                    TrainManager.Trains[k].State = TrainManager.TrainState.Pending;
                }
            }
            TrainManager.PlayerTrain = TrainManager.Trains[Game.PrecedingTrainTimeDeltas.Length];
            // load trains
            double TrainProgressMaximum = 0.7 + 0.3 * (double)TrainManager.Trains.Length;

            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                if (TrainManager.Trains[k].State == TrainManager.TrainState.Bogus)
                {
                    // bogus train
                    string Folder = Program.FileSystem.GetDataFolder("Compatibility", "PreTrain");
                    TrainDatParser.ParseTrainData(Folder, System.Text.Encoding.UTF8, TrainManager.Trains[k]);
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    SoundCfgParser.LoadNoSound(TrainManager.Trains[k]);
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.3 / TrainProgressMaximum;
                    TrainProgressCurrentSum   += TrainProgressCurrentWeight;
                }
                else
                {
                    // real train
                    TrainProgressCurrentWeight = 0.1 / TrainProgressMaximum;
                    TrainDatParser.ParseTrainData(CurrentTrainFolder, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.2 / TrainProgressMaximum;
                    SoundCfgParser.ParseSoundConfig(CurrentTrainFolder, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    // door open/close speed
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        if (TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency <= 0.0)
                        {
                            if (TrainManager.Trains[k].Cars[i].Sounds.DoorOpenL.SoundBufferIndex >= 0 & TrainManager.Trains[k].Cars[i].Sounds.DoorOpenR.SoundBufferIndex >= 0)
                            {
                                double a = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorOpenL.SoundBufferIndex);
                                double b = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorOpenR.SoundBufferIndex);
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Sounds.DoorOpenL.SoundBufferIndex >= 0)
                            {
                                double a = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorOpenL.SoundBufferIndex);
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Sounds.DoorOpenR.SoundBufferIndex >= 0)
                            {
                                double a = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorOpenR.SoundBufferIndex);
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else
                            {
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = 0.8;
                            }
                        }
                        if (TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency <= 0.0)
                        {
                            if (TrainManager.Trains[k].Cars[i].Sounds.DoorCloseL.SoundBufferIndex >= 0 & TrainManager.Trains[k].Cars[i].Sounds.DoorCloseR.SoundBufferIndex >= 0)
                            {
                                double a = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorCloseL.SoundBufferIndex);
                                double b = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorCloseR.SoundBufferIndex);
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.2;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Sounds.DoorCloseL.SoundBufferIndex >= 0)
                            {
                                double a = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorCloseL.SoundBufferIndex);
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.2;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Sounds.DoorCloseR.SoundBufferIndex >= 0)
                            {
                                double a = SoundManager.GetSoundLength(TrainManager.Trains[k].Cars[i].Sounds.DoorCloseR.SoundBufferIndex);
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.2;
                            }
                            else
                            {
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = 0.2;
                            }
                        }
                        const double f = 0.015;
                        const double g = 2.75;
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Game.Generator.NextDouble() - 0.5)));
                        TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Game.Generator.NextDouble() - 0.5)));
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency  /= TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch;
                        TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency /= TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch;

                        /*
                         * Remove the following two lines, then the pitch at which doors play
                         * takes their randomized opening and closing times into account.
                         * */
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch  = 1.0;
                        TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch = 1.0;
                    }
                }
                for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                {
                    TrainManager.Trains[k].Cars[i].FrontAxle.Follower.Train = TrainManager.Trains[k];
                    TrainManager.Trains[k].Cars[i].RearAxle.Follower.Train  = TrainManager.Trains[k];
                    TrainManager.Trains[k].Cars[i].BeaconReceiver.Train     = TrainManager.Trains[k];
                }
                // add panel section
                if (k == TrainManager.PlayerTrain.TrainIndex)
                {
                    TrainManager.Trains[k].Cars[TrainManager.Trains[k].DriverCar].CarSections             = new TrainManager.CarSection[1];
                    TrainManager.Trains[k].Cars[TrainManager.Trains[k].DriverCar].CarSections[0].Elements = new ObjectManager.AnimatedObject[] { };
                    TrainManager.Trains[k].Cars[TrainManager.Trains[k].DriverCar].CarSections[0].Overlay  = true;
                    TrainProgressCurrentWeight = 0.7 / TrainProgressMaximum;
                    TrainManager.ParsePanelConfig(CurrentTrainFolder, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                }
                // add exterior section
                if (TrainManager.Trains[k].State != TrainManager.TrainState.Bogus)
                {
                    ObjectManager.UnifiedObject[] CarObjects;
                    ExtensionsCfgParser.ParseExtensionsConfig(CurrentTrainFolder, CurrentTrainEncoding, out CarObjects, TrainManager.Trains[k]);
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        if (CarObjects[i] == null)
                        {
                            // load default exterior object
                            string file = Interface.GetCombinedFileName(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                            ObjectManager.StaticObject so = ObjectManager.LoadStaticObject(file, System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                            if (so == null)
                            {
                                CarObjects[i] = null;
                            }
                            else
                            {
                                double sx = TrainManager.Trains[k].Cars[i].Width;
                                double sy = TrainManager.Trains[k].Cars[i].Height;
                                double sz = TrainManager.Trains[k].Cars[i].Length;
                                CsvB3dObjectParser.ApplyScale(so, sx, sy, sz);
                                CarObjects[i] = so;
                            }
                        }
                        if (CarObjects[i] != null)
                        {
                            // add object
                            int j = TrainManager.Trains[k].Cars[i].CarSections.Length;
                            Array.Resize <TrainManager.CarSection>(ref TrainManager.Trains[k].Cars[i].CarSections, j + 1);
                            if (CarObjects[i] is ObjectManager.StaticObject)
                            {
                                ObjectManager.StaticObject s = (ObjectManager.StaticObject)CarObjects[i];
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements                       = new ObjectManager.AnimatedObject[1];
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements[0]                    = new ObjectManager.AnimatedObject();
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements[0].States             = new ObjectManager.AnimatedObjectState[1];
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements[0].States[0].Position = new World.Vector3D(0.0, 0.0, 0.0);
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements[0].States[0].Object   = s;
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements[0].CurrentState       = 0;
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements[0].ObjectIndex        = ObjectManager.CreateDynamicObject();
                            }
                            else if (CarObjects[i] is ObjectManager.AnimatedObjectCollection)
                            {
                                ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)CarObjects[i];
                                TrainManager.Trains[k].Cars[i].CarSections[j].Elements = new ObjectManager.AnimatedObject[a.Objects.Length];
                                for (int h = 0; h < a.Objects.Length; h++)
                                {
                                    TrainManager.Trains[k].Cars[i].CarSections[j].Elements[h]             = a.Objects[h];
                                    TrainManager.Trains[k].Cars[i].CarSections[j].Elements[h].ObjectIndex = ObjectManager.CreateDynamicObject();
                                }
                            }
                        }
                    }
                }
                // place cars
                {
                    double z = 0.0;
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        TrainManager.Trains[k].Cars[i].FrontAxle.Follower.TrackPosition = z - 0.5 * TrainManager.Trains[k].Cars[i].Length + TrainManager.Trains[k].Cars[i].FrontAxlePosition;
                        TrainManager.Trains[k].Cars[i].RearAxle.Follower.TrackPosition  = z - 0.5 * TrainManager.Trains[k].Cars[i].Length + TrainManager.Trains[k].Cars[i].RearAxlePosition;
                        TrainManager.Trains[k].Cars[i].BeaconReceiver.TrackPosition     = z - 0.5 * TrainManager.Trains[k].Cars[i].Length + TrainManager.Trains[k].Cars[i].BeaconReceiverPosition;
                        z -= TrainManager.Trains[k].Cars[i].Length;
                        if (i < TrainManager.Trains[k].Cars.Length - 1)
                        {
                            z -= 0.5 * (TrainManager.Trains[k].Couplers[i].MinimumDistanceBetweenCars + TrainManager.Trains[k].Couplers[i].MaximumDistanceBetweenCars);
                        }
                    }
                }
                // configure ai / timetable
                if (TrainManager.Trains[k] == TrainManager.PlayerTrain)
                {
                    TrainManager.Trains[k].TimetableDelta = 0.0;
                }
                else if (TrainManager.Trains[k].State != TrainManager.TrainState.Bogus)
                {
                    TrainManager.Trains[k].AI                  = new Game.SimpleHumanDriverAI(TrainManager.Trains[k]);
                    TrainManager.Trains[k].TimetableDelta      = Game.PrecedingTrainTimeDeltas[k];
                    TrainManager.Trains[k].Specs.DoorOpenMode  = TrainManager.DoorMode.Manual;
                    TrainManager.Trains[k].Specs.DoorCloseMode = TrainManager.DoorMode.Manual;
                }
            }
            TrainProgress = 1.0;
            // finished created objects
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            ObjectManager.FinishCreatingObjects();
            // update sections
            if (Game.Sections.Length > 0)
            {
                Game.UpdateSection(Game.Sections.Length - 1);
            }
            // load plugin
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                if (TrainManager.Trains[i].State != TrainManager.TrainState.Bogus)
                {
                    if (TrainManager.Trains[i] == TrainManager.PlayerTrain)
                    {
                        if (!PluginManager.LoadCustomPlugin(TrainManager.Trains[i], CurrentTrainFolder, CurrentTrainEncoding))
                        {
                            PluginManager.LoadDefaultPlugin(TrainManager.Trains[i], CurrentTrainFolder);
                        }
                    }
                    else
                    {
                        PluginManager.LoadDefaultPlugin(TrainManager.Trains[i], CurrentTrainFolder);
                    }
                }
            }
            // continue after opengl is initialized

            /*
             * The rest of the loading procedure is located in MainLoop.cs :: StartLoop.
             * This is due to the fact that the OpenGL window has not been initialized yet,
             * but the follow-up initialization code needs a valid OpenGL context.
             * */
        }