Refactor external tool attributes

This commit is contained in:
YoshiRulz 2020-02-01 01:53:12 +10:00
parent 3143c38b7d
commit 593e1ef97d
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
16 changed files with 242 additions and 316 deletions

View File

@ -1,67 +1,26 @@
using System;
using BizHawk.Client.Common;
namespace BizHawk.Client.ApiHawk
{
/// <summary>
/// This class holds logic interaction for the ExternalToolAttribute
/// This attribute helps BizHawk to handle ExternalTools
/// </summary>
/// <remarks>This class needs to be in the assembly or old tools will throw on load instead of being recognised as old.</remarks>
[AttributeUsage(AttributeTargets.Assembly)]
[Obsolete("last used in 2.4, use [ExternalTool] instead")]
public sealed class BizHawkExternalToolAttribute : Attribute
{
#region cTor(s)
public BizHawkExternalToolAttribute(string name, string description, string iconResourceName) {}
public BizHawkExternalToolAttribute(string name, string description) {}
public BizHawkExternalToolAttribute(string name) {}
}
/// <summary>
/// Initialize a new instance of <see cref="BizHawkExternalToolAttribute"/>
/// </summary>
/// <param name="name">Tool's name</param>
/// <param name="description">Small description about the tool itself</param>
/// <param name="iconResourceName">Icon embedded resource name</param>
public BizHawkExternalToolAttribute(string name, string description, string iconResourceName)
{
Name = name;
Description = description;
IconResourceName = iconResourceName;
}
/// <summary>
/// Initialize a new instance of <see cref="BizHawkExternalToolAttribute"/>
/// </summary>
/// <param name="name">Tool's name</param>
/// <param name="description">Small description about the tool itself</param>
public BizHawkExternalToolAttribute(string name, string description)
: this(name, description, "")
{ }
/// <summary>
/// Initialize a new instance of <see cref="BizHawkExternalToolAttribute"/>
/// </summary>
/// <param name="name">Tool's name</param>
public BizHawkExternalToolAttribute(string name)
:this(name, "", "")
{}
#endregion
#region Properties
/// <summary>
/// Gets tool's friendly name
/// </summary>
public string Name { get; }
/// <summary>
/// Gets tool's description
/// </summary>
public string Description { get; }
/// <summary>
/// Get the name of the embedded resource icon
/// </summary>
/// <remarks>Don't forget to set compile => Embedded resource to the icon file in your project</remarks>
public string IconResourceName { get; }
#endregion
/// <inheritdoc cref="BizHawkExternalToolAttribute"/>
[AttributeUsage(AttributeTargets.Assembly)]
[Obsolete("last used in 2.4, use [ExternalToolApplicability.*] instead")]
public sealed class BizHawkExternalToolUsageAttribute : Attribute
{
public BizHawkExternalToolUsageAttribute(BizHawkExternalToolUsage usage, CoreSystem system, string gameHash) {}
public BizHawkExternalToolUsageAttribute(BizHawkExternalToolUsage usage, CoreSystem system) {}
public BizHawkExternalToolUsageAttribute() {}
}
}

View File

