예제 #1
0
        /// <summary>
        /// Write the path to file. This will need to confirm to the MSTS definition for .pat files.
        /// </summary>
        /// <param name="trainpath">The path itself, that needs to be written</param>
        public static void WritePatFile(Trainpath trainpath)
        {
            if (trainpath == null)
            {
                return;
            }

            if (trainpath.IsBroken)
            {
                InformUserPathIsBroken();
                //return;
            }

            if (trainpath.FirstNode == null)
            {
                DisplayNoPathAvailable();
                return;
            }

            if (UserCancelledBecauseOfUnfinishedPath(trainpath))
            {
                return;
            }

            if (GetFileName(trainpath))
            {
                CreatePDPsAndTrpathNodes(trainpath);
                WriteToFile(trainpath);
                trainpath.IsModified = false;
            }
        }
예제 #2
0
        static bool UserCancelledBecauseOfUnfinishedPath(Trainpath trainpath)
        {
            List <string> cancelReasons = new List <string>();

            if (!trainpath.HasEnd)
            {
                cancelReasons.Add(TrackViewer.catalog.GetString("* The path does not have a well-defined end-point"));
            }
            //if (trainpath.IsBroken) cancelReasons.Add(TrackViewer.catalog.GetString("* The path has broken nodes or links"));
            if (trainpath.FirstNodeOfTail != null)
            {
                cancelReasons.Add(TrackViewer.catalog.GetString("* The path has a stored and not-yet reconnected tail"));
            }

            if (cancelReasons.Count == 0)
            {
                return(false);
            }

            string message = TrackViewer.catalog.GetString("The current path is not finished:") + "\n";

            message += String.Join("\n", cancelReasons.ToArray());
            message += "\n" + TrackViewer.catalog.GetString("Do you want to continue?");

            DialogResult dialogResult = MessageBox.Show(message,
                                                        TrackViewer.catalog.GetString("Trackviewer Path Editor"), MessageBoxButtons.OKCancel, MessageBoxIcon.Question);

            return(dialogResult == DialogResult.Cancel);
        }
예제 #3
0
        /// <summary>
        /// Write the path to file. This will need to confirm to the MSTS definition for .pat files.
        /// The user will be prompted for the path and possibly other things just to make sure
        /// </summary>
        /// <param name="trainpath">The path itself, that needs to be written</param>
        public static void WritePatFile(Trainpath trainpath)
        {
            if (trainpath == null)
            {
                return;
            }

            if (trainpath.IsBroken)
            {
                InformUserPathIsBroken();
                //return;
            }

            if (trainpath.FirstNode == null)
            {
                DisplayNoPathAvailable();
                return;
            }

            if (UserCancelledBecauseOfUnfinishedPath(trainpath))
            {
                return;
            }

            if (GetFileName(trainpath))
            {
                WritePatFileDirect(trainpath);
            }
        }
예제 #4
0
        /// <summary>
        /// Actual output routine. Here also path properties like Name, Start, and End are added.
        /// </summary>
        /// <param name="trainpath">The path, needed for some properties</param>
        /// <remarks>Output will be in unicode, and also in US-EN</remarks>
        private static void WriteToFile(Trainpath trainpath)
        {
            System.IO.StreamWriter file = new System.IO.StreamWriter(fullFilePath, false, System.Text.Encoding.Unicode);
            file.WriteLine("SIMISA@@@@@@@@@@JINX0P0t______");
            file.WriteLine("");
            file.WriteLine("Serial ( 1 )");
            file.WriteLine("TrackPDPs (");
            foreach (string line in trackPDPs)
            {
                file.WriteLine(line);
            }
            file.WriteLine(")");
            file.WriteLine("TrackPath (");
            file.WriteLine("\tTrPathName ( \"" + trainpath.PathId + "\" )");

            // How to format hex? "{0:X8}" is not working for me. Neither is {0:X08}.
            // Fortunately, {0:X} will use 8 characters anyway. Maybe because it knows the length from the number of bits in the number
            string flagsString = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:X}", trainpath.PathFlags);

            file.WriteLine("\tTrPathFlags ( " + flagsString + " )");

            file.WriteLine("\tName ( \"" + trainpath.PathName + "\" )");
            file.WriteLine("\tTrPathStart ( \"" + trainpath.PathStart + "\" )");
            file.WriteLine("\tTrPathEnd ( \"" + trainpath.PathEnd + "\" )");
            file.Write("\tTrPathNodes ( ");
            file.WriteLine(trpathnodes.Count());
            foreach (string line in trpathnodes)
            {
                file.WriteLine(line);
            }
            file.WriteLine("\t)");
            file.WriteLine(")");
            file.Close();
        }
