diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj
index 04447545af..f4b3331a92 100644
--- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj
+++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj
@@ -142,6 +142,7 @@
+
diff --git a/BizHawk.Client.Common/lua/LuaHelper.cs b/BizHawk.Client.Common/lua/LuaHelper.cs
new file mode 100644
index 0000000000..9180ec421f
--- /dev/null
+++ b/BizHawk.Client.Common/lua/LuaHelper.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using LuaInterface;
+using System.Reflection;
+
+namespace BizHawk.Client.Common
+{
+ public static class LuaHelper
+ {
+ public static LuaTable ToLuaTable(Lua lua, object obj)
+ {
+ var table = lua.NewTable();
+
+ var type = obj.GetType();
+
+ var methods = type.GetMethods();
+ foreach (var method in methods)
+ {
+ if (method.IsPublic)
+ {
+ table[method.Name] = lua.RegisterFunction("", obj, method);
+ }
+ }
+
+ return table;
+ }
+ }
+}
diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
index 678fcc9649..ead9568e34 100644
--- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
+++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
@@ -771,6 +771,12 @@
+
+ Form
+
+
+ LuaCanvas.cs
+
Component
@@ -1330,6 +1336,9 @@
HexFind.cs
+
+ LuaCanvas.cs
+
LuaConsole.cs
diff --git a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs
index a991a4be3d..d6d71faa46 100644
--- a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs
+++ b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs
@@ -596,5 +596,16 @@ namespace BizHawk.Client.EmuHawk
GlobalWin.OSD.AddGUIText(message, x, y, background ?? Color.Black, forecolor ?? Color.White, a);
}
+
+ [LuaMethodAttributes(
+ "createcanvas",
+ "Creates a canvas of the given size."
+ )]
+ public LuaTable Text(int width, int height)
+ {
+ var canvas = new LuaCanvas(width, height);
+ canvas.Show();
+ return LuaHelper.ToLuaTable(Lua, canvas);
+ }
}
}
diff --git a/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.Designer.cs b/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.Designer.cs
new file mode 100644
index 0000000000..5e893f83a2
--- /dev/null
+++ b/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.Designer.cs
@@ -0,0 +1,66 @@
+namespace BizHawk.Client.EmuHawk
+{
+ partial class LuaCanvas
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.pictureBox = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox
+ //
+ this.pictureBox.Location = new System.Drawing.Point(0, 0);
+ this.pictureBox.Margin = new System.Windows.Forms.Padding(0);
+ this.pictureBox.Name = "pictureBox";
+ this.pictureBox.Size = new System.Drawing.Size(282, 260);
+ this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
+ this.pictureBox.TabIndex = 0;
+ this.pictureBox.TabStop = false;
+ //
+ // LuaCanvas
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.AutoSize = true;
+ this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.ClientSize = new System.Drawing.Size(284, 261);
+ this.Controls.Add(this.pictureBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Name = "LuaCanvas";
+ this.Text = "LuaCanvas";
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox pictureBox;
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs b/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs
new file mode 100644
index 0000000000..601c7145fc
--- /dev/null
+++ b/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BizHawk.Client.EmuHawk
+{
+ public partial class LuaCanvas : Form
+ {
+ private Graphics graphics;
+
+ public LuaCanvas(int width, int height)
+ {
+ InitializeComponent();
+ pictureBox.Width = width;
+ pictureBox.Height = height;
+ pictureBox.Image = new Bitmap(width, height);
+ graphics = Graphics.FromImage(pictureBox.Image);
+ }
+
+ public void SetTitle(string title)
+ {
+ this.Text = title;
+ }
+
+ public void Clear(Color color)
+ {
+ graphics.Clear(color);
+ }
+
+ public void Refresh()
+ {
+ pictureBox.Refresh();
+ }
+
+ public void DrawRectangle(int x, int y, int width, int height, Color? outline = null, Color? fill = null)
+ {
+ if (fill.HasValue)
+ {
+ var brush = new SolidBrush(fill.Value);
+ graphics.FillRectangle(brush, x, y, width, height);
+ }
+
+ var pen = new Pen(outline.HasValue ? outline.Value : Color.Black);
+ graphics.DrawRectangle(pen, x, y, width, height);
+ }
+
+ public void DrawText(int x, int y, string message, Color? color = null, int? fontsize = null, string fontfamily = null, string fontstyle = null)
+ {
+ var family = FontFamily.GenericMonospace;
+ if (fontfamily != null)
+ {
+ family = new FontFamily(fontfamily);
+ }
+
+ var fstyle = FontStyle.Regular;
+ if (fontstyle != null)
+ {
+ switch (fontstyle.ToLower())
+ {
+ 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;
+ }
+ }
+
+ var font = new Font(family, fontsize ?? 12, fstyle, GraphicsUnit.Pixel);
+ graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
+ graphics.DrawString(message, font, new SolidBrush(color ?? Color.White), x, y);
+ }
+ }
+}
diff --git a/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.resx b/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.resx
new file mode 100644
index 0000000000..29dcb1b3a3
--- /dev/null
+++ b/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/output/Lua/test.lua b/output/Lua/test.lua
new file mode 100644
index 0000000000..9c847b916b
--- /dev/null
+++ b/output/Lua/test.lua
@@ -0,0 +1,5 @@
+local canvas = gui.createcanvas(200, 200);
+canvas.Clear(0xFF000000);
+canvas.DrawRectangle(50, 50, 100, 100, 0xFFFF0000, 0xFF0000FF);
+canvas.DrawText(0, 0, "Hello, world!");
+canvas.Refresh();
\ No newline at end of file