Example #1
0
		/********************
			PUBLIC METHODS
		*********************/
		//
		// PROCESS COMMAND
		//
		/// <summary>Processes commands.</summary>
		/// <returns><c>true</c>, if command was processed, <c>false</c> otherwise.</returns>
		/// <param name="command">The Interface.Command command to process.</param>
		internal bool ProcessCommand(Interface.Command command)
		{
			if (command != Interface.Command.RouteInformation)	// only accept RouteInformation command
				return false;
			// cycle through available state
			setState( (state)((int)(currentState + 1) % (int)state.numOf) );
			return true;
		}
Example #2
0
		/// <summary>Adds a message to the in-game interface render queue</summary>
		/// <param name="Text">The text of the message</param>
		/// <param name="Depencency"></param>
		/// <param name="Mode"></param>
		/// <param name="Color">The color of the message text</param>
		/// <param name="Timeout">The time this message will display for</param>
		internal static void AddMessage(string Text, MessageDependency Depencency, Interface.GameMode Mode, MessageColor Color, double Timeout)
		{
			if (Interface.CurrentOptions.GameMode <= Mode)
			{
				if (Depencency == MessageDependency.RouteLimit | Depencency == MessageDependency.SectionLimit)
				{
					for (int i = 0; i < Messages.Length; i++)
					{
						if (Messages[i].Depencency == Depencency) return;
					}
				}
				int n = Messages.Length;
				Array.Resize<Message>(ref Messages, n + 1);
				Messages[n].InternalText = Text;
				Messages[n].DisplayText = "";
				Messages[n].Depencency = Depencency;
				Messages[n].Timeout = Timeout;
				Messages[n].Color = Color;
				Messages[n].RendererPosition = new Vector2(0.0, 0.0);
				Messages[n].RendererAlpha = 0.0;
			}
		}
Example #3
0
        private static void LoadMaterials(string FileName, ref Material[] Materials)
        {
            string[] Lines = File.ReadAllLines(FileName);
            Material mm    = new Material();
            bool     fm    = false;

            //Preprocess
            for (int i = 0; i < Lines.Length; i++)
            {
                // Strip hash comments
                int c = Lines[i].IndexOf("#", StringComparison.Ordinal);
                if (c >= 0)
                {
                    Lines[i] = Lines[i].Substring(0, c);
                }
                // collect arguments
                List <string> Arguments = new List <string>(Lines[i].Split(new char[] { ' ', '\t' }, StringSplitOptions.None));
                for (int j = Arguments.Count - 1; j >= 0; j--)
                {
                    Arguments[j] = Arguments[j].Trim();
                    if (Arguments[j] == string.Empty)
                    {
                        Arguments.RemoveAt(j);
                    }
                }
                if (Arguments.Count == 0)
                {
                    continue;
                }

                switch (Arguments[0].ToLowerInvariant())
                {
                case "newmtl":
                    if (fm == true)
                    {
                        Array.Resize(ref Materials, Materials.Length + 1);
                        Materials[Materials.Length - 1] = mm;
                    }
                    mm     = new Material();
                    mm.Key = Arguments[1];
                    fm     = true;
                    break;

                case "ka":
                    //Ambient color not supported
                    break;

                case "kd":
                    //Equivilant to SetColor
                    double r = 1, g = 1, b = 1;
                    if (Arguments.Count >= 2 && !double.TryParse(Arguments[1], out r))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Ambient Color R in Material Definition for " + mm.Key);
                    }
                    if (Arguments.Count >= 3 && !double.TryParse(Arguments[2], out g))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Ambient Color G in Material Definition for " + mm.Key);
                    }
                    if (Arguments.Count >= 4 && !double.TryParse(Arguments[3], out b))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Ambient Color B in Material Definition for " + mm.Key);
                    }
                    r        = 255 * r;
                    g        = 255 * g;
                    b        = 255 * b;
                    mm.Color = new Color32((byte)r, (byte)g, (byte)b);
                    break;

                case "ks":
                    //Specular color not supported
                    break;

                case "ke":
                    //Emissive color not supported
                    break;

                case "d":
                    //Sets the alpha value for the face
                    double a = 1;
                    if (Arguments.Count >= 2 && !double.TryParse(Arguments[1], out a))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Alpha in Material Definition for " + mm.Key);
                    }
                    mm.Color.A = (byte)((1 - a) * 255);
                    break;

                case "map_kd":
                case "map_ka":
                    string tday = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[Arguments.Count - 1]);
                    if (File.Exists(tday))
                    {
                        mm.DaytimeTexture = tday;
                    }
                    else
                    {
                        Interface.AddMessage(MessageType.Error, true, "Material texture file " + Arguments[Arguments.Count - 1] + " was not found.");
                    }
                    break;

                case "map_ke":
                    //Emissive color map not supported
                    break;

                case "illum":
                    //Illumination mode not supported
                    break;
                }
            }
            Array.Resize(ref Materials, Materials.Length + 1);
            Materials[Materials.Length - 1] = mm;
        }
Example #4
0
        private void CloseButton_Click(object sender, EventArgs e)
        {
            InterpolationMode previousInterpolationMode = Interface.CurrentOptions.Interpolation;
            int previousAntialasingLevel = Interface.CurrentOptions.AntiAliasingLevel;
            int previousAnsiotropicLevel = Interface.CurrentOptions.AnisotropicFilteringLevel;

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

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

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

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

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

            case 5:
                Interface.CurrentOptions.Interpolation = OpenBveApi.Graphics.InterpolationMode.AnisotropicFiltering;
                break;
            }

            //Ansiotropic filtering level
            Interface.CurrentOptions.AnisotropicFilteringLevel = (int)AnsiotropicLevel.Value;
            //Antialiasing level
            Interface.CurrentOptions.AntiAliasingLevel = (int)AntialiasingLevel.Value;
            if (Interface.CurrentOptions.AntiAliasingLevel != previousAntialasingLevel)
            {
                Program.currentGraphicsMode = new GraphicsMode(new ColorFormat(8, 8, 8, 8), 24, 8, Interface.CurrentOptions.AntiAliasingLevel);
            }

            //Transparency quality
            switch (TransparencyQuality.SelectedIndex)
            {
            case 0:
                Interface.CurrentOptions.TransparencyMode = TransparencyMode.Performance;
                break;

            default:
                Interface.CurrentOptions.TransparencyMode = TransparencyMode.Quality;
                break;
            }

            //Set width and height
            if (Program.Renderer.Screen.Width != width.Value || Program.Renderer.Screen.Height != height.Value)
            {
                if (width.Value >= 300)
                {
                    Program.Renderer.Screen.Width   = (int)width.Value;
                    Program.currentGameWindow.Width = (int)width.Value;
                }

                if (height.Value >= 300)
                {
                    Program.Renderer.Screen.Height   = (int)height.Value;
                    Program.currentGameWindow.Height = (int)height.Value;
                }

                Program.Renderer.UpdateViewport();
            }

            //Check if interpolation mode or ansiotropic filtering level has changed, and trigger a reload
            if (previousInterpolationMode != Interface.CurrentOptions.Interpolation || previousAnsiotropicLevel != Interface.CurrentOptions.AnisotropicFilteringLevel)
            {
                Program.LightingRelative = -1.0;
                Game.Reset();
                for (int i = 0; i < Program.Files.Length; i++)
                {
                    try
                    {
                        UnifiedObject o;
                        Program.CurrentHost.LoadObject(Program.Files[i], System.Text.Encoding.UTF8, out o);
                        o.CreateObject(Vector3.Zero, 0.0, 0.0, 0.0);
                    }
                    catch (Exception ex)
                    {
                        Interface.AddMessage(MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Program.Files[i] + ".");
                    }
                }

                Program.Renderer.InitializeVisibility();
                Program.Renderer.UpdateVisibility(0.0, true);
                ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
            }

            Interface.CurrentOptions.CurrentXParser   = (XParsers)comboBoxNewXParser.SelectedIndex;
            Interface.CurrentOptions.CurrentObjParser = (ObjParsers)comboBoxNewObjParser.SelectedIndex;
            for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
            {
                if (Program.CurrentHost.Plugins[i].Object != null)
                {
                    Program.CurrentHost.Plugins[i].Object.SetObjectParser(Interface.CurrentOptions.CurrentXParser);
                    Program.CurrentHost.Plugins[i].Object.SetObjectParser(Interface.CurrentOptions.CurrentObjParser);
                }
            }

            if (checkBoxOptimizeObjects.Checked)
            {
                Interface.CurrentOptions.ObjectOptimizationBasicThreshold = 1000;
                Interface.CurrentOptions.ObjectOptimizationFullThreshold  = 250;
            }
            else
            {
                Interface.CurrentOptions.ObjectOptimizationBasicThreshold = 0;
                Interface.CurrentOptions.ObjectOptimizationFullThreshold  = 0;
            }
            Options.SaveOptions();
            this.Close();
        }
Example #5
0
        /// <summary>Loads a custom plugin for the specified train.</summary>
        /// <param name="train">The train to attach the plugin to.</param>
        /// <param name="trainFolder">The absolute path to the train folder.</param>
        /// <param name="encoding">The encoding to be used.</param>
        /// <returns>Whether the plugin was loaded successfully.</returns>
        internal static bool LoadCustomPlugin(TrainManager.Train train, string trainFolder, System.Text.Encoding encoding)
        {
            string config = OpenBveApi.Path.CombineFile(trainFolder, "ats.cfg");

            if (!System.IO.File.Exists(config))
            {
                return(false);
            }
            string Text = System.IO.File.ReadAllText(config, encoding);

            Text = Text.Replace("\r", "").Replace("\n", "");
            string file;

            try
            {
                file = OpenBveApi.Path.CombineFile(trainFolder, Text);
            }
            catch
            {
                Interface.AddMessage(MessageType.Error, true, "The train plugin path was malformed in " + config);
                return(false);
            }
            string title = System.IO.Path.GetFileName(file);

            if (!System.IO.File.Exists(file))
            {
                if (Text.EndsWith(".dll") && encoding.Equals(System.Text.Encoding.Unicode))
                {
                    // Our filename ends with .dll so probably is not mangled Unicode
                    Interface.AddMessage(MessageType.Error, true, "The train plugin " + title + " could not be found in " + config);
                    return(false);
                }
                // Try again with ASCII encoding
                Text = System.IO.File.ReadAllText(config, System.Text.Encoding.GetEncoding(1252));
                Text = Text.Replace("\r", "").Replace("\n", "");
                try
                {
                    file = OpenBveApi.Path.CombineFile(trainFolder, Text);
                }
                catch
                {
                    Interface.AddMessage(MessageType.Error, true, "The train plugin path was malformed in " + config);
                    return(false);
                }
                title = System.IO.Path.GetFileName(file);
                if (!System.IO.File.Exists(file))
                {
                    // Nope, still not found
                    Interface.AddMessage(MessageType.Error, true, "The train plugin " + title + " could not be found in " + config);
                    return(false);
                }
            }
            Program.FileSystem.AppendToLogFile("Loading train plugin: " + file);
            bool success = LoadPlugin(train, file, trainFolder);

            if (success == false)
            {
                Loading.PluginError = Translations.GetInterfaceString("errors_plugin_failure1").Replace("[plugin]", file);
            }
            else
            {
                Program.FileSystem.AppendToLogFile("Train plugin loaded successfully.");
            }
            return(success);
        }
