Merge pull request #540 from Hathor86/CustomTool-Improvement

Custom tool improvement
This commit is contained in:
Hathor86 2015-11-22 20:49:10 +01:00
commit dee47067ad
11 changed files with 1001 additions and 884 deletions

2
.gitignore vendored
View File

@ -247,7 +247,7 @@
/References/*.xml
/output/ELFSharp.dll
/output/dll/ELFSharp.dll
/output/GameTools/*.dll
/output/ExternalTools/*.*
*.opensdf
*.user
*.suo

View File

@ -157,7 +157,7 @@ namespace BizHawk.Client.Common
new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "Macros", Path = Path.Combine(".", "Movies", "Macros"), Ordinal = 10 },
new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "TAStudio states", Path = Path.Combine(".", "Movies", "TAStudio states"), Ordinal = 11 },
new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "Multi-Disk Bundles", Path = Path.Combine(".", "Tools"), Ordinal = 12 },
new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "GameTools", Path = Path.Combine(".", "GameTools"), Ordinal = 13 },
new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "External Tools", Path = Path.Combine(".", "ExternalTools"), Ordinal = 13 },
new PathEntry { System = "INTV", SystemDisplayName="Intellivision", Type = "Base", Path = Path.Combine(".", "Intellivision"), Ordinal = 0 },
new PathEntry { System = "INTV", SystemDisplayName="Intellivision", Type = "ROM", Path = ".", Ordinal = 1 },

View File

@ -807,7 +807,7 @@
<Compile Include="tools\HexEditor\HexFind.Designer.cs">
<DependentUpon>HexFind.cs</DependentUpon>
</Compile>
<Compile Include="tools\ICustomGameTool.cs" />
<Compile Include="tools\IExternalToolForm.cs" />
<Compile Include="tools\IToolForm.cs" />
<Compile Include="tools\Lua\EnvironmentSandbox.cs" />
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Client.cs" />

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@ using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Reflection;
using System.Linq;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
@ -51,7 +53,7 @@ namespace BizHawk.Client.EmuHawk
var font = new System.Drawing.Font(SaveRAMSubMenu.Font, needBold ? FontStyle.Bold : FontStyle.Regular);
SaveRAMSubMenu.Font.Dispose();
SaveRAMSubMenu.Font = font;
}
}
}
private void RecentRomMenuItem_DropDownOpened(object sender, EventArgs e)
@ -350,7 +352,7 @@ namespace BizHawk.Client.EmuHawk
_lastOpenRomFilter = ofd.FilterIndex;
//-----------------
LoadRom(file.FullName, args);
}
@ -1248,10 +1250,73 @@ namespace BizHawk.Client.EmuHawk
AutoHawkMenuItem.Visible = VersionInfo.DeveloperBuild;
BasicBotMenuItem.Enabled = GlobalWin.Tools.IsAvailable<BasicBot>();
string toolPath = Path.Combine(Global.Config.PathEntries["Global", "GameTools"].Path, string.Format("{0}.dll", Global.Game.Name));
customToolToolStripMenuItem.Enabled = File.Exists(toolPath);
gameSharkConverterToolStripMenuItem.Enabled = GlobalWin.Tools.IsAvailable<GameShark>();
gameSharkConverterToolStripMenuItem.Enabled = GlobalWin.Tools.IsAvailable<GameShark>();
}
private void ExternalToolToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
{
externalToolToolStripMenuItem.DropDownItems.Clear();
string path = Path.Combine(Global.Config.PathEntries["Global", "External Tools"].Path);
if (Directory.Exists(path))
{
DirectoryInfo dInfo = new DirectoryInfo(path);
Type[] assemblyTypes;
Assembly externalToolFile;
foreach (FileInfo fi in dInfo.GetFiles("*.dll"))
{
try
{
externalToolFile = Assembly.ReflectionOnlyLoadFrom(fi.FullName);
}
catch (BadImageFormatException)
{
ToolStripMenuItem item = new ToolStripMenuItem(fi.Name, Properties.Resources.ExclamationRed);
item.ToolTipText = "This is not an assembly";
item.ForeColor = Color.Gray;
externalToolToolStripMenuItem.DropDownItems.Add(item);
continue;
}
ToolStripMenuItem externalToolMenu = new ToolStripMenuItem(externalToolFile.GetName().Name);
/*
The reason of using this ugly try catch is due to the use of ReflectionOnlyLoadFrom methods
When the assembly is loaded this way, referenced assemblies are not loaded and so, as soon as a type
existing in another assembly, it raises the exception.
But the advantage of this is that memory footprint is reduced
*/
try
{
assemblyTypes = externalToolFile.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
assemblyTypes = ex.Types.Where<Type>(t => t != null && t.FullName.Contains("BizHawk.Client.EmuHawk.CustomMainForm")).ToArray<Type>();
}
if (assemblyTypes.Count() == 1)
{
externalToolMenu.Image = Properties.Resources.Debugger;
externalToolMenu.Tag = fi.FullName;
externalToolMenu.Click += delegate (object sender2, EventArgs e2)
{
GlobalWin.Tools.Load<IExternalToolForm>(fi.FullName);
};
}
else
{
externalToolMenu.Image = Properties.Resources.ExclamationRed;
externalToolMenu.ForeColor = Color.Gray;
}
externalToolToolStripMenuItem.DropDownItems.Add(externalToolMenu);
}
}
if (externalToolToolStripMenuItem.DropDownItems.Count == 0)
{
externalToolToolStripMenuItem.DropDownItems.Add("None");
}
}
private void AutoHawkMenuItem_Click(object sender, EventArgs e)
@ -1319,11 +1384,6 @@ namespace BizHawk.Client.EmuHawk
OpenLuaConsole();
}
private void CustomToolMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.Tools.Load<ICustomGameTool>();
}
private void batchRunnerToolStripMenuItem_Click(object sender, EventArgs e)
{
new BatchRun().ShowDialog();
@ -2748,7 +2808,7 @@ namespace BizHawk.Client.EmuHawk
{
var args = new LoadRomArgs();
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePaths[0] };
LoadRom(filePaths[0],args);
LoadRom(filePaths[0], args);
}
}

