a better way to set up lua libraries, including a proof of concept for callbacks (in this case passing in a method for logging to an output window, but there can be other applications as well)

This commit is contained in:
adelikat 2013-10-31 00:31:25 +00:00
parent 0db498ae58
commit 6e3d55372f
10 changed files with 221 additions and 168 deletions

View File

@ -460,6 +460,7 @@
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.NES.cs" /> <Compile Include="tools\Lua\Libraries\EmuLuaLibrary.NES.cs" />
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Savestate.cs" /> <Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Savestate.cs" />
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.SNES.cs" /> <Compile Include="tools\Lua\Libraries\EmuLuaLibrary.SNES.cs" />
<Compile Include="tools\Lua\Libraries\LuaLibraryBase.cs" />
<Compile Include="tools\Lua\LuaButton.cs"> <Compile Include="tools\Lua\LuaButton.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>

View File

@ -2,61 +2,67 @@
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public static class BitLuaLibrary public class BitLuaLibrary : LuaLibraryBase
{ {
public static string Name = "bit"; public override string Name { get { return "bit"; } }
public static string[] Functions = new[] public override string[] Functions
{ {
"band", get
"bnot", {
"bor", return new[]
"bxor", {
"lshift", "band",
"rol", "bnot",
"ror", "bor",
"rshift", "bxor",
}; "lshift",
"rol",
"ror",
"rshift",
};
}
}
public static uint bit_band(object val, object amt) public static uint bit_band(object val, object amt)
{ {
return (uint)(LuaCommon.LuaInt(val) & LuaCommon.LuaInt(amt)); return (uint)(LuaInt(val) & LuaInt(amt));
} }
public static uint bit_bnot(object val) public static uint bit_bnot(object val)
{ {
return (uint)(~LuaCommon.LuaInt(val)); return (uint)(~LuaInt(val));
} }
public static uint bit_bor(object val, object amt) public static uint bit_bor(object val, object amt)
{ {
return (uint)(LuaCommon.LuaInt(val) | LuaCommon.LuaInt(amt)); return (uint)(LuaInt(val) | LuaInt(amt));
} }
public static uint bit_bxor(object val, object amt) public static uint bit_bxor(object val, object amt)
{ {
return (uint)(LuaCommon.LuaInt(val) ^ LuaCommon.LuaInt(amt)); return (uint)(LuaInt(val) ^ LuaInt(amt));
} }
public static uint bit_lshift(object val, object amt) public static uint bit_lshift(object val, object amt)
{ {
return (uint)(LuaCommon.LuaInt(val) << LuaCommon.LuaInt(amt)); return (uint)(LuaInt(val) << LuaInt(amt));
} }
public static uint bit_rol(object val, object amt) public static uint bit_rol(object val, object amt)
{ {
return (uint)((LuaCommon.LuaInt(val) << LuaCommon.LuaInt(amt)) return (uint)((LuaInt(val) << LuaInt(amt))
| (LuaCommon.LuaInt(val) >> (32 - LuaCommon.LuaInt(amt)))); | (LuaInt(val) >> (32 - LuaInt(amt))));
} }
public static uint bit_ror(object val, object amt) public static uint bit_ror(object val, object amt)
{ {
return (uint)((LuaCommon.LuaInt(val) >> LuaCommon.LuaInt(amt)) return (uint)((LuaInt(val) >> LuaInt(amt))
| (LuaCommon.LuaInt(val) << (32 - LuaCommon.LuaInt(amt)))); | (LuaInt(val) << (32 - LuaInt(amt))));
} }
public static uint bit_rshift(object val, object amt) public static uint bit_rshift(object val, object amt)
{ {
return (uint)(LuaCommon.LuaInt(val) >> LuaCommon.LuaInt(amt)); return (uint)(LuaInt(val) >> LuaInt(amt));
} }
} }
} }

View File