예제 #5
0
 /// <summary>
 /// Constructor. This will actually load the .pat from file and create menus as needed
 /// </summary>
 /// <param name="routeData">The route information that contains track data base and track section data</param>
 /// <param name="drawTrackDB">The drawn tracks to know about where the mouse is</param>
 /// <param name="path">Path to the .pat file</param>
 public PathEditor(RouteData routeData, DrawTrackDB drawTrackDB, ORTS.Menu.Path path)
     : this(routeData, drawTrackDB)
 {
     FileName         = path.FilePath.Split('\\').Last();
     CurrentTrainPath = new Trainpath(trackDB, tsectionDat, path.FilePath);
     EditingIsActive  = false;
     OnPathChanged();
 }
예제 #6
0
 /// <summary>
 /// Constructor. This will create a new empty path.
 /// </summary>
 /// <param name="routeData">The route information that contains track data base and track section data</param>
 /// <param name="drawTrackDB">The drawn tracks to know about where the mouse is</param>/// <param name="pathsDirectory">The directory where paths will be stored</param>
 public PathEditor(RouteData routeData, DrawTrackDB drawTrackDB, string pathsDirectory)
     : this(routeData, drawTrackDB)
 {
     CurrentTrainPath          = new Trainpath(trackDB, tsectionDat);
     FileName                  = CurrentTrainPath.PathId + ".pat";
     CurrentTrainPath.FilePath = System.IO.Path.Combine(pathsDirectory, FileName);
     EditingIsActive           = true;
     OnPathChanged();
 }
예제 #7
0
 /// <summary>
 /// Get the filename to save the path file from the user.
 /// </summary>
 /// <param name="trainpath">The current path to get the default file path and name</param>
 /// <returns>Boolean describing whether user wants to write to file or not.</returns>
 static bool GetFileName(Trainpath trainpath)
 {
     Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
     dlg.OverwritePrompt  = true;
     dlg.InitialDirectory = Path.GetDirectoryName(trainpath.FilePath);
     dlg.FileName         = trainpath.PathId;
     dlg.DefaultExt       = ".pat";
     dlg.Filter           = "PAT Files (.pat)|*.pat";
     if (dlg.ShowDialog() == true)
     {
         fullFilePath       = dlg.FileName;
         trainpath.FilePath = fullFilePath;
         return(true);
     }
     return(false);
 }
예제 #8
0
 /// <summary>
 /// Get the filename to save the path file from the user.
 /// </summary>
 /// <param name="trainpath">The current path to get the default file path and name</param>
 /// <returns>Boolean describing whether user wants to write to file or not.</returns>
 private static bool GetFileName(Trainpath trainpath)
 {
     Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog
     {
         OverwritePrompt  = true,
         InitialDirectory = Path.GetDirectoryName(trainpath.FilePath),
         FileName         = trainpath.PathId,
         DefaultExt       = ".pat",
         Filter           = "PAT Files (.pat)|*.pat"
     };
     if (dlg.ShowDialog() == true)
     {
         trainpath.FilePath = dlg.FileName;
         return(true);
     }
     return(false);
 }
예제 #9
0
        /// <summary>
        /// Run through all path nodes and create the trackPDPs and the trPathNodes
        /// </summary>
        /// <param name="trainpath">The path itself, that needs to be written</param>
        static void CreatePDPsAndTrpathNodes(Trainpath trainpath)
        {
            trackPDPs     = new List <string>();
            trpathnodes   = new List <string>();
            pdpOfJunction = new Dictionary <int, int>();

            uint          nextMainIndex   = 1;
            TrainpathNode currentMainNode = trainpath.FirstNode;

            while (currentMainNode.NextMainNode != null)
            {
                TrainpathNode nextMainNode = currentMainNode.NextMainNode;

                if (currentMainNode.NextSidingNode == null)
                {
                    AddNode(currentMainNode, nextMainIndex, nonext);
                }
                else
                {
                    // This is a siding start.
                    // We print, in this else statement, the siding start, and all extra siding nodes.
                    // But we also need to know, for the last siding node, the siding end index, which is on main track.

                    uint nextSidingIndex = nextMainIndex;

                    // Find the amount of extra nodes in the siding path.
                    // This can be 0 or more.
                    uint          extraSidingNodes  = 0;
                    TrainpathNode currentSidingNode = currentMainNode.NextSidingNode;
                    while (currentSidingNode.NextSidingNode != null)
                    {
                        extraSidingNodes++;
                        currentSidingNode = currentSidingNode.NextSidingNode;
                    }
                    nextMainIndex += extraSidingNodes;

                    // Find the number of main Nodes
                    TrainpathNode sidingEndNode  = currentSidingNode;
                    TrainpathNode tempMainNode   = currentMainNode.NextMainNode;
                    uint          extraMainNodes = 0;
                    while (tempMainNode != sidingEndNode)
                    {
                        extraMainNodes++;
                        tempMainNode = tempMainNode.NextMainNode; // It should exist, if not path editor itself is broken.
                    }


                    if (extraSidingNodes == 0)
                    {
                        // Apparently there are no extra nodes in the siding, it is a direct path
                        AddNode(currentMainNode, nextMainIndex, nextMainIndex + extraMainNodes);
                    }
                    else
                    {
                        // Write the siding start node
                        AddNode(currentMainNode, nextMainIndex, nextSidingIndex);

                        // Write the intermediate siding nodes, so neither the first nor the last
                        // For simple passing paths, there are no intermeidate siding nodes
                        currentSidingNode = currentMainNode.NextSidingNode;
                        while (currentSidingNode.NextSidingNode.NextSidingNode != null)
                        {
                            nextSidingIndex++;
                            AddNode(currentSidingNode, nonext, nextSidingIndex);
                            currentSidingNode = currentSidingNode.NextSidingNode;
                        }

                        // Write the final siding node, linking to main path again.
                        AddNode(currentSidingNode, nonext, nextMainIndex + extraMainNodes);
                    }
                }
                nextMainIndex++;
                currentMainNode = nextMainNode;
            }

            // final node
            AddNode(currentMainNode, nonext, nonext);
        }
