ParseSoundConfig() static private method

static private ParseSoundConfig ( string TrainPath, System Encoding, TrainManager Train ) : void
TrainPath string
Encoding System
Train TrainManager
return void
コード例 #1
0
        private static void LoadEverythingThreaded()
        {
            string RailwayFolder = GetRailwayFolder(CurrentRouteFile);
            string ObjectFolder  = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Object");
            string SoundFolder   = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Sound");

            Game.Reset(true);
            Game.MinimalisticSimulation = true;
            // screen
            Program.Renderer.Camera.CurrentMode = CameraViewMode.Interior;

            Program.CurrentRoute.TrackFollowingObjects = TrainManager.TFOs;
            bool loaded = false;

            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Route loading plugins available.");
            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableObjectPluginCount + " Object loading plugins available.");
            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Sound loading plugins available.");
            for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
            {
                if (Program.CurrentHost.Plugins[i].Route != null && Program.CurrentHost.Plugins[i].Route.CanLoadRoute(CurrentRouteFile))
                {
                    object Route = (object)Program.CurrentRoute;                     //must cast to allow us to use the ref keyword.
                    if (Program.CurrentHost.Plugins[i].Route.LoadRoute(CurrentRouteFile, CurrentRouteEncoding, CurrentTrainFolder, ObjectFolder, SoundFolder, false, ref Route))
                    {
                        Program.CurrentRoute = (CurrentRoute)Route;
                        Program.Renderer.Lighting.OptionAmbientColor  = Program.CurrentRoute.Atmosphere.AmbientLightColor;
                        Program.Renderer.Lighting.OptionDiffuseColor  = Program.CurrentRoute.Atmosphere.DiffuseLightColor;
                        Program.Renderer.Lighting.OptionLightPosition = Program.CurrentRoute.Atmosphere.LightPosition;
                        loaded = true;
                        break;
                    }
                    var currentError = Translations.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", System.IO.Path.GetFileName(CurrentRouteFile));
                    MessageBox.Show(currentError, @"OpenBVE", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Interface.AddMessage(MessageType.Critical, false, "The route and train loader encountered the following critical error: " + Program.CurrentHost.Plugins[i].Route.LastException.Message);
                    CrashHandler.LoadingCrash(Program.CurrentHost.Plugins[i].Route.LastException.Message, false);
                    Program.RestartArguments = " ";
                    Cancel = true;
                    return;
                }
            }

            TrainManager.TFOs = Program.CurrentRoute.TrackFollowingObjects;
            if (!loaded)
            {
                throw new Exception("No plugins capable of loading routefile " + CurrentRouteFile + " were found.");
            }
            Thread createIllustrations = new Thread(Program.CurrentRoute.Information.LoadInformation)
            {
                IsBackground = true
            };

            createIllustrations.Start();
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Program.CurrentRoute.Atmosphere.CalculateSeaLevelConstants();
            if (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
            {
                double t = Program.CurrentRoute.BogusPreTrainInstructions[0].Time;
                double p = Program.CurrentRoute.BogusPreTrainInstructions[0].TrackPosition;
                for (int i = 1; i < Program.CurrentRoute.BogusPreTrainInstructions.Length; i++)
                {
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].Time > t)
                    {
                        t = Program.CurrentRoute.BogusPreTrainInstructions[i].Time;
                    }
                    else
                    {
                        t += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].Time = t;
                    }
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition > p)
                    {
                        p = Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition;
                    }
                    else
                    {
                        p += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition = p;
                    }
                }
            }
            Program.Renderer.CameraTrackFollower = new TrackFollower(Program.CurrentHost)
            {
                Train = null, Car = null
            };
            if (Program.CurrentRoute.Stations.Length == 1)
            {
                //Log the fact that only a single station is present, as this is probably not right
                Program.FileSystem.AppendToLogFile("The processed route file only contains a single station.");
            }
            Program.FileSystem.AppendToLogFile("Route file loaded successfully.");
            // initialize trains
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            TrainManager.Trains = new TrainManager.Train[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                if (k == TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
                {
                    TrainManager.Trains[k] = new TrainManager.Train(TrainState.Bogus);
                }
                else
                {
                    TrainManager.Trains[k] = new TrainManager.Train(TrainState.Pending);
                }
            }
            TrainManager.PlayerTrain = TrainManager.Trains[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length];

            UnifiedObject[] CarObjects     = null;
            UnifiedObject[] BogieObjects   = null;
            UnifiedObject[] CouplerObjects = null;

            // load trains
            double TrainProgressMaximum = 0.7 + 0.3 * (double)TrainManager.Trains.Length;

            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                //Sleep for 20ms to allow route loading locks to release
                Thread.Sleep(20);
                if (TrainManager.Trains[k].State == TrainState.Bogus)
                {
                    // bogus train
                    string TrainData = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility", "PreTrain"), "train.dat");
                    TrainDatParser.ParseTrainData(TrainData, System.Text.Encoding.UTF8, TrainManager.Trains[k]);
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainManager.Trains[k].InitializeCarSounds();
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.3 / TrainProgressMaximum;
                    TrainProgressCurrentSum   += TrainProgressCurrentWeight;
                }
                else
                {
                    TrainManager.Trains[k].TrainFolder = CurrentTrainFolder;
                    // real train
                    if (TrainManager.Trains[k].IsPlayerTrain)
                    {
                        Program.FileSystem.AppendToLogFile("Loading player train: " + TrainManager.Trains[k].TrainFolder);
                    }
                    else
                    {
                        Program.FileSystem.AppendToLogFile("Loading AI train: " + TrainManager.Trains[k].TrainFolder);
                    }
                    TrainProgressCurrentWeight = 0.1 / TrainProgressMaximum;
                    string TrainData = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.dat");
                    TrainDatParser.ParseTrainData(TrainData, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.2 / TrainProgressMaximum;
                    SoundCfgParser.ParseSoundConfig(TrainManager.Trains[k].TrainFolder, 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].Doors[0].OpenSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration;
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 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].Doors[0].CloseSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration;
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8;
                            }
                            else
                            {
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = 0.8;
                            }
                        }
                        const double f = 0.015;
                        const double g = 2.75;
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                        TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.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;
                    }
                }
                // add panel section
                if (TrainManager.Trains[k].IsPlayerTrain)
                {
                    TrainProgressCurrentWeight = 0.7 / TrainProgressMaximum;
                    TrainManager.Trains[k].ParsePanelConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    Program.FileSystem.AppendToLogFile("Train panel loaded sucessfully.");
                }
                // add exterior section
                if (TrainManager.Trains[k].State != TrainState.Bogus)
                {
                    bool   LoadObjects         = false;
                    bool[] VisibleFromInterior = new bool[TrainManager.Trains[k].Cars.Length];
                    if (CarObjects == null)
                    {
                        CarObjects     = new UnifiedObject[TrainManager.Trains[k].Cars.Length];
                        BogieObjects   = new UnifiedObject[TrainManager.Trains[k].Cars.Length * 2];
                        CouplerObjects = new UnifiedObject[TrainManager.Trains[k].Cars.Length];
                        LoadObjects    = true;
                    }
                    string tXml = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.xml");
                    if (System.IO.File.Exists(tXml))
                    {
                        TrainXmlParser.Parse(tXml, TrainManager.Trains[k], ref CarObjects, ref BogieObjects, ref CouplerObjects, ref VisibleFromInterior);
                    }
                    else
                    {
                        ExtensionsCfgParser.ParseExtensionsConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, ref CarObjects, ref BogieObjects, ref CouplerObjects, ref VisibleFromInterior, TrainManager.Trains[k], LoadObjects);
                    }
                    TrainManager.PlayerTrain.CameraCar = TrainManager.Trains[k].DriverCar;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    //Stores the current array index of the bogie object to add
                    //Required as there are two bogies per car, and we're using a simple linear array....
                    int currentBogieObject = 0;
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        if (CarObjects[i] == null)
                        {
                            // load default exterior object
                            string       file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                            StaticObject so;
                            Program.CurrentHost.LoadStaticObject(file, System.Text.Encoding.UTF8, false, out so);
                            if (so == null)
                            {
                                CarObjects[i] = null;
                            }
                            else
                            {
                                StaticObject c = (StaticObject)so.Clone();                                 //Clone as otherwise the cached object doesn't scale right
                                c.ApplyScale(TrainManager.Trains[k].Cars[i].Width, TrainManager.Trains[k].Cars[i].Height, TrainManager.Trains[k].Cars[i].Length);
                                CarObjects[i] = c;
                            }
                        }
                        if (CarObjects[i] != null)
                        {
                            // add object
                            TrainManager.Trains[k].Cars[i].LoadCarSections(CarObjects[i], VisibleFromInterior[i]);
                        }

                        if (CouplerObjects[i] != null)
                        {
                            TrainManager.Trains[k].Cars[i].Coupler.LoadCarSections(CouplerObjects[i], VisibleFromInterior[i]);
                        }
                        //Load bogie objects
                        if (BogieObjects[currentBogieObject] != null)
                        {
                            TrainManager.Trains[k].Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject], VisibleFromInterior[i]);
                        }
                        currentBogieObject++;
                        if (BogieObjects[currentBogieObject] != null)
                        {
                            TrainManager.Trains[k].Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject], VisibleFromInterior[i]);
                        }
                        currentBogieObject++;
                    }
                }
                // place cars
                TrainManager.Trains[k].PlaceCars(0.0);

                // configure other properties
                if (TrainManager.Trains[k].IsPlayerTrain)
                {
                    TrainManager.Trains[k].TimetableDelta = 0.0;
                    if (Game.InitialReversedConsist)
                    {
                        TrainManager.Trains[k].Reverse();
                        TrainManager.PlayerTrain.CameraCar         = TrainManager.Trains[k].DriverCar;
                        Program.Renderer.Camera.CurrentRestriction = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].CameraRestrictionMode;
                    }
                }
                else if (TrainManager.Trains[k].State != TrainState.Bogus)
                {
                    TrainManager.Trains[k].AI                  = new Game.SimpleHumanDriverAI(TrainManager.Trains[k], Interface.CurrentOptions.PrecedingTrainSpeedLimit);
                    TrainManager.Trains[k].TimetableDelta      = Program.CurrentRoute.PrecedingTrainTimeDeltas[k];
                    TrainManager.Trains[k].Specs.DoorOpenMode  = DoorMode.Manual;
                    TrainManager.Trains[k].Specs.DoorCloseMode = DoorMode.Manual;
                }
            }

            /*
             * HACK: Store the TrainManager.Trains reference in the RouteManager also
             *		 Note that this may change when the TrainManager is separated from the lump
             *       Remember not to modify via this ref
             */
            // ReSharper disable once CoVariantArrayConversion
            Program.CurrentRoute.Trains = TrainManager.Trains;
            TrainProgress = 1.0;
            // finished created objects
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Array.Resize(ref ObjectManager.AnimatedWorldObjects, ObjectManager.AnimatedWorldObjectsUsed);
            // update sections
            if (Program.CurrentRoute.Sections.Length > 0)
            {
                Program.CurrentRoute.UpdateAllSections();
            }
            // load plugin
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                if (TrainManager.Trains[i].State != TrainState.Bogus)
                {
                    if (TrainManager.Trains[i].IsPlayerTrain)
                    {
                        if (!TrainManager.Trains[i].LoadCustomPlugin(TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding))
                        {
                            TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder);
                        }
                    }
                    else
                    {
                        TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder);
                    }
                    for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++)
                    {
                        if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
                        {
                            ITrainInputDevice trainInputDevice = (ITrainInputDevice)InputDevicePlugin.AvailablePlugins[j];
                            trainInputDevice.SetVehicleSpecs(TrainManager.Trains[i].vehicleSpecs());
                        }
                    }
                }
            }
        }