Example #6
0
            /********************
             *      MENU C'TOR
             *********************/
            public SingleMenu(MenuType menuType, int data = 0)
            {
                int  i, menuItem;
                int  jump = 0;
                Size size;

                Align     = Renderer.TextAlignment.TopMiddle;
                Height    = Width = 0;
                Selection = 0;                                                                  // defaults to first menu item
                switch (menuType)
                {
                case MenuType.Top:                                      // top level menu
                    for (i = 0; i < Game.Stations.Length; i++)
                    {
                        if (Game.PlayerStopsAtStation(i) & Game.Stations[i].Stops.Length > 0)
                        {
                            jump = 1;
                            break;
                        }
                    }
                    Items    = new MenuEntry[4 + jump];
                    Items[0] = new MenuCommand(Interface.GetInterfaceString("menu_resume"), MenuTag.BackToSim, 0);
                    if (jump > 0)
                    {
                        Items[1] = new MenuCommand(Interface.GetInterfaceString("menu_jump"), MenuTag.MenuJumpToStation, 0);
                    }
                    Items[1 + jump] = new MenuCommand(Interface.GetInterfaceString("menu_exit"), MenuTag.MenuExitToMainMenu, 0);
                    Items[2 + jump] = new MenuCommand(Interface.GetInterfaceString("menu_customize_controls"), MenuTag.MenuControls, 0);
                    Items[3 + jump] = new MenuCommand(Interface.GetInterfaceString("menu_quit"), MenuTag.MenuQuit, 0);
                    break;

                case MenuType.JumpToStation:                    // list of stations to jump to
                    // count the number of available stations
                    menuItem = 0;
                    for (i = 0; i < Game.Stations.Length; i++)
                    {
                        if (Game.PlayerStopsAtStation(i) & Game.Stations [i].Stops.Length > 0)
                        {
                            menuItem++;
                        }
                    }
                    // list available stations, selecting the next station as predefined choice
                    jump     = 0;                                                                               // no jump found yet
                    Items    = new MenuEntry[menuItem + 1];
                    Items[0] = new MenuCommand(Interface.GetInterfaceString("menu_back"), MenuTag.MenuBack, 0);
                    menuItem = 1;
                    for (i = 0; i < Game.Stations.Length; i++)
                    {
                        if (Game.PlayerStopsAtStation(i) & Game.Stations[i].Stops.Length > 0)
                        {
                            Items[menuItem] = new MenuCommand(Game.Stations[i].Name, MenuTag.JumpToStation, i);
                            // if no preferred jump-to-station found yet and this station is
                            // after the last station the user stopped at, select this item
                            if (jump == 0 && i > TrainManager.PlayerTrain.LastStation)
                            {
                                jump      = i;
                                Selection = menuItem;
                            }
                            menuItem++;
                        }
                    }
                    Align = Renderer.TextAlignment.TopLeft;
                    break;

                case MenuType.ExitToMainMenu:
                    Items     = new MenuEntry[3];
                    Items[0]  = new MenuCaption(Interface.GetInterfaceString("menu_exit_question"));
                    Items[1]  = new MenuCommand(Interface.GetInterfaceString("menu_exit_no"), MenuTag.MenuBack, 0);
                    Items[2]  = new MenuCommand(Interface.GetInterfaceString("menu_exit_yes"), MenuTag.ExitToMainMenu, 0);
                    Selection = 1;
                    break;

                case MenuType.Quit:                                     // ask for quit confirmation
                    Items     = new MenuEntry[3];
                    Items[0]  = new MenuCaption(Interface.GetInterfaceString("menu_quit_question"));
                    Items[1]  = new MenuCommand(Interface.GetInterfaceString("menu_quit_no"), MenuTag.MenuBack, 0);
                    Items[2]  = new MenuCommand(Interface.GetInterfaceString("menu_quit_yes"), MenuTag.Quit, 0);
                    Selection = 1;
                    break;

                case MenuType.Controls:
                    //Refresh the joystick list
                    Joysticks.RefreshJoysticks();
                    Items    = new MenuEntry[Interface.CurrentControls.Length + 1];
                    Items[0] = new MenuCommand(Interface.GetInterfaceString("menu_back"), MenuTag.MenuBack, 0);
                    for (i = 0; i < Interface.CurrentControls.Length; i++)
                    {
                        Items[i + 1] = new MenuCommand(Interface.CurrentControls[i].Command.ToString(), MenuTag.Control, i);
                    }
                    Align = Renderer.TextAlignment.TopLeft;
                    break;

                case MenuType.Control:
                    //Refresh the joystick list
                    Joysticks.RefreshJoysticks();
                    Selection = SelectionNone;
                    Items     = new MenuEntry[4];
                    // get code name and description
                    Interface.Control loadedControl = Interface.CurrentControls[data];
                    for (int h = 0; h < Interface.CommandInfos.Length; h++)
                    {
                        if (Interface.CommandInfos[h].Command == loadedControl.Command)
                        {
                            Items[0] = new MenuCommand(loadedControl.Command.ToString() + " - " +
                                                       Interface.CommandInfos[h].Description, MenuTag.None, 0);
                            break;
                        }
                    }
                    // get assignment
                    String str = "";
                    switch (loadedControl.Method)
                    {
                    case Interface.ControlMethod.Keyboard:
                        if (loadedControl.Modifier != Interface.KeyboardModifier.None)
                        {
                            str = Interface.GetInterfaceString("menu_keyboard") + " [" + loadedControl.Modifier + "-" + loadedControl.Key + "]";
                        }
                        else
                        {
                            str = Interface.GetInterfaceString("menu_keyboard") + " [" + loadedControl.Key + "]";
                        }
                        break;

                    case Interface.ControlMethod.Joystick:
                        str = Interface.GetInterfaceString("menu_joystick") + " " + loadedControl.Device + " [" + loadedControl.Component + " " + loadedControl.Element + "]";
                        switch (loadedControl.Component)
                        {
                        case Interface.JoystickComponent.FullAxis:
                        case Interface.JoystickComponent.Axis:
                            str += " " + (loadedControl.Direction == 1 ? Interface.GetInterfaceString("menu_joystickdirection_positive") : Interface.GetInterfaceString("menu_joystickdirection_negative"));
                            break;

//						case Interface.JoystickComponent.Button:	// NOTHING TO DO FOR THIS CASE!
//							str = str;
//							break;
                        case Interface.JoystickComponent.Hat:
                            str += " " + (OpenTK.Input.HatPosition)loadedControl.Direction;
                            break;

                        case Interface.JoystickComponent.Invalid:
                            str = Interface.GetInterfaceString("menu_joystick_notavailable");
                            break;
                        }
                        break;

                    case Interface.ControlMethod.Invalid:
                        str = Interface.GetInterfaceString("menu_joystick_notavailable");
                        break;
                    }
                    Items[1] = new MenuCommand(Interface.GetInterfaceString("menu_assignment_current") + " " + str, MenuTag.None, 0);
                    Items[2] = new MenuCommand(" ", MenuTag.None, 0);
                    Items[3] = new MenuCommand(Interface.GetInterfaceString("menu_assign"), MenuTag.None, 0);
                    break;
                }

                // compute menu extent
                for (i = 0; i < Items.Length; i++)
                {
                    size = Renderer.MeasureString(Game.Menu.MenuFont, Items [i].Text);
                    if (size.Width > Width)
                    {
                        Width = size.Width;
                    }
                    if (!(Items[i] is MenuCaption) && size.Width > ItemWidth)
                    {
                        ItemWidth = size.Width;
                    }
                }
                Height  = Items.Length * Game.Menu.LineHeight;
                TopItem = 0;
            }
        //Parses an XML background definition
        public static BackgroundHandle ReadBackgroundXML(string fileName)
        {
            List <StaticBackground> Backgrounds = new List <StaticBackground>();
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

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

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

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

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

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

                                case "object":
                                    string f;
                                    try
                                    {
                                        f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(fileName), c.InnerText);
                                    }
                                    catch
                                    {
                                        Interface.AddMessage(MessageType.Error, true, "BackgroundObject FileName is malformed in file " + fileName);
                                        break;
                                    }
                                    if (!System.IO.File.Exists(f))
                                    {
                                        Interface.AddMessage(MessageType.Error, true, "FileName " + f + " not found in file " + fileName);
                                    }
                                    else
                                    {
                                        UnifiedObject obj;
                                        Program.CurrentHost.LoadObject(f, System.Text.Encoding.Default, out obj);
                                        o = (StaticObject)obj;
                                    }
                                    break;

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

                                case "texture":
                                    string file;
                                    try
                                    {
                                        file = OpenBveApi.Path.CombineFile(Path, c.InnerText);
                                    }
                                    catch
                                    {
                                        Interface.AddMessage(MessageType.Error, true, "BackgroundTexture FileName is malformed in file " + fileName);
                                        break;
                                    }
                                    if (!System.IO.File.Exists(file))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The background texture file " + c.InnerText + " does not exist in " + fileName);
                                    }
                                    else
                                    {
                                        Program.CurrentHost.RegisterTexture(file, new TextureParameters(null, null), out t);
                                    }
                                    break;

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

                                case "transitiontime":
                                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out TransitionTime))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " is not a valid background transition time in " + fileName);
                                    }
                                    break;
                                }
                            }
                            //Create background if texture is not null
                            if (t != null && o == null)
                            {
                                Backgrounds.Add(new StaticBackground(t, repetitions, false, TransitionTime, mode, DisplayTime));
                            }
                            if (t == null && o != null)
                            {
                                //All other parameters are ignored if an object has been defined
                                //TODO: Error message stating they have been ignored
                                return(new BackgroundObject(o));
                            }
                        }
                    }
                    if (Backgrounds.Count == 1)
                    {
                        return(Backgrounds[0]);
                    }
                    if (Backgrounds.Count > 1)
                    {
                        //Sort list- Not worried about when they start or end, so use simple LINQ
                        Backgrounds = Backgrounds.OrderBy(o => o.Time).ToList();
                        //If more than 2 backgrounds, convert to array and return a new dynamic background
                        return(new DynamicBackground(Backgrounds.ToArray()));
                    }
                }
            }
            //We couldn't find any valid XML, so return false
            throw new InvalidDataException();
        }
Example #8
0
        internal static ObjectManager.StaticObject ReadObject(string FileName)
        {
            currentFolder = System.IO.Path.GetDirectoryName(FileName);
            currentFile   = FileName;
            rootMatrix    = Matrix4D.NoTransformation;

#if !DEBUG
            try
            {
#endif
            XFileParser parser = new XFileParser(System.IO.File.ReadAllBytes(FileName));
            Scene scene        = parser.GetImportedData();

            ObjectManager.StaticObject obj = new ObjectManager.StaticObject();
            MeshBuilder builder            = new MeshBuilder();

            // Global
            foreach (var mesh in scene.GlobalMeshes)
            {
                MeshBuilder(ref obj, ref builder, mesh);
            }

            if (scene.RootNode != null)
            {
                // Root Node
                if (scene.RootNode.TrafoMatrix != OpenTK.Matrix4.Zero)
                {
                    rootMatrix = ConvertMatrix(scene.RootNode.TrafoMatrix);
                }

                foreach (var mesh in scene.RootNode.Meshes)
                {
                    MeshBuilder(ref obj, ref builder, mesh);
                }

                // Children Node
                foreach (var node in scene.RootNode.Children)
                {
                    ChildrenNode(ref obj, ref builder, node);
                }
            }

            builder.Apply(ref obj);
            obj.Mesh.CreateNormals();
            if (rootMatrix != Matrix4D.NoTransformation)
            {
                for (int i = 0; i < obj.Mesh.Vertices.Length; i++)
                {
                    obj.Mesh.Vertices[i].Coordinates.Transform(rootMatrix);
                }
            }
            return(obj);

#if !DEBUG
        }

        catch (Exception e)
        {
            Interface.AddMessage(MessageType.Error, false, e.Message + " in " + FileName);
            return(null);
        }
#endif
        }
Example #9
0
		internal void SetControlJoyCustomData(int device, Interface.JoystickComponent component, int element, int dir)
		{
			if (isCustomisingControl && CustomControlIdx < Interface.CurrentControls.Length)
			{
				Interface.CurrentControls[CustomControlIdx].Method		= Interface.ControlMethod.Joystick;
				Interface.CurrentControls[CustomControlIdx].Device		= device;
				Interface.CurrentControls[CustomControlIdx].Component	= component;
				Interface.CurrentControls[CustomControlIdx].Element		= element;
				Interface.CurrentControls[CustomControlIdx].Direction	= dir;
				Interface.SaveControls(null);
				PopMenu();
				isCustomisingControl	= false;
			}
		}
