public class ChatLineAddedArgs : EventArgs
{
ChatBufferItem mItem;
+ public ChatBufferItem Item { get { return mItem; } }
public ChatLineAddedArgs(ChatBufferItem item)
{
using System.Text;
using System.Text.RegularExpressions;
using System.Drawing;
+using System.Drawing.Imaging;
+using System.Windows.Forms;
+using OpenTK.Graphics.OpenGL;
namespace Radegast.Rendering
{
public class ChatOverlay : IDisposable
{
+ public static Font ChatFont = new Font(FontFamily.GenericSansSerif, 11f, FontStyle.Regular, GraphicsUnit.Point);
+ public static float ChatLineTimeOnScreen = 20f; // time in seconds chat line appears on the screen
+ public static float ChatLineFade = 1.5f; // number of seconds before expiry to start fading chat off
+ public static OpenTK.Graphics.Color4 ChatBackground = new OpenTK.Graphics.Color4(0f, 0f, 0f, 0.5f);
+
RadegastInstance Instance;
SceneWindow Window;
float runningTime;
+
+ Queue<ChatLine> chatLines;
+ int screenWidth, screenHeight;
public ChatOverlay(RadegastInstance instance, SceneWindow window)
{
this.Instance = instance;
this.Window = window;
Instance.TabConsole.MainChatManger.ChatLineAdded += new EventHandler<ChatLineAddedArgs>(MainChatManger_ChatLineAdded);
+ chatLines = new Queue<ChatLine>();
}
public void Dispose()
{
Instance.TabConsole.MainChatManger.ChatLineAdded -= new EventHandler<ChatLineAddedArgs>(MainChatManger_ChatLineAdded);
+
+ if (chatLines != null)
+ {
+ lock (chatLines)
+ {
+ foreach (var line in chatLines)
+ {
+ line.Dispose();
+ }
+ }
+ chatLines = null;
+ }
}
void MainChatManger_ChatLineAdded(object sender, ChatLineAddedArgs e)
{
+ lock (chatLines)
+ {
+ chatLines.Enqueue(new ChatLine(e.Item, runningTime));
+ }
}
- public void RenderChat(float time)
+ public void RenderChat(float time, RenderPass pass)
{
runningTime += time;
+ if (chatLines.Count == 0) return;
+
+ int c = 0;
+ int expired = 0;
+ screenWidth = Window.Viewport[2];
+ screenHeight = Window.Viewport[3];
+ ChatLine[] lines;
+
+ lock (chatLines)
+ {
+ lines = chatLines.ToArray();
+ c = lines.Length;
+ for (int i = 0; i < c; i++)
+ {
+ if ((runningTime - lines[i].TimeAdded) > ChatLineTimeOnScreen)
+ {
+ expired++;
+ ChatLine goner = chatLines.Dequeue();
+ goner.Dispose();
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (expired > 0)
+ {
+ lines = chatLines.ToArray();
+ c = lines.Length;
+ }
+ }
+
+ if (c == 0)
+ {
+ runningTime = 0f;
+ return;
+ }
+
+ int maxWidth = (int)((float)screenWidth * 0.7f);
+
+ int actualMaxWidth = 0;
+ int height = 0;
+ for (int i = 0; i < c; i++)
+ {
+ lines[i].PrepareText(maxWidth);
+ if (lines[i].Width > actualMaxWidth) actualMaxWidth = lines[i].Width;
+ height += lines[i].Height;
+ }
+
+ int x = 5;
+ int y = 5;
+ GL.Enable(EnableCap.Texture2D);
+ GL.Color4(ChatBackground);
+ RHelp.Draw2DBox(x, y, actualMaxWidth + 6, height + 10, 1f);
+ GL.Color4(1f, 1f, 1f, 1f);
+ for (int i = c - 1; i >= 0; i--)
+ {
+ ChatLine line = lines[i];
+ float remain = ChatLineTimeOnScreen - (runningTime - line.TimeAdded);
+ if (remain < ChatLineFade)
+ {
+ float alpha = remain / ChatLineFade;
+ GL.Color4(1f, 1f, 1f, alpha);
+ }
+ line.Render(x + 3, y + 5);
+ y += line.Height;
+ }
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ GL.Disable(EnableCap.Texture2D);
+ GL.Color4(1f, 1f, 1f, 1f);
+ }
+ }
+
+ public class ChatLine : IDisposable
+ {
+ public float TimeAdded;
+ public int Width;
+ public int Height;
+
+ int textureID = -1;
+ int widthForTextureGenerated = -1;
+ ChatBufferItem item;
+
+ public ChatLine(ChatBufferItem item, float timeAdded)
+ {
+ this.item = item;
+ this.TimeAdded = timeAdded;
+ }
+
+ public void Dispose()
+ {
+ if (textureID > 0)
+ {
+ GL.DeleteTexture(textureID);
+ textureID = -1;
+ }
+ }
+
+ public void PrepareText(int maxWidth)
+ {
+ if (maxWidth != widthForTextureGenerated)
+ {
+ string txt = item.From + item.Text;
+
+ // If we're modiefied and have texture already delete it from graphics card
+ if (textureID > 0)
+ {
+ GL.DeleteTexture(textureID);
+ textureID = -1;
+ }
+
+ TextFormatFlags flags = TextFormatFlags.Top | TextFormatFlags.Left | TextFormatFlags.WordBreak;
+
+ Size s = TextRenderer.MeasureText(
+ txt,
+ ChatOverlay.ChatFont,
+ new Size(maxWidth, 2000), flags);
+
+ Width = s.Width;
+ Height = s.Height;
+
+ Bitmap img = new Bitmap(
+ Width,
+ Height,
+ System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+
+ Graphics g = Graphics.FromImage(img);
+
+ TextRenderer.DrawText(
+ g,
+ txt,
+ ChatOverlay.ChatFont,
+ new Rectangle(0, 0, img.Width + 2, img.Height + 2),
+ RHelp.WinColor(new OpenTK.Graphics.Color4(0.95f, 0.95f, 0.95f, 1f)),
+ Color.Transparent,
+ flags);
+
+ widthForTextureGenerated = maxWidth;
+ textureID = RHelp.GLLoadImage(img, true);
+ g.Dispose();
+ img.Dispose();
+ }
+ }
+
+ public void Render(int x, int y)
+ {
+ if (textureID == -1) return;
+ GL.BindTexture(TextureTarget.Texture2D, textureID);
+ RHelp.Draw2DBox(x, y, Width, Height, 0f);
}
}
}
/// <summary>\r
/// Size of OpenGL window we're drawing on\r
/// </summary>\r
- int[] Viewport = new int[4];\r
+ public int[] Viewport = new int[4];\r
\r
#endregion Public fields\r
\r
GL.MatrixMode(MatrixMode.Modelview);\r
}\r
\r
- public int GLLoadImage(Bitmap bitmap, bool hasAlpha)\r
- {\r
- int ret = -1;\r
- GL.GenTextures(1, out ret);\r
- GL.BindTexture(TextureTarget.Texture2D, ret);\r
-\r
- Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);\r
-\r
- BitmapData bitmapData =\r
- bitmap.LockBits(\r
- rectangle,\r
- ImageLockMode.ReadOnly,\r
- hasAlpha ? System.Drawing.Imaging.PixelFormat.Format32bppArgb : System.Drawing.Imaging.PixelFormat.Format24bppRgb);\r
-\r
- GL.TexImage2D(\r
- TextureTarget.Texture2D,\r
- 0,\r
- hasAlpha ? PixelInternalFormat.Rgba : PixelInternalFormat.Rgb8,\r
- bitmap.Width,\r
- bitmap.Height,\r
- 0,\r
- hasAlpha ? OpenTK.Graphics.OpenGL.PixelFormat.Bgra : OpenTK.Graphics.OpenGL.PixelFormat.Bgr,\r
- PixelType.UnsignedByte,\r
- bitmapData.Scan0);\r
-\r
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);\r
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);\r
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);\r
- if (RenderSettings.HasMipmap)\r
- {\r
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);\r
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1);\r
- GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);\r
- }\r
- else\r
- {\r
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);\r
- }\r
-\r
- bitmap.UnlockBits(bitmapData);\r
- return ret;\r
- }\r
-\r
#region Texture thread\r
bool TextureThreadRunning = true;\r
\r
Bitmap bitmap = (Bitmap)img;\r
\r
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);\r
- item.Data.TextureInfo.TexturePointer = GLLoadImage(bitmap, item.Data.TextureInfo.HasAlpha);\r
+ item.Data.TextureInfo.TexturePointer = RHelp.GLLoadImage(bitmap, item.Data.TextureInfo.HasAlpha);\r
GL.Flush();\r
bitmap.Dispose();\r
}\r
GL.DeleteTexture(terrainTexture);\r
}\r
\r
- terrainTexture = GLLoadImage(terrainImage, false);\r
+ terrainTexture = RHelp.GLLoadImage(terrainImage, false);\r
terrainImage.Dispose();\r
terrainImage = null;\r
}\r
GLHUDBegin();\r
RenderText(RenderPass.Simple);\r
RenderStats();\r
- chatOverlay.RenderChat(lastFrameTime);\r
+ chatOverlay.RenderChat(lastFrameTime, RenderPass.Simple);\r
GLHUDEnd();\r
GL.Disable(EnableCap.Blend);\r
}\r
using System.Threading;\r
using OpenTK.Graphics.OpenGL;\r
using System.Runtime.InteropServices;\r
+using System.Drawing;\r
+using System.Drawing.Imaging;\r
using OpenMetaverse;\r
using OpenMetaverse.Rendering;\r
\r
return new OpenTK.Vector4(v.X, v.Y, v.Z, v.W);\r
}\r
\r
+ public static Color WinColor(OpenTK.Graphics.Color4 color)\r
+ {\r
+ return Color.FromArgb((int)(color.A * 255), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255));\r
+ }\r
+\r
+ public static Color WinColor(Color4 color)\r
+ {\r
+ return Color.FromArgb((int)(color.A * 255), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255));\r
+ }\r
+\r
#region Cached image save and load\r
public static readonly string RAD_IMG_MAGIC = "radegast_img";\r
\r
2, 3, 7, 6 // Bottom Face\r
};\r
#endregion Static vertices and indices for a cube (used for bounding box drawing)\r
+\r
+ public static int GLLoadImage(Bitmap bitmap, bool hasAlpha)\r
+ {\r
+ int ret = -1;\r
+ GL.GenTextures(1, out ret);\r
+ GL.BindTexture(TextureTarget.Texture2D, ret);\r
+\r
+ Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);\r
+\r
+ BitmapData bitmapData =\r
+ bitmap.LockBits(\r
+ rectangle,\r
+ ImageLockMode.ReadOnly,\r
+ hasAlpha ? System.Drawing.Imaging.PixelFormat.Format32bppArgb : System.Drawing.Imaging.PixelFormat.Format24bppRgb);\r
+\r
+ GL.TexImage2D(\r
+ TextureTarget.Texture2D,\r
+ 0,\r
+ hasAlpha ? PixelInternalFormat.Rgba : PixelInternalFormat.Rgb8,\r
+ bitmap.Width,\r
+ bitmap.Height,\r
+ 0,\r
+ hasAlpha ? OpenTK.Graphics.OpenGL.PixelFormat.Bgra : OpenTK.Graphics.OpenGL.PixelFormat.Bgr,\r
+ PixelType.UnsignedByte,\r
+ bitmapData.Scan0);\r
+\r
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);\r
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);\r
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);\r
+ if (RenderSettings.HasMipmap)\r
+ {\r
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);\r
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1);\r
+ GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);\r
+ }\r
+ else\r
+ {\r
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);\r
+ }\r
+\r
+ bitmap.UnlockBits(bitmapData);\r
+ return ret;\r
+ }\r
+\r
+ public static void Draw2DBox(float x, float y, float width, float height, float depth)\r
+ {\r
+ GL.Begin(BeginMode.Quads);\r
+ {\r
+ GL.TexCoord2(0, 1);\r
+ GL.Vertex3(x, y, depth);\r
+ GL.TexCoord2(1, 1);\r
+ GL.Vertex3(x + width, y, depth);\r
+ GL.TexCoord2(1, 0);\r
+ GL.Vertex3(x + width, y + height, depth);\r
+ GL.TexCoord2(0, 0);\r
+ GL.Vertex3(x, y + height, depth);\r
+ }\r
+ GL.End();\r
+ }\r
}\r
\r
/// <summary>\r
void InitWater()
{
Bitmap normal = (Bitmap)Bitmap.FromFile(System.IO.Path.Combine("shader_data", "normalmap.png"));
- reflectionTexture = GLLoadImage(normal, false);
- refractionTexture = GLLoadImage(normal, false);
- normalmap = GLLoadImage(normal, false);
- depthTexture = GLLoadImage(normal, false);
- dudvmap = GLLoadImage((Bitmap)Bitmap.FromFile(System.IO.Path.Combine("shader_data", "dudvmap.png")), false);
+ reflectionTexture = RHelp.GLLoadImage(normal, false);
+ refractionTexture = RHelp.GLLoadImage(normal, false);
+ normalmap = RHelp.GLLoadImage(normal, false);
+ depthTexture = RHelp.GLLoadImage(normal, false);
+ dudvmap = RHelp.GLLoadImage((Bitmap)Bitmap.FromFile(System.IO.Path.Combine("shader_data", "dudvmap.png")), false);
waterProgram.Load("water.vert", "water.frag");
}