View File

@ -3999,4 +3999,4 @@ namespace BizHawk.Client.EmuHawk
}
}
}
}

View File

@ -121,39 +121,6 @@
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="gameSharkConverterToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
+/f/AtNpu+2UY3h4AAAAAElFTkSuQmCC
</value>
</data>
<data name="DisplayConfigMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@ -174,6 +141,39 @@
SgAAEEoBNcinnwAAAHBJREFUOE/NkOEKACEIg330e/NOA2PqTqL+XPBpbcMokUfGFUy0xTrFitogNHgG
qUJDzs58ERpydua1/OwJiv967hQr4QkfaHJSPDzYICR4OwOOsOK3+c2Oh/I5QMUEDijD1gbMEiKZpaF5
BBW3kfECg6SiSi9TP3UAAAAASUVORK5CYII=
</value>
</data>
<data name="gameSharkConverterToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<data name="N64PluginSettingsMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Interface to implements in order to make a custom tool for a specific game
/// </summary>
public interface ICustomGameTool:IToolForm
{
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Interface to implements in order to make a custom tool
/// </summary>
public interface IExternalToolForm : IToolForm
{
/// <summary>
/// <see cref="FormClosedEventHandler"/>
/// </summary>
event FormClosedEventHandler FormClosed;
}
}

View File