Example #10
0
        //
        // DRAW LOADING SCREEN
        //
        /// <summary>Draws on OpenGL canvas the route/train loading screen</summary>
        internal static void DrawLoadingScreen()
        {
            // begin HACK //
            if (!BlendEnabled)
            {
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                BlendEnabled = true;
            }
            if (LightingEnabled)
            {
                GL.Disable(EnableCap.Lighting);
                LightingEnabled = false;
            }
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.PushMatrix();
            // fill the screen with background colour
            GL.Color4(bkgR, bkgG, bkgB, bkgA);
            Renderer.RenderOverlaySolid(0.0, 0.0, (double)Screen.Width, (double)Screen.Height);
            GL.Color4(1.0f, 1.0f, 1.0f, 1.0f);

            // BACKGROUND IMAGE
            int bkgHeight, bkgWidth;
            int fontHeight = (int)Fonts.SmallFont.FontSize;
            int logoBottom;
//			int		versionTop;
            int halfWidth = Screen.Width / 2;

            if (TextureLoadingBkg != null)
            {
                // stretch the background image to fit at least one screen dimension
                double ratio = (double)TextureLoadingBkg.Width / (double)TextureLoadingBkg.Height;
                if (Screen.Width / ratio > Screen.Height)     // if screen ratio is shorter than bkg...
                {
                    bkgHeight = Screen.Height;                // set height to screen height
                    bkgWidth  = (int)(Screen.Height * ratio); // and scale width proprtionally
                }
                else                                          // if screen ratio is wider than bkg...
                {
                    bkgWidth  = Screen.Width;                 // set width to screen width
                    bkgHeight = (int)(Screen.Width / ratio);  // and scale height accordingly
                }
                // draw the background image down from the top screen edge
                DrawRectangle(TextureLoadingBkg, new Point((Screen.Width - bkgWidth) / 2, 0), new Size(bkgWidth, bkgHeight), Color128.White);
            }
            // if the route has no custom loading image, add the openBVE logo
            // (the route custom image is loaded in OldParsers/CsvRwRouteParser.cs)
            if (!customLoadScreen)
            {
                if (TextureLogo != null)
                {
                    // place the centre of the logo at from the screen top
                    int logoTop = (int)(Screen.Height * logoCentreYFactor - TextureLogo.Height / 2);
                    logoBottom = logoTop + TextureLogo.Height;
                    DrawRectangle(TextureLogo, new Point((Screen.Width - TextureLogo.Width) / 2, logoTop), new Size(TextureLogo.Width, TextureLogo.Height), Color128.White);
                }
            }
            else
            {
                // if custom route image, no logo and leave a conventional black area below the potential logo
            }
            logoBottom = Screen.Height / 2;
            // take the height remaining below the logo and divide in 3 horiz. parts
            int blankHeight = (Screen.Height - logoBottom) / 3;

            // VERSION NUMBER
            // place the version above the first division
            int versionTop = logoBottom + blankHeight - fontHeight;

            DrawString(Fonts.SmallFont, "Version " + typeof(Renderer).Assembly.GetName().Version,
                       new Point(halfWidth, versionTop), TextAlignment.TopMiddle, Color128.White);
            // for the moment, do not show any URL; would go right below the first division
//			DrawString(Fonts.SmallFont, "https://sites.google.com/site/openbvesim/home",
//				new Point(halfWidth, versionTop + fontHeight+2),
//				TextAlignment.TopMiddle, Color128.White);

            // PROGRESS MESSAGE AND BAR
            // place progress bar right below the second division
            int    progressTop   = Screen.Height - blankHeight;
            int    progressWidth = Screen.Width - progrMargin * 2;
            double routeProgress = Math.Max(0.0, Math.Min(1.0, Loading.RouteProgress));
            double trainProgress = Math.Max(0.0, Math.Min(1.0, Loading.TrainProgress));
            // draw progress message right above the second division
            string text = Interface.GetInterfaceString(
                routeProgress < 1.0 ? "loading_loading_route" :
                (trainProgress < 1.0 ? "loading_loading_train" : "message_loading"));

            DrawString(Fonts.SmallFont, text, new Point(halfWidth, progressTop - fontHeight - 6),
                       TextAlignment.TopMiddle, Color128.White);
            // sum of route progress and train progress arrives up to 2.0:
            // => times 50.0 to convert to %
            double percent = 50.0 * (routeProgress + trainProgress);
            string percStr = percent.ToString("0") + "%";

            // progress frame
            DrawRectangle(null, new Point(progrMargin - progrBorder, progressTop - progrBorder),
                          new Size(progressWidth + progrBorder * 2, fontHeight + 6), Color128.White);
            // progress bar
            DrawRectangle(null, new Point(progrMargin, progressTop),
                          new Size(progressWidth * (int)percent / 100, fontHeight + 4), ColourProgressBar);
            // progress percent
            DrawString(Fonts.SmallFont, percStr, new Point(halfWidth, progressTop),
                       TextAlignment.TopMiddle, Color128.Black);
            GL.PopMatrix();
        }
Example #11
0
        private void button1_Click(object sender, EventArgs e)
        {
            InterpolationMode previousInterpolationMode = Interface.CurrentOptions.Interpolation;
            int previousAntialasingLevel = Interface.CurrentOptions.AntialiasingLevel;
            int previousAnsiotropicLevel = Interface.CurrentOptions.AnisotropicFilteringLevel;

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

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

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

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

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

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

            default:
                Interface.CurrentOptions.TransparencyMode = TransparencyMode.Quality;
                break;
            }
            //Set width and height
            if (Renderer.ScreenWidth != width.Value || Renderer.ScreenHeight != height.Value)
            {
                Renderer.ScreenWidth             = (int)width.Value;
                Renderer.ScreenHeight            = (int)height.Value;
                Program.currentGameWindow.Width  = (int)width.Value;
                Program.currentGameWindow.Height = (int)height.Value;
                Program.UpdateViewport();
            }
            //Check if interpolation mode or ansiotropic filtering level has changed, and trigger a reload
            if (previousInterpolationMode != Interface.CurrentOptions.Interpolation || previousAnsiotropicLevel != Interface.CurrentOptions.AnisotropicFilteringLevel)
            {
                Program.ReducedMode      = false;
                Program.LightingRelative = -1.0;
                Game.Reset();
                Textures.UnloadAllTextures();
                Interface.ClearMessages();
                for (int i = 0; i < Program.Files.Length; i++)
                {
#if !DEBUG
                    try {
#endif
                    UnifiedObject o = ObjectManager.LoadObject(Program.Files[i], System.Text.Encoding.UTF8, false, false, false);
                    ObjectManager.CreateObject(o, Vector3.Zero,
                                               new Transformation(0.0, 0.0, 0.0), new Transformation(0.0, 0.0, 0.0), true, 0.0,
                                               0.0, 25.0, 0.0);
#if !DEBUG
                }
                catch (Exception ex) {
                    Interface.AddMessage(MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Program.Files[i] + ".");
                }
#endif
                }
                ObjectManager.InitializeVisibility();
                ObjectManager.UpdateVisibility(0.0, true);
                ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
            }
            Renderer.TransparentColorDepthSorting     = Interface.CurrentOptions.TransparencyMode == TransparencyMode.Quality & Interface.CurrentOptions.Interpolation != OpenBveApi.Graphics.InterpolationMode.NearestNeighbor & Interface.CurrentOptions.Interpolation != OpenBveApi.Graphics.InterpolationMode.Bilinear;
            Interface.CurrentOptions.CurrentXParser   = comboBoxNewXParser.SelectedIndex;
            Interface.CurrentOptions.CurrentObjParser = comboBoxNewObjParser.SelectedIndex;
            Options.SaveOptions();
            this.Close();
        }
Example #12
0
        // --- functions ---
        internal override bool Load(VehicleSpecs specs, InitializationModes mode)
        {
            int result;

            try
            {
                result = Win32LoadDLL(this.PluginFile, this.PluginFile);
            }
            catch (Exception ex)
            {
                base.LastException = ex;
                throw;
            }
            if (result == 0)
            {
                int    errorCode    = Marshal.GetLastWin32Error();
                string errorMessage = new Win32Exception(errorCode).Message;
                Interface.AddMessage(MessageType.Error, true,
                                     String.Format("Error loading Win32 plugin: {0} (0x{1})", errorMessage, errorCode.ToString("x")));
                return(false);
            }
            try
            {
                Win32Load();
            }
            catch (Exception ex)
            {
                base.LastException = ex;
                throw;
            }
            int version;

            try
            {
                version = Win32GetPluginVersion();
            }
            catch (Exception ex)
            {
                base.LastException = ex;
                throw;
            }
            if (version != 131072)
            {
                Interface.AddMessage(MessageType.Error, false, "The train plugin " + base.PluginTitle + " is of an unsupported version.");
                try
                {
                    Win32Dispose();
                }
                catch (Exception ex)
                {
                    base.LastException = ex;
                    throw;
                }
                Win32UnloadDLL();
                return(false);
            }
            try
            {
                Win32VehicleSpec win32Spec;
                win32Spec.BrakeNotches = specs.BrakeNotches;
                win32Spec.PowerNotches = specs.PowerNotches;
                win32Spec.AtsNotch     = specs.AtsNotch;
                win32Spec.B67Notch     = specs.B67Notch;
                win32Spec.Cars         = specs.Cars;
                Win32SetVehicleSpec(ref win32Spec.BrakeNotches);
            }
            catch (Exception ex)
            {
                base.LastException = ex;
                throw;
            }
            try
            {
                Win32Initialize((int)mode);
            }
            catch (Exception ex)
            {
                base.LastException = ex;
                throw;
            }
            UpdatePower();
            UpdateBrake();
            UpdateReverser();
            if (PanelHandle.IsAllocated)
            {
                PanelHandle.Free();
            }
            if (SoundHandle.IsAllocated)
            {
                SoundHandle.Free();
            }
            PanelHandle = GCHandle.Alloc(Panel, GCHandleType.Pinned);
            SoundHandle = GCHandle.Alloc(Sound, GCHandleType.Pinned);
            return(true);
        }
 // load texture rgba
 private static void LoadTextureRGBAforData(Bitmap Bitmap, World.ColorRGB TransparentColor, byte TransparentColorUsed, int TextureIndex)
 {
     try
     {
         // load bytes
         int Width, Height, Stride; byte[] Data;
         {
             if (Textures[TextureIndex].ClipWidth == 0)
             {
                 Textures[TextureIndex].ClipWidth = Bitmap.Width;
             }
             if (Textures[TextureIndex].ClipHeight == 0)
             {
                 Textures[TextureIndex].ClipHeight = Bitmap.Height;
             }
             Width  = Textures[TextureIndex].ClipWidth;
             Height = Textures[TextureIndex].ClipHeight;
             Bitmap    c   = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
             Graphics  g   = Graphics.FromImage(c);
             Rectangle dst = new Rectangle(0, 0, Width, Height);
             Rectangle src = new Rectangle(Textures[TextureIndex].ClipLeft, Textures[TextureIndex].ClipTop, Textures[TextureIndex].ClipWidth, Textures[TextureIndex].ClipHeight);
             g.DrawImage(Bitmap, dst, src, GraphicsUnit.Pixel);
             g.Dispose();
             BitmapData d = c.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, c.PixelFormat);
             Stride = d.Stride;
             Data   = new byte[Stride * Height];
             System.Runtime.InteropServices.Marshal.Copy(d.Scan0, Data, 0, Stride * Height);
             c.UnlockBits(d);
             c.Dispose();
         }
         // load mode
         if (Textures[TextureIndex].LoadMode == TextureLoadMode.Bve4SignalGlow)
         {
             // bve 4 signal glow
             int  p = 0, pn = Stride - 4 * Width;
             byte tr, tg, tb;
             if (TransparentColorUsed != 0)
             {
                 tr = TransparentColor.R;
                 tg = TransparentColor.G;
                 tb = TransparentColor.B;
             }
             else
             {
                 tr = 0; tg = 0; tb = 0;
             }
             // invert lightness
             byte[] Temp = new byte[Stride * Height];
             for (int y = 0; y < Height; y++)
             {
                 for (int x = 0; x < Width; x++)
                 {
                     if (Data[p] == tb & Data[p + 1] == tg & Data[p + 2] == tr)
                     {
                         Temp[p]     = 0;
                         Temp[p + 1] = 0;
                         Temp[p + 2] = 0;
                     }
                     else if (Data[p] != 255 | Data[p + 1] != 255 | Data[p + 2] != 255)
                     {
                         int b = Data[p], g = Data[p + 1], r = Data[p + 2];
                         InvertLightness(ref r, ref g, ref b);
                         int l = r >= g & r >= b ? r : g >= b ? g : b;
                         Temp[p]     = (byte)(l * b / 255);
                         Temp[p + 1] = (byte)(l * g / 255);
                         Temp[p + 2] = (byte)(l * r / 255);
                     }
                     else
                     {
                         Temp[p]     = Data[p];
                         Temp[p + 1] = Data[p + 1];
                         Temp[p + 2] = Data[p + 2];
                     }
                     p += 4;
                 }
                 p += pn;
             }
             p = 0;
             // blur the image and multiply by lightness
             int s = 4;
             int n = Stride - (2 * s + 1 << 2);
             for (int y = 0; y < Height; y++)
             {
                 for (int x = 0; x < Width; x++)
                 {
                     int q = p - s * (Stride + 4);
                     int r = 0, g = 0, b = 0, c = 0;
                     for (int yr = y - s; yr <= y + s; yr++)
                     {
                         if (yr >= 0 & yr < Height)
                         {
                             for (int xr = x - s; xr <= x + s; xr++)
                             {
                                 if (xr >= 0 & xr < Width)
                                 {
                                     b += (int)Temp[q];
                                     g += (int)Temp[q + 1];
                                     r += (int)Temp[q + 2];
                                     c++;
                                 }
                                 q += 4;
                             }
                             q += n;
                         }
                         else
                         {
                             q += Stride;
                         }
                     }
                     if (c == 0)
                     {
                         Data[p]     = 0;
                         Data[p + 1] = 0;
                         Data[p + 2] = 0;
                         Data[p + 3] = 255;
                     }
                     else
                     {
                         r /= c; g /= c; b /= c;
                         int l = r >= g & r >= b ? r : g >= b ? g : b;
                         Data[p]     = (byte)(l * b / 255);
                         Data[p + 1] = (byte)(l * g / 255);
                         Data[p + 2] = (byte)(l * r / 255);
                         Data[p + 3] = 255;
                     }
                     p += 4;
                 }
                 p += pn;
             }
             Textures[TextureIndex].Transparency    = TextureTransparencyMode.None;
             Textures[TextureIndex].DontAllowUnload = true;
         }
         else if (TransparentColorUsed != 0)
         {
             // transparent color
             int  p = 0, pn = Stride - 4 * Width;
             byte tr   = TransparentColor.R;
             byte tg   = TransparentColor.G;
             byte tb   = TransparentColor.B;
             bool used = false;
             // check if alpha is actually used
             int y;
             for (y = 0; y < Height; y++)
             {
                 int x; for (x = 0; x < Width; x++)
                 {
                     if (Data[p + 3] != 255)
                     {
                         break;
                     }
                     p += 4;
                 }
                 if (x < Width)
                 {
                     break;
                 }
                 p += pn;
             }
             if (y == Height)
             {
                 Textures[TextureIndex].Transparency = TextureTransparencyMode.TransparentColor;
             }
             // duplicate color data from adjacent pixels
             p = 0; pn = Stride - 4 * Width;
             for (y = 0; y < Height; y++)
             {
                 for (int x = 0; x < Width; x++)
                 {
                     if (Data[p] == tb & Data[p + 1] == tg & Data[p + 2] == tr)
                     {
                         used = true;
                         if (x == 0)
                         {
                             int q = p;
                             int v; for (v = y; v < Height; v++)
                             {
                                 int u; for (u = v == y ? x + 1 : 0; u < Width; u++)
                                 {
                                     if (Data[q] != tb | Data[q + 1] != tg | Data[q + 2] != tr)
                                     {
                                         Data[p]     = Data[q];
                                         Data[p + 1] = Data[q + 1];
                                         Data[p + 2] = Data[q + 2];
                                         Data[p + 3] = 0;
                                         break;
                                     }
                                     q += 4;
                                 }
                                 if (u < Width)
                                 {
                                     break;
                                 }
                                 else
                                 {
                                     q += pn;
                                 }
                             }
                             if (v == Height)
                             {
                                 if (y == 0)
                                 {
                                     Data[p]     = 128;
                                     Data[p + 1] = 128;
                                     Data[p + 2] = 128;
                                     Data[p + 3] = 0;
                                 }
                                 else
                                 {
                                     Data[p]     = Data[p - Stride];
                                     Data[p + 1] = Data[p - Stride + 1];
                                     Data[p + 2] = Data[p - Stride + 2];
                                     Data[p + 3] = 0;
                                 }
                             }
                         }
                         else
                         {
                             Data[p]     = Data[p - 4];
                             Data[p + 1] = Data[p - 3];
                             Data[p + 2] = Data[p - 2];
                             Data[p + 3] = 0;
                         }
                     }
                     p += 4;
                 }
                 p += pn;
             }
             // transparent color is not actually used
             if (!used & Textures[TextureIndex].Transparency == TextureTransparencyMode.TransparentColor)
             {
                 Textures[TextureIndex].Transparency = TextureTransparencyMode.None;
             }
         }
         else if (Textures[TextureIndex].Transparency == TextureTransparencyMode.Alpha)
         {
             // check if alpha is actually used
             int p = 0, pn = Stride - 4 * Width;
             int y; for (y = 0; y < Height; y++)
             {
                 int x; for (x = 0; x < Width; x++)
                 {
                     if (Data[p + 3] != 255)
                     {
                         break;
                     }
                     p += 4;
                 }
                 if (x < Width)
                 {
                     break;
                 }
                 p += pn;
             }
             if (y == Height)
             {
                 Textures[TextureIndex].Transparency = TextureTransparencyMode.None;
             }
         }
         // non-power of two
         int TargetWidth;
         int TargetHeight;
         if (Interface.CurrentOptions.NoTextureResize)
         {
             TargetWidth  = Width;
             TargetHeight = Height;
         }
         else
         {
             TargetWidth  = Interface.RoundToPowerOfTwo(Width);
             TargetHeight = Interface.RoundToPowerOfTwo(Height);
             if (TargetWidth != Width | TargetHeight != Height)
             {
                 Bitmap     b = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
                 BitmapData d = b.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, b.PixelFormat);
                 System.Runtime.InteropServices.Marshal.Copy(Data, 0, d.Scan0, d.Stride * d.Height);
                 b.UnlockBits(d);
                 Bitmap   c = new Bitmap(TargetWidth, TargetHeight, PixelFormat.Format32bppArgb);
                 Graphics g = Graphics.FromImage(c);
                 g.DrawImage(b, 0, 0, TargetWidth, TargetHeight);
                 g.Dispose();
                 b.Dispose();
                 d      = c.LockBits(new Rectangle(0, 0, TargetWidth, TargetHeight), ImageLockMode.ReadOnly, c.PixelFormat);
                 Stride = d.Stride;
                 Data   = new byte[Stride * TargetHeight];
                 System.Runtime.InteropServices.Marshal.Copy(d.Scan0, Data, 0, Stride * TargetHeight);
                 c.UnlockBits(d);
                 c.Dispose();
             }
         }
         Textures[TextureIndex].Width  = TargetWidth;
         Textures[TextureIndex].Height = TargetHeight;
         Textures[TextureIndex].Data   = Data;
     }
     catch (Exception ex)
     {
         Interface.AddMessage(Interface.MessageType.Error, false, "Internal error in TextureManager.cs::LoadTextureRGBAForData: " + ex.Message);
         throw;
     }
 }