@ -1,75 +0,0 @@
using System;
using BizHawk.Client.Common;
namespace BizHawk.Client.ApiHawk
{
/// <summary>
/// This class holds logic interaction for the BizHawkExternalToolUsageAttribute
/// This attribute helps ApiHawk to know how a tool can be enabled or not
/// </summary>
[AttributeUsage(AttributeTargets.Assembly)]
public sealed class BizHawkExternalToolUsageAttribute : Attribute
{
#region cTor(s)
/// <exception cref="InvalidOperationException">
/// <paramref name="usage"/> is <see cref="BizHawkExternalToolUsage.EmulatorSpecific"/> and <paramref name="system"/> is <see cref="CoreSystem.Null"/>, or
/// usage is <see cref="BizHawkExternalToolUsage.GameSpecific"/> and <paramref name="gameHash"/> is blank
/// </exception>
public BizHawkExternalToolUsageAttribute(BizHawkExternalToolUsage usage, CoreSystem system, string gameHash)
{
if (usage == BizHawkExternalToolUsage.EmulatorSpecific && system == CoreSystem.Null)
{
throw new InvalidOperationException("A system must be set");
}
if (usage == BizHawkExternalToolUsage.GameSpecific && gameHash.Trim() == "")
{
throw new InvalidOperationException("A game hash must be set");
}
ToolUsage = usage;
System = system;
GameHash = gameHash;
}
/// <summary>
/// Initialize a new instance of <see cref="BizHawkExternalToolUsageAttribute"/>
/// </summary>
/// <param name="usage"><see cref="BizHawkExternalToolUsage"/> i.e. what your external tool is for</param>
/// <param name="system"><see cref="CoreSystem"/> that your external tool is used for</param>
public BizHawkExternalToolUsageAttribute(BizHawkExternalToolUsage usage, CoreSystem system)
:this(usage, system, "")
{}
/// <summary>
/// Initialize a new instance of <see cref="BizHawkExternalToolUsageAttribute"/>
/// </summary>
public BizHawkExternalToolUsageAttribute()
:this(BizHawkExternalToolUsage.Global, CoreSystem.Null, "")
{ }
#endregion
#region Properties
/// <summary>
/// Gets the specific system used by the external tool
/// </summary>
public CoreSystem System { get; }
/// <summary>
/// Gets the specific game (hash) used by the external tool
/// </summary>
public string GameHash { get; }
/// <summary>
/// Gets the tool usage
/// </summary>
public BizHawkExternalToolUsage ToolUsage { get; }
#endregion
}
}

View File