コード例 #2
0
ファイル: Loading.cs プロジェクト: cwfitzgerald/OpenBVE
        private static void LoadEverythingThreaded()
        {
            Program.FileSystem.AppendToLogFile("Loading route file: " + CurrentRouteFile);
            Program.FileSystem.AppendToLogFile("INFO: Route file hash " + CsvRwRouteParser.GetChecksum(CurrentRouteFile));
            string RailwayFolder = GetRailwayFolder(CurrentRouteFile);
            string ObjectFolder  = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Object");
            string SoundFolder   = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Sound");

            Game.Reset(true, false);
            Game.MinimalisticSimulation = true;
            // screen
            Program.Renderer.Camera.CurrentMode = CameraViewMode.Interior;
            //First, check the format of the route file
            //RW routes were written for BVE1 / 2, and have a different command syntax
            bool IsRW = CsvRwRouteParser.isRWFile(CurrentRouteFile);

            Program.FileSystem.AppendToLogFile("Route file format is: " + (IsRW ? "RW" : "CSV"));
            CsvRwRouteParser.ParseRoute(CurrentRouteFile, IsRW, CurrentRouteEncoding, CurrentTrainFolder, ObjectFolder, SoundFolder, false);
            Thread createIllustrations = new Thread(Game.RouteInformation.LoadInformation)
            {
                IsBackground = true
            };

            createIllustrations.Start();
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Program.CurrentRoute.Atmosphere.CalculateSeaLevelConstants();
            if (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
            {
                double t = Program.CurrentRoute.BogusPreTrainInstructions[0].Time;
                double p = Program.CurrentRoute.BogusPreTrainInstructions[0].TrackPosition;
                for (int i = 1; i < Program.CurrentRoute.BogusPreTrainInstructions.Length; i++)
                {
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].Time > t)
                    {
                        t = Program.CurrentRoute.BogusPreTrainInstructions[i].Time;
                    }
                    else
                    {
                        t += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].Time = t;
                    }
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition > p)
                    {
                        p = Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition;
                    }
                    else
                    {
                        p += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition = p;
                    }
                }
            }
            World.CameraTrackFollower = new TrackFollower(Program.CurrentHost)
            {
                Train = null, Car = null
            };
            if (Program.CurrentRoute.Stations.Length == 1)
            {
                //Log the fact that only a single station is present, as this is probably not right
                Program.FileSystem.AppendToLogFile("The processed route file only contains a single station.");
            }
            Program.FileSystem.AppendToLogFile("Route file loaded successfully.");
            RouteProgress = 1.0;
            // initialize trains
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            TrainManager.Trains = new TrainManager.Train[Game.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                if (k == TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
                {
                    TrainManager.Trains[k] = new TrainManager.Train(TrainState.Bogus);
                }
                else
                {
                    TrainManager.Trains[k] = new TrainManager.Train(TrainState.Pending);
                }
            }
            TrainManager.PlayerTrain = TrainManager.Trains[Game.PrecedingTrainTimeDeltas.Length];

            UnifiedObject[] CarObjects     = null;
            UnifiedObject[] BogieObjects   = null;
            UnifiedObject[] CouplerObjects = null;

            // load trains
            double TrainProgressMaximum = 0.7 + 0.3 * (double)TrainManager.Trains.Length;

            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                //Sleep for 20ms to allow route loading locks to release
                Thread.Sleep(20);
                if (TrainManager.Trains[k].State == TrainState.Bogus)
                {
                    // bogus train
                    string TrainData = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility", "PreTrain"), "train.dat");
                    TrainDatParser.ParseTrainData(TrainData, System.Text.Encoding.UTF8, TrainManager.Trains[k]);
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainManager.Trains[k].InitializeCarSounds();
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.3 / TrainProgressMaximum;
                    TrainProgressCurrentSum   += TrainProgressCurrentWeight;
                }
                else
                {
                    TrainManager.Trains[k].TrainFolder = CurrentTrainFolder;
                    // real train
                    if (TrainManager.Trains[k].IsPlayerTrain)
                    {
                        Program.FileSystem.AppendToLogFile("Loading player train: " + TrainManager.Trains[k].TrainFolder);
                    }
                    else
                    {
                        Program.FileSystem.AppendToLogFile("Loading AI train: " + TrainManager.Trains[k].TrainFolder);
                    }
                    TrainProgressCurrentWeight = 0.1 / TrainProgressMaximum;
                    string TrainData = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.dat");
                    TrainDatParser.ParseTrainData(TrainData, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.2 / TrainProgressMaximum;
                    SoundCfgParser.ParseSoundConfig(TrainManager.Trains[k].TrainFolder, 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].Doors[0].OpenSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration;
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 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].Doors[0].CloseSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration;
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8;
                            }
                            else
                            {
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = 0.8;
                            }
                        }
                        const double f = 0.015;
                        const double g = 2.75;
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                        TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.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;
                    }
                }
                // add panel section
                if (TrainManager.Trains[k].IsPlayerTrain)
                {
                    TrainProgressCurrentWeight = 0.7 / TrainProgressMaximum;
                    TrainManager.ParsePanelConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    Program.FileSystem.AppendToLogFile("Train panel loaded sucessfully.");
                }
                // add exterior section
                if (TrainManager.Trains[k].State != TrainState.Bogus)
                {
                    bool LoadObjects = false;
                    if (CarObjects == null)
                    {
                        CarObjects     = new UnifiedObject[TrainManager.Trains[k].Cars.Length];
                        BogieObjects   = new UnifiedObject[TrainManager.Trains[k].Cars.Length * 2];
                        CouplerObjects = new UnifiedObject[TrainManager.Trains[k].Cars.Length];
                        LoadObjects    = true;
                    }
                    string tXml = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.xml");
                    if (System.IO.File.Exists(tXml))
                    {
                        TrainXmlParser.Parse(tXml, TrainManager.Trains[k], ref CarObjects, ref BogieObjects, ref CouplerObjects);
                    }
                    else
                    {
                        ExtensionsCfgParser.ParseExtensionsConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, ref CarObjects, ref BogieObjects, ref CouplerObjects, TrainManager.Trains[k], LoadObjects);
                    }
                    World.CameraCar = TrainManager.Trains[k].DriverCar;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    //Stores the current array index of the bogie object to add
                    //Required as there are two bogies per car, and we're using a simple linear array....
                    int currentBogieObject = 0;
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        if (CarObjects[i] == null)
                        {
                            // load default exterior object
                            string       file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                            StaticObject so   = ObjectManager.LoadStaticObject(file, System.Text.Encoding.UTF8, 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;
                                so.ApplyScale(sx, sy, sz);
                                CarObjects[i] = so;
                            }
                        }
                        if (CarObjects[i] != null)
                        {
                            // add object
                            TrainManager.Trains[k].Cars[i].LoadCarSections(CarObjects[i]);
                        }

                        if (CouplerObjects[i] != null)
                        {
                            TrainManager.Trains[k].Cars[i].Coupler.LoadCarSections(CouplerObjects[i]);
                        }
                        //Load bogie objects
                        if (BogieObjects[currentBogieObject] != null)
                        {
                            TrainManager.Trains[k].Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject]);
                        }
                        currentBogieObject++;
                        if (BogieObjects[currentBogieObject] != null)
                        {
                            TrainManager.Trains[k].Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject]);
                        }
                        currentBogieObject++;
                    }
                }
                // place cars
                TrainManager.Trains[k].PlaceCars(0.0);

                // configure other properties
                if (TrainManager.Trains[k].IsPlayerTrain)
                {
                    TrainManager.Trains[k].TimetableDelta = 0.0;
                    if (Game.InitialReversedConsist)
                    {
                        TrainManager.Trains[k].Reverse();
                        World.CameraCar = TrainManager.Trains[k].DriverCar;
                        Program.Renderer.Camera.CurrentRestriction = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].CameraRestrictionMode;
                    }
                }
                else if (TrainManager.Trains[k].State != 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;
                }
            }

            /*
             * HACK: Store the TrainManager.Trains reference in the RouteManager also
             *		 Note that this may change when the TrainManager is separated from the lump
             *       Remember not to modify via this ref
             */
            // ReSharper disable once CoVariantArrayConversion
            Program.CurrentRoute.Trains = TrainManager.Trains;
            TrainProgress = 1.0;
            // finished created objects
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Array.Resize(ref ObjectManager.AnimatedWorldObjects, ObjectManager.AnimatedWorldObjectsUsed);
            // update sections
            if (Program.CurrentRoute.Sections.Length > 0)
            {
                Program.CurrentRoute.UpdateAllSections();
            }
            // load plugin
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                if (TrainManager.Trains[i].State != TrainState.Bogus)
                {
                    if (TrainManager.Trains[i].IsPlayerTrain)
                    {
                        if (!TrainManager.Trains[i].LoadCustomPlugin(TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding))
                        {
                            TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder);
                        }
                    }
                    else
                    {
                        TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder);
                    }
                }
            }
        }
