static private LoadTexture ( Texture handle, OpenGlTextureWrapMode wrap ) : bool | ||
handle | Texture | The handle to the registered texture. |
wrap | OpenGlTextureWrapMode | The texture type indicating the clamp mode. |
return | bool |
/* -------------------------------------------------------------- * This file contains the drawing routines for the loading screen * -------------------------------------------------------------- */ internal static void DrawLoadingScreen() { // begin HACK // Gl.glEnable(Gl.GL_BLEND); BlendEnabled = true; Gl.glDisable(Gl.GL_LIGHTING); LightingEnabled = false; int size = Math.Min(Screen.Width, Screen.Height); DrawRectangle(null, new Point(0, 0), new Size(Screen.Width, Screen.Height), Color128.Black); if (Textures.LoadTexture(TextureLogo, Textures.OpenGlTextureWrapMode.ClampClamp)) { DrawRectangle(TextureLogo, new Point((Screen.Width - size) / 2, (Screen.Height - size) / 2), new Size(size, size), Color128.White); } DrawRectangle(null, new Point((Screen.Width - size) / 2, Screen.Height - (int)Fonts.NormalFont.FontSize - 10), new Size(Screen.Width, (int)Fonts.NormalFont.FontSize + 10), new Color128(0.0f, 0.0f, 0.0f, 0.5f)); // double routeProgress = Math.Max(0.0, Math.Min(1.0, Loading.RouteProgress)); // double trainProgress = Math.Max(0.0, Math.Min(1.0, Loading.TrainProgress)); string text; // if (routeProgress < 1.0) { // text = "Loading route... " + (100.0 * routeProgress).ToString("0") + "%"; // } else if (trainProgress < 1.0) { // text = "Loading train... " + (100.0 * trainProgress).ToString("0") + "%"; // } else { // text = "Loading textures and sounds..."; // } text = Interface.GetInterfaceString("message_loading"); DrawString(Fonts.SmallFont, text, new Point((Screen.Width - size) / 2 + 5, Screen.Height - (int)(Fonts.NormalFont.FontSize / 2) - 5), TextAlignment.CenterLeft, Color128.White); // end HACK // }
/// <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.Disable(EnableCap.Texture2D); if (color.HasValue) { GL.Color4(color.Value.R, color.Value.G, color.Value.B, color.Value.A); } /* * // test triangles instead of quads * // future todo: indexed vbo * GL.Begin(PrimitiveType.Triangles); * 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 + size.Width, point.Y + size.Height); * GL.Vertex2(point.X, point.Y + size.Height); * GL.Vertex2(point.X, point.Y); * GL.End(); */ GL.Begin(PrimitiveType.Quads); // FIXME immediate rendering! 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); // FIXME immediate rendering! 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>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(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, 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)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>Renders a static frustrum based background</summary> /// <param name="Data">The background to render</param> /// <param name="Alpha">The alpha level</param> /// <param name="scale">The scale</param> internal static void RenderBackground(BackgroundManager.StaticBackground Data, float Alpha, float scale) { if (Data.Texture != null && Textures.LoadTexture(Data.Texture, OpenGlTextureWrapMode.RepeatClamp)) { if (LightingEnabled) { GL.Disable(EnableCap.Lighting); LightingEnabled = false; } if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } if (Alpha == 1.0f) { if (BlendEnabled) { GL.Disable(EnableCap.Blend); BlendEnabled = false; } } else if (!BlendEnabled) { GL.Enable(EnableCap.Blend); BlendEnabled = true; } GL.BindTexture(TextureTarget.Texture2D, Data.Texture.OpenGlTextures[(int)OpenGlTextureWrapMode.RepeatClamp].Name); GL.Color4(1.0f, 1.0f, 1.0f, Alpha); if (!BackgroundDisplayListAvailable) { BackgroundDisplayList = GL.GenLists(1); GL.NewList(BackgroundDisplayList, ListMode.Compile); float y0, y1; if (Data.KeepAspectRatio) { int tw = Data.Texture.Width; int th = Data.Texture.Height; double hh = Math.PI * World.BackgroundImageDistance * (double)th / ((double)tw * (double)Data.Repetition); y0 = (float)(-0.5 * hh); y1 = (float)(1.5 * hh); } else { y0 = (float)(-0.125 * World.BackgroundImageDistance); y1 = (float)(0.375 * World.BackgroundImageDistance); } const int n = 32; Vector3[] bottom = new Vector3[n]; Vector3[] top = new Vector3[n]; double angleValue = 2.61799387799149 - 3.14159265358979 / (double)n; const double angleIncrement = 6.28318530717958 / (double)n; /* * To ensure that the whole background cylinder is rendered inside the viewing frustum, * the background is rendered before the scene with z-buffer writes disabled. Then, * the actual distance from the camera is irrelevant as long as it is inside the frustum. * */ for (int i = 0; i < n; i++) { float x = (float)(World.BackgroundImageDistance * Math.Cos(angleValue)); float z = (float)(World.BackgroundImageDistance * Math.Sin(angleValue)); bottom[i] = new Vector3(scale * x, scale * y0, scale * z); top[i] = new Vector3(scale * x, scale * y1, scale * z); angleValue += angleIncrement; } float textureStart = 0.5f * (float)Data.Repetition / (float)n; float textureIncrement = -(float)Data.Repetition / (float)n; double textureX = textureStart; for (int i = 0; i < n; i++) { int j = (i + 1) % n; // side wall GL.Begin(PrimitiveType.Quads); GL.TexCoord2(textureX, 0.005f); GL.Vertex3(top[i].X, top[i].Y, top[i].Z); GL.TexCoord2(textureX, 0.995f); GL.Vertex3(bottom[i].X, bottom[i].Y, bottom[i].Z); GL.TexCoord2(textureX + textureIncrement, 0.995f); GL.Vertex3(bottom[j].X, bottom[j].Y, bottom[j].Z); GL.TexCoord2(textureX + textureIncrement, 0.005f); GL.Vertex3(top[j].X, top[j].Y, top[j].Z); GL.End(); // top cap GL.Begin(PrimitiveType.Triangles); GL.TexCoord2(textureX, 0.005f); GL.Vertex3(top[i].X, top[i].Y, top[i].Z); GL.TexCoord2(textureX + textureIncrement, 0.005f); GL.Vertex3(top[j].X, top[j].Y, top[j].Z); GL.TexCoord2(textureX + 0.5 * textureIncrement, 0.1f); GL.Vertex3(0.0f, top[i].Y, 0.0f); // bottom cap GL.TexCoord2(textureX + 0.5 * textureIncrement, 0.9f); GL.Vertex3(0.0f, bottom[i].Y, 0.0f); GL.TexCoord2(textureX + textureIncrement, 0.995f); GL.Vertex3(bottom[j].X, bottom[j].Y, bottom[j].Z); GL.TexCoord2(textureX, 0.995f); GL.Vertex3(bottom[i].X, bottom[i].Y, bottom[i].Z); GL.End(); // finish textureX += textureIncrement; } GL.EndList(); GL.CallList(BackgroundDisplayList); GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; if (!BlendEnabled) { GL.Enable(EnableCap.Blend); BlendEnabled = true; } BackgroundDisplayListAvailable = true; } else { GL.CallList(BackgroundDisplayList); GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; if (!BlendEnabled) { GL.Enable(EnableCap.Blend); BlendEnabled = true; } } } }
internal static void RenderBackground(BackgroundManager.BackgroundObject Object) { if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } int Mat = -1; for (int i = 0; i < Object.ObjectBackground.Mesh.Faces.Length; i++) { int m = Object.ObjectBackground.Mesh.Faces[i].Material; if (m != Mat) { OpenGlTextureWrapMode wrap = OpenGlTextureWrapMode.ClampClamp; for (int v = 0; v < Object.ObjectBackground.Mesh.Vertices.Length; v++) { if (Object.ObjectBackground.Mesh.Vertices[v].TextureCoordinates.X <0.0f | Object.ObjectBackground.Mesh.Vertices[v].TextureCoordinates.X> 1.0f) { wrap |= OpenGlTextureWrapMode.RepeatClamp; } if (Object.ObjectBackground.Mesh.Vertices[v].TextureCoordinates.Y <0.0f | Object.ObjectBackground.Mesh.Vertices[v].TextureCoordinates.Y> 1.0f) { wrap |= OpenGlTextureWrapMode.ClampRepeat; } } if (Object.ObjectBackground.Mesh.Materials[m].DaytimeTexture != null) { Textures.LoadTexture(Object.ObjectBackground.Mesh.Materials[m].DaytimeTexture, wrap); GL.BindTexture(TextureTarget.Texture2D, Object.ObjectBackground.Mesh.Materials[m].DaytimeTexture.OpenGlTextures[(int)wrap].Name); } } int FaceType = Object.ObjectBackground.Mesh.Faces[i].Flags & MeshFace.FaceTypeMask; switch (FaceType) { case MeshFace.FaceTypeTriangles: GL.Begin(PrimitiveType.Triangles); break; case MeshFace.FaceTypeTriangleStrip: GL.Begin(PrimitiveType.TriangleStrip); break; case MeshFace.FaceTypeQuads: GL.Begin(PrimitiveType.Quads); break; case MeshFace.FaceTypeQuadStrip: GL.Begin(PrimitiveType.QuadStrip); break; default: GL.Begin(PrimitiveType.Polygon); break; } for (int j = 0; j < Object.ObjectBackground.Mesh.Faces[i].Vertices.Length; j++) { GL.Color4(inv255 * (float)Object.ObjectBackground.Mesh.Materials[m].Color.R * 1.0f, inv255 * Object.ObjectBackground.Mesh.Materials[m].Color.G * 1.0f, inv255 * (float)Object.ObjectBackground.Mesh.Materials[m].Color.B * 1.0f, inv255 * (float)Object.ObjectBackground.Mesh.Materials[m].Color.A); VertexTemplate v = Object.ObjectBackground.Mesh.Vertices[Object.ObjectBackground.Mesh.Faces[i].Vertices[j].Index]; if (v is ColoredVertex) { ColoredVertex vv = v as ColoredVertex; GL.Color3(vv.Color.R, vv.Color.G, vv.Color.B); } GL.TexCoord2(v.TextureCoordinates.X, v.TextureCoordinates.Y); GL.Vertex3(v.Coordinates.X, v.Coordinates.Y, v.Coordinates.Z); } GL.End(); } }
/// <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++) { Textures.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++) { Textures.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++) { Textures.Texture texture; Fonts.OpenGlFontChar data; i += font.GetCharacterData(text, i, out texture, out data) - 1; if (Textures.LoadTexture(texture, Textures.OpenGlTextureWrapMode.ClampClamp)) { GL.BindTexture(TextureTarget.Texture2D, texture.OpenGlTextures[(int)Textures.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 // GL.Disable(EnableCap.Texture2D); }
/// <summary>Renders the list of game (textual) messages</summary> /// <param name="Element">The HUD element these are to be rendered onto</param> /// <param name="TimeElapsed">The time elapsed</param> private static void RenderGameMessages(HUD.Element Element, double TimeElapsed) { //Calculate the size of the viewing plane int n = MessageManager.TextualMessages.Count; //Minimum initial width is 16px double totalwidth = 16.0f; for (int j = 0; j < n; j++) { //Update font size for the renderer System.Drawing.Size size = Renderer.MeasureString(Element.Font, (string)MessageManager.TextualMessages[j].MessageToDisplay); MessageManager.TextualMessages[j].Width = size.Width; MessageManager.TextualMessages[j].Height = size.Height; //Run through the list of current messages double a = MessageManager.TextualMessages[j].Width - j * (double)Element.Value1; //If our width is wider than the old, use this as the NEW viewing plane width if (a > totalwidth) { totalwidth = a; } } //Calculate the X-width of the viewing plane Game.MessagesRendererSize.X += 16.0 * TimeElapsed * ((double)totalwidth - Game.MessagesRendererSize.X); totalwidth = (float)Game.MessagesRendererSize.X; double lcrh, lw, rw; //Calculate final viewing plane size to pass to openGL CalculateViewingPlaneSize(Element, out lw, out rw, out lcrh); // start double w = 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++) { var mm = MessageManager.TextualMessages[j]; float br, bg, bb, ba; CreateBackColor(Element.BackgroundColor, mm.Color, out br, out bg, out bb, out ba); float tr, tg, tb, ta; CreateTextColor(Element.TextColor, mm.Color, out tr, out tg, out tb, out ta); float or, og, ob, oa; CreateBackColor(Element.OverlayColor, mm.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 < mm.Timeout) { if (mm.RendererAlpha == 0.0) { mm.RendererPosition.X = x + Element.TransitionVector.X; mm.RendererPosition.Y = y + Element.TransitionVector.Y; mm.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 - mm.RendererPosition.X) + 0.1) * TimeElapsed; double dy = (speed * Math.Abs(ty - mm.RendererPosition.Y) + 0.1) * TimeElapsed; if (Math.Abs(tx - mm.RendererPosition.X) < dx) { mm.RendererPosition.X = tx; } else { mm.RendererPosition.X += Math.Sign(tx - mm.RendererPosition.X) * dx; } if (Math.Abs(ty - mm.RendererPosition.Y) < dy) { mm.RendererPosition.Y = ty; } else { mm.RendererPosition.Y += Math.Sign(ty - mm.RendererPosition.Y) * dy; } } else { tx = x; ty = y + m * Element.Value2; mm.RendererPosition.X = 0.0; const double speed = 12.0; double dy = (speed * Math.Abs(ty - mm.RendererPosition.Y) + 0.1) * TimeElapsed; mm.RendererPosition.X = x; if (Math.Abs(ty - mm.RendererPosition.Y) < dy) { mm.RendererPosition.Y = ty; } else { mm.RendererPosition.Y += Math.Sign(ty - mm.RendererPosition.Y) * dy; } } if ((Element.Transition & HUD.Transition.Fade) != 0) { if (Game.SecondsSinceMidnight >= mm.Timeout) { mm.RendererAlpha -= TimeElapsed; if (mm.RendererAlpha < 0.0) { mm.RendererAlpha = 0.0; } } else { mm.RendererAlpha += TimeElapsed; if (mm.RendererAlpha > 1.0) { mm.RendererAlpha = 1.0; } preserve = true; } } else if (Game.SecondsSinceMidnight > mm.Timeout) { if (Math.Abs(mm.RendererPosition.X - tx) < 0.1 & Math.Abs(mm.RendererPosition.Y - ty) < 0.1) { mm.RendererAlpha = 0.0; } } if (preserve) { m++; } double px = mm.RendererPosition.X + (double)j * (double)Element.Value1; double py = mm.RendererPosition.Y; float alpha = (float)(mm.RendererAlpha * mm.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, Textures.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, Textures.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, Textures.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 = (string)mm.MessageToDisplay; double u = mm.Width; double v = mm.Height; 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, Textures.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, Textures.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, Textures.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>Calculates the viewing plane size for the given HUD element</summary> /// <param name="Element">The element</param> /// <param name="LeftWidth">The left width of the viewing plane</param> /// <param name="RightWidth">The right width of the viewing plane</param> /// <param name="LCrH">The center point of the viewing plane</param> private static void CalculateViewingPlaneSize(HUD.Element Element, out double LeftWidth, out double RightWidth, out double LCrH) { LCrH = 0.0; // left width/height LeftWidth = 0.0; if (Element.TopLeft.BackgroundTexture != null) { if (Textures.LoadTexture(Element.TopLeft.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Element.TopLeft.BackgroundTexture.Width; double v = (double)Element.TopLeft.BackgroundTexture.Height; if (u > LeftWidth) { LeftWidth = u; } if (v > LCrH) { LCrH = v; } } } if (Element.CenterLeft.BackgroundTexture != null) { if (Textures.LoadTexture(Element.CenterLeft.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Element.CenterLeft.BackgroundTexture.Width; double v = (double)Element.CenterLeft.BackgroundTexture.Height; if (u > LeftWidth) { LeftWidth = u; } if (v > LCrH) { LCrH = v; } } } if (Element.BottomLeft.BackgroundTexture != null) { if (Textures.LoadTexture(Element.BottomLeft.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Element.BottomLeft.BackgroundTexture.Width; double v = (double)Element.BottomLeft.BackgroundTexture.Height; if (u > LeftWidth) { LeftWidth = u; } if (v > LCrH) { LCrH = v; } } } // center height if (Element.TopMiddle.BackgroundTexture != null) { if (Textures.LoadTexture(Element.TopMiddle.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Element.TopMiddle.BackgroundTexture.Height; if (v > LCrH) { LCrH = v; } } } if (Element.CenterMiddle.BackgroundTexture != null) { if (Textures.LoadTexture(Element.CenterMiddle.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Element.CenterMiddle.BackgroundTexture.Height; if (v > LCrH) { LCrH = v; } } } if (Element.BottomMiddle.BackgroundTexture != null) { if (Textures.LoadTexture(Element.BottomMiddle.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double v = (double)Element.BottomMiddle.BackgroundTexture.Height; if (v > LCrH) { LCrH = v; } } } // right width/height RightWidth = 0.0; if (Element.TopRight.BackgroundTexture != null) { if (Textures.LoadTexture(Element.TopRight.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Element.TopRight.BackgroundTexture.Width; double v = (double)Element.TopRight.BackgroundTexture.Height; if (u > RightWidth) { RightWidth = u; } if (v > LCrH) { LCrH = v; } } } if (Element.CenterRight.BackgroundTexture != null) { if (Textures.LoadTexture(Element.CenterRight.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Element.CenterRight.BackgroundTexture.Width; double v = (double)Element.CenterRight.BackgroundTexture.Height; if (u > RightWidth) { RightWidth = u; } if (v > LCrH) { LCrH = v; } } } if (Element.BottomRight.BackgroundTexture != null) { if (Textures.LoadTexture(Element.BottomRight.BackgroundTexture, OpenGlTextureWrapMode.ClampClamp)) { double u = (double)Element.BottomRight.BackgroundTexture.Width; double v = (double)Element.BottomRight.BackgroundTexture.Height; if (u > RightWidth) { RightWidth = u; } if (v > LCrH) { LCrH = v; } } } }
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); if (OptionWireframe) { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f); } 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 * alphafactor); } } else { if (OptionWireframe) { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f); } 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; } } if (OptionWireframe) { GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f); } 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 * 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); } } }
/* -------------------------------------------------------------- * This file contains the base drawing routines for screen overlays * -------------------------------------------------------------- */ /// <summary>Is called once by the main renderer loop, in order to render all overlays shown on the screen</summary> /// <param name="TimeElapsed">The time elapsed since the last call to this function</param> private static void RenderOverlays(double TimeElapsed) { //Initialize openGL GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.Enable(EnableCap.Blend); BlendEnabled = true; GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); GL.LoadIdentity(); GL.Ortho(0.0, (double)Screen.Width, (double)Screen.Height, 0.0, -1.0, 1.0); GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); //Check which overlays to show switch (CurrentOutputMode) { case OutputMode.Default: //Route info overlay (if selected) Game.routeInfoOverlay.Show(); //HUD for (int i = 0; i < Interface.CurrentHudElements.Length; i++) { string Command = Interface.CurrentHudElements[i].Subject.ToLowerInvariant(); switch (Command) { case "messages": { RenderGameMessages(Interface.CurrentHudElements[i], TimeElapsed); } break; case "scoremessages": { RenderScoreMessages(Interface.CurrentHudElements[i], TimeElapsed); } break; case "ats": { RenderATSLamps(Interface.CurrentHudElements[i], TimeElapsed); } break; default: { RenderHUDElement(Interface.CurrentHudElements[i], TimeElapsed); } break; } } //Marker textures if (Interface.CurrentOptions.GameMode != Interface.GameMode.Expert) { double y = 8.0; for (int i = 0; i < Game.MarkerTextures.Length; i++) { if (Textures.LoadTexture(Game.MarkerTextures[i], Textures.OpenGlTextureWrapMode.ClampClamp)) { double w = (double)Game.MarkerTextures[i].Width; double h = (double)Game.MarkerTextures[i].Height; GL.Color4(1.0f, 1.0f, 1.0f, 1.0f); RenderOverlayTexture(Game.MarkerTextures[i], (double)Screen.Width - w - 8.0, y, (double)Screen.Width - 8.0, y + h); y += h + 8.0; } } } //Timetable overlay //NOTE: Only affects auto-generated timetable, possibly change this inconsistant behaviour if (Timetable.CurrentTimetable == Timetable.TimetableState.Default) { // default if (Textures.LoadTexture(Timetable.DefaultTimetableTexture, Textures.OpenGlTextureWrapMode.ClampClamp)) { int w = Timetable.DefaultTimetableTexture.Width; int h = Timetable.DefaultTimetableTexture.Height; GL.Color4(1.0f, 1.0f, 1.0f, 1.0f); RenderOverlayTexture(Timetable.DefaultTimetableTexture, (double)(Screen.Width - w), Timetable.DefaultTimetablePosition, (double)Screen.Width, (double)h + Timetable.DefaultTimetablePosition); } } else if (Timetable.CurrentTimetable == Timetable.TimetableState.Custom & Timetable.CustomObjectsUsed == 0) { // custom if (Textures.LoadTexture(Timetable.CurrentCustomTimetableDaytimeTexture, Textures.OpenGlTextureWrapMode.ClampClamp)) { int w = Timetable.CurrentCustomTimetableDaytimeTexture.Width; int h = Timetable.CurrentCustomTimetableDaytimeTexture.Height; GL.Color4(1.0f, 1.0f, 1.0f, 1.0f); RenderOverlayTexture(Timetable.CurrentCustomTimetableDaytimeTexture, (double)(Screen.Width - w), Timetable.CustomTimetablePosition, (double)Screen.Width, (double)h + Timetable.CustomTimetablePosition); } if (Textures.LoadTexture(Timetable.CurrentCustomTimetableDaytimeTexture, Textures.OpenGlTextureWrapMode.ClampClamp)) { int w = Timetable.CurrentCustomTimetableDaytimeTexture.Width; int h = Timetable.CurrentCustomTimetableDaytimeTexture.Height; float alpha; if (Timetable.CurrentCustomTimetableDaytimeTexture != null) { double t = (TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].FrontAxle.Follower.TrackPosition - TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Brightness.PreviousTrackPosition) / (TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Brightness.NextTrackPosition - TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Brightness.PreviousTrackPosition); alpha = (float)((1.0 - t) * TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Brightness.PreviousBrightness + t * TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Brightness.NextBrightness); } else { alpha = 1.0f; } GL.Color4(1.0f, 1.0f, 1.0f, alpha); RenderOverlayTexture(Timetable.CurrentCustomTimetableDaytimeTexture, (double)(Screen.Width - w), Timetable.CustomTimetablePosition, (double)Screen.Width, (double)h + Timetable.CustomTimetablePosition); } } break; case OutputMode.Debug: RenderDebugOverlays(); break; case OutputMode.DebugATS: RenderATSDebugOverlay(); break; } // air brake debug output if (Interface.CurrentOptions.GameMode != Interface.GameMode.Expert & OptionBrakeSystems) { RenderBrakeSystemDebug(); } //If paused, fade out the screen & write PAUSE if (Game.CurrentInterface == Game.InterfaceType.Pause) { // pause GL.Color4(0.0f, 0.0f, 0.0f, 0.5f); RenderOverlaySolid(0.0, 0.0, (double)Screen.Width, (double)Screen.Height); GL.Color4(1.0f, 1.0f, 1.0f, 1.0f); DrawString(Fonts.VeryLargeFont, "PAUSE", new System.Drawing.Point(Screen.Width / 2, Screen.Height / 2), TextAlignment.CenterMiddle, Color128.White, true); } else if (Game.CurrentInterface == Game.InterfaceType.Menu) { Game.Menu.Draw(); } //Fade to black on change ends if (TrainManager.PlayerTrain.Station >= 0 && Game.Stations[TrainManager.PlayerTrain.Station].Type == StationType.ChangeEnds && TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Boarding) { double time = TrainManager.PlayerTrain.StationDepartureTime - Game.SecondsSinceMidnight; if (time < 1.0) { FadeToBlackDueToChangeEnds = Math.Max(0.0, 1.0 - time); } else if (FadeToBlackDueToChangeEnds > 0.0) { FadeToBlackDueToChangeEnds -= TimeElapsed; if (FadeToBlackDueToChangeEnds < 0.0) { FadeToBlackDueToChangeEnds = 0.0; } } } else if (FadeToBlackDueToChangeEnds > 0.0) { FadeToBlackDueToChangeEnds -= TimeElapsed; if (FadeToBlackDueToChangeEnds < 0.0) { FadeToBlackDueToChangeEnds = 0.0; } } if (FadeToBlackDueToChangeEnds > 0.0 & (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead)) { GL.Color4(0.0, 0.0, 0.0, FadeToBlackDueToChangeEnds); RenderOverlaySolid(0.0, 0.0, (double)Screen.Width, (double)Screen.Height); } // finalize GL.PopMatrix(); GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); GL.MatrixMode(MatrixMode.Modelview); GL.Disable(EnableCap.Blend); }
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(); } }
/// <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, 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 = Translations.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 = Translations.QuickReferences.HandleForward; } } else { sc = MessageColor.Gray; if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 1) { t = TrainManager.PlayerTrain.ReverserDescriptions[1]; } else { t = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.QuickReferences.HandleLap; } } else { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 3) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[3]; } else { t = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.QuickReferences.HandleLap; } } else { sc = MessageColor.Orange; if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 3) { t = TrainManager.PlayerTrain.BrakeNotchDescriptions[3]; } else { t = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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 = Translations.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" ? Translations.QuickReferences.DoorsLeft : Translations.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.Stations[s].GetStopIndex(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 "dist_next_station": int i; if (TrainManager.PlayerTrain.Station >= 0 && TrainManager.PlayerTrain.StationState != TrainManager.TrainStopState.Completed) { i = TrainManager.PlayerTrain.LastStation; } else { i = TrainManager.PlayerTrain.LastStation + 1; } if (i > Game.Stations.Length - 1) { i = TrainManager.PlayerTrain.LastStation; } int n = Game.Stations[i].GetStopIndex(TrainManager.PlayerTrain.Cars.Length); double p0 = TrainManager.PlayerTrain.Cars[0].FrontAxle.Follower.TrackPosition - TrainManager.PlayerTrain.Cars[0].FrontAxle.Position + 0.5 * TrainManager.PlayerTrain.Cars[0].Length; double p1; if (Game.Stations[i].Stops.Length > 0) { p1 = Game.Stations[i].Stops[n].TrackPosition; } else { p1 = Game.Stations[i].DefaultTrackPosition; } double m = p1 - p0; if (OptionDistanceToNextStation == DistanceToNextStationDisplayMode.Km) { if (Game.PlayerStopsAtStation(i)) { t = "Stop: "; if (Math.Abs(m) <= 10.0) { t += m.ToString("0.00", Culture) + " m"; } else { m /= 1000.0; t += m.ToString("0.000", Culture) + " km"; } } else { m /= 1000.0; t = "Pass: "******"0.000", Culture) + " km"; } Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else if (OptionDistanceToNextStation == DistanceToNextStationDisplayMode.Mile) { m /= 1609.34; if (Game.PlayerStopsAtStation(i)) { t = "Stop: "; } else { t = "Pass: "******"0.0000", Culture) + " miles"; Element.TransitionState -= speed * TimeElapsed; if (Element.TransitionState < 0.0) { Element.TransitionState = 0.0; } } else { m /= 1609.34; if (Game.PlayerStopsAtStation(i)) { t = "Stop: "; } else { t = "Pass: "******"0.0000", Culture) + " miles"; 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, 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, 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>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; OpenGlTextureWrapMode wrap = 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) { // If the object does not have a stored wrapping mode, determine it now 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 |= OpenGlTextureWrapMode.RepeatClamp; } if (ObjectManager.Objects[ObjectIndex].Mesh.Vertices[v].TextureCoordinates.Y <0.0f | ObjectManager.Objects[ObjectIndex].Mesh.Vertices[v].TextureCoordinates.Y> 1.0f) { wrap |= OpenGlTextureWrapMode.ClampRepeat; } } } else { //Yuck cast, but we need the null, as otherwise requires rewriting the texture indexer wrap = (OpenGlTextureWrapMode)ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].WrapMode; } if (ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture != null) { if (Textures.LoadTexture(ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture, wrap)) { TextureTransparencyType type = ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].DaytimeTexture.Transparency; if (type == TextureTransparencyType.Alpha) { alpha = true; } else if (type == 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)) { TextureTransparencyType type = ObjectManager.Objects[ObjectIndex].Mesh.Materials[k].NighttimeTexture.Transparency; if (type == TextureTransparencyType.Alpha) { alpha = true; } else if (type == TextureTransparencyType.Partial & Interface.CurrentOptions.TransparencyMode == TransparencyMode.Quality) { alpha = true; } } } } if (Type == ObjectType.Overlay & World.CameraRestriction != Camera.RestrictionMode.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 == 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++; } }
/// <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="orientation">The orientation.</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) { 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++) { Textures.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++) { Textures.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.glEnable(Gl.GL_TEXTURE_2D); for (int i = 0; i < text.Length; i++) { Textures.Texture texture; Fonts.OpenGlFontChar data; i += font.GetCharacterData(text, i, out texture, out data) - 1; if (Textures.LoadTexture(texture, Textures.OpenGlTextureWrapMode.ClampClamp)) { Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture.OpenGlTextures[(int)Textures.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.glBlendFunc(Gl.GL_ZERO, Gl.GL_ONE_MINUS_SRC_COLOR); Gl.glBegin(Gl.GL_POLYGON); Gl.glColor4f(color.A, color.A, color.A, 1.0f); Gl.glTexCoord2f(data.TextureCoordinates.Left, data.TextureCoordinates.Top); Gl.glVertex2f(x, y); Gl.glColor4f(color.A, color.A, color.A, 1.0f); Gl.glTexCoord2f(data.TextureCoordinates.Right, data.TextureCoordinates.Top); Gl.glVertex2f(x + data.PhysicalSize.Width, y); Gl.glColor4f(color.A, color.A, color.A, 1.0f); Gl.glTexCoord2f(data.TextureCoordinates.Right, data.TextureCoordinates.Bottom); Gl.glVertex2f(x + data.PhysicalSize.Width, y + data.PhysicalSize.Height); Gl.glColor4f(color.A, color.A, color.A, 1.0f); Gl.glTexCoord2f(data.TextureCoordinates.Left, data.TextureCoordinates.Bottom); Gl.glVertex2f(x, y + data.PhysicalSize.Height); Gl.glEnd(); /* * In the second pass, add the character onto the background. * */ Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE); Gl.glBegin(Gl.GL_POLYGON); Gl.glColor4f(color.R, color.G, color.B, color.A); Gl.glTexCoord2f(data.TextureCoordinates.Left, data.TextureCoordinates.Top); Gl.glVertex2f(x, y); Gl.glColor4f(color.R, color.G, color.B, color.A); Gl.glTexCoord2f(data.TextureCoordinates.Right, data.TextureCoordinates.Top); Gl.glVertex2f(x + data.PhysicalSize.Width, y); Gl.glColor4f(color.R, color.G, color.B, color.A); Gl.glTexCoord2f(data.TextureCoordinates.Right, data.TextureCoordinates.Bottom); Gl.glVertex2f(x + data.PhysicalSize.Width, y + data.PhysicalSize.Height); Gl.glColor4f(color.R, color.G, color.B, color.A); Gl.glTexCoord2f(data.TextureCoordinates.Left, data.TextureCoordinates.Bottom); Gl.glVertex2f(x, y + data.PhysicalSize.Height); Gl.glEnd(); } left += data.TypographicSize.Width; } Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA); // HACK // }
/// <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; } }
// // 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 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); } } } }