Example #14
0
		//
		// PROCESS MENU COMMAND
		//
		/// <summary>Processes a user command for the current menu</summary>
		/// <param name="cmd">The command to apply to the current menu</param>
		/// <param name="timeElapsed">The time elapsed since previous frame</param>
		internal void ProcessCommand(Interface.Command cmd, double timeElapsed)
		{
			
			if (CurrMenu < 0)
			{
				return;
			}
			// MenuBack is managed independently from single menu data
			if (cmd == Interface.Command.MenuBack)
			{
				PopMenu();
				return;
			}

			SingleMenu menu	= Menus[CurrMenu];
			if (menu.Selection == SelectionNone)	// if menu has no selection, do nothing
				return;
			switch (cmd)
			{
			case Interface.Command.MenuUp:		// UP
				if (menu.Selection > 0 &&
				    !(menu.Items[menu.Selection - 1] is MenuCaption))
				{
					menu.Selection--;
					PositionMenu();
				}
				break;
			case Interface.Command.MenuDown:	// DOWN
				if (menu.Selection < menu.Items.Length - 1)
				{
					menu.Selection++;
					PositionMenu();
				}
				break;
//			case Interface.Command.MenuBack:	// ESC:	managed above
//				break;
			case Interface.Command.MenuEnter:	// ENTER
				if (menu.Items[menu.Selection] is MenuCommand)
				{
					MenuCommand menuItem = (MenuCommand)menu.Items[menu.Selection];
					switch (menuItem.Tag)
					{
					// menu management commands
					case MenuTag.MenuBack:				// BACK TO PREVIOUS MENU
						Menu.instance.PopMenu();
						break;
					case MenuTag.MenuJumpToStation:		// TO STATIONS MENU
						Menu.instance.PushMenu(MenuType.JumpToStation);
						break;
					case MenuTag.MenuExitToMainMenu:	// TO EXIT MENU
						Menu.instance.PushMenu(MenuType.ExitToMainMenu);
						break;
					case MenuTag.MenuQuit:				// TO QUIT MENU
						Menu.instance.PushMenu(MenuType.Quit);
						break;
					case MenuTag.MenuControls:			// TO CONTROLS MENU
						Menu.instance.PushMenu(MenuType.Controls);
						break;
					case MenuTag.BackToSim:				// OUT OF MENU BACK TO SIMULATION
						Reset();
						Game.CurrentInterface = Game.InterfaceType.Normal;
						break;

						// simulation commands
					case MenuTag.JumpToStation:			// JUMP TO STATION
						Reset();
						TrainManager.JumpTrain(TrainManager.PlayerTrain, menuItem.Data);
						break;
					case MenuTag.ExitToMainMenu:		// BACK TO MAIN MENU
						Reset();
						Program.RestartArguments =
							Interface.CurrentOptions.GameMode == Interface.GameMode.Arcade ? "/review" : "";
						MainLoop.Quit = true;
						break;
					case MenuTag.Control:				// CONTROL CUSTOMIZATION
						PushMenu(MenuType.Control, ((MenuCommand)menu.Items[menu.Selection]).Data);
						isCustomisingControl	= true;
						CustomControlIdx		= ((MenuCommand)menu.Items[menu.Selection]).Data;
						break;
					case MenuTag.Quit:					// QUIT PROGRAMME
						Reset();
						MainLoop.Quit = true;
						break;
					}
				}
				break;
			case Interface.Command.MiscFullscreen:
				// fullscreen
				Screen.ToggleFullscreen();
				break;
			case Interface.Command.MiscMute:
				// mute
				Sounds.GlobalMute = !Sounds.GlobalMute;
				Sounds.Update(timeElapsed, Interface.CurrentOptions.SoundModel);
				break;
			}
		}
Example #15
0
        //Parses an XML dynamic lighting definition
        public static bool ReadLightingXML(string fileName)
        {
            //Prep
            LibRender.Renderer.LightDefinitions = new LightDefinition[0];
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

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

            bool defined = false;

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

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

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

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

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

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

            for (int i = 0; i < Text.Length; i++)
            {
                if (Text[i] == '\\')
                {
                    Builder.Append(Text, Start, i - Start);
                    if (i + 1 <= Text.Length)
                    {
                        switch (Text[i + 1])
                        {
                        case 'a': Builder.Append('\a'); break;

                        case 'b': Builder.Append('\b'); break;

                        case 't': Builder.Append('\t'); break;

                        case 'n': Builder.Append('\n'); break;

                        case 'v': Builder.Append('\v'); break;

                        case 'f': Builder.Append('\f'); break;

                        case 'r': Builder.Append('\r'); break;

                        case 'e': Builder.Append('\x1B'); break;

                        case 'c':
                            if (i + 2 < Text.Length)
                            {
                                int CodePoint = char.ConvertToUtf32(Text, i + 2);
                                if (CodePoint >= 0x40 & CodePoint <= 0x5F)
                                {
                                    Builder.Append(char.ConvertFromUtf32(CodePoint - 64));
                                }
                                else if (CodePoint == 0x3F)
                                {
                                    Builder.Append('\x7F');
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Unrecognized control character found in " + Text.Substring(i, 3));
                                    return(Text);
                                } i++;
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, "Insufficient characters available in " + Text + " to decode control character escape sequence");
                                return(Text);
                            } break;

                        case '"': Builder.Append('"'); break;

                        case '\\': Builder.Append('\\'); break;

                        case 'x':
                            if (i + 3 < Text.Length)
                            {
                                Builder.Append(char.ConvertFromUtf32(Convert.ToInt32(Text.Substring(i + 2, 2), 16)));
                                i += 2;
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, "Insufficient characters available in " + Text + " to decode hexadecimal escape sequence.");
                                return(Text);
                            } break;

                        case 'u':
                            if (i + 5 < Text.Length)
                            {
                                Builder.Append(char.ConvertFromUtf32(Convert.ToInt32(Text.Substring(i + 2, 4), 16)));
                                i += 4;
                            }
                            else
                            {
                                Interface.AddMessage(MessageType.Error, false, "Insufficient characters available in " + Text + " to decode hexadecimal escape sequence.");
                                return(Text);
                            } break;

                        default:
                            Interface.AddMessage(MessageType.Error, false, "Unrecognized escape sequence found in " + Text + ".");
                            return(Text);
                        }
                        i++; Start = i + 1;
                    }
                    else
                    {
                        Interface.AddMessage(MessageType.Error, false, "Insufficient characters available in " + Text + " to decode escape sequence.");
                        return(Text);
                    }
                }
            }
            Builder.Append(Text, Start, Text.Length - Start);
            return(Builder.ToString());
        }
Example #17
0
        /// <summary>This function processes the list of expressions for $Char, $Rnd, $If and $Sub directives, and evaluates them into the final expressions dataset</summary>
        private static void PreprocessChrRndSub(string FileName, bool IsRW, System.Text.Encoding Encoding, ref Expression[] Expressions)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string[] Subs    = new string[16];
            int      openIfs = 0;

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

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

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

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

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

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

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

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

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

                                    case ')': l--; break;

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

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

                                        case ')': l--; break;
                                        }
                                        if (l < 0)
                                        {
                                            break;
                                        }
                                    }
                                    int x;
                                    if (NumberFormats.TryParseIntVb6(s, out x))
                                    {
                                        if (x >= 0)
                                        {
                                            while (x >= Subs.Length)
                                            {
                                                Array.Resize <string>(ref Subs, Subs.Length << 1);
                                            }
                                            Subs[x]             = Expressions[i].Text.Substring(m + 1, n - m - 1).Trim();
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + Expressions[i].Text.Substring(n);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "Index is expected to be non-negative in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                    }
                                }
                                else
                                {
                                    int x;
                                    if (NumberFormats.TryParseIntVb6(s, out x))
                                    {
                                        if (x >= 0 & x < Subs.Length && Subs[x] != null)
                                        {
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + Subs[x] + Expressions[i].Text.Substring(h + 1);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Interface.AddMessage(MessageType.Error, false, "Index is out of range in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Interface.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                    }
                                }
                            }
                            break;
                            }
                        }
                    }
                    if (continueWithNextExpression)
                    {
                        break;
                    }
                }
            }
            // handle comments introduced via chr, rnd, sub
            {
                int length = Expressions.Length;
                for (int i = 0; i < length; i++)
                {
                    Expressions[i].Text = Expressions[i].Text.Trim();
                    if (Expressions[i].Text.Length != 0)
                    {
                        if (Expressions[i].Text[0] == ';')
                        {
                            for (int j = i; j < length - 1; j++)
                            {
                                Expressions[j] = Expressions[j + 1];
                            }
                            length--;
                            i--;
                        }
                    }
                    else
                    {
                        for (int j = i; j < length - 1; j++)
                        {
                            Expressions[j] = Expressions[j + 1];
                        }
                        length--;
                        i--;
                    }
                }
                if (length != Expressions.Length)
                {
                    Array.Resize <Expression>(ref Expressions, length);
                }
            }
        }