@ -3,33 +3,49 @@ using BizHawk.Client.Common;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public static class MultiClientLuaLibrary public class MultiClientLuaLibrary : LuaLibraryBase
{ {
public static string Name = "client"; public MultiClientLuaLibrary(Action<string> logOutputCallback)
public static string[] Functions = new[] : this()
{ {
"closerom", LogOutputCallback = logOutputCallback;
"getwindowsize", }
"opencheats",
"openhexeditor", public MultiClientLuaLibrary() : base() { }
"openramwatch",
"openramsearch", public override string Name { get { return "client"; } }
"openrom", public override string[] Functions
"opentasstudio", {
"opentoolbox", get
"opentracelogger", {
"pause_av", return new []
"reboot_core", {
"screenheight", "closerom",
"screenshot", "getwindowsize",
"screenshottoclipboard", "opencheats",
"screenwidth", "openhexeditor",
"setscreenshotosd", "openramwatch",
"setwindowsize", "openramsearch",
"unpause_av", "openrom",
"xpos", "opentasstudio",
"ypos", "opentoolbox",
}; "opentracelogger",
"pause_av",
"reboot_core",
"screenheight",
"screenshot",
"screenshottoclipboard",
"screenwidth",
"setscreenshotosd",
"setwindowsize",
"unpause_av",
"xpos",
"ypos",
};
}
}
public Action<string> LogOutputCallback = null;
public static void client_closerom() public static void client_closerom()
{ {
@ -123,7 +139,7 @@ namespace BizHawk.MultiClient
return GlobalWinF.RenderPanel.NativeSize.Width; return GlobalWinF.RenderPanel.NativeSize.Width;
} }
public static void client_setwindowsize(object window_size) public void client_setwindowsize(object window_size)
{ {
try try
{ {
@ -137,12 +153,15 @@ namespace BizHawk.MultiClient
} }
else else
{ {
ConsoleLuaLibrary.console_log("Invalid window size"); if (LogOutputCallback != null)
{
LogOutputCallback("Invalid window size");
}
} }
} }
catch catch
{ {
ConsoleLuaLibrary.console_log("Invalid window size"); LogOutputCallback("Invalid window size");
} }
} }

View File

