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.ComponentModel;
using System.Linq;
using NLua;

View File

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

View File

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

View File

@ -417,16 +417,7 @@ namespace BizHawk.Client.EmuHawk
[LuaMethodExample("local nlcliget = client.getavailabletools( );")]
[LuaMethod("getavailabletools", "Returns a list of the tools currently open")]
public LuaTable GetAvailableTools()
{
var xx = GlobalWin.Tools.AvailableTools.ToList();
var x = GlobalWin.Tools.AvailableTools
.Select(t => t.Name.ToLower())
.ToList()
.ToLuaTable(Lua);
return x;
}
public LuaTable GetAvailableTools() => GlobalWin.Tools.AvailableTools.Select(tool => tool.Name.ToLower()).EnumerateToLuaTable(Lua);
[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")]

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
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>())
{
return;
@ -82,55 +102,11 @@ namespace BizHawk.Client.EmuHawk
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];
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());
}
}
GlobalWin.Tools.LuaConsole.WriteToOutputWindow(separator);
SerialiseAndWrite(outputs[outIndex]);
}
if (!string.IsNullOrEmpty(terminator))

View File

@ -160,22 +160,7 @@ namespace BizHawk.Client.EmuHawk
[LuaMethodExample("local nltasget = tastudio.getselection( );")]
[LuaMethod("getselection", "gets the currently selected frames")]
public LuaTable GetSelection()
{
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;
}
public LuaTable GetSelection() => Engaged() ? Tastudio.GetSelection().EnumerateToLuaTable(Lua) : Lua.NewTable();
[LuaMethodExample("")]
[LuaMethod("submitinputchange", "")]
@ -377,8 +362,7 @@ namespace BizHawk.Client.EmuHawk
b.Frame,
Text = b.UserText
})
.ToList()
.ToLuaTable(Lua);
.EnumerateToLuaTable(Lua);
}
return Lua.NewTable();
@ -392,29 +376,24 @@ namespace BizHawk.Client.EmuHawk
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);
if (frame < branch.InputLog.Count)
var adapter = new Bk2ControllerAdapter
{
var input = branch.InputLog[frame];
Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
var adapter = new Bk2ControllerAdapter
{
Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
adapter.SetControllersAsMnemonic(branch.InputLog[frame]);
adapter.SetControllersAsMnemonic(input);
foreach (var button in adapter.Definition.BoolButtons)
{
table[button] = adapter.IsPressed(button);
}
foreach (var button in adapter.Definition.BoolButtons)
{
table[button] = adapter.IsPressed(button);
}
foreach (var button in adapter.Definition.FloatControls)
{
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();
// Register lua libraries
var libs = Assembly
.Load("BizHawk.Client.Common")
.GetTypes()
.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)
foreach (var lib in Assembly.Load("BizHawk.Client.Common").GetTypes()
.Concat(Assembly.GetAssembly(typeof(EmuLuaLibrary)).GetTypes())
.Where(t => typeof(LuaLibraryBase).IsAssignableFrom(t) && t.IsSealed && ServiceInjector.IsAvailable(serviceProvider, t)))
{
bool addLibrary = true;
var attributes = lib.GetCustomAttributes(typeof(LuaLibraryAttribute), false);
@ -90,13 +79,12 @@ namespace BizHawk.Client.EmuHawk
// Add LuaCanvas to Docs
Type luaCanvas = typeof(LuaCanvas);
var methods = luaCanvas
.GetMethods()
.Where(m => m.GetCustomAttributes(typeof(LuaMethodAttribute), false).Any());
foreach (var method in methods)
foreach (var method in luaCanvas.GetMethods())
{
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()
{
if (ScriptList.Any() && GuiLibrary.SurfaceIsNull)
if (ScriptList.Count != 0 && GuiLibrary.SurfaceIsNull)
{
GuiLibrary.DrawNew("emu");
}
@ -130,7 +118,7 @@ namespace BizHawk.Client.EmuHawk
public override void EndLuaDrawing()
{
if (ScriptList.Any())
if (ScriptList.Count != 0)
{
GuiLibrary.DrawFinish();
}