@ -53,6 +53,8 @@ namespace BizHawk.Client.EmuHawk
private void SetTools()
{
ToolBoxStrip.Items.Clear();
var availableTools = Assembly
.GetAssembly(typeof(IToolForm))
.GetTypes()
@ -73,8 +75,8 @@ namespace BizHawk.Client.EmuHawk
ShowIcon = (instance as Form).ShowIcon
})
.ToList();
foreach (var tool in availableTools)
foreach (var tool in availableTools)
{
var t = new ToolStripButton
{

View File

@ -16,10 +16,7 @@ namespace BizHawk.Client.EmuHawk
{
public class ToolManager
{
public ToolManager(Form owner)
{
_owner = owner;
}
#region Fields
private readonly Form _owner;
@ -28,31 +25,70 @@ namespace BizHawk.Client.EmuHawk
// Also a UsesRam, and similar method
private readonly List<IToolForm> _tools = new List<IToolForm>();
/// <summary>
/// Loads the tool dialog T, if it does not exist it will be created, if it is already open, it will be focused
/// </summary>
public T Load<T>(bool focus = true) where T : IToolForm
{
return (T)Load(typeof(T), focus);
}
#endregion
#region cTor(s)
/// <summary>
/// Loads a tool dialog of type toolType if it does not exist it will be
/// created, if it is already open, it will be focused.
/// Initialize an new ToolManager instance
/// </summary>
public IToolForm Load(Type toolType, bool focus = true)
/// <param name="owner">Form that handle the ToolManager</param>
public ToolManager(Form owner)
{
_owner = owner;
}
#endregion
/// <summary>
/// Loads the tool dialog T (T must implemants <see cref="IToolForm"/>) , if it does not exist it will be created, if it is already open, it will be focused
/// This method should be used only if you can't use the generic one
/// </summary>
/// <param name="toolType">Type of tool you want to load</param>
/// <param name="focus">Define if the tool form has to get the focus or not (Default is true)</param>
/// <returns>An instanciated <see cref="IToolForm"/></returns>
/// <exception cref="ArgumentException">Raised if <paramref name="toolType"/> can't be casted into IToolForm </exception>
internal IToolForm Load(Type toolType, bool focus = true)
{
if (!typeof(IToolForm).IsAssignableFrom(toolType))
{
throw new ArgumentException(string.Format("Type {0} does not implement IToolForm.", toolType.Name));
}
else
{
MethodInfo method = GetType().GetMethod("Load").MakeGenericMethod(toolType);
return (IToolForm)method.Invoke(this, new object[] { focus });
}
}
if (!IsAvailable(toolType))
/// <summary>
/// Loads the tool dialog T (T must implemants <see cref="IToolForm"/>) , if it does not exist it will be created, if it is already open, it will be focused
/// </summary>
/// <typeparam name="T">Type of tool you want to load</typeparam>
/// <param name="focus">Define if the tool form has to get the focus or not (Default is true)</param>
/// <returns>An instanciated <see cref="IToolForm"/></returns>
public T Load<T>(bool focus = true)
where T : class, IToolForm
{
return Load<T>(string.Empty, focus);
}
/// <summary>
/// Loads the tool dialog T (T must implemants <see cref="IToolForm"/>) , if it does not exist it will be created, if it is already open, it will be focused
/// </summary>
/// <typeparam name="T">Type of tool you want to load</typeparam>
/// <param name="focus">Define if the tool form has to get the focus or not (Default is true)</param>
/// <param name="toolPath">Path to the dll of the external tool</param>
/// <returns>An instanciated <see cref="IToolForm"/></returns>
public T Load<T>(string toolPath, bool focus = true)
where T : class, IToolForm
{
if (!IsAvailable<T>())
{
return null;
}
var existingTool = _tools.FirstOrDefault(x => toolType.IsAssignableFrom(x.GetType()));
T existingTool = (T)_tools.FirstOrDefault(x => x is T);
if (existingTool != null)
{
@ -72,28 +108,29 @@ namespace BizHawk.Client.EmuHawk
}
}
var newTool = CreateInstance(toolType);
IToolForm newTool = CreateInstance<T>(toolPath);
if (newTool == null)
{
return null;
}
if (newTool == null)
{
return null;
}
if (newTool is Form)
if (newTool is Form)
{
(newTool as Form).Owner = GlobalWin.MainForm;
}
ServiceInjector.UpdateServices(Global.Emulator.ServiceProvider, newTool);
string toolType = typeof(T).ToString();
// auto settings
if (newTool is IToolFormAutoConfig)
{
ToolDialogSettings settings;
if (!Global.Config.CommonToolSettings.TryGetValue(toolType.ToString(), out settings))
if (!Global.Config.CommonToolSettings.TryGetValue(toolType, out settings))
{
settings = new ToolDialogSettings();
Global.Config.CommonToolSettings[toolType.ToString()] = settings;
Global.Config.CommonToolSettings[toolType] = settings;
}
AttachSettingHooks(newTool as IToolFormAutoConfig, settings);
}
@ -102,17 +139,17 @@ namespace BizHawk.Client.EmuHawk
if (HasCustomConfig(newTool))
{
Dictionary<string, object> settings;
if (!Global.Config.CustomToolSettings.TryGetValue(toolType.ToString(), out settings))
if (!Global.Config.CustomToolSettings.TryGetValue(toolType, out settings))
{
settings = new Dictionary<string, object>();
Global.Config.CustomToolSettings[toolType.ToString()] = settings;
Global.Config.CustomToolSettings[toolType] = settings;
}
InstallCustomConfig(newTool, settings);
}
newTool.Restart();
newTool.Show();
return newTool;
return (T)newTool;
}
public void AutoLoad()
@ -301,7 +338,7 @@ namespace BizHawk.Client.EmuHawk
}
}
/// <summary>
/// Determines whether a given IToolForm is already loaded
/// </summary>
@ -327,7 +364,7 @@ namespace BizHawk.Client.EmuHawk
/// <summary>
/// Gets the instance of T, or creates and returns a new instance
/// </summary>
public IToolForm Get<T>() where T : IToolForm
public IToolForm Get<T>() where T : class, IToolForm
{
return Load<T>(false);
}
@ -501,61 +538,71 @@ namespace BizHawk.Client.EmuHawk
_tools.Clear();
}
private IToolForm CreateInstance<T>()
where T: IToolForm
/// <summary>
/// Create a new instance of an IToolForm and return it
/// </summary>
/// <typeparam name="T">Type of tool you want to create</typeparam>
/// <param name="dllPath">Path dll for an external tool</param>
/// <returns>New instance of an IToolForm</returns>
private IToolForm CreateInstance<T>(string dllPath)
where T : IToolForm
{
return CreateInstance(typeof(T));
return CreateInstance(typeof(T), dllPath);
}
private IToolForm CreateInstance(Type toolType)
{
IToolForm tool;
/// <summary>
/// Create a new instance of an IToolForm and return it
/// </summary>
/// <param name="toolType">Type of tool you want to create</param>
/// <param name="dllPath">Path dll for an external tool</param>
/// <returns>New instance of an IToolForm</returns>
private IToolForm CreateInstance(Type toolType, string dllPath)
{
IToolForm tool;
//Specific case for custom tools
if (toolType == typeof(ICustomGameTool))
{
string path = Path.Combine(Global.Config.PathEntries["Global", "GameTools"].Path, string.Format("{0}.dll", Global.Game.Name));
if (File.Exists(path)
&& MessageBox.Show("A custom plugin has been found for the ROM you're loading. Do you want to load it?\r\nAccept ONLY if you trust the source and if you know what you're doing. In any other case, choose no."
, "Answer to life, universe and everything else?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
// As the object is "remote"(external to the project), the CreateInstanceFrom returns a handle.We need to Unwrap in order to make the casting
tool = System.Activator.CreateInstanceFrom(path, "BizHawk.Client.EmuHawk.CustomMainForm").Unwrap() as IToolForm;
if (tool == null)
{
MessageBox.Show("It seems that the object CustomMainForm does not implement IToolForm. Please review the code.", "Boom!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
}
catch (MissingMethodException)
{
MessageBox.Show("It seems that the object CustomMainForm does not have a public default constructor. Please review the code.", "Boom!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
catch (TypeLoadException)
{
MessageBox.Show("It seems that the object CustomMainForm does not exists. Please review the code.", "Boom!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
}
else
{
return null;
}
}
else
{
tool = (IToolForm)Activator.CreateInstance(toolType);
}
//Specific case for custom tools
//TODO: Use AppDomain in order to be able to unload the assembly
if (toolType == typeof(IExternalToolForm))
{
if (MessageBox.Show(@"Are you sure want to load this external tool?\r\nAccept ONLY if you trust the source and if you know what you're doing. In any other case, choose no."
, "Confirmm loading", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
tool = Activator.CreateInstanceFrom(dllPath, "BizHawk.Client.EmuHawk.CustomMainForm").Unwrap() as IExternalToolForm;
if (tool == null)
{
MessageBox.Show("It seems that the object CustomMainForm does not implement IExternalToolForm. Please review the code.", "No, no, no. Wrong Way !", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
}
catch (MissingMethodException)
{
MessageBox.Show("It seems that the object CustomMainForm does not have a public default constructor. Please review the code.", "No, no, no. Wrong Way !", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
catch (TypeLoadException ex)
{
MessageBox.Show("It seems that the object CustomMainForm does not exists. Please review the code.", "No, no, no. Wrong Way !", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
}
else
{
return null;
}
}
else
{
tool = (IToolForm)Activator.CreateInstance(toolType);
}
// Add to our list of tools
_tools.Add(tool);
return tool;
}
// Add to our list of tools
_tools.Add(tool);
return tool;
}
public void UpdateToolsBefore(bool fromLua = false)
public void UpdateToolsBefore(bool fromLua = false)
{
if (Has<LuaConsole>())
{
@ -694,7 +741,7 @@ namespace BizHawk.Client.EmuHawk
return tool as RamWatch;
}
}
var newTool = new RamWatch();
_tools.Add(newTool);
return newTool;
@ -889,7 +936,7 @@ namespace BizHawk.Client.EmuHawk
public static string GenerateDefaultCheatFilename()
{
var pathEntry = Global.Config.PathEntries[Global.Game.System, "Cheats"]
?? Global.Config.PathEntries[Global.Game.System, "Base"];
?? Global.Config.PathEntries[Global.Game.System, "Base"];
var path = PathManager.MakeAbsolutePath(pathEntry.Path, Global.Game.System);