@ -6,16 +6,22 @@ using LuaInterface;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public static class ConsoleLuaLibrary public class ConsoleLuaLibrary : LuaLibraryBase
{ {
public static string Name = "console"; public override string Name { get { return "console"; } }
public static string[] Functions = new[] public override string[] Functions
{ {
"clear", get
"getluafunctionslist", {
"log", return new[]
"output", {
}; "clear",
"getluafunctionslist",
"log",
"output",
};
}
}
public static void console_clear() public static void console_clear()
{ {
@ -24,13 +30,12 @@ namespace BizHawk.MultiClient
public static string console_getluafunctionslist() public static string console_getluafunctionslist()
{ {
string list = ""; StringBuilder list = new StringBuilder();
foreach (LuaDocumentation.LibraryFunction l in GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList) foreach (var function in GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList)
{ {
list += l.name + "\n"; list.AppendLine(function.Name);
} }
return list.ToString();
return list;
} }
public static void console_log(object lua_input) public static void console_log(object lua_input)

View File

@ -4,25 +4,31 @@ using BizHawk.Emulation.Consoles.Nintendo;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public static class NESLuaLibrary public class NESLuaLibrary : LuaLibraryBase
{ {
public static string Name = "nes"; public override string Name { get { return "nes"; } }
public static string[] Functions = new[] public override string[] Functions
{ {
"addgamegenie", get
"getallowmorethaneightsprites", {
"getbottomscanline", return new[]
"getclipleftandright", {
"getdispbackground", "addgamegenie",
"getdispsprites", "getallowmorethaneightsprites",
"gettopscanline", "getbottomscanline",
"removegamegenie", "getclipleftandright",
"setallowmorethaneightsprites", "getdispbackground",
"setclipleftandright", "getdispsprites",
"setdispbackground", "gettopscanline",
"setdispsprites", "removegamegenie",
"setscanlines", "setallowmorethaneightsprites",
}; "setclipleftandright",
"setdispbackground",
"setdispsprites",
"setscanlines",
};
}
}
public static void nes_addgamegenie(string code) public static void nes_addgamegenie(string code)
{ {
@ -145,8 +151,8 @@ namespace BizHawk.MultiClient
public static void nes_setscanlines(object top, object bottom, bool pal = false) public static void nes_setscanlines(object top, object bottom, bool pal = false)
{ {
int first = LuaCommon.LuaInt(top); int first = LuaInt(top);
int last = LuaCommon.LuaInt(bottom); int last = LuaInt(bottom);
if (first > 127) if (first > 127)
{ {
first = 127; first = 127;

View File

@ -2,28 +2,34 @@
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public static class SNESLuaLibrary public class SNESLuaLibrary : LuaLibraryBase
{ {
public static string Name = "snes"; public override string Name { get { return "snes"; } }
public static string[] Functions = new[] public override string[] Functions
{ {
"getlayer_bg_1", get
"getlayer_bg_2", {
"getlayer_bg_3", return new[]
"getlayer_bg_4", {
"getlayer_obj_1", "getlayer_bg_1",
"getlayer_obj_2", "getlayer_bg_2",
"getlayer_obj_3", "getlayer_bg_3",
"getlayer_obj_4", "getlayer_bg_4",
"setlayer_bg_1", "getlayer_obj_1",
"setlayer_bg_2", "getlayer_obj_2",
"setlayer_bg_3", "getlayer_obj_3",
"setlayer_bg_4", "getlayer_obj_4",
"setlayer_obj_1", "setlayer_bg_1",
"setlayer_obj_2", "setlayer_bg_2",
"setlayer_obj_3", "setlayer_bg_3",
"setlayer_obj_4", "setlayer_bg_4",
}; "setlayer_obj_1",
"setlayer_obj_2",
"setlayer_obj_3",
"setlayer_obj_4",
};
}
}
public static bool snes_getlayer_bg_1() public static bool snes_getlayer_bg_1()
{ {

View File

@ -231,50 +231,11 @@ namespace BizHawk.MultiClient
{ {
lua.RegisterFunction("print", this, GetType().GetMethod("print")); lua.RegisterFunction("print", this, GetType().GetMethod("print"));
lua.NewTable("bit"); new BitLuaLibrary().LuaRegister(lua, Docs);
foreach (var funcName in BitLuaLibrary.Functions) new MultiClientLuaLibrary(ConsoleLuaLibrary.console_log).LuaRegister(lua, Docs);
{ new ConsoleLuaLibrary().LuaRegister(lua, Docs);
string libName = BitLuaLibrary.Name + "." + funcName; new NESLuaLibrary().LuaRegister(lua, Docs);
var method = (typeof(BitLuaLibrary)).GetMethod(BitLuaLibrary.Name + "_" + funcName); new SNESLuaLibrary().LuaRegister(lua, Docs);
lua.RegisterFunction(libName, this, method);
Docs.Add(BitLuaLibrary.Name, funcName, method);
}
lua.NewTable("client");
foreach (var funcName in MultiClientLuaLibrary.Functions)
{
string libName = MultiClientLuaLibrary.Name + "." + funcName;
var method = (typeof(MultiClientLuaLibrary)).GetMethod(MultiClientLuaLibrary.Name + "_" + funcName);
lua.RegisterFunction(libName, this, method);
Docs.Add(MultiClientLuaLibrary.Name, funcName, method);
}
lua.NewTable("console");
foreach (var funcName in ConsoleLuaLibrary.Functions)
{
string libName = ConsoleLuaLibrary.Name + "." + funcName;
var method = (typeof(ConsoleLuaLibrary)).GetMethod(ConsoleLuaLibrary.Name + "_" + funcName);
lua.RegisterFunction(libName, this, method);
Docs.Add(ConsoleLuaLibrary.Name, funcName, method);
}
lua.NewTable("nes");
foreach (var funcName in NESLuaLibrary.Functions)
{
string libName = NESLuaLibrary.Name + "." + funcName;
var method = (typeof(NESLuaLibrary)).GetMethod(NESLuaLibrary.Name + "_" + funcName);
lua.RegisterFunction(libName, this, method);
Docs.Add(NESLuaLibrary.Name, funcName, method);
}
lua.NewTable("snes");
foreach (var funcName in SNESLuaLibrary.Functions)
{
string libName = SNESLuaLibrary.Name + "." + funcName;
var method = (typeof(SNESLuaLibrary)).GetMethod(SNESLuaLibrary.Name + "_" + funcName);
lua.RegisterFunction(libName, this, method);
Docs.Add(SNESLuaLibrary.Name, funcName, method);
}
lua.NewTable("gui"); lua.NewTable("gui");
foreach (string t in GuiFunctions) foreach (string t in GuiFunctions)

View File

@ -0,0 +1,43 @@
using System;
using LuaInterface;
namespace BizHawk.MultiClient
{
public abstract class LuaLibraryBase
{
public abstract string Name { get; }
public abstract string[] Functions { get; }
public virtual void LuaRegister(Lua lua, ILuaDocumentation docs = null)
{
lua.NewTable(Name);
foreach (string methodName in Functions)
{
string func = Name + "." + methodName;
var method = GetType().GetMethod(Name + "_" + methodName);
lua.RegisterFunction(
Name + "." + methodName,
this,
GetType().GetMethod(Name + "_" + methodName)
);
if (docs != null)
{
docs.Add(Name, methodName, method);
}
}
}
protected static int LuaInt(object lua_arg)
{
return Convert.ToInt32((double)lua_arg);
}
protected static uint LuaUInt(object lua_arg)
{
return Convert.ToUInt32((double)lua_arg);
}
}
}

View File

@ -1,11 +1,17 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public class LuaDocumentation public interface ILuaDocumentation
{
void Add(string method_lib, string method_name, System.Reflection.MethodInfo method);
}
public class LuaDocumentation : ILuaDocumentation
{ {
public List<LibraryFunction> FunctionList = new List<LibraryFunction>(); public List<LibraryFunction> FunctionList = new List<LibraryFunction>();
@ -22,7 +28,7 @@ namespace BizHawk.MultiClient
public void Sort() public void Sort()
{ {
FunctionList = FunctionList.OrderBy(x => x.library).ThenBy(x => x.name).ToList(); FunctionList = FunctionList.OrderBy(x => x.Library).ThenBy(x => x.Name).ToList();
} }
public List<string> GetLibraryList() public List<string> GetLibraryList()
@ -30,7 +36,7 @@ namespace BizHawk.MultiClient
HashSet<string> libs = new HashSet<string>(); HashSet<string> libs = new HashSet<string>();
foreach (LibraryFunction function in FunctionList) foreach (LibraryFunction function in FunctionList)
{ {
libs.Add(function.library); libs.Add(function.Library);
} }
return libs.ToList(); return libs.ToList();
@ -38,27 +44,27 @@ namespace BizHawk.MultiClient
public List<string> GetFunctionsByLibrary(string library) public List<string> GetFunctionsByLibrary(string library)
{ {
return (from t in FunctionList where t.library == library select t.name).ToList(); return (from t in FunctionList where t.Library == library select t.Name).ToList();
} }
public class LibraryFunction public class LibraryFunction
{ {
public LibraryFunction(string method_lib, string method_name, System.Reflection.MethodInfo method) public LibraryFunction(string method_lib, string method_name, System.Reflection.MethodInfo method)
{ {
library = method_lib; Library = method_lib;
name = method_name; Name = method_name;
System.Reflection.ParameterInfo[] info = method.GetParameters(); System.Reflection.ParameterInfo[] info = method.GetParameters();
foreach (System.Reflection.ParameterInfo p in info) foreach (System.Reflection.ParameterInfo p in info)
{ {
parameters.Add(p.ToString()); Parameters.Add(p.ToString());
} }
return_type = method.ReturnType.ToString(); return_type = method.ReturnType.ToString();
} }
public string library = ""; public string Library = String.Empty;
public string name = ""; public string Name = String.Empty;
public List<string> parameters = new List<string>(); public List<string> Parameters = new List<string>();
public string return_type = ""; public string return_type = String.Empty;
public string ParameterList public string ParameterList
{ {
@ -66,11 +72,11 @@ namespace BizHawk.MultiClient
{ {
StringBuilder list = new StringBuilder(); StringBuilder list = new StringBuilder();
list.Append('('); list.Append('(');
for (int i = 0; i < parameters.Count; i++) for (int i = 0; i < Parameters.Count; i++)
{ {
string param = parameters[i].Replace("System", "").Replace("Object", "").Replace(" ", "").Replace(".", "").Replace("LuaInterface", ""); string param = Parameters[i].Replace("System", "").Replace("Object", "").Replace(" ", "").Replace(".", "").Replace("LuaInterface", "");
list.Append(param); list.Append(param);
if (i < parameters.Count - 1) if (i < Parameters.Count - 1)
{ {
list.Append(','); list.Append(',');
} }

View File

@ -26,8 +26,8 @@ namespace BizHawk.MultiClient
foreach (LuaDocumentation.LibraryFunction l in GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList) foreach (LuaDocumentation.LibraryFunction l in GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList)
{ {
ListViewItem item = new ListViewItem {Text = l.ReturnType}; ListViewItem item = new ListViewItem {Text = l.ReturnType};
item.SubItems.Add(l.library + "."); item.SubItems.Add(l.Library + ".");
item.SubItems.Add(l.name); item.SubItems.Add(l.Name);
item.SubItems.Add(l.ParameterList); item.SubItems.Add(l.ParameterList);
FunctionView.Items.Add(item); FunctionView.Items.Add(item);
} }
@ -44,10 +44,10 @@ namespace BizHawk.MultiClient
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.ReturnType).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.ReturnType).ToList();
break; break;
case 1: //Library case 1: //Library
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.library).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.Library).ToList();
break; break;
case 2: //Name case 2: //Name
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.name).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.Name).ToList();
break; break;
case 3: //Parameters case 3: //Parameters
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.ParameterList).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderByDescending(x => x.ParameterList).ToList();
@ -62,10 +62,10 @@ namespace BizHawk.MultiClient
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.ReturnType).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.ReturnType).ToList();
break; break;
case 1: //Library case 1: //Library
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.library).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.Library).ToList();
break; break;
case 2: //Name case 2: //Name
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.name).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.Name).ToList();
break; break;
case 3: //Parameters case 3: //Parameters
GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.ParameterList).ToList(); GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList.OrderBy(x => x.ParameterList).ToList();
@ -133,7 +133,7 @@ namespace BizHawk.MultiClient
foreach (int index in indexes) foreach (int index in indexes)
{ {
var library_function = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList[index]; var library_function = GlobalWinF.MainForm.LuaConsole1.LuaImp.Docs.FunctionList[index];
sb.Append(library_function.library).Append('.').Append(library_function.name).Append("()\n"); sb.Append(library_function.Library).Append('.').Append(library_function.Name).Append("()\n");
} }
if (sb.Length > 0) if (sb.Length > 0)