Example #18
0
        // --- functions ---

        /// <summary>Reports a problem to the host application.</summary>
        /// <param name="type">The type of problem that is reported.</param>
        /// <param name="text">The textual message that describes the problem.</param>
        public override void ReportProblem(OpenBveApi.Hosts.ProblemType type, string text)
        {
            Interface.AddMessage(Interface.MessageType.Error, false, text);
        }
Example #19
0
        private static void PreprocessSortByTrackPosition(bool IsRW, double[] UnitFactors, ref Expression[] Expressions)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            PositionedExpression[]           p       = new PositionedExpression[Expressions.Length];
            int    n           = 0;
            double a           = -1.0;
            bool   NumberCheck = !IsRW;

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

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

            for (int i = 0; i < n; i++)
            {
                if (p[i].TrackPosition != a)
                {
                    a    = p[i].TrackPosition;
                    e[m] = new Expression
                    {
                        Text   = (a / UnitFactors[UnitFactors.Length - 1]).ToString(Culture),
                        Line   = -1,
                        Column = -1
                    };
                    m++;
                }
                e[m] = p[i].Expression;
                m++;
            }
            Array.Resize <Expression>(ref e, m);
            Expressions = e;
        }
Example #20
0
        private static void  MeshBuilder(ref ObjectManager.StaticObject obj, ref MeshBuilder builder, AssimpNET.X.Mesh mesh)
        {
            if (builder.Vertices.Length != 0)
            {
                builder.Apply(ref obj);
                builder = new MeshBuilder();
            }

            int nVerts = mesh.Positions.Count;

            if (nVerts == 0)
            {
                //Some null objects contain an empty mesh
                Interface.AddMessage(MessageType.Warning, false, "nVertices should be greater than zero in Mesh " + mesh.Name);
            }
            int v = builder.Vertices.Length;

            Array.Resize(ref builder.Vertices, v + nVerts);
            for (int i = 0; i < nVerts; i++)
            {
                builder.Vertices[v + i] = new Vertex(mesh.Positions[i].X, mesh.Positions[i].Y, mesh.Positions[i].Z);
            }

            int nFaces = mesh.PosFaces.Count;
            int f      = builder.Faces.Length;

            Array.Resize(ref builder.Faces, f + nFaces);
            for (int i = 0; i < nFaces; i++)
            {
                int fVerts = mesh.PosFaces[i].Indices.Count;
                if (nFaces == 0)
                {
                    throw new Exception("fVerts must be greater than zero");
                }
                builder.Faces[f + i]          = new MeshFace();
                builder.Faces[f + i].Vertices = new MeshFaceVertex[fVerts];
                for (int j = 0; j < fVerts; j++)
                {
                    builder.Faces[f + i].Vertices[j].Index = (ushort)mesh.PosFaces[i].Indices[j];
                }
            }

            int nMaterials   = mesh.Materials.Count;
            int nFaceIndices = mesh.FaceMaterials.Count;

            for (int i = 0; i < nFaceIndices; i++)
            {
                int fMaterial = (int)mesh.FaceMaterials[i];
                builder.Faces[i].Material = (ushort)(fMaterial + 1);
            }
            for (int i = 0; i < nMaterials; i++)
            {
                int m = builder.Materials.Length;
                Array.Resize(ref builder.Materials, m + 1);
                builder.Materials[m]       = new Material();
                builder.Materials[m].Color = new Color32((byte)(255 * mesh.Materials[i].Diffuse.R), (byte)(255 * mesh.Materials[i].Diffuse.G), (byte)(255 * mesh.Materials[i].Diffuse.B), (byte)(255 * mesh.Materials[i].Diffuse.A));
                double  mPower    = mesh.Materials[i].SpecularExponent;             //TODO: Unsure what this does...
                Color24 mSpecular = new Color24((byte)mesh.Materials[i].Specular.R, (byte)mesh.Materials[i].Specular.G, (byte)mesh.Materials[i].Specular.B);
                builder.Materials[m].EmissiveColor        = new Color24((byte)(255 * mesh.Materials[i].Emissive.R), (byte)(255 * mesh.Materials[i].Emissive.G), (byte)(255 * mesh.Materials[i].Emissive.B));
                builder.Materials[m].EmissiveColorUsed    = true;              //TODO: Check exact behaviour
                builder.Materials[m].TransparentColor     = Color24.Black;     //TODO: Check, also can we optimise which faces have the transparent color set?
                builder.Materials[m].TransparentColorUsed = true;

                if (mesh.Materials[i].Textures.Count > 0)
                {
                    builder.Materials[m].DaytimeTexture = OpenBveApi.Path.CombineFile(currentFolder, mesh.Materials[i].Textures[0].Name);
                    if (!System.IO.File.Exists(builder.Materials[m].DaytimeTexture))
                    {
                        Interface.AddMessage(MessageType.Error, true, "Texure " + builder.Materials[m].DaytimeTexture + " was not found in file " + currentFile);
                        builder.Materials[m].DaytimeTexture = null;
                    }
                }
            }

            if (mesh.TexCoords.Length > 0 && mesh.TexCoords[0] != null)
            {
                int nCoords = mesh.TexCoords[0].Count;
                for (int i = 0; i < nCoords; i++)
                {
                    builder.Vertices[i].TextureCoordinates = new Vector2(mesh.TexCoords[0][i].X, mesh.TexCoords[0][i].Y);
                }
            }

            int nNormals = mesh.Normals.Count;

            Vector3[] normals = new Vector3[nNormals];
            for (int i = 0; i < nNormals; i++)
            {
                normals[i] = new Vector3(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z);
                normals[i].Normalize();
            }
            int nFaceNormals = mesh.NormFaces.Count;

            if (nFaceNormals > builder.Faces.Length)
            {
                throw new Exception("nFaceNormals must match the number of faces in the mesh");
            }
            for (int i = 0; i < nFaceNormals; i++)
            {
                int nVertexNormals = mesh.NormFaces[i].Indices.Count;
                if (nVertexNormals > builder.Faces[i].Vertices.Length)
                {
                    throw new Exception("nVertexNormals must match the number of verticies in the face");
                }
                for (int j = 0; j < nVertexNormals; j++)
                {
                    builder.Faces[i].Vertices[j].Normal = normals[(int)mesh.NormFaces[i].Indices[j]];
                }
            }

            int nVertexColors = (int)mesh.NumColorSets;

            for (int i = 0; i < nVertexColors; i++)
            {
                builder.Vertices[i] = new ColoredVertex((Vertex)builder.Vertices[i], new Color128(mesh.Colors[0][i].R, mesh.Colors[0][i].G, mesh.Colors[0][i].B, mesh.Colors[0][i].A));
            }
        }
Example #21
0
        private static void PreprocessSplitIntoExpressions(string FileName, bool IsRW, string[] Lines, out Expression[] Expressions, bool AllowRwRouteDescription, double trackPositionOffset)
        {
            Expressions = new Expression[4096];
            int e = 0;

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

                        case ')':
                            Level--;
                            break;

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

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

                        case ')':
                            Level--;
                            break;

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

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

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

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

                        case '@':
                            if (Level == 1 & IsRW & Interface.CurrentOptions.EnableBveTsHacks)
                            {
                                //BVE2 doesn't care if a bracket is unclosed, fixes various routefiles
                                Level--;
                            }
                            else if (Level == 2 && IsRW & Interface.CurrentOptions.EnableBveTsHacks)
                            {
                                int k = j;
                                while (k > 0)
                                {
                                    k--;
                                    if (Lines[i][k] == '(')
                                    {
                                        //Opening bracket has been used instead of closing bracket, again BVE2 ignores this
                                        Level -= 2;
                                        break;
                                    }
                                    if (!char.IsWhiteSpace(Lines[i][k]))
                                    {
                                        //Bracket not found, and this isn't whitespace either, so break out
                                        break;
                                    }
                                }
                            }
                            if (Level == 0 & IsRW)
                            {
                                string t = Lines[i].Substring(a, j - a).Trim();
                                if (t.Length > 0 && !t.StartsWith(";"))
                                {
                                    Expressions[e] = new Expression
                                    {
                                        File   = FileName,
                                        Text   = t,
                                        Line   = i + 1,
                                        Column = c + 1,
                                        TrackPositionOffset = trackPositionOffset
                                    };
                                    e++;
                                }
                                a = j + 1;
                                c++;
                            }
                            break;
                        }
                    }
                    if (Lines[i].Length - a > 0)
                    {
                        string t = Lines[i].Substring(a).Trim();
                        if (t.Length > 0 && !t.StartsWith(";"))
                        {
                            Expressions[e] = new Expression
                            {
                                File   = FileName,
                                Text   = t,
                                Line   = i + 1,
                                Column = c + 1,
                                TrackPositionOffset = trackPositionOffset
                            };
                            e++;
                        }
                    }
                }
            }
            Array.Resize <Expression>(ref Expressions, e);
        }