コード例 #3
0
        /// <summary>Parses a base track following object node</summary>
        /// <param name="ObjectPath">Absolute path to the object folder of route data</param>
        /// <param name="FileName">The filename of the containing XML file</param>
        /// <param name="SectionElement">The XElement to parse</param>
        /// <param name="Train">The track following object to parse this node into</param>
        private static void ParseTrackFollowingObjectNode(string ObjectPath, string FileName, XElement SectionElement, TrainManager.TrackFollowingObject Train)
        {
            string Section = SectionElement.Name.LocalName;

            string TrainDirectory       = string.Empty;
            bool   ConsistReversed      = false;
            List <Game.TravelData> Data = new List <Game.TravelData>();

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

                switch (Key.ToLowerInvariant())
                {
                case "definition":
                    ParseDefinitionNode(FileName, KeyNode, Train);
                    break;

                case "train":
                    ParseTrainNode(ObjectPath, FileName, KeyNode, ref TrainDirectory, ref ConsistReversed);
                    break;

                case "points":
                case "stops":
                    ParseTravelDataNodes(FileName, KeyNode, Data);
                    break;

                default:
                    Interface.AddMessage(MessageType.Warning, false, $"Unsupported key {Key} encountered in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    break;
                }
            }

            if (Data.Count < 2)
            {
                Interface.AddMessage(MessageType.Error, false, $"There must be at least two points to go through in {FileName}");
                return;
            }

            if (!(Data.First() is Game.TravelStopData) || !(Data.Last() is Game.TravelStopData))
            {
                Interface.AddMessage(MessageType.Error, false, $"The first and the last point to go through must be the \"Stop\" node in {FileName}");
                return;
            }

            if (string.IsNullOrEmpty(TrainDirectory))
            {
                Interface.AddMessage(MessageType.Error, false, $"No train has been specified in {FileName}");
                return;
            }

            /*
             * First check for a train.ai file- Functionally identical, but allows for differently configured AI
             * trains not to show up as drivable
             */
            string TrainData = OpenBveApi.Path.CombineFile(TrainDirectory, "train.ai");

            if (!File.Exists(TrainData))
            {
                // Check for the standard drivable train.dat
                TrainData = OpenBveApi.Path.CombineFile(TrainDirectory, "train.dat");
            }
            string ExteriorFile = OpenBveApi.Path.CombineFile(TrainDirectory, "extensions.cfg");

            if (!File.Exists(TrainData) || !File.Exists(ExteriorFile))
            {
                Interface.AddMessage(MessageType.Error, true, $"The supplied train folder in TrackFollowingObject {FileName} did not contain a complete set of data.");
                return;
            }
            TrainDatParser.ParseTrainData(TrainData, TextEncoding.GetSystemEncodingFromFile(TrainData), Train);
            SoundCfgParser.ParseSoundConfig(TrainDirectory, Train);
            Train.AI = new Game.TrackFollowingObjectAI(Train, Data.ToArray());

            UnifiedObject[] CarObjects          = new UnifiedObject[Train.Cars.Length];
            UnifiedObject[] BogieObjects        = new UnifiedObject[Train.Cars.Length * 2];
            UnifiedObject[] CouplerObjects      = new UnifiedObject[Train.Cars.Length - 1];
            bool[]          VisibleFromInterior = new bool[Train.Cars.Length];
            ExtensionsCfgParser.ParseExtensionsConfig(System.IO.Path.GetDirectoryName(ExteriorFile), TextEncoding.GetSystemEncodingFromFile(ExteriorFile), ref CarObjects, ref BogieObjects, ref CouplerObjects, ref VisibleFromInterior, Train, true);

            int currentBogieObject = 0;

            for (int i = 0; i < Train.Cars.Length; i++)
            {
                if (CarObjects[i] == null)
                {
                    // load default exterior object
                    string       file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                    StaticObject so;
                    Program.CurrentHost.LoadStaticObject(file, Encoding.UTF8, false, out so);
                    if (so == null)
                    {
                        CarObjects[i] = null;
                    }
                    else
                    {
                        double sx = Train.Cars[i].Width;
                        double sy = Train.Cars[i].Height;
                        double sz = Train.Cars[i].Length;
                        so.ApplyScale(sx, sy, sz);
                        CarObjects[i] = so;
                    }
                }
                if (CarObjects[i] != null)
                {
                    // add object
                    Train.Cars[i].LoadCarSections(CarObjects[i], false);
                }

                //Load bogie objects
                if (BogieObjects[currentBogieObject] != null)
                {
                    Train.Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject], false);
                }
                currentBogieObject++;
                if (BogieObjects[currentBogieObject] != null)
                {
                    Train.Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject], false);
                }
                currentBogieObject++;
            }

            // door open/close speed
            foreach (var Car in Train.Cars)
            {
                if (Car.Specs.DoorOpenFrequency <= 0.0)
                {
                    if (Car.Doors[0].OpenSound.Buffer != null & Car.Doors[1].OpenSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        Program.Sounds.LoadBuffer(Car.Doors[1].OpenSound.Buffer);
                        double a = Car.Doors[0].OpenSound.Buffer.Duration;
                        double b = Car.Doors[1].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                    }
                    else if (Car.Doors[0].OpenSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        double a = Car.Doors[0].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                    }
                    else if (Car.Doors[1].OpenSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        double b = Car.Doors[1].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 0.8;
                    }
                    else
                    {
                        Car.Specs.DoorOpenFrequency = 0.8;
                    }
                }
                if (Car.Specs.DoorCloseFrequency <= 0.0)
                {
                    if (Car.Doors[0].CloseSound.Buffer != null & Car.Doors[1].CloseSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        Program.Sounds.LoadBuffer(Car.Doors[1].CloseSound.Buffer);
                        double a = Car.Doors[0].CloseSound.Buffer.Duration;
                        double b = Car.Doors[1].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                    }
                    else if (Car.Doors[0].CloseSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        double a = Car.Doors[0].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8;
                    }
                    else if (Car.Doors[1].CloseSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        double b = Car.Doors[1].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8;
                    }
                    else
                    {
                        Car.Specs.DoorCloseFrequency = 0.8;
                    }
                }
                const double f = 0.015;
                const double g = 2.75;
                Car.Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                Car.Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                Car.Specs.DoorOpenFrequency  /= Car.Specs.DoorOpenPitch;
                Car.Specs.DoorCloseFrequency /= Car.Specs.DoorClosePitch;

                /*
                 * Remove the following two lines, then the pitch at which doors play
                 * takes their randomized opening and closing times into account.
                 * */
                Car.Specs.DoorOpenPitch  = 1.0;
                Car.Specs.DoorClosePitch = 1.0;
            }

            foreach (var Car in Train.Cars)
            {
                Car.FrontAxle.Follower.TrackIndex            = Data[0].RailIndex;
                Car.RearAxle.Follower.TrackIndex             = Data[0].RailIndex;
                Car.FrontBogie.FrontAxle.Follower.TrackIndex = Data[0].RailIndex;
                Car.FrontBogie.RearAxle.Follower.TrackIndex  = Data[0].RailIndex;
                Car.RearBogie.FrontAxle.Follower.TrackIndex  = Data[0].RailIndex;
                Car.RearBogie.RearAxle.Follower.TrackIndex   = Data[0].RailIndex;
            }

            if (ConsistReversed)
            {
                Train.Reverse();
            }
            Train.PlaceCars(Data[0].Position);
        }
