Reduce LINQ usage in Lua subsystem

This commit is contained in:
YoshiRulz 2019-12-16 04:08:10 +10:00
parent 91ef301a23
commit 05801dc2c5
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
7 changed files with 64 additions and 149 deletions

View File

@ -1,6 +1,5 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Linq;
using NLua; using NLua;

View File

@ -1,6 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using NLua; using NLua;
@ -8,6 +7,8 @@ namespace BizHawk.Client.Common
{ {
public static class LuaExtensions public static class LuaExtensions
{ {
public static LuaTable EnumerateToLuaTable<T>(this IEnumerable<T> list, Lua lua) => list.ToList().ToLuaTable(lua);
public static LuaTable ToLuaTable<T>(this IList<T> list, Lua lua, int indexFrom = 0) public static LuaTable ToLuaTable<T>(this IList<T> list, Lua lua, int indexFrom = 0)
{ {
var table = lua.NewTable(); var table = lua.NewTable();
@ -34,26 +35,16 @@ namespace BizHawk.Client.Common
public static LuaTable TableFromObject(this Lua lua, object obj) public static LuaTable TableFromObject(this Lua lua, object obj)
{ {
var table = lua.NewTable(); var table = lua.NewTable();
foreach (var method in obj.GetType().GetMethods())
var type = obj.GetType();
var methods = type.GetMethods();
foreach (var method in methods)
{ {
if (method.IsPublic) if (!method.IsPublic) continue;
{ var foundAttrs = method.GetCustomAttributes(typeof(LuaMethodAttribute), false);
string luaName = ""; // Empty will default to the actual method name; table[method.Name] = lua.RegisterFunction(
foundAttrs.Length == 0 ? string.Empty : ((LuaMethodAttribute) foundAttrs[0]).Name, // empty string will default to the actual method name
var luaMethodAttr = (LuaMethodAttribute)method.GetCustomAttributes(typeof(LuaMethodAttribute)).FirstOrDefault(); obj,
if (luaMethodAttr != null) method
{ );
luaName = luaMethodAttr.Name;
}
table[method.Name] = lua.RegisterFunction(luaName, obj, method);
}
} }
return table; return table;
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq;
using System.Threading; using System.Threading;
using NLua; using NLua;
@ -86,19 +85,11 @@ namespace BizHawk.Client.Common
public void LuaRegister(Type callingLibrary, LuaDocumentation docs = null) public void LuaRegister(Type callingLibrary, LuaDocumentation docs = null)
{ {
Lua.NewTable(Name); Lua.NewTable(Name);
foreach (var method in GetType().GetMethods())
var luaAttr = typeof(LuaMethodAttribute);
var methods = GetType()
.GetMethods()
.Where(m => m.GetCustomAttributes(luaAttr, false).Any());
foreach (var method in methods)
{ {
var luaMethodAttr = (LuaMethodAttribute)method.GetCustomAttributes(luaAttr, false).First(); var foundAttrs = method.GetCustomAttributes(typeof(LuaMethodAttribute), false);
var luaName = $"{Name}.{luaMethodAttr.Name}"; if (foundAttrs.Length == 0) continue;
Lua.RegisterFunction(luaName, this, method); Lua.RegisterFunction($"{Name}.{((LuaMethodAttribute) foundAttrs[0]).Name}", this, method);
docs?.Add(new LibraryFunction(Name, callingLibrary.Description(), method)); docs?.Add(new LibraryFunction(Name, callingLibrary.Description(), method));
} }
} }

View File

@ -417,16 +417,7 @@ namespace BizHawk.Client.EmuHawk
[LuaMethodExample("local nlcliget = client.getavailabletools( );")] [LuaMethodExample("local nlcliget = client.getavailabletools( );")]
[LuaMethod("getavailabletools", "Returns a list of the tools currently open")] [LuaMethod("getavailabletools", "Returns a list of the tools currently open")]
public LuaTable GetAvailableTools() public LuaTable GetAvailableTools() => GlobalWin.Tools.AvailableTools.Select(tool => tool.Name.ToLower()).EnumerateToLuaTable(Lua);
{
var xx = GlobalWin.Tools.AvailableTools.ToList();
var x = GlobalWin.Tools.AvailableTools
.Select(t => t.Name.ToLower())
.ToList()
.ToLuaTable(Lua);
return x;
}
[LuaMethodExample("local nlcliget = client.gettool( \"Tool name\" );")] [LuaMethodExample("local nlcliget = client.gettool( \"Tool name\" );")]
[LuaMethod("gettool", "Returns an object that represents a tool of the given name (not case sensitive). If the tool is not open, it will be loaded if available. Use gettools to get a list of names")] [LuaMethod("gettool", "Returns an object that represents a tool of the given name (not case sensitive). If the tool is not open, it will be loaded if available. Use gettools to get a list of names")]

View File

@ -71,6 +71,26 @@ namespace BizHawk.Client.EmuHawk
// Outputs the given object to the output box on the Lua Console dialog. Note: Can accept a LuaTable // Outputs the given object to the output box on the Lua Console dialog. Note: Can accept a LuaTable
private static void LogWithSeparator(string separator, string terminator, params object[] outputs) private static void LogWithSeparator(string separator, string terminator, params object[] outputs)
{ {
static string SerialiseTable(LuaTable lti)
{
var keyObjs = lti.Keys;
var valueObjs = lti.Values;
if (keyObjs.Count != valueObjs.Count) throw new IndexOutOfRangeException("each value must be paired with one key, they differ in number");
var values = new List<object>(keyObjs.Count);
var kvpIndex = 0;
foreach (var valueObj in valueObjs) values[kvpIndex++] = valueObj;
return string.Concat(keyObjs.Cast<object>()
.Select((kObj, i) => $"\"{kObj}\": \"{values[i]}\"\n")
.OrderBy(s => s)
);
}
static void SerialiseAndWrite(object output) => GlobalWin.Tools.LuaConsole.WriteToOutputWindow(
output is LuaTable table
? SerialiseTable(table)
: output?.ToString() ?? "nil"
);
if (!GlobalWin.Tools.Has<LuaConsole>()) if (!GlobalWin.Tools.Has<LuaConsole>())
{ {
return; return;
@ -82,55 +102,11 @@ namespace BizHawk.Client.EmuHawk
return; return;
} }
for (var outIndex = 0; outIndex < outputs.Length; outIndex++) SerialiseAndWrite(outputs[0]);
for (int outIndex = 1, indexAfterLast = outputs.Length; outIndex != indexAfterLast; outIndex++)
{ {
var output = outputs[outIndex]; GlobalWin.Tools.LuaConsole.WriteToOutputWindow(separator);
SerialiseAndWrite(outputs[outIndex]);
if (outIndex != 0)
{
GlobalWin.Tools.LuaConsole.WriteToOutputWindow(separator);
}
if (output == null)
{
GlobalWin.Tools.LuaConsole.WriteToOutputWindow("nil");
}
else
{
if (output is LuaTable lti)
{
var sb = new StringBuilder();
var keys = (from object key in lti.Keys select key.ToString()).ToList();
var values = (from object value in lti.Values select value.ToString()).ToList();
var kvps = new List<KeyValuePair<string, string>>();
for (var i = 0; i < keys.Count; i++)
{
if (i < values.Count)
{
kvps.Add(new KeyValuePair<string, string>(keys[i], values[i]));
}
}
foreach (var kvp in kvps.OrderBy(x => x.Key))
{
sb
.Append("\"")
.Append(kvp.Key)
.Append("\": \"")
.Append(kvp.Value)
.Append("\"")
.AppendLine();
}
GlobalWin.Tools.LuaConsole.WriteToOutputWindow(sb.ToString());
}
else
{
GlobalWin.Tools.LuaConsole.WriteToOutputWindow(output.ToString());
}
}
} }
if (!string.IsNullOrEmpty(terminator)) if (!string.IsNullOrEmpty(terminator))

View File

@ -160,22 +160,7 @@ namespace BizHawk.Client.EmuHawk
[LuaMethodExample("local nltasget = tastudio.getselection( );")] [LuaMethodExample("local nltasget = tastudio.getselection( );")]
[LuaMethod("getselection", "gets the currently selected frames")] [LuaMethod("getselection", "gets the currently selected frames")]
public LuaTable GetSelection() public LuaTable GetSelection() => Engaged() ? Tastudio.GetSelection().EnumerateToLuaTable(Lua) : Lua.NewTable();
{
LuaTable table = Lua.NewTable();
if (Engaged())
{
var selection = Tastudio.GetSelection().ToList();
for (int i = 0; i < selection.Count; i++)
{
table[i] = selection[i];
}
}
return table;
}
[LuaMethodExample("")] [LuaMethodExample("")]
[LuaMethod("submitinputchange", "")] [LuaMethod("submitinputchange", "")]
@ -377,8 +362,7 @@ namespace BizHawk.Client.EmuHawk
b.Frame, b.Frame,
Text = b.UserText Text = b.UserText
}) })
.ToList() .EnumerateToLuaTable(Lua);
.ToLuaTable(Lua);
} }
return Lua.NewTable(); return Lua.NewTable();
@ -392,29 +376,24 @@ namespace BizHawk.Client.EmuHawk
if (Engaged()) if (Engaged())
{ {
if (Tastudio.CurrentTasMovie.Branches.Any(b => b.UniqueIdentifier.ToString() == branchId)) var branch = Tastudio.CurrentTasMovie.Branches.FirstOrDefault(b => b.UniqueIdentifier.ToString() == branchId);
if (branch != null && frame < branch.InputLog.Count)
{ {
var branch = Tastudio.CurrentTasMovie.Branches.First(b => b.UniqueIdentifier.ToString() == branchId); var adapter = new Bk2ControllerAdapter
if (frame < branch.InputLog.Count)
{ {
var input = branch.InputLog[frame]; Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
var adapter = new Bk2ControllerAdapter adapter.SetControllersAsMnemonic(branch.InputLog[frame]);
{
Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
adapter.SetControllersAsMnemonic(input); foreach (var button in adapter.Definition.BoolButtons)
{
table[button] = adapter.IsPressed(button);
}
foreach (var button in adapter.Definition.BoolButtons) foreach (var button in adapter.Definition.FloatControls)
{ {
table[button] = adapter.IsPressed(button); table[button] = adapter.GetFloat(button);
}
foreach (var button in adapter.Definition.FloatControls)
{
table[button] = adapter.GetFloat(button);
}
} }
} }
} }

View File

@ -45,20 +45,9 @@ namespace BizHawk.Client.EmuHawk
Docs.Clear(); Docs.Clear();
// Register lua libraries // Register lua libraries
var libs = Assembly foreach (var lib in Assembly.Load("BizHawk.Client.Common").GetTypes()
.Load("BizHawk.Client.Common") .Concat(Assembly.GetAssembly(typeof(EmuLuaLibrary)).GetTypes())
.GetTypes() .Where(t => typeof(LuaLibraryBase).IsAssignableFrom(t) && t.IsSealed && ServiceInjector.IsAvailable(serviceProvider, t)))
.Where(t => typeof(LuaLibraryBase).IsAssignableFrom(t))
.Where(t => t.IsSealed)
.Where(t => ServiceInjector.IsAvailable(serviceProvider, t))
.Concat(Assembly
.GetAssembly(typeof(EmuLuaLibrary))
.GetTypes()
.Where(t => typeof(LuaLibraryBase).IsAssignableFrom(t))
.Where(t => t.IsSealed)
.Where(t => ServiceInjector.IsAvailable(serviceProvider, t)));
foreach (var lib in libs)
{ {
bool addLibrary = true; bool addLibrary = true;
var attributes = lib.GetCustomAttributes(typeof(LuaLibraryAttribute), false); var attributes = lib.GetCustomAttributes(typeof(LuaLibraryAttribute), false);
@ -90,13 +79,12 @@ namespace BizHawk.Client.EmuHawk
// Add LuaCanvas to Docs // Add LuaCanvas to Docs
Type luaCanvas = typeof(LuaCanvas); Type luaCanvas = typeof(LuaCanvas);
var methods = luaCanvas foreach (var method in luaCanvas.GetMethods())
.GetMethods()
.Where(m => m.GetCustomAttributes(typeof(LuaMethodAttribute), false).Any());
foreach (var method in methods)
{ {
Docs.Add(new LibraryFunction(nameof(LuaCanvas), luaCanvas.Description(), method)); if (method.GetCustomAttributes(typeof(LuaMethodAttribute), false).Length != 0)
{
Docs.Add(new LibraryFunction(nameof(LuaCanvas), luaCanvas.Description(), method));
}
} }
} }
@ -122,7 +110,7 @@ namespace BizHawk.Client.EmuHawk
public override void StartLuaDrawing() public override void StartLuaDrawing()
{ {
if (ScriptList.Any() && GuiLibrary.SurfaceIsNull) if (ScriptList.Count != 0 && GuiLibrary.SurfaceIsNull)
{ {
GuiLibrary.DrawNew("emu"); GuiLibrary.DrawNew("emu");
} }
@ -130,7 +118,7 @@ namespace BizHawk.Client.EmuHawk
public override void EndLuaDrawing() public override void EndLuaDrawing()
{ {
if (ScriptList.Any()) if (ScriptList.Count != 0)
{ {
GuiLibrary.DrawFinish(); GuiLibrary.DrawFinish();
} }