Example #22
0
        // create route gradient profile
        internal static Bitmap CreateRouteGradientProfile(int Width, int Height)
        {
            // find first and last used element based on stations
            int n  = TrackManager.CurrentTrack.Elements.Length;
            int n0 = n - 1;
            int n1 = 0;

            for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++)
            {
                for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                {
                    if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                    {
                        if (i < n0)
                        {
                            n0 = i;
                        }
                        if (i > n1)
                        {
                            n1 = i;
                        }
                    }
                }
            }
            n0 -= 4;
            n1 += 8;
            if (n0 < 0)
            {
                n0 = 0;
            }
            if (n1 >= TrackManager.CurrentTrack.Elements.Length)
            {
                n1 = TrackManager.CurrentTrack.Elements.Length - 1;
            }
            if (n1 <= n0)
            {
                n1 = n0 + 1;
            }
            // find dimensions
            double y0 = double.PositiveInfinity, y1 = double.NegativeInfinity;

            for (int i = n0; i <= n1; i++)
            {
                double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Y;
                if (y < y0)
                {
                    y0 = y;
                }
                if (y > y1)
                {
                    y1 = y;
                }
            }
            if (y0 >= y1 - 1.0)
            {
                y0 = y1 - 1.0;
            }
            double nd = 1.0 / (double)(n1 - n0);
            double yd = 1.0 / (double)(y1 - y0);
            double ox = 8.0, oy = 8.0;
            double w = (double)(Width - 16);
            double h = (double)(Height - 32);
            // create bitmap
            Bitmap   b = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(b);

            g.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.Clear(Color.White);
            // draw below sea level
            {
                double y  = oy + h * (1.0 - 0.5 * (double)(-Game.RouteInitialElevation - y0) * yd);
                double x0 = ox - w * (double)(n0) * nd;
                double x1 = ox + w * (double)(n - n0) * nd;
                g.FillRectangle(Brushes.PaleGoldenrod, (float)x0, (float)y, (float)x1, (float)(oy + h) - (float)y);
                g.DrawLine(Pens.Gray, (float)x0, (float)y, (float)x1, (float)y);
            }
            // draw route path
            {
                PointF[] p = new PointF[n + 2];
                p[0] = new PointF((float)(ox - w * (double)n0 * nd), (float)(oy + h));
                for (int i = 0; i < n; i++)
                {
                    double x = ox + w * (double)(i - n0) * nd;
                    double y = oy + h * (1.0 - 0.5 * (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                    p[i + 1] = new PointF((float)x, (float)y);
                }
                p[n + 1] = new PointF((float)(ox + w * (double)(n - n0 - 1) * nd), (float)(oy + h));
                g.FillPolygon(Brushes.Tan, p);
                for (int i = 1; i < n; i++)
                {
                    g.DrawLine(Pens.Black, p[i], p[i + 1]);
                }
                g.DrawLine(Pens.Black, 0.0f, (float)(oy + h), (float)Width, (float)(oy + h));
            }
            // draw station names
            {
                Font         f = new Font(FontFamily.GenericSansSerif, 12.0f, GraphicsUnit.Pixel);
                StringFormat m = new StringFormat();
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                            if (Game.Stations[e.StationIndex].Name != string.Empty)
                            {
                                bool stop = Game.PlayerStopsAtStation(e.StationIndex);
                                if (Interface.IsJapanese(Game.Stations[e.StationIndex].Name))
                                {
                                    m.Alignment     = StringAlignment.Near;
                                    m.LineAlignment = StringAlignment.Near;
                                    double x = ox + w * (double)(i - n0) * nd;
                                    double y = oy + h * (1.0 - 0.5 * (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                                    string t = Game.Stations[e.StationIndex].Name;
                                    float  tx = 0.0f, ty = (float)oy;
                                    for (int k = 0; k < t.Length; k++)
                                    {
                                        SizeF s = g.MeasureString(t.Substring(k, 1), f, 65536, StringFormat.GenericTypographic);
                                        if (s.Width > tx)
                                        {
                                            tx = s.Width;
                                        }
                                    }
                                    for (int k = 0; k < t.Length; k++)
                                    {
                                        g.DrawString(t.Substring(k, 1), f, stop ? Brushes.Black : Brushes.LightGray, (float)x - 0.5f * tx, ty);
                                        SizeF s = g.MeasureString(t.Substring(k, 1), f, 65536, StringFormat.GenericTypographic);
                                        ty += s.Height;
                                    }
                                    g.DrawLine(stop ? Pens.Gray : Pens.LightGray, new PointF((float)x, ty + 4.0f), new PointF((float)x, (float)y));
                                }
                                else
                                {
                                    m.Alignment     = StringAlignment.Far;
                                    m.LineAlignment = StringAlignment.Near;
                                    double x = ox + w * (double)(i - n0) * nd;
                                    double y = oy + h * (1.0 - 0.5 * (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                                    g.RotateTransform(-90.0f);
                                    g.TranslateTransform((float)x, (float)oy, System.Drawing.Drawing2D.MatrixOrder.Append);
                                    g.DrawString(Game.Stations[e.StationIndex].Name, f, stop ? Brushes.Black : Brushes.LightGray, new PointF(0.0f, -5.0f), m);
                                    g.ResetTransform();
                                    SizeF s = g.MeasureString(Game.Stations[e.StationIndex].Name, f);
                                    g.DrawLine(stop ? Pens.Gray : Pens.LightGray, new PointF((float)x, (float)(oy + s.Width + 4)), new PointF((float)x, (float)y));
                                }
                            }
                        }
                    }
                }
            }
            // draw route markers
            {
                Font         f  = new Font(FontFamily.GenericSansSerif, 10.0f, GraphicsUnit.Pixel);
                Font         fs = new Font(FontFamily.GenericSansSerif, 9.0f, GraphicsUnit.Pixel);
                StringFormat m  = new StringFormat();
                m.Alignment     = StringAlignment.Far;
                m.LineAlignment = StringAlignment.Center;
                System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                int k = 48 * n / Width;
                for (int i = 0; i < n; i += k)
                {
                    double x = ox + w * (double)(i - n0) * nd;
                    double y = (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd;
                    if (x < w)
                    {
                        string t = ((int)Math.Round(TrackManager.CurrentTrack.Elements[i].StartingTrackPosition)).ToString(Culture);
                        g.DrawString(t + "m", f, Brushes.Black, (float)x, (float)(oy + h + 6.0));
                    }
                    {
                        y = oy + h * (1.0 - 0.5 * y) + 2.0f;
                        string t = ((int)Math.Round(Game.RouteInitialElevation + TrackManager.CurrentTrack.Elements[i].WorldPosition.Y)).ToString(Culture);
                        SizeF  s = g.MeasureString(t, fs);
                        if (y < oy + h - (double)s.Width - 10.0)
                        {
                            g.RotateTransform(-90.0f);
                            g.TranslateTransform((float)x, (float)y + 4.0f, System.Drawing.Drawing2D.MatrixOrder.Append);
                            g.DrawString(t + "m", fs, Brushes.Black, 0.0f, 0.0f, m);
                            g.ResetTransform();
                            g.DrawLine(Pens.Gray, (float)x, (float)(y + s.Width + 12.0), (float)x, (float)(oy + h));
                        }
                    }
                }
            }
            // finalize
            return(b);
        }
Example #23
0
        private static void ParseExtensionsConfig(string filePath, Encoding encoding, out UnifiedObject[] carObjects, out UnifiedObject[] bogieObjects, out UnifiedObject[] couplerObjects, out double[] axleLocations, out double[] couplerDistances, out TrainManager.Train train, bool loadObjects)
        {
            CultureInfo culture = CultureInfo.InvariantCulture;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            if (bogieObjectsCount > 0 & bogieObjectsCount < train.Cars.Length * 2)
            {
                Interface.AddMessage(MessageType.Warning, false, $"An incomplete set of bogie objects was provided in file {filePath}");
            }
        }
Example #24
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;

            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.Derailments  = Interface.CurrentOptions.Derailments;
            TrainManager.Toppling     = Interface.CurrentOptions.Toppling;
            TrainManager.CurrentRoute = Program.CurrentRoute;
            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;
            }
            Program.TrainManager.Trains = new TrainBase[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
            for (int k = 0; k < Program.TrainManager.Trains.Length; k++)
            {
                if (k == Program.TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
                {
                    Program.TrainManager.Trains[k] = new TrainBase(TrainState.Bogus);
                }
                else
                {
                    Program.TrainManager.Trains[k] = new TrainBase(TrainState.Pending);
                }
            }
            TrainManager.PlayerTrain = Program.TrainManager.Trains[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length];



            // load trains
            for (int k = 0; k < Program.TrainManager.Trains.Length; k++)
            {
                AbstractTrain currentTrain = Program.TrainManager.Trains[k];
                for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
                {
                    if (Program.CurrentHost.Plugins[i].Train != null && Program.CurrentHost.Plugins[i].Train.CanLoadTrain(CurrentTrainFolder))
                    {
                        Program.CurrentHost.Plugins[i].Train.LoadTrain(CurrentTrainEncoding, CurrentTrainFolder, ref currentTrain, ref Interface.CurrentControls);
                        break;
                    }
                }
                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                // configure other properties
                if (currentTrain.IsPlayerTrain)
                {
                    currentTrain.TimetableDelta = 0.0;
                    if (Game.InitialReversedConsist)
                    {
                        currentTrain.Reverse();
                        TrainManager.PlayerTrain.CameraCar         = currentTrain.DriverCar;
                        Program.Renderer.Camera.CurrentRestriction = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].CameraRestrictionMode;
                    }
                }
                else if (currentTrain.State != TrainState.Bogus)
                {
                    TrainBase train = currentTrain as TrainBase;
                    currentTrain.AI             = new Game.SimpleHumanDriverAI(train, Interface.CurrentOptions.PrecedingTrainSpeedLimit);
                    currentTrain.TimetableDelta = Program.CurrentRoute.PrecedingTrainTimeDeltas[k];
                    train.Specs.DoorOpenMode    = DoorMode.Manual;
                    train.Specs.DoorCloseMode   = DoorMode.Manual;
                }
            }
            // 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


            CurrentTrain = 0;
            for (int i = 0; i < Program.TrainManager.Trains.Length; i++)
            {
                if (Program.TrainManager.Trains[i].State != TrainState.Bogus)
                {
                    if (Program.TrainManager.Trains[i].IsPlayerTrain)
                    {
                        if (!Program.TrainManager.Trains[i].LoadCustomPlugin(Program.TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding))
                        {
                            Program.TrainManager.Trains[i].LoadDefaultPlugin(Program.TrainManager.Trains[i].TrainFolder);
                        }
                    }
                    else
                    {
                        Program.TrainManager.Trains[i].LoadDefaultPlugin(Program.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(Program.TrainManager.Trains[i].vehicleSpecs());
                        }
                    }
                }
                CurrentTrain++;
            }
        }
Example #25
0
        internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, System.Text.Encoding Encoding,
                                                                          ObjectManager.ObjectLoadMode LoadMode)
        {
            XmlDocument currentXML = new XmlDocument();

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

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

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

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

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

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

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

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

                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + 1);
                            Object.Dynamic = true;
                            ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                            ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState
                            {
                                Object   = Object,
                                Position = CurrentObjects[i].Position,
                            };
                            a.States          = new ObjectManager.AnimatedObjectState[] { aos };
                            Result.Objects[i] = a;
                            if (!string.IsNullOrEmpty(CurrentObjects[i].FunctionScript))
                            {
                                Result.Objects[i].StateFunction =
                                    FunctionScripts.GetFunctionScriptFromPostfixNotation(CurrentObjects[i].FunctionScript + " 1 == --");
                            }
                        }
                    }
                }
                return(Result);
            }
            //Didn't find an acceptable XML object
            //Probably will cause things to throw an absolute wobbly somewhere....
            return(null);
        }