예제 #10
0
 /// <summary>
 /// Write the path to file. This will need to confirm to the MSTS definition for .pat files.
 /// No additional user checks on filename, etc.
 /// </summary>
 /// <param name="trainpath">The path itself, that needs to be written</param>
 public static void WritePatFileDirect(Trainpath trainpath)
 {
     CreatePDPsAndTrpathNodes(trainpath);
     WriteToFile(trainpath);
     trainpath.IsModified = false;
 }
예제 #11
0
        /// <summary>
        /// Take a new path indicating a .pat file, load that path and make it into a tail.
        /// Then try to reconnect the tail. This will then extend the current path with the loaded path
        /// </summary>
        /// <param name="path">The path that needs to be loaded to act as an extension</param>
        public void ExtendWithPath(ORTS.Menu.Path path)
        {
            //If everything works as expected, up to three steps are taken that can all be 'Undo'ne:
            // * Remove End
            // * Add tail
            // * Reconnect tail

            FileName = path.FilePath.Split('\\').Last();
            Trainpath newPath = new Trainpath(trackDB, tsectionDat, path.FilePath);

            // We have a current path and a new path.
            // First check if the new path is usable
            TrainpathNode newStart = newPath.FirstNode;

            if (newPath.FirstNode == null || newPath.FirstNode.NextMainNode == null)
            {
                MessageBox.Show(TrackViewer.catalog.GetString("The selected path contains no or only 1 node. The current path was not extended."));
                return;
            }

            TrainpathNode lastNode = CurrentTrainPath.FirstNode;

            while (lastNode.NextMainNode != null)
            {
                lastNode = lastNode.NextMainNode;
            }
            if (CurrentTrainPath.HasEnd)
            {
                //We need to remove the end and remember the node for reconnection.
                //If the end node and the firstnode of the new path are very close together we must make
                //sure that the junctionnode that will added to replace the end node is not past the firstnode.
                TrainpathNode endNode = lastNode;
                lastNode = endNode.PrevNode;

                EditorActionRemoveEnd actionRemove = new EditorActionRemoveEnd();
                bool endCanBeRemoved = actionRemove.MenuState(CurrentTrainPath, endNode, null, UpdateAfterEdits, 0, 0);
                if (endCanBeRemoved)
                {
                    //This should always be possible, but we should call MenuState anyway because of some initialization it might be doing
                    actionRemove.DoAction();
                    CurrentTrainPath.HasEnd = false;
                }
            }

            //Add the tail
            // The new path contains a startNode that we no longer need, so the tail connects to the next node
            CurrentTrainPath.StoreCurrentPath();
            CurrentTrainPath.FirstNodeOfTail = newPath.FirstNode.NextMainNode;
            CurrentTrainPath.TailHasEnd      = newPath.HasEnd;

            //Now we try to reconnect the tail automatically
            EditorActionAutoConnectTail action = new EditorActionAutoConnectTail();
            bool actionCanBeExecuted           = action.MenuState(CurrentTrainPath, lastNode, null, UpdateAfterEdits, 0, 0);

            if (actionCanBeExecuted)
            {
                action.DoAction();
                MessageBox.Show(TrackViewer.catalog.GetString("The selected path has been added as tail and then reconnected."));
            }
            else
            {
                MessageBox.Show(TrackViewer.catalog.GetString("The selected path has been added as tail. It was not possible to reconnect automatically."));
            }

            //Make sure all of the path is drawn, so that also the tail is visible
            ExtendPathFull();
        }