/// <summary>Intializes motion blur</summary> internal static void InitializeMotionBlur() { if (Interface.CurrentOptions.MotionBlur == Interface.MotionBlurMode.None) { return; } if (PixelBufferOpenGlTextureIndex != 0) { GL.DeleteTextures(1, new int[] { PixelBufferOpenGlTextureIndex }); PixelBufferOpenGlTextureIndex = 0; } int w = Interface.CurrentOptions.NoTextureResize ? Screen.Width : Textures.RoundUpToPowerOfTwo(Screen.Width); int h = Interface.CurrentOptions.NoTextureResize ? Screen.Height : Textures.RoundUpToPowerOfTwo(Screen.Height); PixelBuffer = new byte[4 * w * h]; int[] a = new int[1]; GL.GenTextures(1, a); GL.BindTexture(TextureTarget.Texture2D, a[0]); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMagFilter.Linear); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, w, h, 0, PixelFormat.Rgb, PixelType.UnsignedByte, PixelBuffer); PixelBufferOpenGlTextureIndex = a[0]; GL.CopyTexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgb, 0, 0, w, h, 0); }
/// <summary>This function renderers full-screen motion blur if selected</summary> private static void RenderFullscreenMotionBlur() { if (Screen.Minimized) { /* * HACK: * This breaks if minimized, even if we don't reset the W / H values */ return; } int w = Interface.CurrentOptions.NoTextureResize ? Screen.Width : Textures.RoundUpToPowerOfTwo(Screen.Width); int h = Interface.CurrentOptions.NoTextureResize ? Screen.Height : Textures.RoundUpToPowerOfTwo(Screen.Height); // render if (PixelBufferOpenGlTextureIndex >= 0) { double strength; switch (Interface.CurrentOptions.MotionBlur) { case Interface.MotionBlurMode.Low: strength = 0.0025; break; case Interface.MotionBlurMode.Medium: strength = 0.0040; break; case Interface.MotionBlurMode.High: strength = 0.0064; break; default: strength = 0.0040; break; } double speed = Math.Abs(World.CameraSpeed); double denominator = strength * Game.InfoFrameRate * Math.Sqrt(speed); float factor; if (denominator > 0.001) { factor = (float)Math.Exp(-1.0 / denominator); } else { factor = 0.0f; } // initialize GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); if (!BlendEnabled) { GL.Enable(EnableCap.Blend); BlendEnabled = true; } if (LightingEnabled) { GL.Disable(EnableCap.Lighting); LightingEnabled = false; } GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); GL.LoadIdentity(); GL.Ortho(0.0, (double)Screen.Width, 0.0, (double)Screen.Height, -1.0, 1.0); GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); if (!TexturingEnabled) { GL.Enable(EnableCap.Texture2D); TexturingEnabled = true; } // render GL.BindTexture(TextureTarget.Texture2D, PixelBufferOpenGlTextureIndex); GL.Color4(1.0f, 1.0f, 1.0f, factor); GL.Begin(PrimitiveType.Polygon); GL.TexCoord2(0.0, 0.0); GL.Vertex2(0.0, 0.0); GL.TexCoord2(0.0, 1.0); GL.Vertex2(0.0, (double)h); GL.TexCoord2(1.0, 1.0); GL.Vertex2((double)w, (double)h); GL.TexCoord2(1.0, 0.0); GL.Vertex2((double)w, 0.0); GL.End(); // finalize GL.PopMatrix(); GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); GL.MatrixMode(MatrixMode.Modelview); } // retrieve buffer { GL.BindTexture(TextureTarget.Texture2D, PixelBufferOpenGlTextureIndex); GL.CopyTexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgb8, 0, 0, w, h, 0); } }
// render data private static void RenderData(ref Table Table) { // prepare timetable int w = 384, h = 192; int offsetx = 0; int actualheight = h; float descriptionwidth = 256; float descriptionheight = 16; float stationnamewidth = 16; for (int k = 0; k < 2; k++) { Bitmap b = new Bitmap(w, h); Graphics g = Graphics.FromImage(b); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; g.Clear(Color.Transparent); g.FillRectangle(Brushes.White, new RectangleF(offsetx, 0, w, actualheight)); Font f = new Font(FontFamily.GenericSansSerif, 13.0f, GraphicsUnit.Pixel); Font fs = new Font(FontFamily.GenericSansSerif, 11.0f, GraphicsUnit.Pixel); Font fss = new Font(FontFamily.GenericSansSerif, 9.0f, GraphicsUnit.Pixel); // draw timetable string t; SizeF s; // description float x0 = offsetx + 8; float y0 = 8; if (k == 1) { t = DefaultTimetableDescription; g.DrawString(t, f, Brushes.Black, new RectangleF(x0, 6, descriptionwidth, descriptionheight + 8)); y0 += descriptionheight + 2; } // highest speed t = Translations.GetInterfaceString("timetable_highestspeed"); s = g.MeasureString(t, fs); g.DrawString(t, fs, Brushes.Black, x0, y0); float y0a = y0 + s.Height + 2; float x1 = x0 + s.Width + 4; for (int i = 0; i < Table.Tracks.Length; i++) { float y = y0a + 18 * i; t = Table.Tracks[i].Speed; g.DrawString(t, f, Brushes.Black, x0, y); s = g.MeasureString(t, f); float x = x0 + s.Width + 4; if (x > x1) { x1 = x; } } g.DrawLine(Pens.LightGray, new PointF(x1 - 2, 4 + descriptionheight), new PointF(x1 - 2, y0a + 18 * Table.Tracks.Length - 1)); // driving time t = Translations.GetInterfaceString("timetable_drivingtime"); s = g.MeasureString(t, fs); g.DrawString(t, fs, Brushes.Black, x1, y0); float x2 = x1 + s.Width + 4; for (int i = 0; i < Table.Tracks.Length; i++) { float y = y0a + 18 * i; if (Table.Tracks[i].Time.Hour.Length != 0) { t = Table.Tracks[i].Time.Hour; g.DrawString(t, fss, Brushes.Black, x1, y + 2); } else { t = "0"; } s = g.MeasureString(t, fss, 9999, StringFormat.GenericTypographic); float x = x1 + s.Width - 1; if (Table.Tracks[i].Time.Minute.Length != 0) { t = Table.Tracks[i].Time.Minute; g.DrawString(t, fs, Brushes.Black, x, y + 2); } else { t = "00:"; } s = g.MeasureString(t, fs, 9999, StringFormat.GenericTypographic); x += s.Width + 1; t = Table.Tracks[i].Time.Second; g.DrawString(t, fss, Brushes.Black, x, y + 2); s = g.MeasureString(t, fss, 9999, StringFormat.GenericTypographic); x += s.Width + 8; if (x > x2) { x2 = x; } } for (int i = 0; i < Table.Tracks.Length; i++) { float y = y0a + 18 * i; g.DrawLine(Pens.LightGray, new PointF(offsetx + 4, y - 1), new PointF(x2 - 2, y - 1)); } g.DrawLine(Pens.LightGray, new PointF(x2 - 2, 4 + descriptionheight), new PointF(x2 - 2, y0a + 18 * Table.Tracks.Length - 1)); // station name float y2 = y0; t = Translations.GetInterfaceString("timetable_stationname"); s = g.MeasureString(t, f); g.DrawString(t, f, Brushes.Black, x2, y2); float x3 = x2 + s.Width + 4; for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; g.DrawLine(Pens.LightGray, new PointF(x2 - 2, y - 1), new PointF(w - 4, y - 1)); t = Table.Stations[i].Name; if (Table.Stations[i].NameJapanese & Table.Stations[i].Name.Length > 1) { float[] sizes = new float[t.Length]; float totalsize = 0.0f; for (int j = 0; j < t.Length; j++) { sizes[j] = g.MeasureString(new string(t[j], 1), f, 9999, StringFormat.GenericTypographic).Width; totalsize += sizes[j]; } float space = (stationnamewidth - totalsize) / (float)(t.Length - 1); float x = 0.0f; for (int j = 0; j < t.Length; j++) { g.DrawString(new string(t[j], 1), f, Brushes.Black, x2 + x, y); x += sizes[j] + space; } } else { g.DrawString(t, f, Brushes.Black, x2, y); } s = g.MeasureString(t, f); { float x = x2 + s.Width + 4; if (x > x3) { x3 = x; } } } g.DrawLine(Pens.LightGray, new PointF(x3 - 2, 4 + descriptionheight), new PointF(x3 - 2, y0 + 18 * (Table.Stations.Length + 1))); if (k == 0) { stationnamewidth = x3 - x2 - 6; } // arrival time t = Translations.GetInterfaceString("timetable_arrivaltime"); s = g.MeasureString(t, f); g.DrawString(t, f, Brushes.Black, x3, y2); float x4 = x3 + s.Width + 4; for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; if (Table.Stations[i].Pass) { t = "00"; s = g.MeasureString(t, fs); float x = x3 + s.Width; t = " ↓"; g.DrawString(t, f, Brushes.Black, x, y); s = g.MeasureString(t, f); x += +s.Width + 4; if (x > x4) { x4 = x; } } else { if (Table.Stations[i].Arrival.Hour.Length != 0) { t = Table.Stations[i].Arrival.Hour; g.DrawString(t, fs, Brushes.Black, x3, y); } else { t = "00"; } s = g.MeasureString(t, fs); float x = x3 + s.Width; if (Table.Stations[i].Arrival.Minute.Length != 0 & Table.Stations[i].Arrival.Second.Length != 0) { t = Table.Stations[i].Arrival.Minute + ":" + Table.Stations[i].Arrival.Second; } else { t = ""; } g.DrawString(t, f, Brushes.Black, x, y); s = g.MeasureString(t, f); x += s.Width + 4; if (x > x4) { x4 = x; } } } g.DrawLine(Pens.LightGray, new PointF(x4 - 2, 4 + descriptionheight), new PointF(x4 - 2, y0 + 18 * (Table.Stations.Length + 1))); // departure time t = Translations.GetInterfaceString("timetable_departuretime"); s = g.MeasureString(t, f); g.DrawString(t, f, Brushes.Black, x4, y2); float x5 = x4 + s.Width + 4; for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; if (Table.Stations[i].Terminal) { t = "00"; s = g.MeasureString(t, fs); float x = x4 + s.Width; const float c0 = 4; const float c1 = 32; g.DrawLine(Pens.Black, new PointF(x + c0, y + 6), new PointF(x + c1, y + 6)); g.DrawLine(Pens.Black, new PointF(x + c0, y + 10), new PointF(x + c1, y + 10)); x += c1 + 4; if (x > x5) { x5 = x; } } else { if (Table.Stations[i].Departure.Hour.Length != 0) { t = Table.Stations[i].Departure.Hour; g.DrawString(t, fs, Brushes.Black, x4, y); } else { t = "00"; } s = g.MeasureString(t, fs); float x = x4 + s.Width; if (Table.Stations[i].Departure.Minute.Length != 0 & Table.Stations[i].Departure.Second.Length != 0) { t = Table.Stations[i].Departure.Minute + ":" + Table.Stations[i].Departure.Second; } else { t = ""; } g.DrawString(t, f, Brushes.Black, x, y); s = g.MeasureString(t, f); x += s.Width + 4; if (x > x5) { x5 = x; } } } for (int i = 0; i < Table.Stations.Length; i++) { float y = y0 + 18 * (i + 1) + 2; g.DrawLine(Pens.LightGray, new PointF(x2 - 2, y - 1), new PointF(w - 4, y - 1)); } // border if (k == 1) { g.DrawLine(Pens.Black, new PointF(offsetx + 4, 4), new PointF(offsetx + 4, y0a + 18 * Table.Tracks.Length - 1)); g.DrawLine(Pens.Black, new PointF(offsetx + 4, y0a + 18 * Table.Tracks.Length - 1), new PointF(x2 - 2, y0a + 18 * Table.Tracks.Length - 1)); g.DrawLine(Pens.Black, new PointF(offsetx + 4, 4), new PointF(w - 4, 4)); g.DrawLine(Pens.Black, new PointF(offsetx + 4, 4 + descriptionheight), new PointF(w - 4, 4 + descriptionheight)); g.DrawLine(Pens.Black, new PointF(x2 - 2, y0 + 18 * (Table.Stations.Length + 1)), new PointF(w - 4, y0 + 18 * (Table.Stations.Length + 1))); g.DrawLine(Pens.Black, new PointF(w - 4, 4), new PointF(w - 4, y0 + 18 * (Table.Stations.Length + 1))); g.DrawLine(Pens.Black, new PointF(x2 - 2, y0a + 18 * Table.Tracks.Length - 1), new PointF(x2 - 2, y0 + 18 * (Table.Stations.Length + 1))); } // measure w = (int)Math.Ceiling((double)(x5 + 1)); h = (int)Math.Ceiling((double)(y0 + 18 * (Table.Stations.Length + 1) + 4)); // description if (k == 0) { t = DefaultTimetableDescription; s = g.MeasureString(t, f, w - 16); descriptionwidth = s.Width; descriptionheight = s.Height + 2; h += (int)Math.Ceiling((double)s.Height) + 4; } // finish if (k == 0) { // measures int nw = Textures.RoundUpToPowerOfTwo(w); offsetx = nw - w; w = nw; actualheight = h; h = Textures.RoundUpToPowerOfTwo(h); } else { // create texture g.Dispose(); DefaultTimetableTexture = Textures.RegisterTexture(b); } } }