Example #26
0
        /// <summary>Loads the specified plugin for the specified train.</summary>
        /// <param name="train">The train to attach the plugin to.</param>
        /// <param name="pluginFile">The file to the plugin.</param>
        /// <param name="trainFolder">The train folder.</param>
        /// <returns>Whether the plugin was loaded successfully.</returns>
        private static bool LoadPlugin(TrainManager.Train train, string pluginFile, string trainFolder)
        {
            string pluginTitle = System.IO.Path.GetFileName(pluginFile);

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

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

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

            if (brakeType == BrakeTypes.AutomaticAirBrake)
            {
                brakeNotches = 2;
                powerNotches = train.Handles.Power.MaximumNotch;
                hasHoldBrake = false;
            }
            else
            {
                brakeNotches = train.Handles.Brake.MaximumNotch + (train.Handles.HasHoldBrake ? 1 : 0);
                powerNotches = train.Handles.Power.MaximumNotch;
                hasHoldBrake = train.Handles.HasHoldBrake;
            }

            bool                hasLocoBrake = train.Handles.HasLocoBrake;
            int                 cars         = train.Cars.Length;
            VehicleSpecs        specs        = new VehicleSpecs(powerNotches, brakeType, brakeNotches, hasHoldBrake, hasLocoBrake, cars);
            InitializationModes mode         = (InitializationModes)Game.TrainStart;

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

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

            /*
             * Check if the plugin is a Win32 plugin.
             *
             */
            try {
                if (!CheckWin32Header(pluginFile))
                {
                    Interface.AddMessage(MessageType.Error, false, "The train plugin " + pluginTitle + " is of an unsupported binary format and therefore cannot be used with openBVE.");
                    return(false);
                }
            } catch (Exception ex) {
                Interface.AddMessage(MessageType.Error, false, "The train plugin " + pluginTitle + " could not be read due to the following reason: " + ex.Message);
                return(false);
            }
            if (!Program.CurrentlyRunningOnWindows | IntPtr.Size != 4)
            {
                Interface.AddMessage(MessageType.Warning, false, "The train plugin " + pluginTitle + " can only be used on 32-bit Microsoft Windows or compatible.");
                return(false);
            }
            if (Program.CurrentlyRunningOnWindows && !System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\AtsPluginProxy.dll"))
            {
                Interface.AddMessage(MessageType.Warning, false, "AtsPluginProxy.dll is missing or corrupt- Please reinstall.");
                return(false);
            }
            train.Plugin = new Win32Plugin(pluginFile, train);
            if (train.Plugin.Load(specs, mode))
            {
                return(true);
            }
            else
            {
                train.Plugin = null;
                Interface.AddMessage(MessageType.Error, false, "The train plugin " + pluginTitle + " does not export a train interface and therefore cannot be used with openBVE.");
                return(false);
            }
        }
Example #27
0
 /// <summary>Parses a string into OpenBVE's internal time representation (Seconds since midnight on the first day)</summary>
 /// <param name="Expression">The time in string format</param>
 /// <param name="Value">The number of seconds since midnight on the first day this represents, updated via 'out'</param>
 /// <returns>True if the parse succeeds, false if it does not</returns>
 internal static bool TryParseTime(string Expression, out double Value)
 {
     Expression = Expression.TrimInside();
     if (Expression.Length != 0)
     {
         CultureInfo Culture = CultureInfo.InvariantCulture;
         int         i       = Expression.IndexOf('.');
         if (i == -1)
         {
             i = Expression.IndexOf(':');
         }
         if (i >= 1)
         {
             int h; if (int.TryParse(Expression.Substring(0, i), NumberStyles.Integer, Culture, out h))
             {
                 int n = Expression.Length - i - 1;
                 if (n == 1 | n == 2)
                 {
                     uint m; if (uint.TryParse(Expression.Substring(i + 1, n), NumberStyles.None, Culture, out m))
                     {
                         Value = 3600.0 * (double)h + 60.0 * (double)m;
                         return(true);
                     }
                 }
                 else if (n >= 3)
                 {
                     if (n > 4)
                     {
                         Interface.AddMessage(MessageType.Warning, false, "A maximum of 4 digits of precision are supported in TIME values");
                         n = 4;
                     }
                     uint m; if (uint.TryParse(Expression.Substring(i + 1, 2), NumberStyles.None, Culture, out m))
                     {
                         uint   s;
                         string ss = Expression.Substring(i + 3, n - 2);
                         if (Interface.CurrentOptions.EnableBveTsHacks)
                         {
                             /*
                              * Handles values in the following format:
                              * HH.MM.SS
                              */
                             if (ss.StartsWith("."))
                             {
                                 ss = ss.Substring(1, ss.Length - 1);
                             }
                         }
                         if (uint.TryParse(ss, NumberStyles.None, Culture, out s))
                         {
                             Value = 3600.0 * (double)h + 60.0 * (double)m + (double)s;
                             return(true);
                         }
                     }
                 }
             }
         }
         else if (i == -1)
         {
             int h; if (int.TryParse(Expression, NumberStyles.Integer, Culture, out h))
             {
                 Value = 3600.0 * (double)h;
                 return(true);
             }
         }
     }
     Value = 0.0;
     return(false);
 }
Example #28
0
        /// <summary>Loads a Wavefront object from a file.</summary>
        /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param>
        /// <param name="Encoding">The encoding the file is saved in. If the file uses a byte order mark, the encoding indicated by the byte order mark is used and the Encoding parameter is ignored.</param>
        /// <returns>The object loaded.</returns>
        internal static ObjectManager.StaticObject ReadObject(string FileName, Encoding Encoding)
        {
            ObjectManager.StaticObject Object = new ObjectManager.StaticObject();

            MeshBuilder Builder = new MeshBuilder();

            /*
             * Temporary arrays
             */
            List <Vector3> tempVertices = new List <Vector3>();
            List <Vector3> tempNormals  = new List <Vector3>();
            List <Vector2> tempCoords   = new List <Vector2>();

            Material[] TempMaterials = new Material[0];
            //Stores the current material
            int currentMaterial = -1;

            //Read the contents of the file
            string[] Lines = File.ReadAllLines(FileName, Encoding);

            //Preprocess
            for (int i = 0; i < Lines.Length; i++)
            {
                // Strip hash comments
                int c = Lines[i].IndexOf("#", StringComparison.Ordinal);
                if (c >= 0)
                {
                    Lines[i] = Lines[i].Substring(0, c);
                }
                // collect arguments
                List <string> Arguments = new List <string>(Lines[i].Split(new char[] { ' ', '\t' }, StringSplitOptions.None));
                for (int j = Arguments.Count - 1; j >= 0; j--)
                {
                    Arguments[j] = Arguments[j].Trim();
                    if (Arguments[j] == string.Empty)
                    {
                        Arguments.RemoveAt(j);
                    }
                }
                if (Arguments.Count == 0)
                {
                    continue;
                }
                switch (Arguments[0].ToLowerInvariant())
                {
                case "v":
                    //Vertex
                    Vector3 vertex = new Vector3();
                    if (!double.TryParse(Arguments[1], out vertex.X))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Vertex at Line " + i);
                    }
                    if (!double.TryParse(Arguments[2], out vertex.Y))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Y co-ordinate in Vertex at Line " + i);
                    }
                    if (!double.TryParse(Arguments[3], out vertex.Z))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Z co-ordinate in Vertex at Line " + i);
                    }
                    tempVertices.Add(vertex);
                    break;

                case "vt":
                    //Vertex texture co-ords
                    Vector2 coords = new Vector2();
                    if (!double.TryParse(Arguments[1], out coords.X))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Texture Co-ordinates at Line " + i);
                    }
                    if (!double.TryParse(Arguments[2], out coords.Y))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Texture Co-Ordinates at Line " + i);
                    }
                    tempCoords.Add(coords);
                    break;

                case "vn":
                    Vector3 normal = new Vector3();
                    if (!double.TryParse(Arguments[1], out normal.X))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Vertex Normal at Line " + i);
                    }
                    if (!double.TryParse(Arguments[2], out normal.Y))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Y co-ordinate in Vertex Normal at Line " + i);
                    }
                    if (!double.TryParse(Arguments[3], out normal.Z))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid Z co-ordinate in Vertex Normal at Line " + i);
                    }
                    tempNormals.Add(normal);
                    //Vertex normals
                    break;

                case "vp":
                    //Parameter space verticies, not supported
                    throw new NotSupportedException("Parameter space verticies are not supported by this parser");

                case "f":
                    //Creates a new face

                    //Create the temp list to hook out the vertices
                    List <Vertex>  vertices = new List <Vertex>();
                    List <Vector3> normals  = new List <Vector3>();
                    for (int f = 1; f < Arguments.Count; f++)
                    {
                        Vertex   newVertex     = new Vertex();
                        string[] faceArguments = Arguments[f].Split(new char[] { '/' }, StringSplitOptions.None);
                        int      idx;
                        if (!int.TryParse(faceArguments[0], out idx))
                        {
                            Interface.AddMessage(MessageType.Warning, false, "Invalid Vertex index in Face " + f + " at Line " + i);
                            continue;
                        }

                        int currentVertex = tempVertices.Count;
                        if (idx != Math.Abs(idx))
                        {
                            //Offset, so we seem to need to add one....
                            currentVertex++;
                            currentVertex += idx;
                        }
                        else
                        {
                            currentVertex = idx;
                        }
                        if (currentVertex > tempVertices.Count)
                        {
                            Interface.AddMessage(MessageType.Warning, false, "Vertex index " + idx + " was greater than the available number of vertices in Face " + f + " at Line " + i);
                            continue;
                        }
                        newVertex.Coordinates = tempVertices[currentVertex - 1];
                        if (faceArguments.Length <= 1)
                        {
                            normals.Add(new Vector3());
                        }
                        else
                        {
                            if (!int.TryParse(faceArguments[1], out idx))
                            {
                                if (!string.IsNullOrEmpty(faceArguments[1]))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid Texture Co-ordinate index in Face " + f + " at Line " + i);
                                }
                                newVertex.TextureCoordinates = new Vector2();
                            }
                            else
                            {
                                int currentCoord = tempCoords.Count;
                                if (idx != Math.Abs(idx))
                                {
                                    //Offset, so we seem to need to add one....
                                    currentCoord++;
                                    currentCoord += idx;
                                }
                                else
                                {
                                    currentCoord = idx;
                                }
                                if (currentCoord > tempCoords.Count)
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Texture Co-ordinate index " + currentCoord + " was greater than the available number of texture co-ordinates in Face " + f + " at Line " + i);
                                }
                                else
                                {
                                    newVertex.TextureCoordinates = tempCoords[currentCoord - 1];
                                }
                            }
                        }
                        if (faceArguments.Length <= 2)
                        {
                            normals.Add(new Vector3());
                        }
                        else
                        {
                            if (!int.TryParse(faceArguments[2], out idx))
                            {
                                if (!string.IsNullOrEmpty(faceArguments[2]))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid Vertex Normal index in Face " + f + " at Line " + i);
                                }
                                normals.Add(new Vector3());
                            }
                            else
                            {
                                int currentNormal = tempNormals.Count;
                                if (idx != Math.Abs(idx))
                                {
                                    //Offset, so we seem to need to add one....
                                    currentNormal++;
                                    currentNormal += idx;
                                }
                                else
                                {
                                    currentNormal = idx;
                                }
                                if (currentNormal > tempNormals.Count)
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Vertex Normal index " + currentNormal + " was greater than the available number of normals in Face " + f + " at Line " + i);
                                    normals.Add(new Vector3());
                                }
                                else
                                {
                                    normals.Add(tempNormals[currentNormal - 1]);
                                }
                            }
                        }
                        vertices.Add(newVertex);
                    }
                    MeshFaceVertex[] Vertices = new MeshFaceVertex[vertices.Count];
                    for (int k = 0; k < vertices.Count; k++)
                    {
                        Builder.Vertices.Add(vertices[k]);
                        Vertices[k].Index  = (ushort)(Builder.Vertices.Count - 1);
                        Vertices[k].Normal = normals[k];
                    }
                    Builder.Faces.Add(currentMaterial == -1 ? new MeshFace(Vertices, 0) : new MeshFace(Vertices, (ushort)currentMaterial));
                    break;

                case "g":
                    //Starts a new face group and (normally) applies a new texture
                    ApplyMeshBuilder(ref Object, Builder);
                    Builder = new MeshBuilder();
                    break;

                case "s":
                    /*
                     * Changes the smoothing group applied to these vertexes:
                     * 0- Disabled (Overriden by Vertex normals)
                     * Otherwise appears to be a bitmask (32 available groups)
                     * whereby faces within the same groups have their normals averaged
                     * to appear smooth joins
                     *
                     * Not really supported at the minute, probably requires the engine
                     * twiddling to deliberately support specifiying the shading type for a face
                     *
                     */
                    break;

                case "mtllib":
                    //Loads the library of materials used by this file
                    string MaterialsPath = OpenBveApi.Path.CombineFile(Path.GetDirectoryName(FileName), Arguments[1]);
                    if (File.Exists(MaterialsPath))
                    {
                        LoadMaterials(MaterialsPath, ref TempMaterials);
                    }
                    break;

                case "usemtl":
                    for (int m = 0; m < TempMaterials.Length; m++)
                    {
                        if (TempMaterials[m].Key.ToLowerInvariant() == Arguments[1].ToLowerInvariant())
                        {
                            bool mf = false;
                            for (int k = 0; k < Builder.Materials.Length; k++)
                            {
                                if (Builder.Materials[k].Key.ToLowerInvariant() == Arguments[1].ToLowerInvariant())
                                {
                                    mf = true;
                                    currentMaterial = k;
                                    break;
                                }
                            }
                            if (!mf)
                            {
                                Array.Resize(ref Builder.Materials, Builder.Materials.Length + 1);
                                Builder.Materials[Builder.Materials.Length - 1] = TempMaterials[m];
                                currentMaterial = Builder.Materials.Length - 1;
                            }
                            break;
                        }
                        if (m == TempMaterials.Length)
                        {
                            Interface.AddMessage(MessageType.Error, true, "Material " + Arguments[1] + " was not found.");
                            currentMaterial = -1;
                        }
                    }
                    break;

                default:
                    Interface.AddMessage(MessageType.Warning, false, "Unrecognised command " + Arguments[0]);
                    break;
                }
            }
            ApplyMeshBuilder(ref Object, Builder);
            Object.Mesh.CreateNormals();
            return(Object);
        }
