/// <summary>Draws a rectangle.</summary> /// <param name="texture">The texture, or a null reference.</param> /// <param name="point">The top-left coordinates in pixels.</param> /// <param name="size">The size in pixels.</param> /// <param name="color">The color, or a null reference.</param> internal static void DrawRectangle(Textures.Texture texture, Point point, Size size, Nullable<Color128> color) { // TODO: Remove Nullable<T> from color once RenderOverlayTexture and RenderOverlaySolid are fully replaced. if (texture == null || !Textures.LoadTexture(texture, Textures.OpenGlTextureWrapMode.ClampClamp)) { Gl.glDisable(Gl.GL_TEXTURE_2D); if (color.HasValue) { Gl.glColor4d(color.Value.R, color.Value.G, color.Value.B, color.Value.A); } Gl.glBegin(Gl.GL_QUADS); Gl.glVertex2d(point.X, point.Y); Gl.glVertex2d(point.X + size.Width, point.Y); Gl.glVertex2d(point.X + size.Width, point.Y + size.Height); Gl.glVertex2d(point.X, point.Y + size.Height); Gl.glEnd(); } else { Gl.glEnable(Gl.GL_TEXTURE_2D); Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture.OpenGlTextures[(int)Textures.OpenGlTextureWrapMode.ClampClamp].Name); if (color.HasValue) { Gl.glColor4d(color.Value.R, color.Value.G, color.Value.B, color.Value.A); } Gl.glBegin(Gl.GL_QUADS); Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex2d(point.X, point.Y); Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex2d(point.X + size.Width, point.Y); Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex2d(point.X + size.Width, point.Y + size.Height); Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex2d(point.X, point.Y + size.Height); Gl.glEnd(); } }
/// <summary>Draws a rectangle.</summary> /// <param name="texture">The texture, or a null reference.</param> /// <param name="point">The top-left coordinates in pixels.</param> /// <param name="size">The size in pixels.</param> /// <param name="color">The color, or a null reference.</param> internal static void DrawRectangle(Textures.Texture texture, Point point, Size size, Color128? color) { // TODO: Remove Nullable<T> from color once RenderOverlayTexture and RenderOverlaySolid are fully replaced. if (texture == null || !Textures.LoadTexture(texture, Textures.OpenGlTextureWrapMode.ClampClamp)) { GL.Disable(EnableCap.Texture2D); if (color.HasValue) { GL.Color4(color.Value.R, color.Value.G, color.Value.B, color.Value.A); } GL.Begin(PrimitiveType.Quads); GL.Vertex2(point.X, point.Y); GL.Vertex2(point.X + size.Width, point.Y); GL.Vertex2(point.X + size.Width, point.Y + size.Height); GL.Vertex2(point.X, point.Y + size.Height); GL.End(); } else { GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, texture.OpenGlTextures[(int)Textures.OpenGlTextureWrapMode.ClampClamp].Name); if (color.HasValue) { GL.Color4(color.Value.R, color.Value.G, color.Value.B, color.Value.A); } GL.Begin(PrimitiveType.Quads); GL.TexCoord2(0.0f, 0.0f); GL.Vertex2(point.X, point.Y); GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(point.X + size.Width, point.Y); GL.TexCoord2(1.0f, 1.0f); GL.Vertex2(point.X + size.Width, point.Y + size.Height); GL.TexCoord2(0.0f, 1.0f); GL.Vertex2(point.X, point.Y + size.Height); GL.End(); } }
/// <summary>Creates a new static background, using the default 0.8s fade-in time</summary> /// <param name="Texture">The texture to apply</param> /// <param name="Repetition">The number of times the texture should be repeated around the viewing frustrum</param> /// <param name="KeepAspectRatio">Whether the aspect ratio of the texture should be preseved</param> internal StaticBackground(Textures.Texture Texture, double Repetition, bool KeepAspectRatio) { this.Texture = Texture; this.Repetition = Repetition; this.KeepAspectRatio = KeepAspectRatio; this.TransitionTime = 0.8; this.Time = -1; }
/// <summary>Creates a new static background</summary> /// <param name="Texture">The texture to apply</param> /// <param name="Repetition">The number of times the texture should be repeated around the viewing frustrum</param> /// <param name="KeepAspectRatio">Whether the aspect ratio of the texture should be preseved</param> /// <param name="transitionTime">The time taken in seconds for the fade-in transition to occur</param> /// <param name="Mode">The transition mode</param> /// <param name="Time">The time at which this background is to be displayed, expressed as the number of seconds since midnight</param> internal StaticBackground(Textures.Texture Texture, double Repetition, bool KeepAspectRatio, double transitionTime, BackgroundTransitionMode Mode, double Time) { this.Texture = Texture; this.Repetition = Repetition; this.KeepAspectRatio = KeepAspectRatio; this.TransitionTime = transitionTime; this.Mode = Mode; this.Time = Time; }
// --- functions --- /// <summary>Gets data associated with the specified codepoint.</summary> /// <param name="text">The string containing the codepoint.</param> /// <param name="offset">The offset at which to read the codepoint. For surrogate pairs, two characters are read, and one otherwise.</param> /// <param name="texture">Receives the texture that contains the codepoint.</param> /// <param name="data">Receives the data that describes the codepoint.</param> /// <returns>The number of characters read.</returns> internal int GetCharacterData(string text, int offset, out Textures.Texture texture, out OpenGlFontChar data) { int value = char.ConvertToUtf32(text, offset); int hi = value >> 8; int lo = value & 0xFF; this.Tables[hi] = this.Tables[hi] ?? new OpenGlFontTable(this.Font, hi << 8); texture = this.Tables[hi].Texture; data = this.Tables[hi].Characters[lo]; return value >= 0x10000 ? 2 : 1; }
internal static void RemoveMarker(Textures.Texture Texture) { int n = MarkerTextures.Length; for (int i = 0; i < n; i++) { if (MarkerTextures[i] == Texture) { for (int j = i; j < n - 1; j++) { MarkerTextures[j] = MarkerTextures[j + 1]; } n--; Array.Resize<Textures.Texture>(ref MarkerTextures, n); break; } } }
/// <summary>Registers a texture and returns a handle to the texture.</summary> /// <param name="texture">The texture data.</param> /// <param name="parameters">The parameters that specify how to process the texture.</param> /// <param name="handle">Receives the handle to the texture.</param> /// <returns>Whether loading the texture was successful.</returns> public override bool RegisterTexture(Texture texture, TextureParameters parameters, out Texture handle) { texture = texture.ApplyParameters(parameters); handle = Textures.RegisterTexture(texture); return(true); }
private static void RenderOverlayTexture(Textures.Texture texture, double left, double top, double right, double bottom) { DrawRectangle(texture, new System.Drawing.Point((int)left, (int)top), new System.Drawing.Size((int)(right - left), (int)(bottom - top)), null); }
// // 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(BlendingFactor.SrcAlpha, BlendingFactor.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); DrawRectangle(null, new System.Drawing.Point((int)0, (int)0), new System.Drawing.Size((int)Renderer.ScreenWidth, (int)Renderer.ScreenHeight), null); GL.Color4(1.0f, 1.0f, 1.0f, 1.0f); // BACKGROUND IMAGE int bkgHeight = Renderer.ScreenHeight, bkgWidth = Renderer.ScreenWidth; int fontHeight = (int)Fonts.SmallFont.FontSize; int logoBottom; // int versionTop; int halfWidth = Renderer.ScreenWidth / 2; bool bkgLoaded = TextureLoadingBkg != null; if (TextureLoadingBkg != null && Textures.LoadTexture(TextureLoadingBkg, OpenGlTextureWrapMode.ClampClamp)) { if (TextureLoadingBkg.Width != Renderer.ScreenWidth && TextureLoadingBkg.Height != Renderer.ScreenHeight) { // stretch the background image to fit at least one screen dimension double ratio = (double)TextureLoadingBkg.Width / (double)TextureLoadingBkg.Height; if ((double)Renderer.ScreenWidth / ratio > Renderer.ScreenHeight) // if screen ratio is shorter than bkg... { bkgHeight = Renderer.ScreenHeight; // set height to screen height bkgWidth = (int)(Renderer.ScreenWidth * ratio); // and scale width proprtionally } else // if screen ratio is wider than bkg... { bkgWidth = Renderer.ScreenWidth; // set width to screen width bkgHeight = (int)(Renderer.ScreenHeight / ratio); // and scale height accordingly } } // draw the background image down from the top screen edge try { DrawRectangle(TextureLoadingBkg, new Point((Renderer.ScreenWidth - bkgWidth) / 2, 0), new Size(bkgWidth, bkgHeight), Color128.White); } catch { TextureLoadingBkg = null; } } // if the route has no custom loading image, add the openBVE logo // (the route custom image is loaded in OldParsers/CsvRwRouteParser.cs) if (!customLoadScreen && Interface.CurrentOptions.LoadingLogo && TextureLogo != null) { // place the centre of the logo at from the screen top int logoTop = (int)(Renderer.ScreenHeight * logoCentreYFactor - TextureLogo.Height / 2.0); DrawRectangle(TextureLogo, new Point((Renderer.ScreenWidth - 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 = Renderer.ScreenHeight / 2; if (!bkgLoaded) // if the background texture not yet loaded, do nothing else { return; } // take the height remaining below the logo and divide in 3 horiz. parts int blankHeight = (Renderer.ScreenHeight - logoBottom) / 3; // VERSION NUMBER // place the version above the first division // int versionTop = logoBottom + blankHeight - fontHeight; //RenderString(Fonts.SmallFontSize, "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); // place progress bar right below the second division int progressTop = Renderer.ScreenHeight - blankHeight; int progressWidth = Renderer.ScreenWidth - progrMargin * 2; double routeProgress = Math.Max(0.0, Math.Min(1.0, Loading.RouteProgress)); if (Interface.CurrentOptions.LoadingProgressBar) { // PROGRESS MESSAGE AND BAR double percent = 100.0 * routeProgress; 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); DrawString(Fonts.SmallFont, percStr, new Point(halfWidth, progressTop + 2), TextAlignment.TopMiddle, Color128.Black); } string text = "Loading route, please wait....."; DrawString(Fonts.SmallFont, text, new Point(halfWidth, progressTop - fontHeight - 6), TextAlignment.TopMiddle, Color128.White); GL.PopMatrix(); }
/// <summary>Renders all default HUD elements</summary> /// <param name="Element">The HUD element these are to be rendererd onto</param> /// <param name="TimeElapsed">The time elapsed</param> private static void RenderHUDElement(HUD.Element Element, double TimeElapsed) { TrainManager.TrainDoorState LeftDoors = TrainManager.GetDoorsState(TrainManager.PlayerTrain, true, false); TrainManager.TrainDoorState RightDoors = TrainManager.GetDoorsState(TrainManager.PlayerTrain, false, true); System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture; string Command = Element.Subject.ToLowerInvariant(); // default double w, h; if (Element.CenterMiddle.BackgroundTexture != null) { if (Textures.LoadTexture(Element.CenterMiddle.BackgroundTexture, Textures.OpenGlTextureWrapMode.ClampClamp)) { w = (double)Element.CenterMiddle.BackgroundTexture.Width; h = (double)Element.CenterMiddle.BackgroundTexture.Height; } else { w = 0.0; h = 0.0; } } else { w = 0.0; h = 0.0; } double x = Element.Alignment.X < 0 ? 0.0 : Element.Alignment.X == 0 ? 0.5 * (Screen.Width - w) : Screen.Width - w; double y = Element.Alignment.Y < 0 ? 0.0 : Element.Alignment.Y == 0 ? 0.5 * (Screen.Height - h) : Screen.Height - h; x += Element.Position.X; y += Element.Position.Y; // command const double speed = 1.0; MessageColor sc = MessageColor.None; string t; switch (Command) { case "reverser": if (TrainManager.PlayerTrain.Handles.Reverser.Driver < 0) { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 2) { t = TrainManager.PlayerTrain.ReverserDescriptions[2]; } else { t = Interface.QuickReferences.HandleBackward; } } else if (TrainManager.PlayerTrain.Handles.Reverser.Driver > 0) { sc = MessageColor.Blue; if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 0) { t = TrainManager.PlayerTrain.ReverserDescriptions[0]; } else { t = Interface.QuickReferences.HandleForward; } } else { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 1) { t = TrainManager.PlayerTrain.ReverserDescriptions[1]; } else { t = Interface.QuickReferences.HandleNeutral; } } Element.TransitionState = 0.0; break; case "power": if (TrainManager.PlayerTrain.Handles.SingleHandle) { return; } if (TrainManager.PlayerTrain.Handles.Power.Driver == 0) { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.PowerNotchDescriptions.Length > 0) { t = TrainManager.PlayerTrain.PowerNotchDescriptions[0]; } else { t = Interface.QuickReferences.HandlePowerNull; } } else { sc = MessageColor.Blue; if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.Handles.Power.Driver < TrainManager.PlayerTrain.PowerNotchDescriptions.Length) { t = TrainManager.PlayerTrain.PowerNotchDescriptions[TrainManager.PlayerTrain.Handles.Power.Driver]; } else { t = Interface.QuickReferences.HandlePower + TrainManager.PlayerTrain.Handles.Power.Driver.ToString(Culture); } } Element.TransitionState = 0.0; break; case "brake": if (TrainManager.PlayerTrain.Handles.SingleHandle) { return; } if (TrainManager.PlayerTrain.Handles.Brake is TrainManager.AirBrakeHandle) { if (TrainManager.PlayerTrain.Handles.EmergencyBrake.Driver) { sc = MessageColor.Red; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 0) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[0]; } else { t = Interface.QuickReferences.HandleEmergency; } } else if (TrainManager.PlayerTrain.Handles.Brake.Driver == (int)TrainManager.AirBrakeHandleState.Release) { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1]; } else { t = Interface.QuickReferences.HandleRelease; } } else if (TrainManager.PlayerTrain.Handles.Brake.Driver == (int)TrainManager.AirBrakeHandleState.Lap) { sc = MessageColor.Blue; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 2) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[2]; } else { t = Interface.QuickReferences.HandleLap; } } else { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 3) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[3]; } else { t = Interface.QuickReferences.HandleService; } } } else { if (TrainManager.PlayerTrain.Handles.EmergencyBrake.Driver) { sc = MessageColor.Red; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 0) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[0]; } else { t = Interface.QuickReferences.HandleEmergency; } } else if (TrainManager.PlayerTrain.Handles.HoldBrake.Driver) { sc = MessageColor.Green; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 2) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[2]; } else { t = Interface.QuickReferences.HandleHoldBrake; } } else if (TrainManager.PlayerTrain.Handles.Brake.Driver == 0) { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1]; } else { t = Interface.QuickReferences.HandleBrakeNull; } } else { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && ((TrainManager.PlayerTrain.Handles.HasHoldBrake && TrainManager.PlayerTrain.Handles.Brake.Driver + 2 < TrainManager.PlayerTrain.BrakeNotchDescriptions.Length) || (!TrainManager.PlayerTrain.Handles.HasHoldBrake && TrainManager.PlayerTrain.Handles.Brake.Driver + 1 < TrainManager.PlayerTrain.BrakeNotchDescriptions.Length))) { t = TrainManager.PlayerTrain.Handles.HasHoldBrake ? TrainManager.PlayerTrain.BrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.Brake.Driver + 2] : TrainManager.PlayerTrain.BrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.Brake.Driver + 1]; } else { t = Interface.QuickReferences.HandleBrake + TrainManager.PlayerTrain.Handles.Brake.Driver.ToString(Culture); } } } Element.TransitionState = 0.0; break; case "locobrake": if (!TrainManager.PlayerTrain.Handles.HasLocoBrake) { return; } if (TrainManager.PlayerTrain.Handles.LocoBrake is TrainManager.LocoAirBrakeHandle) { if (TrainManager.PlayerTrain.Handles.LocoBrake.Driver == (int)TrainManager.AirBrakeHandleState.Release) { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1]; } else { t = Interface.QuickReferences.HandleRelease; } } else if (TrainManager.PlayerTrain.Handles.LocoBrake.Driver == (int)TrainManager.AirBrakeHandleState.Lap) { sc = MessageColor.Blue; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 2) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[2]; } else { t = Interface.QuickReferences.HandleLap; } } else { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 3) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[3]; } else { t = Interface.QuickReferences.HandleService; } } } else { if (TrainManager.PlayerTrain.Handles.LocoBrake.Driver == 0) { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.LocoBrakeNotchDescriptions != null && TrainManager.PlayerTrain.LocoBrakeNotchDescriptions.Length > 1) { t = TrainManager.PlayerTrain.LocoBrakeNotchDescriptions[1]; } else { t = Interface.QuickReferences.HandleBrakeNull; } } else { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.LocoBrakeNotchDescriptions != null && TrainManager.PlayerTrain.Handles.LocoBrake.Driver < TrainManager.PlayerTrain.LocoBrakeNotchDescriptions.Length) { t = TrainManager.PlayerTrain.LocoBrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.LocoBrake.Driver]; } else { t = Interface.QuickReferences.HandleLocoBrake + TrainManager.PlayerTrain.Handles.LocoBrake.Driver.ToString(Culture); } } } Element.TransitionState = 0.0; break; case "single": if (!TrainManager.PlayerTrain.Handles.SingleHandle) { return; } if (TrainManager.PlayerTrain.Handles.EmergencyBrake.Driver) { sc = MessageColor.Red; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 0) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[0]; } else { t = Interface.QuickReferences.HandleEmergency; } } else if (TrainManager.PlayerTrain.Handles.HoldBrake.Driver) { sc = MessageColor.Green; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1]; } else { t = Interface.QuickReferences.HandleHoldBrake; } } else if (TrainManager.PlayerTrain.Handles.Brake.Driver > 0) { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.Handles.Brake.Driver + 3 < TrainManager.PlayerTrain.BrakeNotchDescriptions.Length) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.Brake.Driver + 3]; } else { t = Interface.QuickReferences.HandleBrake + TrainManager.PlayerTrain.Handles.Brake.Driver.ToString(Culture); } } else if (TrainManager.PlayerTrain.Handles.Power.Driver > 0) { sc = MessageColor.Blue; if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.Handles.Power.Driver < TrainManager.PlayerTrain.PowerNotchDescriptions.Length) { t = TrainManager.PlayerTrain.PowerNotchDescriptions[TrainManager.PlayerTrain.Handles.Power.Driver]; } else { t = Interface.QuickReferences.HandlePower + TrainManager.PlayerTrain.Handles.Power.Driver.ToString(Culture); } } else { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.PowerNotchDescriptions.Length > 0) { t = TrainManager.PlayerTrain.PowerNotchDescriptions[0]; } else { t = Interface.QuickReferences.HandlePowerNull; } } Element.TransitionState = 0.0; break; case "doorsleft": case "doorsright": { if ((LeftDoors & TrainManager.TrainDoorState.AllClosed) == 0 | (RightDoors & TrainManager.TrainDoorState.AllClosed) == 0) { Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } TrainManager.TrainDoorState Doors = Command == "doorsleft" ? LeftDoors : RightDoors; if ((Doors & TrainManager.TrainDoorState.Mixed) != 0) { sc = MessageColor.Orange; } else if ((Doors & TrainManager.TrainDoorState.AllClosed) != 0) { sc = MessageColor.Gray; } else if (TrainManager.PlayerTrain.Specs.DoorCloseMode == TrainManager.DoorMode.Manual) { sc = MessageColor.Green; } else { sc = MessageColor.Blue; } t = Command == "doorsleft" ? Interface.QuickReferences.DoorsLeft : Interface.QuickReferences.DoorsRight; } break; case "stopleft": case "stopright": case "stopnone": { int s = TrainManager.PlayerTrain.Station; if (s >= 0 && Game.PlayerStopsAtStation(s) && Interface.CurrentOptions.GameMode != Interface.GameMode.Expert) { bool cond; if (Command == "stopleft") { cond = Game.Stations[s].OpenLeftDoors; } else if (Command == "stopright") { cond = Game.Stations[s].OpenRightDoors; } else { cond = !Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors; } if (TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Pending & cond) { Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } t = Element.Text; } break; case "stoplefttick": case "stoprighttick": case "stopnonetick": { int s = TrainManager.PlayerTrain.Station; if (s >= 0 && Game.PlayerStopsAtStation(s) && Interface.CurrentOptions.GameMode != Interface.GameMode.Expert) { int c = Game.GetStopIndex(s, TrainManager.PlayerTrain.Cars.Length); if (c >= 0) { bool cond; if (Command == "stoplefttick") { cond = Game.Stations[s].OpenLeftDoors; } else if (Command == "stoprighttick") { cond = Game.Stations[s].OpenRightDoors; } else { cond = !Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors; } if (TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Pending & cond) { Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } double d = TrainManager.PlayerTrain.StationDistanceToStopPoint; double r; if (d > 0.0) { r = d / Game.Stations[s].Stops[c].BackwardTolerance; } else { r = d / Game.Stations[s].Stops[c].ForwardTolerance; } if (r < -1.0) { r = -1.0; } if (r > 1.0) { r = 1.0; } y -= r * (double)Element.Value1; } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } t = Element.Text; } break; case "clock": { int hours = (int)Math.Floor(Game.SecondsSinceMidnight); int seconds = hours % 60; hours /= 60; int minutes = hours % 60; hours /= 60; hours %= 24; t = hours.ToString(Culture).PadLeft(2, '0') + ":" + minutes.ToString(Culture).PadLeft(2, '0') + ":" + seconds.ToString(Culture).PadLeft(2, '0'); if (OptionClock) { Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } } break; case "gradient": if (OptionGradient == GradientDisplayMode.Percentage) { if (World.CameraTrackFollower.Pitch != 0) { double pc = World.CameraTrackFollower.Pitch; t = Math.Abs(pc).ToString("0.00", Culture) + "%" + (Math.Abs(pc) == pc ? " ↗" : " ↘"); } else { t = "Level"; } Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else if (OptionGradient == GradientDisplayMode.UnitOfChange) { if (World.CameraTrackFollower.Pitch != 0) { double gr = 1000 / World.CameraTrackFollower.Pitch; t = "1 in " + Math.Abs(gr).ToString("0", Culture) + (Math.Abs(gr) == gr ? " ↗" : " ↘"); } else { t = "Level"; } Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else if (OptionGradient == GradientDisplayMode.Permil) { if (World.CameraTrackFollower.Pitch != 0) { double pm = World.CameraTrackFollower.Pitch; t = Math.Abs(pm).ToString("0.00", Culture) + "‰" + (Math.Abs(pm) == pm ? " ↗" : " ↘"); } else { t = "Level"; } Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { if (World.CameraTrackFollower.Pitch != 0) { double gr = 1000 / World.CameraTrackFollower.Pitch; t = "1 in " + Math.Abs(gr).ToString("0", Culture) + (Math.Abs(gr) == gr ? " ↗" : " ↘"); } else { t = "Level"; } Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } break; case "speed": if (OptionSpeed == SpeedDisplayMode.Kmph) { double kmph = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) * 3.6; t = kmph.ToString("0.00", Culture) + " km/h"; Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else if (OptionSpeed == SpeedDisplayMode.Mph) { double mph = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) * 2.2369362920544; t = mph.ToString("0.00", Culture) + " mph"; Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { double mph = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) * 2.2369362920544; t = mph.ToString("0.00", Culture) + " mph"; Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } break; case "fps": int fps = (int)Math.Round(Game.InfoFrameRate); t = fps.ToString(Culture) + " fps"; if (OptionFrameRates) { Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } break; case "ai": t = "A.I."; if (TrainManager.PlayerTrain.AI != null) { Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { Element.TransitionState += speed * TimeElapsed; if (Element.TransitionState > 1.0) { Element.TransitionState = 1.0; } } break; case "score": if (Interface.CurrentOptions.GameMode == Interface.GameMode.Arcade) { t = Game.CurrentScore.CurrentValue.ToString(Culture) + " / " + Game.CurrentScore.Maximum.ToString(Culture); if (Game.CurrentScore.CurrentValue < 0) { sc = MessageColor.Red; } else if (Game.CurrentScore.CurrentValue > 0) { sc = MessageColor.Green; } else { sc = MessageColor.Gray; } Element.TransitionState = 0.0; } else { Element.TransitionState = 1.0; t = ""; } break; default: t = Element.Text; break; } // transitions float alpha = 1.0f; if ((Element.Transition & HUD.Transition.Move) != 0) { double s = Element.TransitionState; x += Element.TransitionVector.X * s * s; y += Element.TransitionVector.Y * s * s; } if ((Element.Transition & HUD.Transition.Fade) != 0) { alpha = (float)(1.0 - Element.TransitionState); } else if (Element.Transition == HUD.Transition.None) { alpha = (float)(1.0 - Element.TransitionState); } // render if (alpha != 0.0f) { // background if (Element.Subject == "reverser") { w = Math.Max(w, TrainManager.PlayerTrain.MaxReverserWidth); //X-Pos doesn't need to be changed } if (Element.Subject == "power") { w = Math.Max(w, TrainManager.PlayerTrain.MaxPowerNotchWidth); if (TrainManager.PlayerTrain.MaxReverserWidth > 48) { x += (TrainManager.PlayerTrain.MaxReverserWidth - 48); } } if (Element.Subject == "brake") { w = Math.Max(w, TrainManager.PlayerTrain.MaxBrakeNotchWidth); if (TrainManager.PlayerTrain.MaxReverserWidth > 48) { x += (TrainManager.PlayerTrain.MaxReverserWidth - 48); } if (TrainManager.PlayerTrain.MaxPowerNotchWidth > 48) { x += (TrainManager.PlayerTrain.MaxPowerNotchWidth - 48); } } if (Element.Subject == "single") { w = Math.Max(Math.Max(w, TrainManager.PlayerTrain.MaxPowerNotchWidth), TrainManager.PlayerTrain.MaxBrakeNotchWidth); if (TrainManager.PlayerTrain.MaxReverserWidth > 48) { x += (TrainManager.PlayerTrain.MaxReverserWidth - 48); } } if (Element.CenterMiddle.BackgroundTexture != null) { if (Textures.LoadTexture(Element.CenterMiddle.BackgroundTexture, Textures.OpenGlTextureWrapMode.ClampClamp)) { float r, g, b, a; CreateBackColor(Element.BackgroundColor, sc, out r, out g, out b, out a); GL.Color4(r, g, b, a * alpha); RenderOverlayTexture(Element.CenterMiddle.BackgroundTexture, x, y, x + w, y + h); } } { // text System.Drawing.Size size = MeasureString(Element.Font, t); float u = size.Width; float v = size.Height; double p = Math.Round(Element.TextAlignment.X < 0 ? x : Element.TextAlignment.X == 0 ? x + 0.5 * (w - u) : x + w - u); double q = Math.Round(Element.TextAlignment.Y < 0 ? y : Element.TextAlignment.Y == 0 ? y + 0.5 * (h - v) : y + h - v); p += Element.TextPosition.X; q += Element.TextPosition.Y; float r, g, b, a; CreateTextColor(Element.TextColor, sc, out r, out g, out b, out a); DrawString(Element.Font, t, new System.Drawing.Point((int)p, (int)q), TextAlignment.TopLeft, new Color128(r, g, b, a * alpha), Element.TextShadow); } // overlay if (Element.CenterMiddle.OverlayTexture != null) { if (Textures.LoadTexture(Element.CenterMiddle.OverlayTexture, Textures.OpenGlTextureWrapMode.ClampClamp)) { float r, g, b, a; CreateBackColor(Element.OverlayColor, sc, out r, out g, out b, out a); GL.Color4(r, g, b, a * alpha); RenderOverlayTexture(Element.CenterMiddle.OverlayTexture, x, y, x + w, y + h); } } } }
/// <summary>Renders the list of score messages</summary> /// <param name="Element">The HUD element these are to be rendererd onto</param> /// <param name="TimeElapsed">The time elapsed</param> private static void RenderScoreMessages(HUD.Element Element, double TimeElapsed) { // score messages int n = Game.ScoreMessages.Length; float totalwidth = 16.0f; float[] widths = new float[n]; float[] heights = new float[n]; for (int j = 0; j < n; j++) { System.Drawing.Size size = MeasureString(Element.Font, Game.ScoreMessages[j].Text); widths[j] = size.Width; heights[j] = size.Height; float a = widths[j] - j * Element.Value1; if (a > totalwidth) { totalwidth = a; } } Game.ScoreMessagesRendererSize.X += 16.0 * TimeElapsed * ((double)totalwidth - Game.ScoreMessagesRendererSize.X); totalwidth = (float)Game.ScoreMessagesRendererSize.X; double lcrh, lw, rw; CalculateViewingPlaneSize(Element, out lw, out rw, out lcrh); // start double w = Element.Alignment.X == 0 ? lw + rw + 128 : totalwidth + lw + rw; double h = Element.Value2 * n; double x = Element.Alignment.X < 0 ? 0.0 : Element.Alignment.X > 0 ? Screen.Width - w : 0.5 * (Screen.Width - w); double y = Element.Alignment.Y < 0 ? 0.0 : Element.Alignment.Y > 0 ? Screen.Height - h : 0.5 * (Screen.Height - h); x += Element.Position.X; y += Element.Position.Y; int m = 0; for (int j = 0; j < n; j++) { float br, bg, bb, ba; CreateBackColor(Element.BackgroundColor, Game.ScoreMessages[j].Color, out br, out bg, out bb, out ba); float tr, tg, tb, ta; CreateTextColor(Element.TextColor, Game.ScoreMessages[j].Color, out tr, out tg, out tb, out ta); float or, og, ob, oa; CreateBackColor(Element.OverlayColor, Game.ScoreMessages[j].Color, out or, out og, out ob, out oa); double tx, ty; bool preserve = false; if ((Element.Transition & HUD.Transition.Move) != 0) { if (Game.SecondsSinceMidnight < Game.ScoreMessages[j].Timeout) { if (Game.ScoreMessages[j].RendererAlpha == 0.0) { Game.ScoreMessages[j].RendererPosition.X = x + Element.TransitionVector.X; Game.ScoreMessages[j].RendererPosition.Y = y + Element.TransitionVector.Y; Game.ScoreMessages[j].RendererAlpha = 1.0; } tx = x; ty = y + m * Element.Value2; preserve = true; } else if (Element.Transition == HUD.Transition.MoveAndFade) { tx = x; ty = y + m * Element.Value2; } else { tx = x + Element.TransitionVector.X; ty = y + (j + 1) * Element.TransitionVector.Y; } const double speed = 2.0; double dx = (speed * Math.Abs(tx - Game.ScoreMessages[j].RendererPosition.X) + 0.1) * TimeElapsed; double dy = (speed * Math.Abs(ty - Game.ScoreMessages[j].RendererPosition.Y) + 0.1) * TimeElapsed; if (Math.Abs(tx - Game.ScoreMessages[j].RendererPosition.X) < dx) { Game.ScoreMessages[j].RendererPosition.X = tx; } else { Game.ScoreMessages[j].RendererPosition.X += Math.Sign(tx - Game.ScoreMessages[j].RendererPosition.X) * dx; } if (Math.Abs(ty - Game.ScoreMessages[j].RendererPosition.Y) < dy) { Game.ScoreMessages[j].RendererPosition.Y = ty; } else { Game.ScoreMessages[j].RendererPosition.Y += Math.Sign(ty - Game.ScoreMessages[j].RendererPosition.Y) * dy; } } else { tx = x; ty = y + m * Element.Value2; Game.ScoreMessages[j].RendererPosition.X = 0.0; const double speed = 12.0; double dy = (speed * Math.Abs(ty - Game.ScoreMessages[j].RendererPosition.Y) + 0.1) * TimeElapsed; Game.ScoreMessages[j].RendererPosition.X = x; if (Math.Abs(ty - Game.ScoreMessages[j].RendererPosition.Y) < dy) { Game.ScoreMessages[j].RendererPosition.Y = ty; } else { Game.ScoreMessages[j].RendererPosition.Y += Math.Sign(ty - Game.ScoreMessages[j].RendererPosition.Y) * dy; } } if ((Element.Transition & HUD.Transition.Fade) != 0) { if (Game.SecondsSinceMidnight >= Game.ScoreMessages[j].Timeout) { Game.ScoreMessages[j].RendererAlpha -= TimeElapsed; if (Game.ScoreMessages[j].RendererAlpha < 0.0) { Game.ScoreMessages[j].RendererAlpha = 0.0; } } else { Game.ScoreMessages[j].RendererAlpha += TimeElapsed; if (Game.ScoreMessages[j].RendererAlpha > 1.0) { Game.ScoreMessages[j].RendererAlpha = 1.0; } preserve = true; } } else if (Game.SecondsSinceMidnight > Game.ScoreMessages[j].Timeout) { if (Math.Abs(Game.ScoreMessages[j].RendererPosition.X - tx) < 0.1 & Math.Abs(Game.ScoreMessages[j].RendererPosition.Y - ty) < 0.1) { Game.ScoreMessages[j].RendererAlpha = 0.0; } } if (preserve) { m++; } double px = Game.ScoreMessages[j].RendererPosition.X + (double)j * (double)Element.Value1; double py = Game.ScoreMessages[j].RendererPosition.Y; float alpha = (float)(Game.ScoreMessages[j].RendererAlpha * Game.ScoreMessages[j].RendererAlpha); // graphics HUD.Image Left = j == 0 ? Element.TopLeft : j < n - 1 ? Element.CenterLeft : Element.BottomLeft; HUD.Image Middle = j == 0 ? Element.TopMiddle : j < n - 1 ? Element.CenterMiddle : Element.BottomMiddle; HUD.Image Right = j == 0 ? Element.TopRight : j < n - 1 ? Element.CenterRight : Element.BottomRight; // left background if (Left.BackgroundTexture != null) { if (Textures.LoadTexture(Left.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Left.BackgroundTexture.Width; double v = (double)Left.BackgroundTexture.Height; GL.Color4(br, bg, bb, ba * alpha); RenderOverlayTexture(Left.BackgroundTexture, px, py, px + u, py + v); } } // right background if (Right.BackgroundTexture != null) { if (Textures.LoadTexture(Right.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Right.BackgroundTexture.Width; double v = (double)Right.BackgroundTexture.Height; GL.Color4(br, bg, bb, ba * alpha); RenderOverlayTexture(Right.BackgroundTexture, px + w - u, py, px + w, py + v); } } // middle background if (Middle.BackgroundTexture != null) { if (Textures.LoadTexture(Middle.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Middle.BackgroundTexture.Height; GL.Color4(br, bg, bb, ba * alpha); RenderOverlayTexture(Middle.BackgroundTexture, px + lw, py, px + w - rw, py + v); } } { // text string t = Game.ScoreMessages[j].Text; double u = widths[j]; double v = heights[j]; double p = Math.Round((Element.TextAlignment.X < 0 ? px : Element.TextAlignment.X > 0 ? px + w - u : px + 0.5 * (w - u)) - j * Element.Value1); double q = Math.Round(Element.TextAlignment.Y < 0 ? py : Element.TextAlignment.Y > 0 ? py + lcrh - v : py + 0.5 * (lcrh - v)); p += Element.TextPosition.X; q += Element.TextPosition.Y; DrawString(Element.Font, t, new System.Drawing.Point((int)p, (int)q), TextAlignment.TopLeft, new Color128(tr, tg, tb, ta * alpha), Element.TextShadow); } // left overlay if (Left.OverlayTexture != null) { if (Textures.LoadTexture(Left.OverlayTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Left.OverlayTexture.Width; double v = (double)Left.OverlayTexture.Height; GL.Color4(or, og, ob, oa * alpha); RenderOverlayTexture(Left.OverlayTexture, px, py, px + u, py + v); } } // right overlay if (Right.OverlayTexture != null) { if (Textures.LoadTexture(Right.OverlayTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Right.OverlayTexture.Width; double v = (double)Right.OverlayTexture.Height; GL.Color4(or, og, ob, oa * alpha); RenderOverlayTexture(Right.OverlayTexture, px + w - u, py, px + w, py + v); } } // middle overlay if (Middle.OverlayTexture != null) { if (Textures.LoadTexture(Middle.OverlayTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Middle.OverlayTexture.Height; GL.Color4(or, og, ob, oa * alpha); RenderOverlayTexture(Middle.OverlayTexture, px + lw, py, px + w - rw, py + v); } } } }
/// <summary>This function renderers full-screen motion blur if selected</summary> private static void RenderFullscreenMotionBlur() { if (Screen.Minimized) { /* * HACK: * This breaks if minimized, even if we don't reset the W / H values */ return; } int w = Interface.CurrentOptions.NoTextureResize ? Screen.Width : Textures.RoundUpToPowerOfTwo(Screen.Width); int h = Interface.CurrentOptions.NoTextureResize ? Screen.Height : Textures.RoundUpToPowerOfTwo(Screen.Height); // render if (PixelBufferOpenGlTextureIndex >= 0) { double strength; switch (Interface.CurrentOptions.MotionBlur) { case Interface.MotionBlurMode.Low: strength = 0.0025; break; case Interface.MotionBlurMode.Medium: strength = 0.0040; break; case Interface.MotionBlurMode.High: strength = 0.0064; break; default: strength = 0.0040; break; } double speed = Math.Abs(World.CameraSpeed); double denominator = strength * Game.InfoFrameRate * Math.Sqrt(speed); float factor; if (denominator > 0.001) { factor = (float)Math.Exp(-1.0 / denominator); } else { factor = 0.0f; } // initialize GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); if (!BlendEnabled) { GL.Enable(EnableCap.Blend); BlendEnabled = true; } if (LightingEnabled) { GL.Disable(EnableCap.Lighting); LightingEnabled = false; } GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); GL.LoadIdentity(); GL.Ortho(0.0, (double)Screen.Width, 0.0, (double)Screen.Height, -1.0, 1.0); GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } // render GL.BindTexture(TextureTarget.Texture2D, PixelBufferOpenGlTextureIndex); GL.Color4(1.0f, 1.0f, 1.0f, factor); GL.Begin(PrimitiveType.Polygon); GL.TexCoord2(0.0, 0.0); GL.Vertex2(0.0, 0.0); GL.TexCoord2(0.0, 1.0); GL.Vertex2(0.0, (double)h); GL.TexCoord2(1.0, 1.0); GL.Vertex2((double)w, (double)h); GL.TexCoord2(1.0, 0.0); GL.Vertex2((double)w, 0.0); GL.End(); // finalize GL.PopMatrix(); GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); GL.MatrixMode(MatrixMode.Modelview); } // retrieve buffer { GL.BindTexture(TextureTarget.Texture2D, PixelBufferOpenGlTextureIndex); GL.CopyTexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgb8, 0, 0, w, h, 0); } }
/// <summary>Loads the current HUD</summary> internal static void LoadHUD() { CultureInfo Culture = CultureInfo.InvariantCulture; string Folder = Program.FileSystem.GetDataFolder("In-game", Interface.CurrentOptions.UserInterfaceFolder); string File = OpenBveApi.Path.CombineFile(Folder, "interface.cfg"); CurrentHudElements = new Element[16]; int Length = 0; if (System.IO.File.Exists(File)) { string[] Lines = System.IO.File.ReadAllLines(File, new System.Text.UTF8Encoding()); for (int i = 0; i < Lines.Length; i++) { int j = Lines[i].IndexOf(';'); if (j >= 0) { Lines[i] = Lines[i].Substring(0, j).Trim(); } else { Lines[i] = Lines[i].Trim(); } if (Lines[i].Length != 0) { if (!Lines[i].StartsWith(";", StringComparison.Ordinal)) { if (Lines[i].Equals("[element]", StringComparison.OrdinalIgnoreCase)) { Length++; if (Length > CurrentHudElements.Length) { Array.Resize <Element>(ref CurrentHudElements, CurrentHudElements.Length << 1); } CurrentHudElements[Length - 1] = new Element(); } else if (Length == 0) { MessageBox.Show("Line outside of [element] structure encountered at line " + (i + 1).ToString(Culture) + " in " + File); } else { j = Lines[i].IndexOf("=", StringComparison.Ordinal); if (j >= 0) { string Command = Lines[i].Substring(0, j).TrimEnd(); string[] Arguments = Lines[i].Substring(j + 1).TrimStart().Split(new char[] { ',' }, StringSplitOptions.None); for (j = 0; j < Arguments.Length; j++) { Arguments[j] = Arguments[j].Trim(); } switch (Command.ToLowerInvariant()) { case "subject": if (Arguments.Length == 1) { CurrentHudElements[Length - 1].Subject = Arguments[0]; } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "position": if (Arguments.Length == 2) { float x, y; if (!float.TryParse(Arguments[0], NumberStyles.Float, Culture, out x)) { MessageBox.Show("X is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!float.TryParse(Arguments[1], NumberStyles.Float, Culture, out y)) { MessageBox.Show("Y is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].Position.X = x; CurrentHudElements[Length - 1].Position.Y = y; } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "alignment": if (Arguments.Length == 2) { int x, y; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out x)) { MessageBox.Show("X is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[1], NumberStyles.Integer, Culture, out y)) { MessageBox.Show("Y is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].Alignment.X = Math.Sign(x); CurrentHudElements[Length - 1].Alignment.Y = Math.Sign(y); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "topleft": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].TopLeft.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].TopLeft.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "topmiddle": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].TopMiddle.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].TopMiddle.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "topright": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].TopRight.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].TopRight.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "centerleft": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].CenterLeft.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].CenterLeft.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "centermiddle": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].CenterMiddle.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].CenterMiddle.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "centerright": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].CenterRight.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].CenterRight.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "bottomleft": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].BottomLeft.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].BottomLeft.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "bottommiddle": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].BottomMiddle.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].BottomMiddle.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "bottomright": if (Arguments.Length == 2) { if (Arguments[0].Length != 0 & !Arguments[0].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[0]), out CurrentHudElements[Length - 1].BottomRight.BackgroundTexture); } if (Arguments[1].Length != 0 & !Arguments[1].Equals("null", StringComparison.OrdinalIgnoreCase)) { Textures.RegisterTexture(OpenBveApi.Path.CombineFile(Folder, Arguments[1]), out CurrentHudElements[Length - 1].BottomRight.OverlayTexture); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "backcolor": if (Arguments.Length == 4) { int r, g, b, a; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out r)) { MessageBox.Show("R is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[1], NumberStyles.Integer, Culture, out g)) { MessageBox.Show("G is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[2], NumberStyles.Integer, Culture, out b)) { MessageBox.Show("B is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[3], NumberStyles.Integer, Culture, out a)) { MessageBox.Show("A is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; a = a < 0 ? 0 : a > 255 ? 255 : a; CurrentHudElements[Length - 1].BackgroundColor = new Color32((byte)r, (byte)g, (byte)b, (byte)a); } break; } MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); break; case "overlaycolor": if (Arguments.Length == 4) { int r, g, b, a; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out r)) { MessageBox.Show("R is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[1], NumberStyles.Integer, Culture, out g)) { MessageBox.Show("G is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[2], NumberStyles.Integer, Culture, out b)) { MessageBox.Show("B is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[3], NumberStyles.Integer, Culture, out a)) { MessageBox.Show("A is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; a = a < 0 ? 0 : a > 255 ? 255 : a; CurrentHudElements[Length - 1].OverlayColor = new Color32((byte)r, (byte)g, (byte)b, (byte)a); } break; } MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); break; case "textcolor": if (Arguments.Length == 4) { int r, g, b, a; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out r)) { MessageBox.Show("R is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[1], NumberStyles.Integer, Culture, out g)) { MessageBox.Show("G is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[2], NumberStyles.Integer, Culture, out b)) { MessageBox.Show("B is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[3], NumberStyles.Integer, Culture, out a)) { MessageBox.Show("A is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; a = a < 0 ? 0 : a > 255 ? 255 : a; CurrentHudElements[Length - 1].TextColor = new Color32((byte)r, (byte)g, (byte)b, (byte)a); } break; } MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); break; case "textposition": if (Arguments.Length == 2) { float x, y; if (!float.TryParse(Arguments[0], NumberStyles.Float, Culture, out x)) { MessageBox.Show("X is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!float.TryParse(Arguments[1], NumberStyles.Float, Culture, out y)) { MessageBox.Show("Y is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].TextPosition.X = x; CurrentHudElements[Length - 1].TextPosition.Y = y; } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "textalignment": if (Arguments.Length == 2) { int x, y; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out x)) { MessageBox.Show("X is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!int.TryParse(Arguments[1], NumberStyles.Integer, Culture, out y)) { MessageBox.Show("Y is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].TextAlignment.X = Math.Sign(x); CurrentHudElements[Length - 1].TextAlignment.Y = Math.Sign(y); } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "textsize": if (Arguments.Length == 1) { int s; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out s)) { MessageBox.Show("SIZE is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { switch (s) { case 0: CurrentHudElements[Length - 1].Font = Fonts.VerySmallFont; break; case 1: CurrentHudElements[Length - 1].Font = Fonts.SmallFont; break; case 2: CurrentHudElements[Length - 1].Font = Fonts.NormalFont; break; case 3: CurrentHudElements[Length - 1].Font = Fonts.LargeFont; break; case 4: CurrentHudElements[Length - 1].Font = Fonts.VeryLargeFont; break; default: CurrentHudElements[Length - 1].Font = Fonts.NormalFont; break; } } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "textshadow": if (Arguments.Length == 1) { int s; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out s)) { MessageBox.Show("SHADOW is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].TextShadow = s != 0; } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "text": if (Arguments.Length == 1) { CurrentHudElements[Length - 1].Text = Arguments[0]; } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "value": if (Arguments.Length == 1) { int n; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out n)) { MessageBox.Show("VALUE1 is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].Value1 = n; } } else if (Arguments.Length == 2) { float a, b; if (!float.TryParse(Arguments[0], NumberStyles.Float, Culture, out a)) { MessageBox.Show("VALUE1 is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!float.TryParse(Arguments[1], NumberStyles.Float, Culture, out b)) { MessageBox.Show("VALUE2 is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].Value1 = a; CurrentHudElements[Length - 1].Value2 = b; } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "transition": if (Arguments.Length == 1) { int n; if (!int.TryParse(Arguments[0], NumberStyles.Integer, Culture, out n)) { MessageBox.Show("TRANSITION is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].Transition = (HUD.Transition)n; } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; case "transitionvector": if (Arguments.Length == 2) { float x, y; if (!float.TryParse(Arguments[0], NumberStyles.Float, Culture, out x)) { MessageBox.Show("X is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else if (!float.TryParse(Arguments[1], NumberStyles.Float, Culture, out y)) { MessageBox.Show("Y is invalid in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } else { CurrentHudElements[Length - 1].TransitionVector.X = x; CurrentHudElements[Length - 1].TransitionVector.Y = y; } } else { MessageBox.Show("Incorrect number of arguments supplied in " + Command + " at line " + (i + 1).ToString(Culture) + " in " + File); } break; default: MessageBox.Show("Invalid command encountered at line " + (i + 1).ToString(Culture) + " in " + File); break; } } else { MessageBox.Show("Invalid statement encountered at line " + (i + 1).ToString(Culture) + " in " + File); } } } } } } Array.Resize <Element>(ref CurrentHudElements, Length); }
internal void Apply(ref ObjectManager.StaticObject Object) { if (TransformMatrix != Matrix4D.NoTransformation) { for (int i = 0; i < Vertices.Length; i++) { Vertices[i].Coordinates.Transform(TransformMatrix); } } if (Faces.Length != 0) { int mf = Object.Mesh.Faces.Length; int mm = Object.Mesh.Materials.Length; int mv = Object.Mesh.Vertices.Length; Array.Resize <MeshFace>(ref Object.Mesh.Faces, mf + Faces.Length); Array.Resize <MeshMaterial>(ref Object.Mesh.Materials, mm + Materials.Length); Array.Resize <VertexTemplate>(ref Object.Mesh.Vertices, mv + Vertices.Length); for (int i = 0; i < Vertices.Length; i++) { Object.Mesh.Vertices[mv + i] = Vertices[i]; } for (int i = 0; i < Faces.Length; i++) { Object.Mesh.Faces[mf + i] = Faces[i]; for (int j = 0; j < Object.Mesh.Faces[mf + i].Vertices.Length; j++) { Object.Mesh.Faces[mf + i].Vertices[j].Index += (ushort)mv; } Object.Mesh.Faces[mf + i].Material += (ushort)mm; } for (int i = 0; i < Materials.Length; i++) { Object.Mesh.Materials[mm + i].Flags = (byte)((Materials[i].EmissiveColorUsed ? MeshMaterial.EmissiveColorMask : 0) | (Materials[i].TransparentColorUsed ? MeshMaterial.TransparentColorMask : 0)); Object.Mesh.Materials[mm + i].Color = Materials[i].Color; Object.Mesh.Materials[mm + i].TransparentColor = Materials[i].TransparentColor; if (Materials[i].DaytimeTexture != null || Materials[i].Text != null) { Texture tday; if (Materials[i].Text != null) { Bitmap bitmap = null; if (Materials[i].DaytimeTexture != null) { bitmap = new Bitmap(Materials[i].DaytimeTexture); } Bitmap texture = TextOverlay.AddTextToBitmap(bitmap, Materials[i].Text, Materials[i].Font, 12, Materials[i].BackgroundColor, Materials[i].TextColor, Materials[i].TextPadding); tday = Textures.RegisterTexture(texture, new TextureParameters(null, new Color24(Materials[i].TransparentColor.R, Materials[i].TransparentColor.G, Materials[i].TransparentColor.B))); } else { if (Materials[i].TransparentColorUsed) { Textures.RegisterTexture(Materials[i].DaytimeTexture, new TextureParameters(null, new Color24(Materials[i].TransparentColor.R, Materials[i].TransparentColor.G, Materials[i].TransparentColor.B)), out tday); } else { Textures.RegisterTexture(Materials[i].DaytimeTexture, out tday); } } Object.Mesh.Materials[mm + i].DaytimeTexture = tday; } else { Object.Mesh.Materials[mm + i].DaytimeTexture = null; } Object.Mesh.Materials[mm + i].EmissiveColor = Materials[i].EmissiveColor; if (Materials[i].NighttimeTexture != null) { Texture tnight; if (Materials[i].TransparentColorUsed) { Textures.RegisterTexture(Materials[i].NighttimeTexture, new TextureParameters(null, new Color24(Materials[i].TransparentColor.R, Materials[i].TransparentColor.G, Materials[i].TransparentColor.B)), out tnight); } else { Textures.RegisterTexture(Materials[i].NighttimeTexture, out tnight); } Object.Mesh.Materials[mm + i].NighttimeTexture = tnight; } else { Object.Mesh.Materials[mm + i].NighttimeTexture = null; } Object.Mesh.Materials[mm + i].DaytimeNighttimeBlend = 0; Object.Mesh.Materials[mm + i].BlendMode = Materials[i].BlendMode; Object.Mesh.Materials[mm + i].GlowAttenuationData = Materials[i].GlowAttenuationData; Object.Mesh.Materials[mm + i].WrapMode = Materials[i].WrapMode; } } }
internal void Apply(out ObjectManager.StaticObject Object) { Object = new ObjectManager.StaticObject { Mesh = { Faces = new MeshFace[] { }, Materials = new MeshMaterial[] { }, Vertices = new VertexTemplate[] { } } }; if (faces.Count != 0) { int mf = Object.Mesh.Faces.Length; int mm = Object.Mesh.Materials.Length; int mv = Object.Mesh.Vertices.Length; Array.Resize(ref Object.Mesh.Faces, mf + faces.Count); Array.Resize(ref Object.Mesh.Materials, mm + materials.Count); Array.Resize(ref Object.Mesh.Vertices, mv + verticies.Count); for (int i = 0; i < verticies.Count; i++) { Object.Mesh.Vertices[mv + i] = new OpenBveApi.Objects.Vertex(verticies[i].Coordinates, verticies[i].TextureCoordinates); } for (int i = 0; i < faces.Count; i++) { Object.Mesh.Faces[i] = new MeshFace(faces[i].Vertices); Object.Mesh.Faces[i].Material = (ushort)faces[i].Material; for (int k = 0; k < faces[i].Vertices.Length; k++) { Object.Mesh.Faces[i].Vertices[k].Normal = verticies[faces[i].Vertices[k]].Normal; } for (int j = 0; j < Object.Mesh.Faces[mf + i].Vertices.Length; j++) { Object.Mesh.Faces[mf + i].Vertices[j].Index += (ushort)mv; } Object.Mesh.Faces[mf + i].Material += (ushort)mm; } for (int i = 0; i < materials.Count; i++) { Object.Mesh.Materials[mm + i].Flags = 0; Object.Mesh.Materials[mm + i].Color = materials[i].Color; Object.Mesh.Materials[mm + i].TransparentColor = Color24.Black; Object.Mesh.Materials[mm + i].BlendMode = MeshMaterialBlendMode.Normal; if (materials[i].DaytimeTexture != null) { OpenBveApi.Textures.Texture tday; Textures.RegisterTexture(materials[i].DaytimeTexture, out tday); Object.Mesh.Materials[mm + i].DaytimeTexture = tday; } else { Object.Mesh.Materials[mm + i].DaytimeTexture = null; } Object.Mesh.Materials[mm + i].EmissiveColor = materials[i].EmissiveColor; Object.Mesh.Materials[mm + i].NighttimeTexture = null; Object.Mesh.Materials[mm + i].DaytimeNighttimeBlend = 0; Object.Mesh.Materials[mm + i].GlowAttenuationData = materials[i].GlowAttenuationData; Object.Mesh.Materials[mm + i].WrapMode = materials[i].WrapMode; } } }
private static void RenderFace(ref World.MeshMaterial Material, VertexTemplate[] Vertices, Textures.OpenGlTextureWrapMode wrap, ref World.MeshFace Face, double CameraX, double CameraY, double CameraZ) { // texture if (Material.DaytimeTexture != null) { if (Textures.LoadTexture(Material.DaytimeTexture, wrap)) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (Material.DaytimeTexture.OpenGlTextures[(int)wrap] != LastBoundTexture) { GL.BindTexture(TextureTarget.Texture2D, Material.DaytimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = Material.DaytimeTexture.OpenGlTextures[(int)wrap]; } } else { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; LastBoundTexture = null; } } } else { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; LastBoundTexture = null; } } // blend mode float factor; if (Material.BlendMode == World.MeshMaterialBlendMode.Additive) { factor = 1.0f; if (!BlendEnabled) { GL.Enable(EnableCap.Blend); } GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); if (FogEnabled) { GL.Disable(EnableCap.Fog); } } else if (Material.NighttimeTexture == null) { float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } if (Material.NighttimeTexture != null) { if (LightingEnabled) { GL.Disable(EnableCap.Lighting); LightingEnabled = false; } } else { if (OptionLighting & !LightingEnabled) { GL.Enable(EnableCap.Lighting); LightingEnabled = true; } } // render daytime polygon int FaceType = Face.Flags & World.MeshFace.FaceTypeMask; switch (FaceType) { case World.MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case World.MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case World.MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case World.MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } if (Material.GlowAttenuationData != 0) { float alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ); GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); } else { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A); } if ((Material.Flags & World.MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 *(float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); } else { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); } if (Material.DaytimeTexture != null) { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } } else { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } } GL.End(); // render nighttime polygon if (Material.NighttimeTexture != null && Textures.LoadTexture(Material.NighttimeTexture, wrap)) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (!BlendEnabled) { GL.Enable(EnableCap.Blend); } GL.BindTexture(TextureTarget.Texture2D, Material.NighttimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = null; GL.AlphaFunc(AlphaFunction.Greater, 0.0f); GL.Enable(EnableCap.AlphaTest); switch (FaceType) { case World.MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case World.MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case World.MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case World.MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } float alphafactor; if (Material.GlowAttenuationData != 0) { alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ); float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } alphafactor *= blend; } else { alphafactor = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (alphafactor > 1.0f) { alphafactor = 1.0f; } } GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); if ((Material.Flags & World.MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 *(float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); } else { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); } for (int j = 0; j < Face.Vertices.Length; j++) { GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); if (Vertices[Face.Vertices[j].Index] is ColoredVertex) { ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index]; GL.Color3(v.Color.R, v.Color.G, v.Color.B); } GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } GL.End(); RestoreAlphaFunc(); if (!BlendEnabled) { GL.Disable(EnableCap.Blend); } } // normals if (OptionNormals) { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; } for (int j = 0; j < Face.Vertices.Length; j++) { GL.Begin(PrimitiveType.Lines); GL.Color4(inv255 * (float)Material.Color.R, inv255 * (float)Material.Color.G, inv255 * (float)Material.Color.B, 1.0f); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X + Face.Vertices[j].Normal.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y + Face.Vertices[j].Normal.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z + Face.Vertices[j].Normal.Z - CameraZ)); GL.End(); } } // finalize if (Material.BlendMode == World.MeshMaterialBlendMode.Additive) { GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); if (!BlendEnabled) { GL.Disable(EnableCap.Blend); } if (FogEnabled) { GL.Enable(EnableCap.Fog); } } }
/// <summary>Registers a texture and returns a handle to the texture.</summary> /// <param name="texture">The texture data.</param> /// <param name="parameters">The parameters that specify how to process the texture.</param> /// <param name="handle">Receives the handle to the texture.</param> /// <returns>Whether loading the texture was successful.</returns> public override bool RegisterTexture(OpenBveApi.Textures.Texture texture, OpenBveApi.Textures.TextureParameters parameters, out OpenBveApi.Textures.TextureHandle handle) { texture = texture.ApplyParameters(parameters); handle = Textures.RegisterTexture(texture); return(true); }
// create element private static int CreateElement(TrainManager.Train Train, double Left, double Top, double Width, double Height, double FullWidth, double FullHeight, double WorldLeft, double WorldTop, double WorldWidth, double WorldHeight, double WorldZ, double DriverX, double DriverY, double DriverZ, Textures.Texture Texture, Color32 Color, bool AddStateToLastElement) { // create object ObjectManager.StaticObject Object = new ObjectManager.StaticObject(); Vector3[] v = new Vector3[4]; double sx = 0.5 * WorldWidth * Width / FullWidth; double sy = 0.5 * WorldHeight * Height / FullHeight; v[0] = new Vector3(-sx, -sy, 0); v[1] = new Vector3(-sx, sy, 0); v[2] = new Vector3(sx, sy, 0); v[3] = new Vector3(sx, -sy, 0); World.Vertex t0 = new World.Vertex(v[0], new Vector2(0.0f, 1.0f)); World.Vertex t1 = new World.Vertex(v[1], new Vector2(0.0f, 0.0f)); World.Vertex t2 = new World.Vertex(v[2], new Vector2(1.0f, 0.0f)); World.Vertex t3 = new World.Vertex(v[3], new Vector2(1.0f, 1.0f)); Object.Mesh.Vertices = new World.Vertex[] { t0, t1, t2, t3 }; Object.Mesh.Faces = new World.MeshFace[] { new World.MeshFace(new int[] { 0, 1, 2, 3 }) }; Object.Mesh.Materials = new World.MeshMaterial[1]; Object.Mesh.Materials[0].Flags = Texture != null ? (byte)World.MeshMaterial.TransparentColorMask : (byte)0; Object.Mesh.Materials[0].Color = Color; Object.Mesh.Materials[0].TransparentColor = new Color24(0, 0, 255); Object.Mesh.Materials[0].DaytimeTexture = Texture; Object.Mesh.Materials[0].NighttimeTexture = null; Object.Dynamic = true; // calculate offset Vector3 o; o.X = WorldLeft + sx + WorldWidth * Left / FullWidth; o.Y = WorldTop - sy - WorldHeight * Top / FullHeight; o.Z = WorldZ; // add object if (AddStateToLastElement) { int n = Train.Cars[Train.DriverCar].CarSections[0].Elements.Length - 1; int j = Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States.Length; Array.Resize<ObjectManager.AnimatedObjectState>(ref Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States, j + 1); Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[j].Position = o; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[j].Object = Object; return n; } else { int n = Train.Cars[Train.DriverCar].CarSections[0].Elements.Length; Array.Resize<ObjectManager.AnimatedObject>(ref Train.Cars[Train.DriverCar].CarSections[0].Elements, n + 1); Train.Cars[Train.DriverCar].CarSections[0].Elements[n] = new ObjectManager.AnimatedObject(); Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States = new ObjectManager.AnimatedObjectState[1]; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[0].Position = o; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[0].Object = Object; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].CurrentState = 0; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].ObjectIndex = ObjectManager.CreateDynamicObject(); ObjectManager.Objects[Train.Cars[Train.DriverCar].CarSections[0].Elements[n].ObjectIndex] = ObjectManager.CloneObject(Object); return n; } }
/// <summary>This method is called once the route and train data have been preprocessed, in order to physically setup the simulation</summary> private void SetupSimulation() { if (Loading.Cancel) { Close(); } lock (BaseRenderer.GdiPlusLock) { Timetable.CreateTimetable(); } //Check if any critical errors have occured during the route or train loading for (int i = 0; i < Interface.MessageCount; i++) { if (Interface.LogMessages[i].Type == MessageType.Critical) { MessageBox.Show("A critical error has occured:\n\n" + Interface.LogMessages[i].Text + "\n\nPlease inspect the error log file for further information.", "Load", MessageBoxButtons.OK, MessageBoxIcon.Hand); Close(); } } Program.Renderer.Lighting.Initialize(); Game.LogRouteName = System.IO.Path.GetFileName(MainLoop.currentResult.RouteFile); Game.LogTrainName = System.IO.Path.GetFileName(MainLoop.currentResult.TrainFolder); Game.LogDateTime = DateTime.Now; if (Interface.CurrentOptions.LoadInAdvance) { Textures.LoadAllTextures(); } else { Program.Renderer.TextureManager.UnloadAllTextures(); } // camera Program.Renderer.InitializeVisibility(); TrainManager.PlayerTrain.DriverBody = new DriverBody(TrainManager.PlayerTrain); Program.Renderer.CameraTrackFollower.UpdateAbsolute(0.0, true, false); Program.Renderer.CameraTrackFollower.UpdateAbsolute(-0.1, true, false); Program.Renderer.CameraTrackFollower.UpdateAbsolute(0.1, true, false); Program.Renderer.CameraTrackFollower.TriggerType = EventTriggerType.Camera; // starting time and track position Program.CurrentRoute.SecondsSinceMidnight = 0.0; Game.StartupTime = 0.0; int PlayerFirstStationIndex = -1; double PlayerFirstStationPosition; int os = -1; bool f = false; for (int i = 0; i < Program.CurrentRoute.Stations.Length; i++) { if (!String.IsNullOrEmpty(Game.InitialStationName)) { if (Game.InitialStationName.ToLowerInvariant() == Program.CurrentRoute.Stations[i].Name.ToLowerInvariant()) { PlayerFirstStationIndex = i; } } if (Program.CurrentRoute.Stations[i].StopMode == StationStopMode.AllStop | Program.CurrentRoute.Stations[i].StopMode == StationStopMode.PlayerStop & Program.CurrentRoute.Stations[i].Stops.Length != 0) { if (f == false) { os = i; f = true; } } } if (PlayerFirstStationIndex == -1) { if (os == -1) { PlayerFirstStationIndex = 0; } else { PlayerFirstStationIndex = os; } } { int s = Program.CurrentRoute.Stations[PlayerFirstStationIndex].GetStopIndex(TrainManager.PlayerTrain.NumberOfCars); if (s >= 0) { PlayerFirstStationPosition = Program.CurrentRoute.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition; double TrainLength = 0.0; for (int c = 0; c < TrainManager.PlayerTrain.Cars.Length; c++) { TrainLength += TrainManager.PlayerTrain.Cars[c].Length; } for (int j = 0; j < Program.CurrentRoute.BufferTrackPositions.Length; j++) { if (PlayerFirstStationPosition > Program.CurrentRoute.BufferTrackPositions[j] && PlayerFirstStationPosition - TrainLength < Program.CurrentRoute.BufferTrackPositions[j]) { /* * HACK: The initial start position for the player train is stuck on a set of buffers * This means we have to make some one the fly adjustments to the first station stop position */ //Set the start position to be the buffer position plus the train length plus 1m PlayerFirstStationPosition = Program.CurrentRoute.BufferTrackPositions[j] + TrainLength + 1; //Update the station stop location if (s >= 0) { Program.CurrentRoute.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition = PlayerFirstStationPosition; } else { Program.CurrentRoute.Stations[PlayerFirstStationIndex].DefaultTrackPosition = PlayerFirstStationPosition; } break; } } } else { PlayerFirstStationPosition = Program.CurrentRoute.Stations[PlayerFirstStationIndex].DefaultTrackPosition; } if (Game.InitialStationTime != -1) { Program.CurrentRoute.SecondsSinceMidnight = Game.InitialStationTime; Game.StartupTime = Game.InitialStationTime; } else { if (Program.CurrentRoute.Stations[PlayerFirstStationIndex].ArrivalTime < 0.0) { if (Program.CurrentRoute.Stations[PlayerFirstStationIndex].DepartureTime < 0.0) { Program.CurrentRoute.SecondsSinceMidnight = 0.0; Game.StartupTime = 0.0; } else { Program.CurrentRoute.SecondsSinceMidnight = Program.CurrentRoute.Stations[PlayerFirstStationIndex].DepartureTime - Program.CurrentRoute.Stations[PlayerFirstStationIndex].StopTime; Game.StartupTime = Program.CurrentRoute.Stations[PlayerFirstStationIndex].DepartureTime - Program.CurrentRoute.Stations[PlayerFirstStationIndex].StopTime; } } else { Program.CurrentRoute.SecondsSinceMidnight = Program.CurrentRoute.Stations[PlayerFirstStationIndex].ArrivalTime; Game.StartupTime = Program.CurrentRoute.Stations[PlayerFirstStationIndex].ArrivalTime; } } } int OtherFirstStationIndex = -1; double OtherFirstStationPosition = 0.0; double OtherFirstStationTime = 0.0; for (int i = 0; i < Program.CurrentRoute.Stations.Length; i++) { if (Program.CurrentRoute.Stations[i].StopMode == StationStopMode.AllStop | Program.CurrentRoute.Stations[i].StopMode == StationStopMode.PlayerPass & Program.CurrentRoute.Stations[i].Stops.Length != 0) { OtherFirstStationIndex = i; int s = Program.CurrentRoute.Stations[i].GetStopIndex(TrainManager.PlayerTrain.Cars.Length); if (s >= 0) { OtherFirstStationPosition = Program.CurrentRoute.Stations[i].Stops[s].TrackPosition; } else { OtherFirstStationPosition = Program.CurrentRoute.Stations[i].DefaultTrackPosition; } if (Program.CurrentRoute.Stations[i].ArrivalTime < 0.0) { if (Program.CurrentRoute.Stations[i].DepartureTime < 0.0) { OtherFirstStationTime = 0.0; } else { OtherFirstStationTime = Program.CurrentRoute.Stations[i].DepartureTime - Program.CurrentRoute.Stations[i].StopTime; } } else { OtherFirstStationTime = Program.CurrentRoute.Stations[i].ArrivalTime; } break; } } if (Game.PrecedingTrainTimeDeltas.Length != 0) { OtherFirstStationTime -= Game.PrecedingTrainTimeDeltas[Game.PrecedingTrainTimeDeltas.Length - 1]; if (OtherFirstStationTime < Program.CurrentRoute.SecondsSinceMidnight) { Program.CurrentRoute.SecondsSinceMidnight = OtherFirstStationTime; } } // initialize trains for (int i = 0; i < TrainManager.Trains.Length; i++) { TrainManager.Trains[i].Initialize(); int s = TrainManager.Trains[i].IsPlayerTrain ? PlayerFirstStationIndex : OtherFirstStationIndex; if (s >= 0) { if (Program.CurrentRoute.Stations[s].OpenLeftDoors) { for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { TrainManager.Trains[i].Cars[j].Doors[0].AnticipatedOpen = true; } } if (Program.CurrentRoute.Stations[s].OpenRightDoors) { for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { TrainManager.Trains[i].Cars[j].Doors[1].AnticipatedOpen = true; } } } if (Program.CurrentRoute.Sections.Length != 0) { Program.CurrentRoute.Sections[0].Enter(TrainManager.Trains[i]); } for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { double length = TrainManager.Trains[i].Cars[0].Length; TrainManager.Trains[i].Cars[j].Move(-length); TrainManager.Trains[i].Cars[j].Move(length); } } foreach (var Train in TrainManager.TFOs) { Train.Initialize(); foreach (var Car in Train.Cars) { double length = Train.Cars[0].Length; Car.Move(-length); Car.Move(length); } } // score Game.CurrentScore.ArrivalStation = PlayerFirstStationIndex + 1; Game.CurrentScore.DepartureStation = PlayerFirstStationIndex; Game.CurrentScore.Maximum = 0; for (int i = 0; i < Program.CurrentRoute.Stations.Length; i++) { if (i != PlayerFirstStationIndex & Program.CurrentRoute.Stations[i].PlayerStops()) { if (i == 0 || Program.CurrentRoute.Stations[i - 1].Type != StationType.ChangeEnds && Program.CurrentRoute.Stations[i - 1].Type != StationType.Jump) { Game.CurrentScore.Maximum += Game.ScoreValueStationArrival; } } } if (Game.CurrentScore.Maximum <= 0) { Game.CurrentScore.Maximum = Game.ScoreValueStationArrival; } // signals if (Program.CurrentRoute.Sections.Length > 0) { Program.CurrentRoute.UpdateAllSections(); } // move train in position for (int i = 0; i < TrainManager.Trains.Length; i++) { double p; if (TrainManager.Trains[i].IsPlayerTrain) { p = PlayerFirstStationPosition; } else if (TrainManager.Trains[i].State == TrainState.Bogus) { p = Program.CurrentRoute.BogusPreTrainInstructions[0].TrackPosition; TrainManager.Trains[i].AI = new Game.BogusPretrainAI(TrainManager.Trains[i]); } else { p = OtherFirstStationPosition; } for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { TrainManager.Trains[i].Cars[j].Move(p); } } // timetable if (Timetable.DefaultTimetableDescription.Length == 0) { Timetable.DefaultTimetableDescription = Game.LogTrainName; } // initialize camera if (Program.Renderer.Camera.CurrentRestriction == CameraRestrictionMode.NotAvailable || Program.Renderer.Camera.CurrentRestriction == CameraRestrictionMode.Restricted3D) { Program.Renderer.Camera.CurrentMode = CameraViewMode.InteriorLookAhead; } //Place the initial camera in the driver car TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].UpdateCamera(); Program.Renderer.CameraTrackFollower.UpdateAbsolute(-1.0, true, false); Program.Renderer.UpdateVisibility(Program.Renderer.CameraTrackFollower.TrackPosition + Program.Renderer.Camera.Alignment.Position.Z); Program.Renderer.Camera.SavedExterior = new CameraAlignment(new OpenBveApi.Math.Vector3(-2.5, 1.5, -15.0), 0.3, -0.2, 0.0, PlayerFirstStationPosition, 1.0); Program.Renderer.Camera.SavedTrack = new CameraAlignment(new OpenBveApi.Math.Vector3(-3.0, 2.5, 0.0), 0.3, 0.0, 0.0, TrainManager.PlayerTrain.Cars[0].TrackPosition - 10.0, 1.0); // signalling sections for (int i = 0; i < TrainManager.Trains.Length; i++) { int s = TrainManager.Trains[i].CurrentSectionIndex; Program.CurrentRoute.Sections[s].Enter(TrainManager.Trains[i]); } if (Program.CurrentRoute.Sections.Length > 0) { Program.CurrentRoute.UpdateAllSections(); } // fast-forward until start time { Game.MinimalisticSimulation = true; const double w = 0.25; double u = Game.StartupTime - Program.CurrentRoute.SecondsSinceMidnight; if (u > 0) { while (true) { double v = u < w ? u : w; u -= v; Program.CurrentRoute.SecondsSinceMidnight += v; TrainManager.UpdateTrains(v); if (u <= 0.0) { break; } TotalTimeElapsedForSectionUpdate += v; if (TotalTimeElapsedForSectionUpdate >= 1.0) { if (Program.CurrentRoute.Sections.Length > 0) { Program.CurrentRoute.UpdateAllSections(); } TotalTimeElapsedForSectionUpdate = 0.0; } } } Game.MinimalisticSimulation = false; } // animated objects ObjectManager.UpdateAnimatedWorldObjects(0.0, true); TrainManager.UpdateTrainObjects(0.0, true); //HACK: This function calls a single update on all objects attached to the player's train // but ignores any specified damping so that all needles etc. are in the correct place // for the first frame, rather than spinning wildly to get to the starting point. TrainManager.PlayerTrain.UpdateCabObjects(); // timetable if (TrainManager.PlayerTrain.Station >= 0) { Timetable.UpdateCustomTimetable(Program.CurrentRoute.Stations[TrainManager.PlayerTrain.Station].TimetableDaytimeTexture, Program.CurrentRoute.Stations[TrainManager.PlayerTrain.Station].TimetableNighttimeTexture); if (Timetable.CustomObjectsUsed != 0 & Timetable.CustomTimetableAvailable && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.AutoGenerated && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.None) { Timetable.CurrentTimetable = Timetable.TimetableState.Custom; } } //Create AI driver for the player train if specified via the commmand line if (Game.InitialAIDriver == true) { TrainManager.PlayerTrain.AI = new Game.SimpleHumanDriverAI(TrainManager.PlayerTrain, Double.PositiveInfinity); if (TrainManager.PlayerTrain.Plugin != null && !TrainManager.PlayerTrain.Plugin.SupportsAI) { MessageManager.AddMessage(Translations.GetInterfaceString("notification_aiunable"), MessageDependency.None, GameMode.Expert, OpenBveApi.Colors.MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null); } } // warnings / errors if (Interface.MessageCount != 0) { int filesNotFound = 0; int errors = 0; int warnings = 0; for (int i = 0; i < Interface.MessageCount; i++) { if (Interface.LogMessages[i].FileNotFound) { filesNotFound++; } else if (Interface.LogMessages[i].Type == MessageType.Error) { errors++; } else if (Interface.LogMessages[i].Type == MessageType.Warning) { warnings++; } } string NotFound = null; string Messages; if (filesNotFound != 0) { NotFound = filesNotFound.ToString() + " file(s) not found"; MessageManager.AddMessage(NotFound, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null); } if (errors != 0 & warnings != 0) { Messages = errors.ToString() + " error(s), " + warnings.ToString() + " warning(s)"; MessageManager.AddMessage(Messages, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null); } else if (errors != 0) { Messages = errors.ToString() + " error(s)"; MessageManager.AddMessage(Messages, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null); } else { Messages = warnings.ToString() + " warning(s)"; MessageManager.AddMessage(Messages, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null); } Game.RouteInformation.FilesNotFound = NotFound; Game.RouteInformation.ErrorsAndWarnings = Messages; //Print the plugin error encountered (If any) for 10s //This must be done after the simulation has init, as otherwise the timeout doesn't work if (Loading.PluginError != null) { MessageManager.AddMessage(Loading.PluginError, MessageDependency.None, GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null); MessageManager.AddMessage(Translations.GetInterfaceString("errors_plugin_failure2"), MessageDependency.None, GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null); } } loadComplete = true; RenderRealTimeElapsed = 0.0; RenderTimeElapsed = 0.0; World.InitializeCameraRestriction(); Loading.SimulationSetup = true; switch (Game.InitialViewpoint) { case 0: if (Game.InitialReversedConsist) { /* * HACK: The cab view has been created using the position of the initial driver car. * Trigger a forced change to ensure that it is now correctly positioned in the consist */ TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].ChangeCarSection(TrainManager.CarSectionType.Interior); } break; case 1: //Switch camera to exterior MainLoop.SaveCameraSettings(); Program.Renderer.Camera.CurrentMode = CameraViewMode.Exterior; MainLoop.RestoreCameraSettings(); for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++) { TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior); //Make bogies visible TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0); } Program.Renderer.Camera.AlignmentDirection = new CameraAlignment(); Program.Renderer.Camera.AlignmentSpeed = new CameraAlignment(); Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange); World.UpdateAbsoluteCamera(0.0); Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance); break; case 2: //Switch camera to track MainLoop.SaveCameraSettings(); Program.Renderer.Camera.CurrentMode = CameraViewMode.Track; MainLoop.RestoreCameraSettings(); for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++) { TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior); TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0); } Program.Renderer.Camera.AlignmentDirection = new CameraAlignment(); Program.Renderer.Camera.AlignmentSpeed = new CameraAlignment(); Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange); World.UpdateAbsoluteCamera(0.0); Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance); break; case 3: //Switch camera to flyby MainLoop.SaveCameraSettings(); Program.Renderer.Camera.CurrentMode = CameraViewMode.FlyBy; MainLoop.RestoreCameraSettings(); for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++) { TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior); TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0); } Program.Renderer.Camera.AlignmentDirection = new CameraAlignment(); Program.Renderer.Camera.AlignmentSpeed = new CameraAlignment(); Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange); World.UpdateAbsoluteCamera(0.0); Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance); break; case 4: //Switch camera to flyby MainLoop.SaveCameraSettings(); Program.Renderer.Camera.CurrentMode = CameraViewMode.FlyByZooming; MainLoop.RestoreCameraSettings(); for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++) { TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior); TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0); TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0); } Program.Renderer.Camera.AlignmentDirection = new CameraAlignment(); Program.Renderer.Camera.AlignmentSpeed = new CameraAlignment(); Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange); World.UpdateAbsoluteCamera(0.0); Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance); break; } }
internal static void Main(string[] args) { // platform and mono int p = (int)Environment.OSVersion.Platform; if (p == 4 | p == 128) { // general Unix CurrentPlatform = Platform.Linux; } else if (p == 6) { // Mac CurrentPlatform = Platform.Mac; } else { // non-Unix CurrentPlatform = Platform.Windows; } CurrentlyRunOnMono = Type.GetType("Mono.Runtime") != null; CurrentHost = new Host(); // file system FileSystem = FileSystem.FromCommandLineArgs(args); FileSystem.CreateFileSystem(); Plugins.LoadPlugins(); // command line arguments SkipArgs = new bool[args.Length]; if (args.Length != 0) { string File = System.IO.Path.Combine(Application.StartupPath, "RouteViewer.exe"); if (System.IO.File.Exists(File)) { int Skips = 0; System.Text.StringBuilder NewArgs = new System.Text.StringBuilder(); for (int i = 0; i < args.Length; i++) { if (args[i] != null && System.IO.File.Exists(args[i])) { if (System.IO.Path.GetExtension(args[i]).Equals(".csv", StringComparison.OrdinalIgnoreCase)) { string Text = System.IO.File.ReadAllText(args[i], System.Text.Encoding.UTF8); if (Text.Length != -1 && Text.IndexOf("CreateMeshBuilder", StringComparison.OrdinalIgnoreCase) == -1) { if (NewArgs.Length != 0) { NewArgs.Append(" "); } NewArgs.Append("\"" + args[i] + "\""); SkipArgs[i] = true; Skips++; } } } else { SkipArgs[i] = true; Skips++; } } if (NewArgs.Length != 0) { System.Diagnostics.Process.Start(File, NewArgs.ToString()); } if (Skips == args.Length) { return; } } } Options.LoadOptions(); Interface.CurrentOptions.ObjectOptimizationBasicThreshold = 1000; Interface.CurrentOptions.ObjectOptimizationFullThreshold = 250; Interface.CurrentOptions.AntialiasingLevel = 16; Interface.CurrentOptions.AnisotropicFilteringLevel = 16; // initialize camera currentGraphicsMode = new GraphicsMode(new ColorFormat(8, 8, 8, 8), 24, 8, Interface.CurrentOptions.AntialiasingLevel); currentGameWindow = new ObjectViewer(Renderer.ScreenWidth, Renderer.ScreenHeight, currentGraphicsMode, "Object Viewer", GameWindowFlags.Default); currentGameWindow.Visible = true; currentGameWindow.TargetUpdateFrequency = 0; currentGameWindow.TargetRenderFrequency = 0; currentGameWindow.Title = "Object Viewer"; currentGameWindow.Run(); // quit Textures.UnloadAllTextures(); }
/// <summary>Changes to or from fullscreen mode.</summary> internal static void ToggleFullscreen() { Fullscreen = !Fullscreen; // begin HACK // Renderer.ClearDisplayLists(); GL.Disable(EnableCap.Fog); GL.Disable(EnableCap.Lighting); Renderer.LightingEnabled = false; Textures.UnloadAllTextures(); if (Fullscreen) { IList <DisplayResolution> resolutions = OpenTK.DisplayDevice.Default.AvailableResolutions; for (int i = 0; i < resolutions.Count; i++) { //Test each resolution if (resolutions[i].Width == Interface.CurrentOptions.FullscreenWidth && resolutions[i].Height == Interface.CurrentOptions.FullscreenHeight && resolutions[i].BitsPerPixel == Interface.CurrentOptions.FullscreenBits) { OpenTK.DisplayDevice.Default.ChangeResolution(resolutions[i]); Program.currentGameWindow.Width = resolutions[i].Width; Program.currentGameWindow.Height = resolutions[i].Height; Screen.Width = Interface.CurrentOptions.FullscreenWidth; Screen.Height = Interface.CurrentOptions.FullscreenHeight; Program.currentGameWindow.WindowState = WindowState.Fullscreen; break; } } if (Program.currentGameWindow.WindowState != WindowState.Fullscreen) { MessageBox.Show(Interface.GetInterfaceString("errors_fullscreen_switch1") + System.Environment.NewLine + Interface.GetInterfaceString("errors_fullscreen_switch2"), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand); Fullscreen = false; } } else { OpenTK.DisplayDevice.Default.RestoreResolution(); Program.currentGameWindow.WindowState = WindowState.Normal; Program.currentGameWindow.Width = Interface.CurrentOptions.WindowWidth; Program.currentGameWindow.Height = Interface.CurrentOptions.WindowHeight; Screen.Width = Interface.CurrentOptions.WindowWidth; Screen.Height = Interface.CurrentOptions.WindowHeight; } Renderer.InitializeLighting(); MainLoop.UpdateViewport(MainLoop.ViewPortChangeMode.NoChange); MainLoop.InitializeMotionBlur(); Timetable.CreateTimetable(); Timetable.UpdateCustomTimetable(null, null); World.InitializeCameraRestriction(); if (Renderer.OptionBackfaceCulling) { GL.Enable(EnableCap.CullFace); } else { GL.Disable(EnableCap.CullFace); } Renderer.ReAddObjects(); // end HACK // //Reset the camera when switching between fullscreen and windowed mode //Otherwise, if the aspect ratio changes distortion will occur until the view is changed or the camera reset if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead) { World.CameraCurrentAlignment.Position = new OpenBveApi.Math.Vector3(0.0, 0.0, 0.0); } World.CameraCurrentAlignment.Yaw = 0.0; World.CameraCurrentAlignment.Pitch = 0.0; World.CameraCurrentAlignment.Roll = 0.0; if (World.CameraMode == World.CameraViewMode.Track) { TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, TrainManager.PlayerTrain.Cars[0].FrontAxle.Follower.TrackPosition, true, false); } }
// // SET CUSTOM LOADING SCREEN BACKGROUND // /// <summary>Sets the loading screen background to a custom image</summary> /// <summary>Sets the loading screen background to a custom image</summary> internal static void SetLoadingBkg(string fileName) { Textures.RegisterTexture(fileName, out TextureLoadingBkg); customLoadScreen = true; }
private static void RenderFace(ref World.MeshMaterial Material, World.Vertex[] Vertices, Textures.OpenGlTextureWrapMode wrap, ref World.MeshFace Face, double CameraX, double CameraY, double CameraZ) { // texture if (Material.DaytimeTexture != null) { if (Textures.LoadTexture(Material.DaytimeTexture, wrap)) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (Material.DaytimeTexture.OpenGlTextures[(int)wrap] != LastBoundTexture) { GL.BindTexture(TextureTarget.Texture2D, Material.DaytimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = Material.DaytimeTexture.OpenGlTextures[(int)wrap]; } } else { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; LastBoundTexture = null; } } } else { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; LastBoundTexture = null; } } // blend mode float factor; if (Material.BlendMode == World.MeshMaterialBlendMode.Additive) { factor = 1.0f; if (!BlendEnabled) GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One); if (FogEnabled) { GL.Disable(EnableCap.Fog); } } else if (Material.NighttimeTexture == null) { float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) blend = 1.0f; factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } if (Material.NighttimeTexture != null) { if (LightingEnabled) { GL.Disable(EnableCap.Lighting); LightingEnabled = false; } } else { if (OptionLighting & !LightingEnabled) { GL.Enable(EnableCap.Lighting); LightingEnabled = true; } } // render daytime polygon int FaceType = Face.Flags & World.MeshFace.FaceTypeMask; switch (FaceType) { case World.MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case World.MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case World.MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case World.MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } if (Material.GlowAttenuationData != 0) { float alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ); GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); } else { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A); } if ((Material.Flags & World.MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 * (float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); EmissiveEnabled = true; } else if (EmissiveEnabled) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); EmissiveEnabled = false; } if (Material.DaytimeTexture != null) { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } } else { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } } GL.End(); // render nighttime polygon if (Material.NighttimeTexture != null && Textures.LoadTexture(Material.NighttimeTexture, wrap)) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (!BlendEnabled) { GL.Enable(EnableCap.Blend); } GL.BindTexture(TextureTarget.Texture2D, Material.NighttimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = null; GL.AlphaFunc(AlphaFunction.Greater, 0.0f); GL.Enable(EnableCap.AlphaTest); switch (FaceType) { case World.MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case World.MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case World.MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case World.MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } float alphafactor; if (Material.GlowAttenuationData != 0) { alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ); float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) blend = 1.0f; alphafactor *= blend; } else { alphafactor = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (alphafactor > 1.0f) alphafactor = 1.0f; } GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); if ((Material.Flags & World.MeshMaterial.EmissiveColorMask) != 0) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 * (float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); EmissiveEnabled = true; } else if (EmissiveEnabled) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); EmissiveEnabled = false; } for (int j = 0; j < Face.Vertices.Length; j++) { GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } GL.End(); RestoreAlphaFunc(); if (!BlendEnabled) { GL.Disable(EnableCap.Blend); } } // normals if (OptionNormals) { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; } for (int j = 0; j < Face.Vertices.Length; j++) { GL.Begin(PrimitiveType.Lines); GL.Color4(inv255 * (float)Material.Color.R, inv255 * (float)Material.Color.G, inv255 * (float)Material.Color.B, 1.0f); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X + Face.Vertices[j].Normal.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y + Face.Vertices[j].Normal.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z + Face.Vertices[j].Normal.Z - CameraZ)); GL.End(); } } // finalize if (Material.BlendMode == World.MeshMaterialBlendMode.Additive) { GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); if (!BlendEnabled) GL.Disable(EnableCap.Blend); if (FogEnabled) { GL.Enable(EnableCap.Fog); } } }
private static void ApplyMeshBuilder(ref ObjectManager.StaticObject Object, MeshBuilder Builder) { if (Builder.Faces.Count != 0) { int mf = Object.Mesh.Faces.Length; int mm = Object.Mesh.Materials.Length; int mv = Object.Mesh.Vertices.Length; Array.Resize <World.MeshFace>(ref Object.Mesh.Faces, mf + Builder.Faces.Count); if (mm == 0) { if (Object.Mesh.Materials.Length == 0) { /* * If the object has no materials defined at all, we need to add one */ Array.Resize(ref Object.Mesh.Materials, 1); Object.Mesh.Materials[0] = new World.MeshMaterial(); Object.Mesh.Materials[0].Color = new Color32(255, 255, 255); Object.Mesh.Materials[0].Flags = (byte)(0 | 0); Object.Mesh.Materials[0].DaytimeTexture = null; Object.Mesh.Materials[0].NighttimeTexture = null; mm++; } } if (Builder.Materials.Length > 0) { Array.Resize <World.MeshMaterial>(ref Object.Mesh.Materials, mm + Builder.Materials.Length); } else { /* * If no materials have been defined for this face group, use the last material */ mm -= 1; } Array.Resize <VertexTemplate>(ref Object.Mesh.Vertices, mv + Builder.Vertices.Count); for (int i = 0; i < Builder.Vertices.Count; i++) { Object.Mesh.Vertices[mv + i] = Builder.Vertices[i]; } for (int i = 0; i < Builder.Faces.Count; i++) { Object.Mesh.Faces[mf + i] = Builder.Faces[i]; for (int j = 0; j < Object.Mesh.Faces[mf + i].Vertices.Length; j++) { Object.Mesh.Faces[mf + i].Vertices[j].Index += (ushort)mv; } Object.Mesh.Faces[mf + i].Material += (ushort)mm; } for (int i = 0; i < Builder.Materials.Length; i++) { Object.Mesh.Materials[mm + i].Flags = (byte)((Builder.Materials[i].EmissiveColorUsed ? World.MeshMaterial.EmissiveColorMask : 0) | (Builder.Materials[i].TransparentColorUsed ? World.MeshMaterial.TransparentColorMask : 0)); Object.Mesh.Materials[mm + i].Color = Builder.Materials[i].Color; Object.Mesh.Materials[mm + i].TransparentColor = Builder.Materials[i].TransparentColor; if (Builder.Materials[i].DaytimeTexture != null) { Textures.Texture tday; if (Builder.Materials[i].TransparentColorUsed) { Textures.RegisterTexture(Builder.Materials[i].DaytimeTexture, new OpenBveApi.Textures.TextureParameters(null, new Color24(Builder.Materials[i].TransparentColor.R, Builder.Materials[i].TransparentColor.G, Builder.Materials[i].TransparentColor.B)), out tday); } else { Textures.RegisterTexture(Builder.Materials[i].DaytimeTexture, out tday); } Object.Mesh.Materials[mm + i].DaytimeTexture = tday; } else { Object.Mesh.Materials[mm + i].DaytimeTexture = null; } Object.Mesh.Materials[mm + i].EmissiveColor = Builder.Materials[i].EmissiveColor; if (Builder.Materials[i].NighttimeTexture != null) { Textures.Texture tnight; if (Builder.Materials[i].TransparentColorUsed) { Textures.RegisterTexture(Builder.Materials[i].NighttimeTexture, new OpenBveApi.Textures.TextureParameters(null, new Color24(Builder.Materials[i].TransparentColor.R, Builder.Materials[i].TransparentColor.G, Builder.Materials[i].TransparentColor.B)), out tnight); } else { Textures.RegisterTexture(Builder.Materials[i].NighttimeTexture, out tnight); } Object.Mesh.Materials[mm + i].NighttimeTexture = tnight; } else { Object.Mesh.Materials[mm + i].NighttimeTexture = null; } Object.Mesh.Materials[mm + i].DaytimeNighttimeBlend = 0; Object.Mesh.Materials[mm + i].BlendMode = Builder.Materials[i].BlendMode; Object.Mesh.Materials[mm + i].GlowAttenuationData = Builder.Materials[i].GlowAttenuationData; Object.Mesh.Materials[mm + i].WrapMode = Textures.OpenGlTextureWrapMode.RepeatRepeat; } } }
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(Interface.MessageType.Error, false, "No marker nodes defined in XML file " + fileName); return(false); } marker = new CsvRwRouteParser.Marker(); foreach (XmlNode n in DocumentNodes) { if (n.HasChildNodes) { bool EarlyDefined = false, LateDefined = false; string EarlyText = null, Text = null, LateText = null; string[] Trains = null; Textures.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.HasChildNodes) { Interface.AddMessage(Interface.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": var f = OpenBveApi.Path.CombineFile(Path, cc.InnerText); if (System.IO.File.Exists(f)) { if (!Textures.RegisterTexture(f, out EarlyTexture)) { Interface.AddMessage(Interface.MessageType.Error, false, "Loading MessageEarlyTexture " + f + " failed."); } } else { Interface.AddMessage(Interface.MessageType.Error, false, "MessageEarlyTexture " + f + " does not exist."); } break; case "time": if (!Interface.TryParseTime(cc.InnerText, out EarlyTime)) { Interface.AddMessage(Interface.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.HasChildNodes) { Interface.AddMessage(Interface.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": var f = OpenBveApi.Path.CombineFile(Path, cc.InnerText); if (System.IO.File.Exists(f)) { if (!Textures.RegisterTexture(f, out Texture)) { Interface.AddMessage(Interface.MessageType.Error, false, "Loading MessageTexture " + f + " failed."); } } else { Interface.AddMessage(Interface.MessageType.Error, false, "MessageTexture " + f + " does not exist."); } break; case "color": OnTimeColor = ParseColor(cc.InnerText, fileName); break; } } break; case "late": if (!c.HasChildNodes) { Interface.AddMessage(Interface.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": var f = OpenBveApi.Path.CombineFile(Path, cc.InnerText); if (System.IO.File.Exists(f)) { if (!Textures.RegisterTexture(f, out LateTexture)) { Interface.AddMessage(Interface.MessageType.Error, false, "Loading MessageLateTexture " + f + " failed."); } } else { Interface.AddMessage(Interface.MessageType.Error, false, "MessageLateTexture " + f + " does not exist."); } break; case "time": if (!Interface.TryParseTime(cc.InnerText, out LateTime)) { Interface.AddMessage(Interface.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(Interface.MessageType.Error, false, "Marker timeout invalid in " + fileName); } break; case "distance": if (!NumberFormats.TryParseDouble(c.InnerText, new[] { 1.0 }, out EndingPosition)) { Interface.AddMessage(Interface.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(Interface.MessageType.Error, false, "No marker timeout or distance defined in marker XML " + fileName); return(false); } if (EndingPosition != Double.PositiveInfinity) { marker.EndingPosition = 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(Interface.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.MessageColor = EarlyColor; } else { Interface.AddMessage(Interface.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(Interface.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(Interface.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); }
//This renders the frame protected override void OnRenderFrame(FrameEventArgs e) { if (!firstFrame) { //If the load is not complete, then we shouldn't be running the mainloop return; } double TimeElapsed = RenderTimeElapsed; double RealTimeElapsed = RenderRealTimeElapsed; //Next, check if we're in paused/ in a menu if (Program.Renderer.CurrentInterface != InterfaceType.Normal) { MainLoop.UpdateControlRepeats(0.0); MainLoop.ProcessKeyboard(); MainLoop.ProcessControls(0.0); if (Program.Renderer.CurrentInterface == InterfaceType.Pause) { System.Threading.Thread.Sleep(10); } //Renderer.UpdateLighting(); Program.Renderer.RenderScene(TimeElapsed); Program.currentGameWindow.SwapBuffers(); if (MainLoop.Quit != MainLoop.QuitMode.ContinueGame) { Close(); if (Program.CurrentlyRunningOnMono && MainLoop.Quit == MainLoop.QuitMode.QuitProgram) { Environment.Exit(0); } } //If the menu state has not changed, don't update the rendered simulation return; } //Use the OpenTK framerate as this is much more accurate //Also avoids running a calculation if (TotalTimeElapsedForInfo >= 0.2) { Program.Renderer.FrameRate = RenderFrequency; TotalTimeElapsedForInfo = 0.0; } if (Program.Renderer.PreviousInterface != InterfaceType.Normal) { // Update animated objects with zero elapsed time (NOT time elapsed in menu) // and set again to avoid glitching ObjectManager.UpdateAnimatedWorldObjects(0.0, false); Program.Renderer.CurrentInterface = InterfaceType.Normal; } else { ObjectManager.UpdateAnimatedWorldObjects(TimeElapsed, false); } //We need to update the camera position in the render sequence //Not doing this means that the camera doesn't move // update in one piece if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Interior | Program.Renderer.Camera.CurrentMode == CameraViewMode.InteriorLookAhead) { //Update the in-car camera based upon the current driver car (Cabview or passenger view) TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.CameraCar].UpdateCamera(); } else if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Exterior) { //Update the camera position based upon the relative car position TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.CameraCar].UpdateCamera(); } if (Program.Renderer.Camera.CurrentRestriction == CameraRestrictionMode.NotAvailable || Program.Renderer.Camera.CurrentRestriction == CameraRestrictionMode.Restricted3D) { TrainManager.PlayerTrain.DriverBody.Update(TimeElapsed); } //Check if we are running at an accelerated time factor- //Camera motion speed should be the same whatever the game speed is if (TimeFactor != 1) { World.UpdateAbsoluteCamera(TimeElapsed / TimeFactor); } else { World.UpdateAbsoluteCamera(TimeElapsed); } TrainManager.UpdateTrainObjects(TimeElapsed, false); if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Interior | Program.Renderer.Camera.CurrentMode == CameraViewMode.InteriorLookAhead | Program.Renderer.Camera.CurrentMode == CameraViewMode.Exterior) { Program.Renderer.UpdateVisibility(Program.Renderer.CameraTrackFollower.TrackPosition + Program.Renderer.Camera.Alignment.Position.Z); int d = TrainManager.PlayerTrain.DriverCar; Program.Renderer.Camera.CurrentSpeed = TrainManager.PlayerTrain.Cars[d].CurrentSpeed; } else { Program.Renderer.Camera.CurrentSpeed = 0.0; } Program.Renderer.Camera.AlignmentDirection = new CameraAlignment(); if (MainLoop.Quit != MainLoop.QuitMode.ContinueGame) { Program.currentGameWindow.Exit(); if (Program.CurrentlyRunningOnMono && MainLoop.Quit == MainLoop.QuitMode.QuitProgram) { Environment.Exit(0); } } Program.Renderer.Lighting.UpdateLighting(Program.CurrentRoute.SecondsSinceMidnight); Program.Renderer.RenderScene(TimeElapsed); Program.Sounds.Update(TimeElapsed, Interface.CurrentOptions.SoundModel); Program.currentGameWindow.SwapBuffers(); Game.UpdateBlackBox(); // pause/menu // limit framerate if (MainLoop.LimitFramerate) { System.Threading.Thread.Sleep(10); } MainLoop.UpdateControlRepeats(RealTimeElapsed); MainLoop.ProcessKeyboard(); MainLoop.UpdateMouse(RealTimeElapsed); MainLoop.ProcessControls(TimeElapsed); for (int i = 0; i < JoystickManager.AttachedJoysticks.Length; i++) { var railDriver = JoystickManager.AttachedJoysticks[i] as JoystickManager.Raildriver; if (railDriver != null) { if (Interface.CurrentOptions.RailDriverMPH) { railDriver.SetDisplay((int)(TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Specs .CurrentPerceivedSpeed * 2.23694)); } else { railDriver.SetDisplay((int)(TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Specs .CurrentPerceivedSpeed * 3.6)); } } } RenderRealTimeElapsed = 0.0; RenderTimeElapsed = 0.0; #if DEBUG MainLoop.CheckForOpenGlError("MainLoop"); #endif if (Interface.CurrentOptions.UnloadUnusedTextures) { Textures.UnloadUnusedTextures(TimeElapsed); } // finish try { Interface.SaveLogs(); } catch { } }
//Parses an XML background definition public static BackgroundManager.BackgroundHandle ReadBackgroundXML(string fileName) { List <BackgroundManager.StaticBackground> Backgrounds = new List <BackgroundManager.StaticBackground>(); //The current XML file to load XmlDocument currentXML = new XmlDocument(); //Load the object's XML file currentXML.Load(fileName); string Path = System.IO.Path.GetDirectoryName(fileName); double[] UnitOfLength = { 1.0 }; //Check for null if (currentXML.DocumentElement != null) { XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Background"); //Check this file actually contains OpenBVE light definition nodes if (DocumentNodes != null) { foreach (XmlNode n in DocumentNodes) { if (n.ChildNodes.OfType <XmlElement>().Any()) { double DisplayTime = -1; //The time to transition between backgrounds in seconds double TransitionTime = 0.8; //The texture to use (if static) Texture t = null; //The object to use (if object based) ObjectManager.StaticObject o = null; //The transition mode between backgrounds BackgroundManager.BackgroundTransitionMode mode = BackgroundManager.BackgroundTransitionMode.FadeIn; //The number of times the texture is repeated around the viewing frustrum (if appropriate) double repetitions = 6; foreach (XmlNode c in n.ChildNodes) { string[] Arguments = c.InnerText.Split(','); switch (c.Name.ToLowerInvariant()) { case "mode": switch (c.InnerText.ToLowerInvariant()) { case "fadein": mode = BackgroundManager.BackgroundTransitionMode.FadeIn; break; case "fadeout": mode = BackgroundManager.BackgroundTransitionMode.FadeOut; break; case "none": mode = BackgroundManager.BackgroundTransitionMode.None; break; default: Interface.AddMessage(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 b = ObjectManager.LoadObject(f, System.Text.Encoding.Default, false, false, false); o = (ObjectManager.StaticObject)b; } 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 { Textures.RegisterTexture(file, out t); } break; case "time": if (!Interface.TryParseTime(Arguments[0].Trim(), 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 BackgroundManager.StaticBackground(t, repetitions, false, TransitionTime, mode, DisplayTime)); } if (t == null && o != null) { //All other parameters are ignored if an object has been defined //TODO: Error message stating they have been ignored return(new BackgroundManager.BackgroundObject(o)); } } } if (Backgrounds.Count == 1) { return(Backgrounds[0]); } if (Backgrounds.Count > 1) { //Sort list- Not worried about when they start or end, so use simple LINQ Backgrounds = Backgrounds.OrderBy(o => o.Time).ToList(); //If more than 2 backgrounds, convert to array and return a new dynamic background return(new BackgroundManager.DynamicBackground(Backgrounds.ToArray())); } } } //We couldn't find any valid XML, so return false throw new InvalidDataException(); }
internal MarkerStartEvent(double trackPositionDelta, Textures.Texture texture) { this.TrackPositionDelta = trackPositionDelta; this.DontTriggerAnymore = false; this.Texture = texture; }
private static void RenderCube(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, double Size, double CameraX, double CameraY, double CameraZ, Texture TextureIndex) { Vector3[] v = new Vector3[8]; v[0] = new Vector3(Size, Size, -Size); v[1] = new Vector3(Size, -Size, -Size); v[2] = new Vector3(-Size, -Size, -Size); v[3] = new Vector3(-Size, Size, -Size); v[4] = new Vector3(Size, Size, Size); v[5] = new Vector3(Size, -Size, Size); v[6] = new Vector3(-Size, -Size, Size); v[7] = new Vector3(-Size, Size, Size); for (int i = 0; i < 8; i++) { v[i].Rotate(Direction, Up, Side); v[i].X += Position.X - CameraX; v[i].Y += Position.Y - CameraY; v[i].Z += Position.Z - CameraZ; } int[][] Faces = new int[6][]; Faces[0] = new int[] { 0, 1, 2, 3 }; Faces[1] = new int[] { 0, 4, 5, 1 }; Faces[2] = new int[] { 0, 3, 7, 4 }; Faces[3] = new int[] { 6, 5, 4, 7 }; Faces[4] = new int[] { 6, 7, 3, 2 }; Faces[5] = new int[] { 6, 2, 1, 5 }; if (TextureIndex == null || !Textures.LoadTexture(TextureIndex, OpenGlTextureWrapMode.ClampClamp)) { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; } for (int i = 0; i < 6; i++) { GL.Begin(PrimitiveType.Quads); GL.Color3(1.0, 1.0, 1.0); for (int j = 0; j < 4; j++) { GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); } GL.End(); } return; } else { TexturingEnabled = true; GL.Enable(EnableCap.Texture2D); } GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); Vector2[][] t = new Vector2[6][]; t[0] = new Vector2[] { new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0) }; t[1] = new Vector2[] { new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0) }; t[2] = new Vector2[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; t[3] = new Vector2[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; t[4] = new Vector2[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; t[5] = new Vector2[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; for (int i = 0; i < 6; i++) { GL.Begin(PrimitiveType.Quads); GL.Color3(1.0, 1.0, 1.0); for (int j = 0; j < 4; j++) { GL.TexCoord2(t[i][j].X, t[i][j].Y); GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); } GL.End(); } }
private static int CreateElement(TrainManager.Train Train, double Left, double Top, double Width, double Height, double RelativeRotationCenterX, double RelativeRotationCenterY, double Distance, double PanelResolution, double PanelLeft, double PanelRight, double PanelTop, double PanelBottom, double PanelBitmapWidth, double PanelBitmapHeight, double PanelCenterX, double PanelCenterY, double PanelOriginX, double PanelOriginY, double DriverX, double DriverY, double DriverZ, Textures.Texture DaytimeTexture, Textures.Texture NighttimeTexture, Color32 Color, bool AddStateToLastElement) { double WorldWidth, WorldHeight; if (Screen.Width >= Screen.Height) { WorldWidth = 2.0 * Math.Tan(0.5 * World.HorizontalViewingAngle) * EyeDistance; WorldHeight = WorldWidth / World.AspectRatio; } else { WorldHeight = 2.0 * Math.Tan(0.5 * World.VerticalViewingAngle) * EyeDistance / World.AspectRatio; WorldWidth = WorldHeight * World.AspectRatio; } double x0 = Left / PanelResolution; double x1 = (Left + Width) / PanelResolution; double y0 = (PanelBottom - Top) / PanelResolution * World.AspectRatio; double y1 = (PanelBottom - (Top + Height)) / PanelResolution * World.AspectRatio; double xd = 0.5 - PanelCenterX / PanelResolution; x0 += xd; x1 += xd; double yt = PanelBottom - PanelResolution / World.AspectRatio; double yd = (PanelCenterY - yt) / (PanelBottom - yt) - 0.5; y0 += yd; y1 += yd; x0 = (x0 - 0.5) * WorldWidth; x1 = (x1 - 0.5) * WorldWidth; y0 = (y0 - 0.5) * WorldHeight; y1 = (y1 - 0.5) * WorldHeight; double xm = x0 * (1.0 - RelativeRotationCenterX) + x1 * RelativeRotationCenterX; double ym = y0 * (1.0 - RelativeRotationCenterY) + y1 * RelativeRotationCenterY; Vector3[] v = new Vector3[4]; v[0] = new Vector3(x0 - xm, y1 - ym, 0); v[1] = new Vector3(x0 - xm, y0 - ym, 0); v[2] = new Vector3(x1 - xm, y0 - ym, 0); v[3] = new Vector3(x1 - xm, y1 - ym, 0); World.Vertex t0 = new World.Vertex(v[0], new Vector2(0.0f, 1.0f)); World.Vertex t1 = new World.Vertex(v[1], new Vector2(0.0f, 0.0f)); World.Vertex t2 = new World.Vertex(v[2], new Vector2(1.0f, 0.0f)); World.Vertex t3 = new World.Vertex(v[3], new Vector2(1.0f, 1.0f)); ObjectManager.StaticObject Object = new ObjectManager.StaticObject(); Object.Mesh.Vertices = new World.Vertex[] { t0, t1, t2, t3 }; Object.Mesh.Faces = new World.MeshFace[] { new World.MeshFace(new int[] { 0, 1, 2, 3 }) }; Object.Mesh.Materials = new World.MeshMaterial[1]; Object.Mesh.Materials[0].Flags = (byte)(DaytimeTexture != null ? World.MeshMaterial.TransparentColorMask : 0); Object.Mesh.Materials[0].Color = Color; Object.Mesh.Materials[0].TransparentColor = new Color24(0, 0, 255); Object.Mesh.Materials[0].DaytimeTexture = DaytimeTexture; Object.Mesh.Materials[0].NighttimeTexture = NighttimeTexture; Object.Dynamic = true; // calculate offset Vector3 o; o.X = xm + DriverX; o.Y = ym + DriverY; o.Z = EyeDistance - Distance + DriverZ; // add object if (AddStateToLastElement) { int n = Train.Cars[Train.DriverCar].CarSections[0].Elements.Length - 1; int j = Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States.Length; Array.Resize<ObjectManager.AnimatedObjectState>(ref Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States, j + 1); Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[j].Position = o; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[j].Object = Object; return n; } else { int n = Train.Cars[Train.DriverCar].CarSections[0].Elements.Length; Array.Resize<ObjectManager.AnimatedObject>(ref Train.Cars[Train.DriverCar].CarSections[0].Elements, n + 1); Train.Cars[Train.DriverCar].CarSections[0].Elements[n] = new ObjectManager.AnimatedObject(); Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States = new ObjectManager.AnimatedObjectState[1]; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[0].Position = o; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].States[0].Object = Object; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].CurrentState = 0; Train.Cars[Train.DriverCar].CarSections[0].Elements[n].ObjectIndex = ObjectManager.CreateDynamicObject(); ObjectManager.Objects[Train.Cars[Train.DriverCar].CarSections[0].Elements[n].ObjectIndex] = ObjectManager.CloneObject(Object); return n; } }
/// <summary>Renders the ATS lamp overlay</summary> /// <param name="Element">The HUD element these are to be rendererd onto</param> /// <param name="TimeElapsed">The time elapsed</param> private static void RenderATSLamps(HUD.Element Element, double TimeElapsed) { // ats lamps if (CurrentLampCollection.Lamps == null) { InitializeLamps(); } double lcrh, lw, rw; CalculateViewingPlaneSize(Element, out lw, out rw, out lcrh); // start // ReSharper disable once PossibleNullReferenceException int n = CurrentLampCollection.Lamps.Length; double w = (double)CurrentLampCollection.Width + lw + rw; double h = Element.Value2 * n; double x = Element.Alignment.X < 0 ? 0.0 : Element.Alignment.X > 0 ? Screen.Width - w : 0.5 * (Screen.Width - w); double y = Element.Alignment.Y < 0 ? 0.0 : Element.Alignment.Y > 0 ? Screen.Height - h : 0.5 * (Screen.Height - h); x += Element.Position.X; y += Element.Position.Y; for (int j = 0; j < n; j++) { if (CurrentLampCollection.Lamps[j].Type != LampType.None) { int o; if (j == 0) { o = -1; } else if (CurrentLampCollection.Lamps[j - 1].Type == LampType.None) { o = -1; } else if (j < n - 1 && CurrentLampCollection.Lamps[j + 1].Type == LampType.None) { o = 1; } else if (j == n - 1) { o = 1; } else { o = 0; } HUD.Image Left = o < 0 ? Element.TopLeft : o == 0 ? Element.CenterLeft : Element.BottomLeft; HUD.Image Middle = o < 0 ? Element.TopMiddle : o == 0 ? Element.CenterMiddle : Element.BottomMiddle; HUD.Image Right = o < 0 ? Element.TopRight : o == 0 ? Element.CenterRight : Element.BottomRight; MessageColor sc = MessageColor.Gray; if (TrainManager.PlayerTrain.Plugin.Panel.Length >= 272) { switch (CurrentLampCollection.Lamps[j].Type) { case LampType.Ats: if (TrainManager.PlayerTrain.Plugin.Panel[256] != 0) { sc = MessageColor.Orange; } break; case LampType.AtsOperation: if (TrainManager.PlayerTrain.Plugin.Panel[258] != 0) { sc = MessageColor.Red; } break; case LampType.AtsPPower: if (TrainManager.PlayerTrain.Plugin.Panel[259] != 0) { sc = MessageColor.Green; } break; case LampType.AtsPPattern: if (TrainManager.PlayerTrain.Plugin.Panel[260] != 0) { sc = MessageColor.Orange; } break; case LampType.AtsPBrakeOverride: if (TrainManager.PlayerTrain.Plugin.Panel[261] != 0) { sc = MessageColor.Orange; } break; case LampType.AtsPBrakeOperation: if (TrainManager.PlayerTrain.Plugin.Panel[262] != 0) { sc = MessageColor.Orange; } break; case LampType.AtsP: if (TrainManager.PlayerTrain.Plugin.Panel[263] != 0) { sc = MessageColor.Green; } break; case LampType.AtsPFailure: if (TrainManager.PlayerTrain.Plugin.Panel[264] != 0) { sc = MessageColor.Red; } break; case LampType.Atc: if (TrainManager.PlayerTrain.Plugin.Panel[265] != 0) { sc = MessageColor.Orange; } break; case LampType.AtcPower: if (TrainManager.PlayerTrain.Plugin.Panel[266] != 0) { sc = MessageColor.Orange; } break; case LampType.AtcUse: if (TrainManager.PlayerTrain.Plugin.Panel[267] != 0) { sc = MessageColor.Orange; } break; case LampType.AtcEmergency: if (TrainManager.PlayerTrain.Plugin.Panel[268] != 0) { sc = MessageColor.Red; } break; case LampType.Eb: if (TrainManager.PlayerTrain.Plugin.Panel[270] != 0) { sc = MessageColor.Green; } break; case LampType.ConstSpeed: if (TrainManager.PlayerTrain.Plugin.Panel[269] != 0) { sc = MessageColor.Orange; } break; } } // colors float br, bg, bb, ba; CreateBackColor(Element.BackgroundColor, sc, out br, out bg, out bb, out ba); float tr, tg, tb, ta; CreateTextColor(Element.TextColor, sc, out tr, out tg, out tb, out ta); float or, og, ob, oa; CreateBackColor(Element.OverlayColor, sc, out or, out og, out ob, out oa); // left background if (Left.BackgroundTexture != null) { if (Textures.LoadTexture(Left.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Left.BackgroundTexture.Width; double v = (double)Left.BackgroundTexture.Height; GL.Color4(br, bg, bb, ba); RenderOverlayTexture(Left.BackgroundTexture, x, y, x + u, y + v); } } // right background if (Right.BackgroundTexture != null) { if (Textures.LoadTexture(Right.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Right.BackgroundTexture.Width; double v = (double)Right.BackgroundTexture.Height; GL.Color4(br, bg, bb, ba); RenderOverlayTexture(Right.BackgroundTexture, x + w - u, y, x + w, y + v); } } // middle background if (Middle.BackgroundTexture != null) { if (Textures.LoadTexture(Middle.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Middle.BackgroundTexture.Height; GL.Color4(br, bg, bb, ba); RenderOverlayTexture(Middle.BackgroundTexture, x + lw, y, x + w - rw, y + v); } } { // text string t = CurrentLampCollection.Lamps[j].Text; double u = CurrentLampCollection.Lamps[j].Width; double v = CurrentLampCollection.Lamps[j].Height; double p = Math.Round(Element.TextAlignment.X < 0 ? x : Element.TextAlignment.X > 0 ? x + w - u : x + 0.5 * (w - u)); double q = Math.Round(Element.TextAlignment.Y < 0 ? y : Element.TextAlignment.Y > 0 ? y + lcrh - v : y + 0.5 * (lcrh - v)); p += Element.TextPosition.X; q += Element.TextPosition.Y; DrawString(Element.Font, t, new System.Drawing.Point((int)p, (int)q), TextAlignment.TopLeft, new Color128(tr, tg, tb, ta), Element.TextShadow); } // left overlay if (Left.OverlayTexture != null) { if (Textures.LoadTexture(Left.OverlayTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Left.OverlayTexture.Width; double v = (double)Left.OverlayTexture.Height; GL.Color4(or, og, ob, oa); RenderOverlayTexture(Left.OverlayTexture, x, y, x + u, y + v); } } // right overlay if (Right.OverlayTexture != null) { if (Textures.LoadTexture(Right.OverlayTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Right.OverlayTexture.Width; double v = (double)Right.OverlayTexture.Height; GL.Color4(or, og, ob, oa); RenderOverlayTexture(Right.OverlayTexture, x + w - u, y, x + w, y + v); } } // middle overlay if (Middle.OverlayTexture != null) { if (Textures.LoadTexture(Middle.OverlayTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Middle.OverlayTexture.Height; GL.Color4(or, og, ob, oa); RenderOverlayTexture(Middle.OverlayTexture, x + lw, y, x + w - rw, y + v); } } } y += (double)Element.Value2; } }
private static void RenderFace(ref World.MeshMaterial Material, World.Vertex[] Vertices, Textures.OpenGlTextureWrapMode wrap, ref World.MeshFace Face, double CameraX, double CameraY, double CameraZ) { // texture if (Material.DaytimeTexture != null) { if (Textures.LoadTexture(Material.DaytimeTexture, wrap)) { if (!TexturingEnabled) { Gl.glEnable(Gl.GL_TEXTURE_2D); TexturingEnabled = true; } if (Material.DaytimeTexture.OpenGlTextures[(int)wrap] != LastBoundTexture) { Gl.glBindTexture(Gl.GL_TEXTURE_2D, Material.DaytimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = Material.DaytimeTexture.OpenGlTextures[(int)wrap]; } } else { if (TexturingEnabled) { Gl.glDisable(Gl.GL_TEXTURE_2D); TexturingEnabled = false; LastBoundTexture = null; } } } else { if (TexturingEnabled) { Gl.glDisable(Gl.GL_TEXTURE_2D); TexturingEnabled = false; LastBoundTexture = null; } } // blend mode float factor; if (Material.BlendMode == World.MeshMaterialBlendMode.Additive) { factor = 1.0f; if (!BlendEnabled) Gl.glEnable(Gl.GL_BLEND); Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE); if (FogEnabled) { Gl.glDisable(Gl.GL_FOG); } } else if (Material.NighttimeTexture == null) { float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) blend = 1.0f; factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } if (Material.NighttimeTexture != null) { if (LightingEnabled) { Gl.glDisable(Gl.GL_LIGHTING); LightingEnabled = false; } } else { if (OptionLighting & !LightingEnabled) { Gl.glEnable(Gl.GL_LIGHTING); LightingEnabled = true; } } // render daytime polygon int FaceType = Face.Flags & World.MeshFace.FaceTypeMask; switch (FaceType) { case World.MeshFace.FaceTypeTriangles: Gl.glBegin(Gl.GL_TRIANGLES); break; case World.MeshFace.FaceTypeTriangleStrip: Gl.glBegin(Gl.GL_TRIANGLE_STRIP); break; case World.MeshFace.FaceTypeQuads: Gl.glBegin(Gl.GL_QUADS); break; case World.MeshFace.FaceTypeQuadStrip: Gl.glBegin(Gl.GL_QUAD_STRIP); break; default: Gl.glBegin(Gl.GL_POLYGON); break; } if (Material.GlowAttenuationData != 0) { float alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ); Gl.glColor4f(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); } else { Gl.glColor4f(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A); } if ((Material.Flags & World.MeshMaterial.EmissiveColorMask) != 0) { Gl.glMaterialfv(Gl.GL_FRONT_AND_BACK, Gl.GL_EMISSION, new float[] { inv255 * (float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); EmissiveEnabled = true; } else if (EmissiveEnabled) { Gl.glMaterialfv(Gl.GL_FRONT_AND_BACK, Gl.GL_EMISSION, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); EmissiveEnabled = false; } if (Material.DaytimeTexture != null) { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { Gl.glNormal3f(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); Gl.glTexCoord2f(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { Gl.glTexCoord2f(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } } else { if (LightingEnabled) { for (int j = 0; j < Face.Vertices.Length; j++) { Gl.glNormal3f(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z); Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } else { for (int j = 0; j < Face.Vertices.Length; j++) { Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } } } Gl.glEnd(); // render nighttime polygon if (Material.NighttimeTexture != null && Textures.LoadTexture(Material.NighttimeTexture, wrap)) { if (!TexturingEnabled) { Gl.glEnable(Gl.GL_TEXTURE_2D); TexturingEnabled = true; } if (!BlendEnabled) { Gl.glEnable(Gl.GL_BLEND); } Gl.glBindTexture(Gl.GL_TEXTURE_2D, Material.NighttimeTexture.OpenGlTextures[(int)wrap].Name); LastBoundTexture = null; Gl.glAlphaFunc(Gl.GL_GREATER, 0.0f); Gl.glEnable(Gl.GL_ALPHA_TEST); switch (FaceType) { case World.MeshFace.FaceTypeTriangles: Gl.glBegin(Gl.GL_TRIANGLES); break; case World.MeshFace.FaceTypeTriangleStrip: Gl.glBegin(Gl.GL_TRIANGLE_STRIP); break; case World.MeshFace.FaceTypeQuads: Gl.glBegin(Gl.GL_QUADS); break; case World.MeshFace.FaceTypeQuadStrip: Gl.glBegin(Gl.GL_QUAD_STRIP); break; default: Gl.glBegin(Gl.GL_POLYGON); break; } float alphafactor; if (Material.GlowAttenuationData != 0) { alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ); float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (blend > 1.0f) blend = 1.0f; alphafactor *= blend; } else { alphafactor = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount; if (alphafactor > 1.0f) alphafactor = 1.0f; } Gl.glColor4f(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor); if ((Material.Flags & World.MeshMaterial.EmissiveColorMask) != 0) { Gl.glMaterialfv(Gl.GL_FRONT_AND_BACK, Gl.GL_EMISSION, new float[] { inv255 * (float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f }); EmissiveEnabled = true; } else if (EmissiveEnabled) { Gl.glMaterialfv(Gl.GL_FRONT_AND_BACK, Gl.GL_EMISSION, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); EmissiveEnabled = false; } for (int j = 0; j < Face.Vertices.Length; j++) { Gl.glTexCoord2f(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y); Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); } Gl.glEnd(); RestoreAlphaFunc(); if (!BlendEnabled) { Gl.glDisable(Gl.GL_BLEND); } } // normals if (OptionNormals) { if (TexturingEnabled) { Gl.glDisable(Gl.GL_TEXTURE_2D); TexturingEnabled = false; } for (int j = 0; j < Face.Vertices.Length; j++) { Gl.glBegin(Gl.GL_LINES); Gl.glColor4f(inv255 * (float)Material.Color.R, inv255 * (float)Material.Color.G, inv255 * (float)Material.Color.B, 1.0f); Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ)); Gl.glVertex3f((float)(Vertices[Face.Vertices[j].Index].Coordinates.X + Face.Vertices[j].Normal.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y + Face.Vertices[j].Normal.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z + Face.Vertices[j].Normal.Z - CameraZ)); Gl.glEnd(); } } // finalize if (Material.BlendMode == World.MeshMaterialBlendMode.Additive) { Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA); if (!BlendEnabled) Gl.glDisable(Gl.GL_BLEND); if (FogEnabled) { Gl.glEnable(Gl.GL_FOG); } } }
// --- constructors --- /// <summary>Creates a new table of characters.</summary> /// <param name="font">The font.</param> /// <param name="offset">The offset from codepoint U+0000.</param> internal OpenGlFontTable(Font font, int offset) { /* * Measure characters. * */ Size[] physicalSizes = new Size[256]; Size[] typographicSizes = new Size[256]; Bitmap bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb); Graphics graphics = Graphics.FromImage(bitmap); graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; for (int i = 0; i < 256; i++) { SizeF physicalSize = graphics.MeasureString(char.ConvertFromUtf32(offset + i), font, int.MaxValue, StringFormat.GenericDefault); SizeF typographicSize = graphics.MeasureString(char.ConvertFromUtf32(offset + i), font, int.MaxValue, StringFormat.GenericTypographic); physicalSizes[i] = new Size((int)Math.Ceiling(physicalSize.Width), (int)Math.Ceiling(physicalSize.Height)); typographicSizes[i] = new Size((int)Math.Ceiling(typographicSize.Width == 0.0f ? physicalSize.Width : typographicSize.Width), (int)Math.Ceiling(typographicSize.Height == 0.0f ? physicalSize.Height : typographicSize.Height)); } /* * Find suitable bitmap dimensions. * */ const int width = 256; const int border = 1; int x = border; int y = border; int lineHeight = 0; for (int i = 0; i < 256; i++) { if (x + physicalSizes[i].Width + border > width) { x = border; y += lineHeight; lineHeight = 0; } else { x += physicalSizes[i].Width + 2 * border; } if (physicalSizes[i].Height + border > lineHeight) { lineHeight = physicalSizes[i].Height + 2 * border; } } y += lineHeight; int height = (int)RoundToPowerOfTwo((uint)y); graphics.Dispose(); bitmap.Dispose(); /* * Draw character to bitmap. * */ bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); graphics = Graphics.FromImage(bitmap); graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; graphics.Clear(Color.Black); x = border; y = border; lineHeight = 0; this.Characters = new OpenGlFontChar[256]; for (int i = 0; i < 256; i++) { if (x + physicalSizes[i].Width + border > width) { x = border; y += lineHeight; lineHeight = 0; } graphics.DrawString(char.ConvertFromUtf32(offset + i), font, Brushes.White, new PointF(x, y)); float x0 = (float)(x - border) / (float)width; float x1 = (float)(x + physicalSizes[i].Width + border) / (float)width; float y0 = (float)(y - border) / (float)height; float y1 = (float)(y + physicalSizes[i].Height + border) / (float)height; this.Characters[i] = new OpenGlFontChar(new RectangleF(x0, y0, x1 - x0, y1 - y0), new Size(physicalSizes[i].Width + 2 * border, physicalSizes[i].Height + 2 * border), typographicSizes[i]); x += physicalSizes[i].Width + 2 * border; if (physicalSizes[i].Height + border > lineHeight) { lineHeight = physicalSizes[i].Height + 2 * border; } } graphics.Dispose(); this.Texture = Textures.RegisterTexture(bitmap); }
internal Background(Textures.Texture Texture, int Repetition, bool KeepAspectRatio) { this.Texture = Texture; this.Repetition = Repetition; this.KeepAspectRatio = KeepAspectRatio; }
// render data private static void RenderData(ref Table Table) { // prepare timetable int w = 384, h = 192; int offsetx = 0; int actualheight = h; float descriptionwidth = 256; float descriptionheight = 16; float stationnamewidth = 16; for (int k = 0; k < 2; k++) { Bitmap b = new Bitmap(w, h); Graphics g = Graphics.FromImage(b); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; g.Clear(Color.Transparent); g.FillRectangle(Brushes.White, new RectangleF(offsetx, 0, w, actualheight)); Font f = new Font(FontFamily.GenericSansSerif, 13.0f, GraphicsUnit.Pixel); Font fs = new Font(FontFamily.GenericSansSerif, 11.0f, GraphicsUnit.Pixel); Font fss = new Font(FontFamily.GenericSansSerif, 9.0f, GraphicsUnit.Pixel); // draw timetable string t; SizeF s; // description float x0 = offsetx + 8; float y0 = 8; if (k == 1) { t = DefaultTimetableDescription; g.DrawString(t, f, Brushes.Black, new RectangleF(x0, 6, descriptionwidth, descriptionheight + 8)); y0 += descriptionheight + 2; } // highest speed t = Interface.GetInterfaceString("timetable_highestspeed"); s = g.MeasureString(t, fs); g.DrawString(t, fs, Brushes.Black, x0, y0); float y0a = y0 + s.Height + 2; float x1 = x0 + s.Width + 4; for (int i = 0; i < Table.Tracks.Length; i++) { float y = y0a + 18 * i; t = Table.Tracks[i].Speed; g.DrawString(t, f, Brushes.Black, x0, y); s = g.MeasureString(t, f); float x = x0 + s.Width + 4; if (x > x1) { x1 = x; } } g.DrawLine(Pens.LightGray, new PointF(x1 - 2, 4 + descriptionheight), new PointF(x1 - 2, y0a + 18 * Table.Tracks.Length - 1)); // driving time t = Interface.GetInterfaceString("timetable_drivingtime"); s = g.MeasureString(t, fs); g.DrawString(t, fs, Brushes.Black, x1, y0); float x2 = x1 + s.Width + 4; for (int i = 0; i < Table.Tracks.Length; i++) { float y = y0a + 18 * i; if (Table.Tracks[i].Time.Hour.Length != 0) { t = Table.Tracks[i].Time.Hour; g.DrawString(t, fss, Brushes.Black, x1, y + 2); } else { t = "0"; } s = g.MeasureString(t, fss, 9999, StringFormat.GenericTypographic); float x = x1 + s.Width - 1; if (Table.Tracks[i].Time.Minute.Length != 0) { t = Table.Tracks[i].Time.Minute; g.DrawString(t, fs, Brushes.Black, x, y + 2); } else { t = "00:"; } s = g.MeasureString(t, fs, 9999, StringFormat.GenericTypographic); x += s.Width + 1; t = Table.Tracks[i].Time.Second; g.DrawString(t, fss, Brushes.Black, x, y + 2); s = g.MeasureString(t, fss, 9999, StringFormat.GenericTypographic); x += s.Width + 8; if (x > x2) { x2 = x; } } for (int i = 0; i < Table.Tracks.Length; i++) { float y = y0a + 18 * i; g.DrawLine(Pens.LightGray, new PointF(offsetx + 4, y - 1), new PointF(x2 - 2, y - 1)); } g.DrawLine(Pens.LightGray, new PointF(x2 - 2, 4 + descriptionheight), new PointF(x2 - 2, y0a + 18 * Table.Tracks.Length - 1)); // station name float y2 = y0; t = Interface.GetInterfaceString("timetable_stationname"); s = g.MeasureString(t, f); g.DrawString(t, f, Brushes.Black, x2, y2); float x3 = x2 + s.Width + 4; for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; g.DrawLine(Pens.LightGray, new PointF(x2 - 2, y - 1), new PointF(w - 4, y - 1)); t = Table.Stations[i].Name; if (Table.Stations[i].NameJapanese & Table.Stations[i].Name.Length > 1) { float[] sizes = new float[t.Length]; float totalsize = 0.0f; for (int j = 0; j < t.Length; j++) { sizes[j] = g.MeasureString(new string(t[j], 1), f, 9999, StringFormat.GenericTypographic).Width; totalsize += sizes[j]; } float space = (stationnamewidth - totalsize) / (float)(t.Length - 1); float x = 0.0f; for (int j = 0; j < t.Length; j++) { g.DrawString(new string(t[j], 1), f, Brushes.Black, x2 + x, y); x += sizes[j] + space; } } else { g.DrawString(t, f, Brushes.Black, x2, y); } s = g.MeasureString(t, f); { float x = x2 + s.Width + 4; if (x > x3) { x3 = x; } } } g.DrawLine(Pens.LightGray, new PointF(x3 - 2, 4 + descriptionheight), new PointF(x3 - 2, y0 + 18 * (Table.Stations.Length + 1))); if (k == 0) { stationnamewidth = x3 - x2 - 6; } // arrival time t = Interface.GetInterfaceString("timetable_arrivaltime"); s = g.MeasureString(t, f); g.DrawString(t, f, Brushes.Black, x3, y2); float x4 = x3 + s.Width + 4; for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; if (Table.Stations[i].Pass) { t = "00"; s = g.MeasureString(t, fs); float x = x3 + s.Width; t = " ↓"; g.DrawString(t, f, Brushes.Black, x, y); s = g.MeasureString(t, f); x += +s.Width + 4; if (x > x4) { x4 = x; } } else { if (Table.Stations[i].Arrival.Hour.Length != 0) { t = Table.Stations[i].Arrival.Hour; g.DrawString(t, fs, Brushes.Black, x3, y); } else { t = "00"; } s = g.MeasureString(t, fs); float x = x3 + s.Width; if (Table.Stations[i].Arrival.Minute.Length != 0 & Table.Stations[i].Arrival.Second.Length != 0) { t = Table.Stations[i].Arrival.Minute + ":" + Table.Stations[i].Arrival.Second; } else { t = ""; } g.DrawString(t, f, Brushes.Black, x, y); s = g.MeasureString(t, f); x += s.Width + 4; if (x > x4) { x4 = x; } } } g.DrawLine(Pens.LightGray, new PointF(x4 - 2, 4 + descriptionheight), new PointF(x4 - 2, y0 + 18 * (Table.Stations.Length + 1))); // departure time t = Interface.GetInterfaceString("timetable_departuretime"); s = g.MeasureString(t, f); g.DrawString(t, f, Brushes.Black, x4, y2); float x5 = x4 + s.Width + 4; for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; if (Table.Stations[i].Terminal) { t = "00"; s = g.MeasureString(t, fs); float x = x4 + s.Width; const float c0 = 4; const float c1 = 32; g.DrawLine(Pens.Black, new PointF(x + c0, y + 6), new PointF(x + c1, y + 6)); g.DrawLine(Pens.Black, new PointF(x + c0, y + 10), new PointF(x + c1, y + 10)); x += c1 + 4; if (x > x5) { x5 = x; } } else { if (Table.Stations[i].Departure.Hour.Length != 0) { t = Table.Stations[i].Departure.Hour; g.DrawString(t, fs, Brushes.Black, x4, y); } else { t = "00"; } s = g.MeasureString(t, fs); float x = x4 + s.Width; if (Table.Stations[i].Departure.Minute.Length != 0 & Table.Stations[i].Departure.Second.Length != 0) { t = Table.Stations[i].Departure.Minute + ":" + Table.Stations[i].Departure.Second; } else { t = ""; } g.DrawString(t, f, Brushes.Black, x, y); s = g.MeasureString(t, f); x += s.Width + 4; if (x > x5) { x5 = x; } } } for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; g.DrawLine(Pens.LightGray, new PointF(x2 - 2, y - 1), new PointF(w - 4, y - 1)); } // border if (k == 1) { g.DrawLine(Pens.Black, new PointF(offsetx + 4, 4), new PointF(offsetx + 4, y0a + 18 * Table.Tracks.Length - 1)); g.DrawLine(Pens.Black, new PointF(offsetx + 4, y0a + 18 * Table.Tracks.Length - 1), new PointF(x2 - 2, y0a + 18 * Table.Tracks.Length - 1)); g.DrawLine(Pens.Black, new PointF(offsetx + 4, 4), new PointF(w - 4, 4)); g.DrawLine(Pens.Black, new PointF(offsetx + 4, 4 + descriptionheight), new PointF(w - 4, 4 + descriptionheight)); g.DrawLine(Pens.Black, new PointF(x2 - 2, y0 + 18 * (Table.Stations.Length + 1)), new PointF(w - 4, y0 + 18 * (Table.Stations.Length + 1))); g.DrawLine(Pens.Black, new PointF(w - 4, 4), new PointF(w - 4, y0 + 18 * (Table.Stations.Length + 1))); g.DrawLine(Pens.Black, new PointF(x2 - 2, y0a + 18 * Table.Tracks.Length - 1), new PointF(x2 - 2, y0 + 18 * (Table.Stations.Length + 1))); } // measure w = (int)Math.Ceiling((double)(x5 + 1)); h = (int)Math.Ceiling((double)(y0 + 18 * (Table.Stations.Length + 1) + 4)); // description if (k == 0) { t = DefaultTimetableDescription; s = g.MeasureString(t, f, w - 16); descriptionwidth = s.Width; descriptionheight = s.Height + 2; h += (int)Math.Ceiling((double)s.Height) + 4; } // finish if (k == 0) { // measures int nw = Textures.RoundUpToPowerOfTwo(w); offsetx = nw - w; w = nw; actualheight = h; h = Textures.RoundUpToPowerOfTwo(h); } else { // create texture g.Dispose(); DefaultTimetableTexture = Textures.RegisterTexture(b); } } }
internal static void AddMarker(Textures.Texture Texture) { int n = MarkerTextures.Length; Array.Resize<Textures.Texture>(ref MarkerTextures, n + 1); MarkerTextures[n] = Texture; }
/// <summary>Renders a string to the screen.</summary> /// <param name="font">The font to use.</param> /// <param name="text">The string to render.</param> /// <param name="location">The location.</param> /// <param name="alignment">The alignment.</param> /// <param name="color">The color.</param> /// <remarks>This function sets the OpenGL blend function to glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA).</remarks> private static void DrawString(Fonts.OpenGlFont font, string text, Point location, TextAlignment alignment, Color128 color) { if (text == null || font == null) { return; } /* * Prepare the top-left coordinates for rendering, incorporating the * orientation of the string in relation to the specified location. * */ int left; if ((alignment & TextAlignment.Left) == 0) { int width = 0; for (int i = 0; i < text.Length; i++) { Texture texture; Fonts.OpenGlFontChar data; i += font.GetCharacterData(text, i, out texture, out data) - 1; width += data.TypographicSize.Width; } if ((alignment & TextAlignment.Right) != 0) { left = location.X - width; } else { left = location.X - width / 2; } } else { left = location.X; } int top; if ((alignment & TextAlignment.Top) == 0) { int height = 0; for (int i = 0; i < text.Length; i++) { Texture texture; Fonts.OpenGlFontChar data; i += font.GetCharacterData(text, i, out texture, out data) - 1; if (data.TypographicSize.Height > height) { height = data.TypographicSize.Height; } } if ((alignment & TextAlignment.Bottom) != 0) { top = location.Y - height; } else { top = location.Y - height / 2; } } else { top = location.Y; } /* * Render the string. * */ GL.Enable(EnableCap.Texture2D); for (int i = 0; i < text.Length; i++) { Texture texture; Fonts.OpenGlFontChar data; i += font.GetCharacterData(text, i, out texture, out data) - 1; if (Textures.LoadTexture(texture, OpenGlTextureWrapMode.ClampClamp)) { GL.BindTexture(TextureTarget.Texture2D, texture.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); int x = left - (data.PhysicalSize.Width - data.TypographicSize.Width) / 2; int y = top - (data.PhysicalSize.Height - data.TypographicSize.Height) / 2; /* * In the first pass, mask off the background with pure black. * */ GL.BlendFunc(BlendingFactor.Zero, BlendingFactor.OneMinusSrcColor); GL.Begin(PrimitiveType.Polygon); GL.Color4(color.A, color.A, color.A, 1.0f); GL.TexCoord2(data.TextureCoordinates.Left, data.TextureCoordinates.Top); GL.Vertex2(x, y); GL.Color4(color.A, color.A, color.A, 1.0f); GL.TexCoord2(data.TextureCoordinates.Right, data.TextureCoordinates.Top); GL.Vertex2(x + data.PhysicalSize.Width, y); GL.Color4(color.A, color.A, color.A, 1.0f); GL.TexCoord2(data.TextureCoordinates.Right, data.TextureCoordinates.Bottom); GL.Vertex2(x + data.PhysicalSize.Width, y + data.PhysicalSize.Height); GL.Color4(color.A, color.A, color.A, 1.0f); GL.TexCoord2(data.TextureCoordinates.Left, data.TextureCoordinates.Bottom); GL.Vertex2(x, y + data.PhysicalSize.Height); GL.End(); /* * In the second pass, add the character onto the background. * */ GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); GL.Begin(PrimitiveType.Polygon); GL.Color4(color.R, color.G, color.B, color.A); GL.TexCoord2(data.TextureCoordinates.Left, data.TextureCoordinates.Top); GL.Vertex2(x, y); GL.Color4(color.R, color.G, color.B, color.A); GL.TexCoord2(data.TextureCoordinates.Right, data.TextureCoordinates.Top); GL.Vertex2(x + data.PhysicalSize.Width, y); GL.Color4(color.R, color.G, color.B, color.A); GL.TexCoord2(data.TextureCoordinates.Right, data.TextureCoordinates.Bottom); GL.Vertex2(x + data.PhysicalSize.Width, y + data.PhysicalSize.Height); GL.Color4(color.R, color.G, color.B, color.A); GL.TexCoord2(data.TextureCoordinates.Left, data.TextureCoordinates.Bottom); GL.Vertex2(x, y + data.PhysicalSize.Height); GL.End(); } left += data.TypographicSize.Width; } GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); // HACK // }
/// <summary>Creates a clone of the specified object.</summary> /// <param name="Prototype">The prototype.</param> /// <param name="DaytimeTexture">The replacement daytime texture, or a null reference to keep the texture of the prototype.</param> /// <param name="NighttimeTexture">The replacement nighttime texture, or a null reference to keep the texture of the prototype.</param> /// <returns></returns> internal static StaticObject CloneObject(StaticObject Prototype, Textures.Texture DaytimeTexture, Textures.Texture NighttimeTexture) { if (Prototype == null) return null; StaticObject Result = new StaticObject(); Result.StartingDistance = Prototype.StartingDistance; Result.EndingDistance = Prototype.EndingDistance; Result.Dynamic = Prototype.Dynamic; // vertices Result.Mesh.Vertices = new World.Vertex[Prototype.Mesh.Vertices.Length]; for (int j = 0; j < Prototype.Mesh.Vertices.Length; j++) { Result.Mesh.Vertices[j] = Prototype.Mesh.Vertices[j]; } // faces Result.Mesh.Faces = new World.MeshFace[Prototype.Mesh.Faces.Length]; for (int j = 0; j < Prototype.Mesh.Faces.Length; j++) { Result.Mesh.Faces[j].Flags = Prototype.Mesh.Faces[j].Flags; Result.Mesh.Faces[j].Material = Prototype.Mesh.Faces[j].Material; Result.Mesh.Faces[j].Vertices = new World.MeshFaceVertex[Prototype.Mesh.Faces[j].Vertices.Length]; for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { Result.Mesh.Faces[j].Vertices[k] = Prototype.Mesh.Faces[j].Vertices[k]; } } // materials Result.Mesh.Materials = new World.MeshMaterial[Prototype.Mesh.Materials.Length]; for (int j = 0; j < Prototype.Mesh.Materials.Length; j++) { Result.Mesh.Materials[j] = Prototype.Mesh.Materials[j]; if (DaytimeTexture != null) { Result.Mesh.Materials[j].DaytimeTexture = DaytimeTexture; } else { Result.Mesh.Materials[j].DaytimeTexture = Prototype.Mesh.Materials[j].DaytimeTexture; } if (DaytimeTexture != null) { Result.Mesh.Materials[j].NighttimeTexture = NighttimeTexture; } else { Result.Mesh.Materials[j].NighttimeTexture = Prototype.Mesh.Materials[j].NighttimeTexture; } } return Result; }
/// <summary>Makes an object visible within the world</summary> /// <param name="ObjectIndex">The object's index</param> /// <param name="Type">Whether this is a static or dynamic object</param> internal static void ShowObject(int ObjectIndex, ObjectType Type) { if (ObjectManager.Objects[ObjectIndex] == null) { return; } if (ObjectManager.Objects[ObjectIndex].RendererIndex == 0) { if (ObjectCount >= Objects.Length) { Array.Resize <Object>(ref Objects, Objects.Length << 1); } Objects[ObjectCount].ObjectIndex = ObjectIndex; Objects[ObjectCount].Type = Type; int f = ObjectManager.Objects[ObjectIndex].Mesh.Faces.Length; Objects[ObjectCount].FaceListReferences = new ObjectListReference[f]; for (int i = 0; i < f; i++) { bool alpha = false; int k = ObjectManager.Objects[ObjectIndex].Mesh.Faces[i].Material; Textures.OpenGlTextureWrapMode wrap = Textures.OpenGlTextureWrapMode.ClampClamp; if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture != null | ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].NighttimeTexture != null) { if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].WrapMode == null) { // HACK: Objects do not (by default) store information on the texture wrapping mode. // Let's determine the best wrapping mode now and then save it // so we can quickly access it in the rendering loop. for (int v = 0; v < ObjectManager.Objects[ObjectIndex].Mesh.Vertices.Length; v++) { if (ObjectManager.Objects[ObjectIndex].Mesh.Vertices[v].TextureCoordinates.X <0.0f | ObjectManager.Objects[ObjectIndex].Mesh.Vertices[v].TextureCoordinates.X> 1.0f) { wrap |= Textures.OpenGlTextureWrapMode.RepeatClamp; } if (ObjectManager.Objects[ObjectIndex].Mesh.Vertices[v].TextureCoordinates.Y <0.0f | ObjectManager.Objects[ObjectIndex].Mesh.Vertices[v].TextureCoordinates.Y> 1.0f) { wrap |= Textures.OpenGlTextureWrapMode.ClampRepeat; } } if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture != null) { if (Textures.LoadTexture(ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture, wrap)) { OpenBveApi.Textures.TextureTransparencyType type = ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture.Transparency; if (type == OpenBveApi.Textures.TextureTransparencyType.Alpha) { alpha = true; } else if (type == OpenBveApi.Textures.TextureTransparencyType.Partial && Interface.CurrentOptions.TransparencyMode == TransparencyMode.Quality) { alpha = true; } } } if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].NighttimeTexture != null) { if (Textures.LoadTexture(ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].NighttimeTexture, wrap)) { OpenBveApi.Textures.TextureTransparencyType type = ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].NighttimeTexture.Transparency; if (type == OpenBveApi.Textures.TextureTransparencyType.Alpha) { alpha = true; } else if (type == OpenBveApi.Textures.TextureTransparencyType.Partial & Interface.CurrentOptions.TransparencyMode == TransparencyMode.Quality) { alpha = true; } } } } else { //Yuck cast, but we need the null, as otherwise requires rewriting the texture indexer wrap = (Textures.OpenGlTextureWrapMode)ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].WrapMode; } } if (Type == ObjectType.Overlay & World.CameraRestriction != World.CameraRestrictionMode.NotAvailable) { alpha = true; } else if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].Color.A != 255) { alpha = true; } else if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].BlendMode == World.MeshMaterialBlendMode.Additive) { alpha = true; } else if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].GlowAttenuationData != 0) { alpha = true; } ObjectListType listType; switch (Type) { case ObjectType.Static: listType = alpha ? ObjectListType.DynamicAlpha : ObjectListType.StaticOpaque; break; case ObjectType.Dynamic: listType = alpha ? ObjectListType.DynamicAlpha : ObjectListType.DynamicOpaque; break; case ObjectType.Overlay: listType = alpha ? ObjectListType.OverlayAlpha : ObjectListType.OverlayOpaque; break; default: throw new InvalidOperationException(); } if (listType == ObjectListType.StaticOpaque) { /* * For the static opaque list, insert the face into * the first vacant position in the matching group's list. * */ int groupIndex = (int)ObjectManager.Objects[ObjectIndex].GroupIndex; if (groupIndex >= StaticOpaque.Length) { if (StaticOpaque.Length == 0) { StaticOpaque = new ObjectGroup[16]; } while (groupIndex >= StaticOpaque.Length) { Array.Resize <ObjectGroup>(ref StaticOpaque, StaticOpaque.Length << 1); } } if (StaticOpaque[groupIndex] == null) { StaticOpaque[groupIndex] = new ObjectGroup(); } ObjectList list = StaticOpaque[groupIndex].List; int newIndex = list.FaceCount; for (int j = 0; j < list.FaceCount; j++) { if (list.Faces[j] == null) { newIndex = j; break; } } if (newIndex == list.FaceCount) { if (list.FaceCount == list.Faces.Length) { Array.Resize <ObjectFace>(ref list.Faces, list.Faces.Length << 1); } list.FaceCount++; } list.Faces[newIndex] = new ObjectFace { ObjectListIndex = ObjectCount, ObjectIndex = ObjectIndex, FaceIndex = i, Wrap = wrap }; // HACK: Let's store the wrapping mode. StaticOpaque[groupIndex].Update = true; Objects[ObjectCount].FaceListReferences[i] = new ObjectListReference(listType, newIndex); Game.InfoStaticOpaqueFaceCount++; /* * Check if the given object has a bounding box, and insert it to the end of the list of bounding boxes if required */ if (ObjectManager.Objects[ObjectIndex].Mesh.BoundingBox != null) { int Index = list.BoundingBoxes.Length; for (int j = 0; j < list.BoundingBoxes.Length; j++) { if (list.Faces[j] == null) { Index = j; break; } } if (Index == list.BoundingBoxes.Length) { Array.Resize <BoundingBox>(ref list.BoundingBoxes, list.BoundingBoxes.Length << 1); } list.BoundingBoxes[Index].Upper = ObjectManager.Objects[ObjectIndex].Mesh.BoundingBox[0]; list.BoundingBoxes[Index].Lower = ObjectManager.Objects[ObjectIndex].Mesh.BoundingBox[1]; } } else { /* * For all other lists, insert the face at the end of the list. * */ ObjectList list; switch (listType) { case ObjectListType.DynamicOpaque: list = DynamicOpaque; break; case ObjectListType.DynamicAlpha: list = DynamicAlpha; break; case ObjectListType.OverlayOpaque: list = OverlayOpaque; break; case ObjectListType.OverlayAlpha: list = OverlayAlpha; break; default: throw new InvalidOperationException(); } if (list.FaceCount == list.Faces.Length) { Array.Resize <ObjectFace>(ref list.Faces, list.Faces.Length << 1); } list.Faces[list.FaceCount] = new ObjectFace { ObjectListIndex = ObjectCount, ObjectIndex = ObjectIndex, FaceIndex = i, Wrap = wrap }; // HACK: Let's store the wrapping mode. Objects[ObjectCount].FaceListReferences[i] = new ObjectListReference(listType, list.FaceCount); list.FaceCount++; } } ObjectManager.Objects[ObjectIndex].RendererIndex = ObjectCount + 1; ObjectCount++; } }
// update custom timetable internal static void UpdateCustomTimetable(Textures.Texture daytime, Textures.Texture nighttime) { for (int i = 0; i < CustomObjectsUsed; i++) { for (int j = 0; j < CustomObjects[i].States.Length; j++) { for (int k = 0; k < CustomObjects[i].States[j].Object.Mesh.Materials.Length; k++) { if (daytime != null) { CustomObjects[i].States[j].Object.Mesh.Materials[k].DaytimeTexture = daytime; } if (nighttime != null) { CustomObjects[i].States[j].Object.Mesh.Materials[k].NighttimeTexture = nighttime; } } } } if (daytime != null) { CurrentCustomTimetableDaytimeTexture = daytime; } if (nighttime != null) { CurrentCustomTimetableNighttimeTexture = nighttime; } if (CurrentCustomTimetableDaytimeTexture != null | CurrentCustomTimetableNighttimeTexture != null) { CustomTimetableAvailable = true; } else { CustomTimetableAvailable = false; } }
// process events internal static void KeyDown(object sender, KeyboardKeyEventArgs e) { switch (e.Key) { case Key.LShift: case Key.RShift: ShiftPressed = true; break; case Key.F5: // reset ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); //Fonts.Initialize(); Interface.ClearMessages(); for (int i = 0; i < Files.Length; i++) { #if !DEBUG try { #endif ObjectManager.UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false); ObjectManager.CreateObject(o, new Vector3(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); #if !DEBUG } catch (Exception ex) { Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + "."); } #endif } ObjectManager.InitializeVisibility(); ObjectManager.UpdateVisibility(0.0, true); ObjectManager.UpdateAnimatedWorldObjects(0.01, true); break; case Key.F7: { OpenFileDialog Dialog = new OpenFileDialog { CheckFileExists = true, Multiselect = true, Filter = @"All supported object files|*.csv;*.b3d;*.x;*.animated;*.l3dobj;*.l3dgrp;*.obj;*.s|openBVE Objects|*.csv;*.b3d;*.x;*.animated|LokSim 3D Objects|*.l3dobj;*.l3dgrp|Wavefront Objects|*.obj|Microsoft Train Simulator Objects|*.s|All files|*" }; if (Dialog.ShowDialog() == DialogResult.OK) { Application.DoEvents(); string[] f = Dialog.FileNames; int n = Files.Length; Array.Resize <string>(ref Files, n + f.Length); for (int i = 0; i < f.Length; i++) { Files[n + i] = f[i]; } // reset ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); Interface.ClearMessages(); for (int i = 0; i < Files.Length; i++) { #if !DEBUG try { #endif ObjectManager.UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false); ObjectManager.CreateObject(o, new Vector3(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0); #if !DEBUG } catch (Exception ex) { Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + "."); } #endif } ObjectManager.InitializeVisibility(); ObjectManager.FinishCreatingObjects(); ObjectManager.UpdateVisibility(0.0, true); ObjectManager.UpdateAnimatedWorldObjects(0.01, true); } else { if (Program.CurrentlyRunOnMono) { //HACK: Dialog doesn't close properly when pressing the ESC key under Mono //Avoid calling Application.DoEvents() unless absolutely necessary though! Application.DoEvents(); } } Dialog.Dispose(); } break; case Key.F9: if (Interface.MessageCount != 0) { formMessages.ShowMessages(); Application.DoEvents(); } break; case Key.Delete: ReducedMode = false; LightingRelative = -1.0; Game.Reset(); Textures.UnloadAllTextures(); //Fonts.Initialize(); Interface.ClearMessages(); Files = new string[] {}; break; case Key.Left: RotateX = -1; ReducedMode = false; break; case Key.Right: RotateX = 1; ReducedMode = false; break; case Key.Up: RotateY = -1; ReducedMode = false; break; case Key.Down: RotateY = 1; ReducedMode = false; break; case Key.A: case Key.Keypad4: MoveX = -1; ReducedMode = false; break; case Key.D: case Key.Keypad6: MoveX = 1; ReducedMode = false; break; case Key.Keypad8: MoveY = 1; ReducedMode = false; break; case Key.Keypad2: MoveY = -1; ReducedMode = false; break; case Key.W: case Key.Keypad9: MoveZ = 1; ReducedMode = false; break; case Key.S: case Key.Keypad3: MoveZ = -1; ReducedMode = false; break; case Key.Keypad5: ResetCamera(); break; case Key.F: case Key.F1: Renderer.OptionWireframe = !Renderer.OptionWireframe; if (Renderer.OptionWireframe) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } else { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } break; case Key.N: case Key.F2: Renderer.OptionNormals = !Renderer.OptionNormals; break; case Key.L: case Key.F3: LightingTarget = 1 - LightingTarget; ReducedMode = false; break; case Key.I: case Key.F4: Renderer.OptionInterface = !Renderer.OptionInterface; ReducedMode = false; break; case Key.F8: formOptions.ShowOptions(); Application.DoEvents(); break; case Key.G: case Key.C: Renderer.OptionCoordinateSystem = !Renderer.OptionCoordinateSystem; ReducedMode = false; break; case Key.B: if (ShiftPressed) { ColorDialog dialog = new ColorDialog(); dialog.FullOpen = true; if (dialog.ShowDialog() == DialogResult.OK) { Renderer.BackgroundColor = -1; Renderer.ApplyBackgroundColor(dialog.Color.R, dialog.Color.G, dialog.Color.B); } } else { Renderer.BackgroundColor++; if (Renderer.BackgroundColor >= Renderer.MaxBackgroundColor) { Renderer.BackgroundColor = 0; } Renderer.ApplyBackgroundColor(); } ReducedMode = false; break; } }