BizHawk/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs

534 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using LuaInterface;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
public class GuiLuaLibrary : LuaLibraryBase
{
public override string Name { get { return "gui"; } }
public override string[] Functions
{
get
{
return new[]
{
"addmessage",
"alert",
"clearGraphics",
"cleartext",
"drawBezier",
"drawBox",
"drawEllipse",
"drawIcon",
"drawImage",
"drawLine",
"drawPie",
"drawPixel",
"drawPolygon",
"drawRectangle",
"drawString",
"drawText",
"text",
};
}
}
#region Gui API
public void Dispose()
{
foreach (var brush in SolidBrushes.Values) brush.Dispose();
foreach (var brush in Pens.Values) brush.Dispose();
}
public bool SurfaceIsNull
{
get
{
return luaSurface == null;
}
}
/// <summary>
/// sets the current drawing context to a new surface.
/// you COULD pass these back to lua to use as a target in rendering jobs, instead of setting it as current here.
/// could be more powerful.
/// performance test may reveal that repeatedly calling GetGraphics could be slow.
/// we may want to make a class here in LuaImplementation that wraps a DisplaySurface and a Graphics which would be created once
/// </summary>
public void DrawNew()
{
luaSurface = GlobalWin.DisplayManager.GetLuaSurfaceNative();
}
public void DrawNewEmu()
{
luaSurface = GlobalWin.DisplayManager.GetLuaEmuSurfaceEmu();
}
/// <summary>
/// finishes the current drawing and submits it to the display manager (at native [host] resolution pre-osd)
/// you would probably want some way to specify which surface to set it to, when there are other surfaces.
/// most notably, the client output [emulated] resolution
/// </summary>
public void DrawFinish()
{
GlobalWin.DisplayManager.SetLuaSurfaceNativePreOSD(luaSurface);
luaSurface = null;
}
public void DrawFinishEmu()
{
GlobalWin.DisplayManager.SetLuaSurfaceEmu(luaSurface);
luaSurface = null;
}
#endregion
#region Helpers
private DisplaySurface luaSurface;
private readonly Dictionary<Color, SolidBrush> SolidBrushes = new Dictionary<Color, SolidBrush>();
private readonly Dictionary<Color, Pen> Pens = new Dictionary<Color, Pen>();
private static Color GetColor(object color)
{
if (color is double)
{
return Color.FromArgb(int.Parse(long.Parse(color.ToString()).ToString("X"), NumberStyles.HexNumber));
}
else
{
return Color.FromName(color.ToString().ToLower());
}
}
private SolidBrush GetBrush(object color)
{
Color c = GetColor(color);
SolidBrush b;
if (!SolidBrushes.TryGetValue(c, out b))
{
b = new SolidBrush(c);
SolidBrushes[c] = b;
}
return b;
}
private Pen GetPen(object color)
{
Color c = GetColor(color);
Pen p;
if (!Pens.TryGetValue(c, out p))
{
p = new Pen(c);
Pens[c] = p;
}
return p;
}
private Graphics GetGraphics()
{
var g = luaSurface.GetGraphics();
int tx = Global.Emulator.CoreComm.ScreenLogicalOffsetX;
int ty = Global.Emulator.CoreComm.ScreenLogicalOffsetY;
if (tx != 0 || ty != 0)
{
var transform = g.Transform;
transform.Translate(-tx, -ty);
g.Transform = transform;
}
return g;
}
private void DoGuiText(object luaX, object luaY, object luaStr, bool alert, object background = null,
object forecolor = null, object anchor = null)
{
if (!alert)
{
if (forecolor == null)
forecolor = "white";
if (background == null)
background = "black";
}
int dx = LuaInt(luaX);
int dy = LuaInt(luaY);
int a = 0;
if (anchor != null)
{
int x;
if (int.TryParse(anchor.ToString(), out x) == false)
{
if (anchor.ToString().ToLower() == "topleft")
a = 0;
else if (anchor.ToString().ToLower() == "topright")
a = 1;
else if (anchor.ToString().ToLower() == "bottomleft")
a = 2;
else if (anchor.ToString().ToLower() == "bottomright")
a = 3;
}
else
{
a = LuaInt(anchor);
}
}
else
{
dx -= Global.Emulator.CoreComm.ScreenLogicalOffsetX;
dy -= Global.Emulator.CoreComm.ScreenLogicalOffsetY;
}
// blah hacks
dx *= MultiClientLuaLibrary.client_getwindowsize();
dy *= MultiClientLuaLibrary.client_getwindowsize();
GlobalWin.OSD.AddGUIText(luaStr.ToString(), dx, dy, alert, GetColor(background), GetColor(forecolor), a);
}
#endregion
public void gui_addmessage(object luaStr)
{
GlobalWin.OSD.AddMessage(luaStr.ToString());
}
public void gui_alert(object luaX, object luaY, object luaStr, object anchor = null)
{
DoGuiText(luaX, luaY, luaStr, true, null, null, anchor);
}
public void gui_clearGraphics()
{
GlobalWin.DisplayManager.NeedsToPaint = true;
luaSurface.Clear();
}
public static void gui_cleartext()
{
GlobalWin.OSD.ClearGUIText();
}
public void gui_drawBezier(LuaTable points, object color)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
Point[] Points = new Point[4];
int i = 0;
foreach (LuaTable point in points.Values)
{
Points[i] = new Point(LuaInt(point[1]), LuaInt(point[2]));
i++;
if (i >= 4)
break;
}
g.DrawBezier(GetPen(color), Points[0], Points[1], Points[2], Points[3]);
}
catch (Exception)
{
return;
}
}
}
public void gui_drawBox(object X, object Y, object X2, object Y2, object line = null, object background = null)
{
using (var g = GetGraphics())
{
try
{
int int_x = LuaInt(X);
int int_y = LuaInt(Y);
int int_width = LuaInt(X2);
int int_height = LuaInt(Y2);
if (int_x < int_width)
{
int_width = Math.Abs(int_x - int_width);
}
else
{
int_width = int_x - int_width;
int_x -= int_width;
}
if (int_y < int_height)
{
int_height = Math.Abs(int_y - int_height);
}
else
{
int_height = int_y - int_height;
int_y -= int_height;
}
g.DrawRectangle(GetPen(line ?? "white"), int_x, int_y, int_width, int_height);
if (background != null)
{
g.FillRectangle(GetBrush(background), int_x, int_y, int_width, int_height);
}
}
catch (Exception)
{
// need to stop the script from here
return;
}
}
}
public void gui_drawEllipse(object X, object Y, object width, object height, object line, object background = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
g.DrawEllipse(GetPen(line ?? "white"), LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height));
if (background != null)
{
var brush = GetBrush(background);
g.FillEllipse(brush, LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height));
}
}
catch (Exception)
{
// need to stop the script from here
return;
}
}
}
public void gui_drawIcon(object Path, object x, object y, object width = null, object height = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
Icon icon;
if (width != null && height != null)
{
icon = new Icon(Path.ToString(), LuaInt(width), LuaInt(height));
}
else
{
icon = new Icon(Path.ToString());
}
g.DrawIcon(icon, LuaInt(x), LuaInt(y));
}
catch (Exception)
{
return;
}
}
}
public void gui_drawImage(object Path, object x, object y, object width = null, object height = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
Image img = Image.FromFile(Path.ToString());
if (width == null || width.GetType() != typeof(int))
width = img.Width.ToString();
if (height == null || height.GetType() != typeof(int))
height = img.Height.ToString();
g.DrawImage(img, LuaInt(x), LuaInt(y), int.Parse(width.ToString()), int.Parse(height.ToString()));
}
catch (Exception)
{
return;
}
}
}
public void gui_drawLine(object x1, object y1, object x2, object y2, object color = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
g.DrawLine(GetPen(color ?? "white"), LuaInt(x1), LuaInt(y1), LuaInt(x2), LuaInt(y2));
}
catch (Exception)
{
return;
}
}
}
public void gui_drawPie(object X, object Y, object width, object height, object startangle, object sweepangle,
object line, object background = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
g.DrawPie(GetPen(line), LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height), LuaInt(startangle), LuaInt(sweepangle));
if (background != null)
{
var brush = GetBrush(background);
g.FillPie(brush, LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height), LuaInt(startangle), LuaInt(sweepangle));
}
}
catch (Exception)
{
// need to stop the script from here
return;
}
}
}
public void gui_drawPixel(object X, object Y, object color = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
float x = LuaInt(X) + 0.1F;
try
{
g.DrawLine(GetPen(color ?? "white"), LuaInt(X), LuaInt(Y), x, LuaInt(Y));
}
catch (Exception)
{
return;
}
}
}
public void gui_drawPolygon(LuaTable points, object line, object background = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
//this is a test
using (var g = GetGraphics())
{
try
{
Point[] Points = new Point[points.Values.Count];
int i = 0;
foreach (LuaTable point in points.Values)
{
Points[i] = new Point(LuaInt(point[1]), LuaInt(point[2]));
i++;
}
g.DrawPolygon(GetPen(line), Points);
if (background != null)
{
var brush = GetBrush(background);
g.FillPolygon(brush, Points);
}
}
catch (Exception)
{
return;
}
}
}
public void gui_drawRectangle(object X, object Y, object width, object height, object line, object background = null)
{
using (var g = GetGraphics())
{
try
{
int int_x = LuaInt(X);
int int_y = LuaInt(Y);
int int_width = LuaInt(width);
int int_height = LuaInt(height);
g.DrawRectangle(GetPen(line ?? "white"), int_x, int_y, int_width, int_height);
if (background != null)
{
g.FillRectangle(GetBrush(background), int_x, int_y, int_width, int_height);
}
}
catch (Exception)
{
// need to stop the script from here
return;
}
}
}
public void gui_drawString(object X, object Y, object message, object color = null, object fontsize = null, object fontfamily = null, object fontstyle = null)
{
gui_drawText(X, Y, message, color, fontsize, fontfamily, fontstyle);
}
public void gui_drawText(object X, object Y, object message, object color = null, object fontsize = null, object fontfamily = null, object fontstyle = null)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
using (var g = GetGraphics())
{
try
{
int fsize = 12;
if (fontsize != null)
{
fsize = LuaInt(fontsize);
}
FontFamily family = FontFamily.GenericMonospace;
if (fontfamily != null)
{
family = new FontFamily(fontfamily.ToString());
}
FontStyle fstyle = FontStyle.Regular;
if (fontstyle != null)
{
string tmp = fontstyle.ToString().ToLower();
switch (tmp)
{
default:
case "regular":
break;
case "bold":
fstyle = FontStyle.Bold;
break;
case "italic":
fstyle = FontStyle.Italic;
break;
case "strikethrough":
fstyle = FontStyle.Strikeout;
break;
case "underline":
fstyle = FontStyle.Underline;
break;
}
}
Font font = new Font(family, fsize, fstyle, GraphicsUnit.Pixel);
g.DrawString(message.ToString(), font, GetBrush(color ?? "white"), LuaInt(X), LuaInt(Y));
}
catch (Exception)
{
return;
}
}
}
public void gui_text(object luaX, object luaY, object luaStr, object background = null, object forecolor = null,
object anchor = null)
{
DoGuiText(luaX, luaY, luaStr, false, background, forecolor, anchor);
}
}
}