Example #29
0
        /// <summary>Attempts to load and parse the current train's panel configuration file.</summary>
        /// <param name="TrainPath">The absolute on-disk path to the train folder.</param>
        /// <param name="Encoding">The automatically detected or manually set encoding of the panel configuration file.</param>
        /// <param name="Train">The base train on which to apply the panel configuration.</param>
        internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Encoding, Train Train)
        {
            Train.Cars[Train.DriverCar].CarSections    = new CarSection[1];
            Train.Cars[Train.DriverCar].CarSections[0] = new CarSection
            {
                Groups = new ElementsGroup[1]
            };
            Train.Cars[Train.DriverCar].CarSections[0].Groups[0] = new ElementsGroup
            {
                Elements = new ObjectManager.AnimatedObject[] { },
                Overlay  = true
            };
            string File = OpenBveApi.Path.CombineFile(TrainPath, "panel.xml");

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

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

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

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

            var Panel2 = false;

            try
            {
                File = OpenBveApi.Path.CombineFile(TrainPath, "panel2.cfg");
                if (System.IO.File.Exists(File))
                {
                    Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                    Panel2 = true;
                    Panel2CfgParser.ParsePanel2Config("panel2.cfg", TrainPath, Encoding, Train, Train.DriverCar);
                    Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.On;
                    Camera.CurrentRestriction = CameraRestrictionMode.On;
                }
                else
                {
                    File = OpenBveApi.Path.CombineFile(TrainPath, "panel.cfg");
                    if (System.IO.File.Exists(File))
                    {
                        Program.FileSystem.AppendToLogFile("Loading train panel: " + File);
                        PanelCfgParser.ParsePanelConfig(TrainPath, Encoding, Train);
                        Train.Cars[Train.DriverCar].CameraRestrictionMode = CameraRestrictionMode.On;
                        Camera.CurrentRestriction = CameraRestrictionMode.On;
                    }
                    else
                    {
                        Camera.CurrentRestriction = CameraRestrictionMode.NotAvailable;
                    }
                }
            }
            catch
            {
                var currentError = Translations.GetInterfaceString("errors_critical_file");
                currentError = currentError.Replace("[file]", Panel2 ? "panel2.cfg" : "panel.cfg");
                MessageBox.Show(currentError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                Program.RestartArguments = " ";
                Loading.Cancel           = true;
            }
        }
Example #30
0
        public static bool ReadMarkerXML(string fileName, ref CsvRwRouteParser.Marker marker)
        {
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

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

            if (currentXML.DocumentElement != null)
            {
                bool        iM            = false;
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/TextMarker");

                if (DocumentNodes == null || DocumentNodes.Count == 0)
                {
                    DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/ImageMarker");
                    iM            = true;
                }
                if (DocumentNodes == null || DocumentNodes.Count == 0)
                {
                    Interface.AddMessage(MessageType.Error, false, "No marker nodes defined in XML file " + fileName);
                    return(false);
                }
                //marker = new CsvRwRouteParser.Marker();
                foreach (XmlNode n in DocumentNodes)
                {
                    if (n.ChildNodes.OfType <XmlElement>().Any())
                    {
                        bool     EarlyDefined = false, LateDefined = false;
                        string   EarlyText = null, Text = null, LateText = null;
                        string[] Trains = null;
                        Texture  EarlyTexture = null, Texture = null, LateTexture = null;
                        double   EarlyTime = 0.0, LateTime = 0.0, TimeOut = Double.PositiveInfinity, EndingPosition = Double.PositiveInfinity;
                        OpenBveApi.Colors.MessageColor EarlyColor = MessageColor.White, OnTimeColor = MessageColor.White, LateColor = MessageColor.White;
                        foreach (XmlNode c in n.ChildNodes)
                        {
                            switch (c.Name.ToLowerInvariant())
                            {
                            case "early":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false,
                                                         "No paramaters defined for the early message in " + fileName);
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "text":
                                        EarlyText = cc.InnerText;
                                        break;

                                    case "texture":
                                    case "image":
                                        string f;
                                        try
                                        {
                                            f = OpenBveApi.Path.CombineFile(Path, cc.InnerText);
                                        }
                                        catch
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "MessageEarlyTexture path was malformed in file " + fileName);
                                            break;
                                        }
                                        if (System.IO.File.Exists(f))
                                        {
                                            if (!Program.CurrentHost.RegisterTexture(f, new TextureParameters(null, null), out EarlyTexture))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Loading MessageEarlyTexture " + f + " failed.");
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "MessageEarlyTexture " + f + " does not exist.");
                                        }
                                        break;

                                    case "time":
                                        if (!Interface.TryParseTime(cc.InnerText, out EarlyTime))
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Early message time invalid in " + fileName);
                                        }
                                        EarlyDefined = true;
                                        break;

                                    case "color":
                                        EarlyColor = ParseColor(cc.InnerText, fileName);
                                        break;
                                    }
                                }
                                break;

                            case "ontime":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false,
                                                         "No paramaters defined for the on-time message in " + fileName);
                                }
                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "text":
                                        Text = cc.InnerText;
                                        break;

                                    case "texture":
                                    case "image":
                                        string f;
                                        try
                                        {
                                            f = OpenBveApi.Path.CombineFile(Path, cc.InnerText);
                                        }
                                        catch
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "MessageTexture path was malformed in file " + fileName);
                                            break;
                                        }
                                        if (System.IO.File.Exists(f))
                                        {
                                            if (!Program.CurrentHost.RegisterTexture(f, new TextureParameters(null, null), out Texture))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Loading MessageTexture " + f + " failed.");
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "MessageTexture " + f + " does not exist.");
                                        }
                                        break;

                                    case "color":
                                        OnTimeColor = ParseColor(cc.InnerText, fileName);
                                        break;

                                    case "time":
                                        Interface.AddMessage(MessageType.Error, false, "OnTime should not contain a TIME declaration in " + fileName);
                                        break;
                                    }
                                }
                                break;

                            case "late":
                                if (!c.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    Interface.AddMessage(MessageType.Error, false,
                                                         "No paramaters defined for the late message in " + fileName);
                                }

                                foreach (XmlNode cc in c.ChildNodes)
                                {
                                    switch (cc.Name.ToLowerInvariant())
                                    {
                                    case "text":
                                        LateText = cc.InnerText;
                                        break;

                                    case "texture":
                                    case "image":
                                        string f;
                                        try
                                        {
                                            f = OpenBveApi.Path.CombineFile(Path, cc.InnerText);
                                        }
                                        catch
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "MessageLateTexture path was malformed in file " + fileName);
                                            break;
                                        }
                                        if (System.IO.File.Exists(f))
                                        {
                                            if (!Program.CurrentHost.RegisterTexture(f, new TextureParameters(null, null), out LateTexture))
                                            {
                                                Interface.AddMessage(MessageType.Error, false, "Loading MessageLateTexture " + f + " failed.");
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "MessageLateTexture " + f + " does not exist.");
                                        }
                                        break;

                                    case "time":
                                        if (!Interface.TryParseTime(cc.InnerText, out LateTime))
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "Early message time invalid in " + fileName);
                                        }
                                        LateDefined = true;
                                        break;

                                    case "color":
                                        LateColor = ParseColor(cc.InnerText, fileName);
                                        break;
                                    }
                                }
                                break;

                            case "timeout":
                                if (!NumberFormats.TryParseDouble(c.InnerText, new[] { 1.0 }, out TimeOut))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Marker timeout invalid in " + fileName);
                                }
                                break;

                            case "distance":
                                if (!NumberFormats.TryParseDouble(c.InnerText, new[] { 1.0 }, out EndingPosition))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Marker distance invalid in " + fileName);
                                }
                                break;

                            case "trains":
                                Trains = c.InnerText.Split(';');
                                break;
                            }
                        }
                        //Check this marker is valid
                        if (TimeOut == Double.PositiveInfinity && EndingPosition == Double.PositiveInfinity)
                        {
                            Interface.AddMessage(MessageType.Error, false, "No marker timeout or distance defined in marker XML " + fileName);
                            return(false);
                        }
                        if (EndingPosition != Double.PositiveInfinity)
                        {
                            if (Math.Abs(EndingPosition) == EndingPosition)
                            {
                                //Positive
                                marker.EndingPosition = marker.StartingPosition + EndingPosition;
                            }
                            else
                            {
                                //Negative
                                marker.EndingPosition    = marker.StartingPosition;
                                marker.StartingPosition -= EndingPosition;
                            }
                        }
                        MessageManager.TextureMessage t = new MessageManager.TextureMessage();
                        MessageManager.GeneralMessage m = new MessageManager.GeneralMessage();
                        //Add variants

                        if (EarlyDefined)
                        {
                            if (iM)
                            {
                                if (EarlyTexture != null)
                                {
                                    t.MessageEarlyTime    = EarlyTime;
                                    t.MessageEarlyTexture = EarlyTexture;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "An early time was defined, but no message was specified in MarkerXML " + fileName);
                                }
                            }
                            else
                            {
                                if (EarlyText != null)
                                {
                                    m.MessageEarlyTime  = EarlyTime;
                                    m.MessageEarlyText  = EarlyText;
                                    m.MessageEarlyColor = EarlyColor;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "An early time was defined, but no message was specified in MarkerXML " + fileName);
                                }
                            }
                        }
                        if (LateDefined)
                        {
                            if (iM)
                            {
                                if (LateTexture != null)
                                {
                                    t.MessageLateTime    = LateTime;
                                    t.MessageLateTexture = LateTexture;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "A late time was defined, but no message was specified in MarkerXML " + fileName);
                                }
                            }
                            else
                            {
                                if (LateText != null)
                                {
                                    m.MessageLateTime  = LateTime;
                                    m.MessageLateText  = LateText;
                                    m.MessageLateColor = LateColor;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "An early time was defined, but no message was specified in MarkerXML " + fileName);
                                }
                            }
                        }
                        //Final on-time message
                        if (iM)
                        {
                            t.Trains = Trains;
                            if (Texture != null)
                            {
                                t.MessageOnTimeTexture = Texture;
                            }
                        }
                        else
                        {
                            m.Trains = Trains;
                            if (Text != null)
                            {
                                m.MessageOnTimeText = Text;
                                m.Color             = OnTimeColor;
                            }
                        }
                        if (iM)
                        {
                            marker.Message = t;
                        }
                        else
                        {
                            marker.Message = m;
                        }
                    }
                }
            }
            return(true);
        }
Example #31
0
        /// <summary>Saves the current in-game black box log</summary>
        internal static void SaveLogs()
        {
            if (Interface.CurrentOptions.BlackBox == false)
            {
                return;
            }
            string BlackBoxFile = OpenBveApi.Path.CombineFile(Program.FileSystem.SettingsFolder, "logs.bin");

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

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

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

                    Stream.Close();
                }
            }
            catch
            {
                Interface.CurrentOptions.BlackBox = false;
                Interface.AddMessage(MessageType.Error, false, "An unexpected error occurred whilst attempting to write to the black box log- Black box has been disabled.");
            }
        }
Example #32
0
        /// <summary>Loads a Loksim3D GruppenObject</summary>
        /// <param name="FileName">The filename to load</param>
        /// <param name="Encoding">The text encoding of the containing file (Currently ignored, REMOVE??)</param>
        /// <param name="LoadMode">The object load mode</param>
        /// <returns>A new animated object collection, containing the GruppenObject's meshes etc.</returns>
        /// <param name="Rotation">A three-dimemsional vector describing the rotation to be applied</param>
        internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, System.Text.Encoding Encoding, ObjectManager.ObjectLoadMode LoadMode, Vector3 Rotation)
        {
            XmlDocument currentXML = new XmlDocument();

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

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

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

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

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

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

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

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

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

                    //Single mesh object, containing all static components of the LS3D object
                    //If we use multiples, the Z-sorting throws a wobbly
                    ObjectManager.StaticObject staticObject = null;
                    for (int i = 0; i < CurrentObjects.Length; i++)
                    {
                        if (CurrentObjects[i] == null || string.IsNullOrEmpty(CurrentObjects[i].Name))
                        {
                            continue;
                        }
                        ObjectManager.StaticObject             Object         = null;
                        ObjectManager.AnimatedObjectCollection AnimatedObject = null;
                        try
                        {
                            if (CurrentObjects[i].Name.ToLowerInvariant().EndsWith(".l3dgrp"))
                            {
                                AnimatedObject = ReadObject(CurrentObjects[i].Name, Encoding, LoadMode, CurrentObjects[i].Rotation);
                            }
                            else if (CurrentObjects[i].Name.ToLowerInvariant().EndsWith(".l3dobj"))
                            {
                                Object = (ObjectManager.StaticObject)ObjectManager.LoadObject(CurrentObjects[i].Name, Encoding, LoadMode, false, false, false, CurrentObjects[i].Rotation);
                            }
                            else
                            {
                                throw new Exception("Format " + System.IO.Path.GetExtension(CurrentObjects[i].Name) + " is not currently supported by the Loksim3D object parser");
                            }
                        }
                        catch (Exception ex) {
                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message);
                        }
                        if (Object != null)
                        {
                            if (!string.IsNullOrEmpty(CurrentObjects[i].FunctionScript))
                            {
                                //If the function script is not empty, this is a new animated object bit
                                Array.Resize <ObjectManager.UnifiedObject>(ref obj, obj.Length + 1);
                                obj[obj.Length - 1] = Object;
                                int aL = Result.Objects.Length;
                                Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, aL + 1);
                                ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                                ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState
                                {
                                    Object   = Object,
                                    Position = CurrentObjects[i].Position,
                                };
                                a.States           = new ObjectManager.AnimatedObjectState[] { aos };
                                Result.Objects[aL] = a;
                                Result.Objects[aL].StateFunction =
                                    FunctionScripts.GetFunctionScriptFromPostfixNotation(CurrentObjects[i].FunctionScript + " 1 == --");
                            }
                            else
                            {
                                //Otherwise, join to the main static mesh & update co-ords
                                for (int j = 0; j < Object.Mesh.Vertices.Length; j++)
                                {
                                    Object.Mesh.Vertices[j].Coordinates += CurrentObjects[i].Position;
                                }
                                ObjectManager.JoinObjects(ref staticObject, Object);
                            }
                        }
                        else if (AnimatedObject != null)
                        {
                            int rl = Result.Objects.Length;
                            int l  = AnimatedObject.Objects.Length;
                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + l);
                            for (int o = rl; o < rl + l; o++)
                            {
                                if (AnimatedObject.Objects[o - rl] != null)
                                {
                                    Result.Objects[o] = AnimatedObject.Objects[o - rl].Clone();
                                    for (int si = 0; si < Result.Objects[o].States.Length; si++)
                                    {
                                        Result.Objects[o].States[si].Position += CurrentObjects[i].Position;
                                    }
                                }
                                else
                                {
                                    Result.Objects[o]        = new ObjectManager.AnimatedObject();
                                    Result.Objects[o].States = new ObjectManager.AnimatedObjectState[0];
                                }
                            }
                        }
                    }
                    if (staticObject != null)
                    {
                        Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length + 1);
                        ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                        ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState
                        {
                            Object = staticObject,
                        };
                        a.States = new ObjectManager.AnimatedObjectState[] { aos };
                        Result.Objects[Result.Objects.Length - 1] = a;
                    }
                }
                return(Result);
            }
            //Didn't find an acceptable XML object
            //Probably will cause things to throw an absolute wobbly somewhere....
            return(null);
        }
Example #33
0
        // --- functions ---

        /// <summary>Reports a problem to the host application.</summary>
        /// <param name="type">The type of problem that is reported.</param>
        /// <param name="text">The textual message that describes the problem.</param>
        public override void ReportProblem(ProblemType type, string text)
        {
            Interface.AddMessage(MessageType.Error, false, text);
        }
Example #34
0
 public override void AddMessage(MessageType type, bool FileNotFound, string text)
 {
     Interface.AddMessage(type, FileNotFound, text);
 }
Example #35
0
		//
		// SET CONTROL CUSTOM DATA
		//
		internal void SetControlKbdCustomData(Key key, Interface.KeyboardModifier keybMod)
		{
			//Check that we are customising a key, and that our key is NOT the menu back key
			if (isCustomisingControl && key != MenuBackKey && CustomControlIdx < Interface.CurrentControls.Length)
			{
				Interface.CurrentControls[CustomControlIdx].Method = Interface.ControlMethod.Keyboard;
				Interface.CurrentControls[CustomControlIdx].Key = key;
				Interface.CurrentControls[CustomControlIdx].Modifier = keybMod;
				Interface.SaveControls(null);
			}
			PopMenu();
			isCustomisingControl	= false;
			
		}