@ -71,101 +71,78 @@ namespace BizHawk.Client.ApiHawk
}
}
/// <summary>
/// Generate a <see cref="ToolStripMenuItem"/> from an
/// external tool dll.
/// The assembly must have <see cref="BizHawkExternalToolAttribute"/> in its
/// assembly attributes
/// </summary>
/// <param name="fileName">File that will be reflected</param>
/// <returns>A new <see cref="ToolStripMenuItem"/>; assembly path can be found in the Tag property</returns>
/// <remarks>For the moment, you could only load a dll that have a form (which implements <see cref="IExternalToolForm"/>)</remarks>
/// <summary>Generates a <see cref="ToolStripMenuItem"/> from an assembly at <paramref name="fileName"/> containing an external tool.</summary>
/// <returns>
/// a <see cref="ToolStripMenuItem"/> with its <see cref="ToolStripItem.Tag"/> containing a <c>(string, string)</c>;
/// the first is the assembly path (<paramref name="fileName"/>) and the second is the <see cref="Type.FullName"/> of the entry point form's type
/// </returns>
private static ToolStripMenuItem GenerateToolTipFromFileName(string fileName)
{
ToolStripMenuItem item = null;
if (fileName == null) throw new Exception();
var item = new ToolStripMenuItem(Path.GetFileName(fileName)) { Enabled = false };
try
{
if (!OSTailoredCode.IsUnixHost) MotWHack.RemoveMOTW(fileName);
var externalToolFile = Assembly.LoadFrom(fileName);
object[] attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolAttribute), false);
if (attributes != null && attributes.Count() == 1)
var entryPoint = externalToolFile.GetTypes()
.SingleOrDefault(t => typeof(IExternalToolForm).IsAssignableFrom(t) && t.GetCustomAttributes().OfType<ExternalToolAttribute>().Any());
#pragma warning disable CS0618
if (entryPoint == null) throw new ExternalToolAttribute.MissingException(externalToolFile.GetCustomAttributes().OfType<BizHawkExternalToolAttribute>().Any());
#pragma warning restore CS0618
var allAttrs = entryPoint.GetCustomAttributes().ToList();
var applicabilityAttrs = allAttrs.OfType<ExternalToolApplicabilityAttributeBase>().ToList();
if (applicabilityAttrs.Count > 1) throw new ExternalToolApplicabilityAttributeBase.DuplicateException();
var toolAttribute = allAttrs.OfType<ExternalToolAttribute>().First();
var embeddedIconAttr = allAttrs.OfType<ExternalToolEmbeddedIconAttribute>().FirstOrDefault();
if (embeddedIconAttr != null)
{
BizHawkExternalToolAttribute attribute = (BizHawkExternalToolAttribute)attributes[0];
item = new ToolStripMenuItem(attribute.Name) { ToolTipText = attribute.Description };
if (attribute.IconResourceName != "")
var rawIcon = externalToolFile.GetManifestResourceStream(embeddedIconAttr.ResourcePath);
if (rawIcon != null) item.Image = new Bitmap(rawIcon);
}
item.Text = toolAttribute.Name;
item.Tag = (externalToolFile.Location, entryPoint.FullName); // Tag set => no errors (show custom icon even when disabled)
if (applicabilityAttrs.Count == 1)
{
var system = ClientApi.SystemIdConverter.Convert(Global.Emulator.SystemId);
if (applicabilityAttrs[0].NotApplicableTo(system))
{
Stream s = externalToolFile.GetManifestResourceStream($"{externalToolFile.GetName().Name}.{attribute.IconResourceName}");
if (s != null)
{
item.Image = new Bitmap(s);
}
item.ToolTipText = system == CoreSystem.Null
? "This tool doesn't work when no rom is loaded"
: "This tool doesn't work with this system";
return item;
}
var availTypes = externalToolFile.GetTypes();
var customFormType = availTypes.FirstOrDefault(t => t.FullName == "BizHawk.Client.EmuHawk.CustomMainForm")
?? availTypes.SingleOrDefault(t => typeof(IExternalToolForm).IsAssignableFrom(t) && t.CustomAttributes.Any(cad => cad.AttributeType == typeof(ExternalToolEntryPointFormAttribute)));
if (customFormType == null)
if (applicabilityAttrs[0].NotApplicableTo(Global.Game.Hash, system))
{
item.ToolTipText = "Does not have a correctly-formatted CustomMainForm or a form decorated with [ExternalToolEntryPointForm]";
item.Enabled = false;
}
item.Tag = (fileName, customFormType?.FullName);
attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolUsageAttribute), false);
if (attributes != null && attributes.Length == 1)
{
BizHawkExternalToolUsageAttribute attribute2 = (BizHawkExternalToolUsageAttribute)attributes[0];
if(Global.Emulator.SystemId == "NULL" && attribute2.ToolUsage != BizHawkExternalToolUsage.Global)
{
item.ToolTipText = "This tool doesn't work if nothing is loaded";
item.Enabled = false;
}
else if(attribute2.ToolUsage == BizHawkExternalToolUsage.EmulatorSpecific && Global.Emulator.SystemId != ClientApi.SystemIdConverter.ConvertBack(attribute2.System))
{
item.ToolTipText = "This tool doesn't work for current system";
item.Enabled = false;
}
else if (attribute2.ToolUsage == BizHawkExternalToolUsage.GameSpecific && Global.Game.Hash != attribute2.GameHash)
{
item.ToolTipText = "This tool doesn't work for current game";
item.Enabled = false;
}
item.ToolTipText = "This tool doesn't work with this game";
return item;
}
}
else
{
item = new ToolStripMenuItem(externalToolFile.GetName().Name)
{
ToolTipText = "BizHawkExternalTool attribute hasn't been found", Enabled = false
};
}
}
catch (BadImageFormatException)
{
item = new ToolStripMenuItem(fileName);
item.ToolTipText = "This is not an assembly";
item.Enabled = false;
}
#if DEBUG //I added special debug stuff to get additional information. Don't think it can be useful for released versions
catch (ReflectionTypeLoadException ex)
item.Enabled = true;
if (!string.IsNullOrWhiteSpace(toolAttribute.Description)) item.ToolTipText = toolAttribute.Description;
return item;
}
catch (Exception e)
{
foreach (Exception e in ex.LoaderExceptions)
#if DEBUG
if (e is ReflectionTypeLoadException rtle)
{
Debug.WriteLine(e.Message);
foreach (var e1 in rtle.LoaderExceptions) Debug.WriteLine(e1.Message);
}
item.ToolTipText = "Something goes wrong while trying to load";
item.Enabled = false;
}
#else
catch (ReflectionTypeLoadException)
{
item.ToolTipText = "Something goes wrong while trying to load";
item.Enabled = false;
}
#endif
item.ToolTipText = e switch
{
BadImageFormatException _ => "This assembly can't be loaded, probably because it's corrupt or targets an incompatible .NET runtime.",
ExternalToolApplicabilityAttributeBase.DuplicateException _ => "The IExternalToolForm has conflicting applicability attributes.",
ExternalToolAttribute.MissingException e1 => e1.OldAttributeFound
? "The assembly doesn't contain a class implementing IExternalToolForm and annotated with [ExternalTool].\nHowever, the assembly itself is annotated with [BizHawkExternalTool], which is now deprecated. Has the tool been updated since BizHawk 2.4?"
: "The assembly doesn't contain a class implementing IExternalToolForm and annotated with [ExternalTool].",
ReflectionTypeLoadException _ => "Something went wrong while trying to load the assembly.",
_ => $"An exception of type {e.GetType().FullName} was thrown while trying to load the assembly and look for an IExternalToolForm:\n{e.Message}"
};
}
return item;
}