コード例 #4
0
        /// <summary>Parses a base track following object node</summary>
        /// <param name="Element">The XElement to parse</param>
        /// <param name="FileName">The filename of the containing XML file</param>
        /// <param name="Path">The path of the containing XML file</param>
        /// <param name="Train">The track following object to parse this node into</param>
        private static void ParseTrackFollowingObjectNode(XElement Element, string FileName, string Path, TrainManager.TrackFollowingObject Train)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string TrainDirectory       = string.Empty;
            List <Game.TravelData> Data = new List <Game.TravelData>();

            foreach (XElement SectionElement in Element.Elements())
            {
                string Section = SectionElement.Name.LocalName;

                switch (SectionElement.Name.LocalName.ToLowerInvariant())
                {
                case "stops":
                    ParseStopNode(SectionElement, FileName, Data);
                    break;

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

                        switch (Key.ToLowerInvariant())
                        {
                        case "directory":
                        {
                            string trainDirectory = OpenBveApi.Path.CombineDirectory(Path, Value);
                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                trainDirectory = OpenBveApi.Path.CombineFile(Program.FileSystem.InitialTrainFolder, Value);
                            }
                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                trainDirectory = OpenBveApi.Path.CombineFile(Program.FileSystem.TrainInstallationDirectory, Value);
                            }

                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Directory was not found in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            else
                            {
                                TrainDirectory = trainDirectory;
                            }
                        }
                        break;
                        }
                    }
                    break;

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

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

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

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

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

            if (!Data.Any() || string.IsNullOrEmpty(TrainDirectory))
            {
                return;
            }

            // Initial setting
            string TrainData    = OpenBveApi.Path.CombineFile(TrainDirectory, "train.dat");
            string ExteriorFile = OpenBveApi.Path.CombineFile(TrainDirectory, "extensions.cfg");

            if (!System.IO.File.Exists(TrainData) || !System.IO.File.Exists(ExteriorFile))
            {
                Interface.AddMessage(MessageType.Error, true, "The supplied train folder in TrackFollowingObject " + FileName + " did not contain a complete set of data.");
                return;
            }
            TrainDatParser.ParseTrainData(TrainData, TextEncoding.GetSystemEncodingFromFile(TrainData), Train);
            SoundCfgParser.ParseSoundConfig(TrainDirectory, Encoding.UTF8, Train);
            Train.AI = new Game.TrackFollowingObjectAI(Train, Data);

            UnifiedObject[] CarObjects   = new UnifiedObject[Train.Cars.Length];
            UnifiedObject[] BogieObjects = new UnifiedObject[Train.Cars.Length * 2];

            ExtensionsCfgParser.ParseExtensionsConfig(System.IO.Path.GetDirectoryName(ExteriorFile), TextEncoding.GetSystemEncodingFromFile(ExteriorFile), ref CarObjects, ref BogieObjects, Train, true);

            int currentBogieObject = 0;

            for (int i = 0; i < Train.Cars.Length; i++)
            {
                if (CarObjects[i] == null)
                {
                    // load default exterior object
                    string file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                    ObjectManager.StaticObject so = ObjectManager.LoadStaticObject(file, System.Text.Encoding.UTF8, false, false, false);
                    if (so == null)
                    {
                        CarObjects[i] = null;
                    }
                    else
                    {
                        double sx = Train.Cars[i].Width;
                        double sy = Train.Cars[i].Height;
                        double sz = Train.Cars[i].Length;
                        so.ApplyScale(sx, sy, sz);
                        CarObjects[i] = so;
                    }
                }
                if (CarObjects[i] != null)
                {
                    // add object
                    Train.Cars[i].LoadCarSections(CarObjects[i]);
                }

                //Load bogie objects
                if (BogieObjects[currentBogieObject] != null)
                {
                    Train.Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject]);
                }
                currentBogieObject++;
                if (BogieObjects[currentBogieObject] != null)
                {
                    Train.Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject]);
                }
                currentBogieObject++;
            }

            // door open/close speed
            foreach (var Car in Train.Cars)
            {
                if (Car.Specs.DoorOpenFrequency <= 0.0)
                {
                    if (Car.Doors[0].OpenSound.Buffer != null & Car.Doors[1].OpenSound.Buffer != null)
                    {
                        Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        Sounds.LoadBuffer(Car.Doors[1].OpenSound.Buffer);
                        double a = Car.Doors[0].OpenSound.Buffer.Duration;
                        double b = Car.Doors[1].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                    }
                    else if (Car.Doors[0].OpenSound.Buffer != null)
                    {
                        Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        double a = Car.Doors[0].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                    }
                    else if (Car.Doors[1].OpenSound.Buffer != null)
                    {
                        Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        double b = Car.Doors[1].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 0.8;
                    }
                    else
                    {
                        Car.Specs.DoorOpenFrequency = 0.8;
                    }
                }
                if (Car.Specs.DoorCloseFrequency <= 0.0)
                {
                    if (Car.Doors[0].CloseSound.Buffer != null & Car.Doors[1].CloseSound.Buffer != null)
                    {
                        Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        Sounds.LoadBuffer(Car.Doors[1].CloseSound.Buffer);
                        double a = Car.Doors[0].CloseSound.Buffer.Duration;
                        double b = Car.Doors[1].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                    }
                    else if (Car.Doors[0].CloseSound.Buffer != null)
                    {
                        Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        double a = Car.Doors[0].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8;
                    }
                    else if (Car.Doors[1].CloseSound.Buffer != null)
                    {
                        Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        double b = Car.Doors[1].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8;
                    }
                    else
                    {
                        Car.Specs.DoorCloseFrequency = 0.8;
                    }
                }
                const double f = 0.015;
                const double g = 2.75;
                Car.Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                Car.Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                Car.Specs.DoorOpenFrequency  /= Car.Specs.DoorOpenPitch;
                Car.Specs.DoorCloseFrequency /= Car.Specs.DoorClosePitch;

                /*
                 * Remove the following two lines, then the pitch at which doors play
                 * takes their randomized opening and closing times into account.
                 * */
                Car.Specs.DoorOpenPitch  = 1.0;
                Car.Specs.DoorClosePitch = 1.0;
            }

            foreach (var Car in Train.Cars)
            {
                Car.FrontAxle.Follower.TrackIndex            = Data[0].RailIndex;
                Car.RearAxle.Follower.TrackIndex             = Data[0].RailIndex;
                Car.FrontBogie.FrontAxle.Follower.TrackIndex = Data[0].RailIndex;
                Car.FrontBogie.RearAxle.Follower.TrackIndex  = Data[0].RailIndex;
                Car.RearBogie.FrontAxle.Follower.TrackIndex  = Data[0].RailIndex;
                Car.RearBogie.RearAxle.Follower.TrackIndex   = Data[0].RailIndex;
            }

            Train.PlaceCars(Data[0].StopPosition);
        }
コード例 #5
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.
             * */
        }