View File

@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Common.StringExtensions;
namespace BizHawk.Client.Common
{
public static class ExternalToolApplicability
{
/// <remarks>This class is not deprecated, do not remove it.</remarks>
[AttributeUsage(AttributeTargets.Class)]
[Obsolete("this is the default behaviour, you can safely omit this attribute")]
public sealed class Always : ExternalToolApplicabilityAttributeBase
{
public override bool NotApplicableTo(CoreSystem system) => false;
public override bool NotApplicableTo(string romHash, CoreSystem? system) => false;
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class AnyRomLoaded : ExternalToolApplicabilityAttributeBase
{
public override bool NotApplicableTo(CoreSystem system) => system == CoreSystem.Null;
public override bool NotApplicableTo(string romHash, CoreSystem? system) => system == CoreSystem.Null;
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class RomWhitelist : ExternalToolApplicabilityAttributeBase
{
private readonly IList<string> _romHashes;
private readonly CoreSystem _system;
public RomWhitelist(CoreSystem system, params string[] romHashes)
{
if (system == CoreSystem.Null) throw new ArgumentException("there are no roms for the NULL system", nameof(system));
if (!romHashes.All(StringExtensions.IsHex)) throw new ArgumentException("misformatted hash", nameof(romHashes));
_system = system;
_romHashes = romHashes.ToList();
}
public override bool NotApplicableTo(CoreSystem system) => system != _system;
public override bool NotApplicableTo(string romHash, CoreSystem? system) => system != _system || !_romHashes.Contains(romHash);
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class SingleRom : ExternalToolApplicabilityAttributeBase
{
private readonly string _romHash;
private readonly CoreSystem _system;
public SingleRom(CoreSystem system, string romHash)
{
if (system == CoreSystem.Null) throw new ArgumentException("there are no roms for the NULL system", nameof(system));
if (!romHash.IsHex()) throw new ArgumentException("misformatted hash", nameof(romHash));
_system = system;
_romHash = romHash;
}
public override bool NotApplicableTo(CoreSystem system) => system != _system;
public override bool NotApplicableTo(string romHash, CoreSystem? system) => system != _system || romHash != _romHash;
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class SingleSystem : ExternalToolApplicabilityAttributeBase
{
private readonly CoreSystem _system;
public SingleSystem(CoreSystem system)
{
_system = system;
}
public override bool NotApplicableTo(CoreSystem system) => system != _system;
public override bool NotApplicableTo(string romHash, CoreSystem? system) => system != _system;
}
}
public abstract class ExternalToolApplicabilityAttributeBase : Attribute
{
public abstract bool NotApplicableTo(CoreSystem system);
public abstract bool NotApplicableTo(string romHash, CoreSystem? system);
public bool NotApplicableTo(string romHash) => NotApplicableTo(romHash, null);
public class DuplicateException : Exception {}
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class ExternalToolAttribute : Attribute
{
public readonly string Description;
public readonly string Name;
public ExternalToolAttribute(string name, string description = null)
{
Description = description;
Name = string.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name;
}
public class MissingException : Exception
{
public readonly bool OldAttributeFound;
public MissingException(bool oldAttributeFound)
{
OldAttributeFound = oldAttributeFound;
}
}
}
public sealed class ExternalToolEmbeddedIconAttribute : Attribute
{
/// <remarks>The full path, including the assembly name.</remarks>
public readonly string ResourcePath;
/// <param name="resourcePath">The full path, including the assembly name.</param>
public ExternalToolEmbeddedIconAttribute(string resourcePath)
{
ResourcePath = resourcePath;
}
}
}

View File

@ -1,7 +0,0 @@
using System;
namespace BizHawk.Client.Common
{
[AttributeUsage(AttributeTargets.Class)]
public class ExternalToolEntryPointFormAttribute : Attribute {}
}

View File

@ -1411,13 +1411,12 @@ namespace BizHawk.Client.EmuHawk
foreach (var item in ExternalToolManager.ToolStripMenu)
{
if (item.Enabled)
if (item.Tag is ValueTuple<string, string> tuple)
{
item.Click += delegate
if (item.Enabled)
{
var (fileName, customFormTypeName) = ((string, string)) item.Tag;
Tools.LoadExternalToolForm(fileName, customFormTypeName);
};
item.Click += (clickEventSender, clickEventArgs) => Tools.LoadExternalToolForm(tuple.Item1, tuple.Item2);
}
}
else
{

View File

@ -2,6 +2,6 @@
<Import Project="$(ProjectDir)../Common.props" />
<Import Project="$(ProjectDir)../NET48ExternalToolForm.props" />
<ItemGroup>
<Compile Update="CustomMainForm.cs" SubType="Form" />
<Compile Update="AutoGenConfigForm.cs" SubType="Form" />
</ItemGroup>
</Project>

View File

@ -9,11 +9,12 @@ using System.Windows.Forms;
using BizHawk.Client.ApiHawk;
using BizHawk.Client.Common;
using static BizHawk.Client.EmuHawk.ConfigEditorUIGenerators;
using static BizHawk.Experiment.AutoGenConfig.ConfigEditorUIGenerators;
namespace BizHawk.Client.EmuHawk
namespace BizHawk.Experiment.AutoGenConfig
{
public class CustomMainForm : Form, IExternalToolForm
[ExternalTool("AutoGenConfig")]
public class AutoGenConfigForm : Form, IExternalToolForm
{
private static readonly IList<(PropertyInfo, IConfigPropEditorUIGen<Control>)> CachedControlGenerators;
@ -28,7 +29,7 @@ namespace BizHawk.Client.EmuHawk
public static readonly IDictionary<string, object?> DefaultValues;
static CustomMainForm()
static AutoGenConfigForm()
{
CachedControlGenerators = new List<(PropertyInfo, IConfigPropEditorUIGen<Control>)>();
DefaultValues = new Dictionary<string, object?>();
@ -63,7 +64,7 @@ namespace BizHawk.Client.EmuHawk
public bool UpdateBefore => false;
public CustomMainForm()
public AutoGenConfigForm()
{
ClientSize = new Size(640, 720);
SuspendLayout();

View File

@ -8,7 +8,7 @@ using System.Windows.Forms;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
namespace BizHawk.Experiment.AutoGenConfig
{
public static class ConfigEditorUIGenerators
{
@ -19,39 +19,39 @@ namespace BizHawk.Client.EmuHawk
public static readonly IConfigPropEditorUIGen<GroupBox> FinalFallbackGenerator = new UnrepresentablePropEditorUIGen();
private static Color GetComparisonColorRefT<T>(string prop, T? currentValue, CustomMainForm parent, Func<T?, T?, bool> equalityFunc)
private static Color GetComparisonColorRefT<T>(string prop, T? currentValue, AutoGenConfigForm parent, Func<T?, T?, bool> equalityFunc)
where T : class
=> equalityFunc(currentValue, parent.BaselineValues[prop] as T)
? GetInitComparisonColorRefT(prop, currentValue, equalityFunc)
: equalityFunc(currentValue, CustomMainForm.DefaultValues[prop] as T)
? CustomMainForm.ComparisonColors.ChangedUnset
: CustomMainForm.ComparisonColors.Changed;
: equalityFunc(currentValue, AutoGenConfigForm.DefaultValues[prop] as T)
? AutoGenConfigForm.ComparisonColors.ChangedUnset
: AutoGenConfigForm.ComparisonColors.Changed;
private static Color GetComparisonColorValT<T>(string prop, T? currentValue, CustomMainForm parent, Func<T?, T?, bool> equalityFunc)
private static Color GetComparisonColorValT<T>(string prop, T? currentValue, AutoGenConfigForm parent, Func<T?, T?, bool> equalityFunc)
where T : struct
=> equalityFunc(currentValue, parent.BaselineValues[prop]?.Let(it => (T) it))
? GetInitComparisonColorValT(prop, currentValue, equalityFunc)
: equalityFunc(currentValue, CustomMainForm.DefaultValues[prop]?.Let(it => (T) it))
? CustomMainForm.ComparisonColors.ChangedUnset
: CustomMainForm.ComparisonColors.Changed;
: equalityFunc(currentValue, AutoGenConfigForm.DefaultValues[prop]?.Let(it => (T) it))
? AutoGenConfigForm.ComparisonColors.ChangedUnset
: AutoGenConfigForm.ComparisonColors.Changed;
private static Color GetInitComparisonColorRefT<T>(string prop, T? currentValue, Func<T?, T?, bool> equalityFunc)
where T : class
=> equalityFunc(currentValue, CustomMainForm.DefaultValues[prop] as T)
? CustomMainForm.ComparisonColors.UnchangedDefault
: CustomMainForm.ComparisonColors.Unchanged;
=> equalityFunc(currentValue, AutoGenConfigForm.DefaultValues[prop] as T)
? AutoGenConfigForm.ComparisonColors.UnchangedDefault
: AutoGenConfigForm.ComparisonColors.Unchanged;
private static Color GetInitComparisonColorValT<T>(string prop, T? currentValue, Func<T?, T?, bool> equalityFunc)
where T : struct
=> equalityFunc(currentValue, CustomMainForm.DefaultValues[prop]?.Let(it => (T) it))
? CustomMainForm.ComparisonColors.UnchangedDefault
: CustomMainForm.ComparisonColors.Unchanged;
=> equalityFunc(currentValue, AutoGenConfigForm.DefaultValues[prop]?.Let(it => (T) it))
? AutoGenConfigForm.ComparisonColors.UnchangedDefault
: AutoGenConfigForm.ComparisonColors.Unchanged;
private static CustomMainForm GetMainFormParent(Control c)
private static AutoGenConfigForm GetMainFormParent(Control c)
{
var parent = c.Parent;
while (!(parent is CustomMainForm)) parent = parent.Parent;
return (CustomMainForm) parent;
while (!(parent is AutoGenConfigForm)) parent = parent.Parent;
return (AutoGenConfigForm) parent;
}
private static string GetPropertyNameDesc(PropertyInfo pi)

View File

@ -1,41 +0,0 @@
using System.Drawing;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BizHawk.Client.ApiHawk;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AutoGenConfig")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AutoGenConfig")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: BizHawkExternalTool("AutoGenConfig")]
[assembly: BizHawkExternalToolUsage()]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("34ef725e-ecfd-4e25-b7fd-5c995dd62eef")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,7 +1,7 @@
using System;
using System.Runtime.CompilerServices;
namespace BizHawk.Client.EmuHawk
namespace BizHawk.Experiment.AutoGenConfig
{
internal static class ScopingExtensions
{

View File

@ -5,12 +5,12 @@ using System.Windows.Forms;
using BizHawk.Client.ApiHawk;
using BizHawk.Client.Common;
using BizHawk.Common;
using BizHawk.DBManTool;
using Community.CsharpSqlite.SQLiteClient;
namespace BizHawk.Client.EmuHawk
namespace BizHawk.DBManTool
{
[ExternalTool("DBMan", "DB Manager")]
public class CustomMainForm : Form, IExternalToolForm
{
public CustomMainForm()

View File

@ -1,8 +1,5 @@
using System.Drawing;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Runtime.InteropServices;
using BizHawk.Client.ApiHawk;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@ -16,9 +13,6 @@ using BizHawk.Client.ApiHawk;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: BizHawkExternalTool("DBMan", "DB Manager")]
[assembly: BizHawkExternalToolUsage()]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.

View File

@ -1,4 +1,4 @@
namespace BizHawk.Client.EmuHawk
namespace HelloWorld
{
public partial class CustomMainForm
{

View File

@ -8,9 +8,12 @@ using BizHawk.Emulation.Common;
using DisplayType = BizHawk.Client.Common.DisplayType;
namespace BizHawk.Client.EmuHawk
namespace HelloWorld
{
/// <remarks><see cref="IExternalToolForm">ExternalToolForms</see> must be a class named <c>CustomMainForm</c> in namespace <c>BizHawk.Client.EmuHawk</c>.</remarks>
/// <remarks>All of this is example code, but it's at least a little more substantiative than a simple "hello world".</remarks>
[ExternalTool("HelloWorld", "An example of how to interact with EmuHawk")]
// [ExternalToolApplicability.SingleRom(CoreSystem.NES, "EA343F4E445A9050D4B4FBAC2C77D0693B1D0922")] // example of limiting tool usage (this is SMB1)
[ExternalToolEmbeddedIcon("HelloWorld.icon_Hello.ico")]
public partial class CustomMainForm : Form, IExternalToolForm
{
/// <remarks><see cref="RequiredServiceAttribute">RequiredServices</see> are populated by EmuHawk at runtime.</remarks>

View File

@ -1,8 +1,5 @@
using System.Drawing;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Runtime.InteropServices;
using BizHawk.Client.ApiHawk;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@ -16,18 +13,6 @@ using BizHawk.Client.ApiHawk;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//As you can see this is a dedicated attribute. You can write the name of your tool, a small description
//and give an icon. The icon should be compiled as an embedded resource and you must give the entire path
[assembly: BizHawkExternalTool("Hello World", "My first External tool for BizHawk emulator", "icon_Hello.ico")]
//This attribute say what the is for. here, I don't anything
//It's equivalent to [assembly: BizHawkExternalToolUsage(BizHawkExternalToolUsage.Global, string.Empty)]
//Here is an example for an emulator specific: BizHawkExternalToolUsage(BizHawkExternalToolUsage.EmulatorSpecific, EmulatedSystem.NES)]
//Here is an example for an game specific: BizHawkExternalToolUsage(BizHawkExternalToolUsage.GameSpecific, "6B47BB75D16514B6A476AA0C73A683A2A4C18765")] => Super Mario World (USA)
//By setting this, your tool is contextualized, that mean you can't load it if emulator is in state you don't want
//It avoid crash
[assembly: BizHawkExternalToolUsage()]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.