mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
Add basic plugin sys
reference PKHeX.Core, main window loads assemblies & initializes providing an ISaveProvider and the menustrip control (to insert controls into) pretty rough but should allow for inserting external control buttons & allowing it to edit the UI a little example: https://github.com/kwsch/PKHeXPluginExample feedback is appreciated
This commit is contained in:
parent
9d0ab043e7
commit
857919bd28
11 changed files with 141 additions and 10 deletions
48
PKHeX.Core/Editing/IPKMView.cs
Normal file
48
PKHeX.Core/Editing/IPKMView.cs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple interface representing a <see cref="PKM"/> viewer.
|
||||||
|
/// </summary>
|
||||||
|
public interface IPKMView
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches the currently loaded <see cref="PKM"/> data from the viewer.
|
||||||
|
/// </summary>
|
||||||
|
PKM Data { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the Viewer supports using Unicode characters or not.
|
||||||
|
/// </summary>
|
||||||
|
bool Unicode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the Viewer's controls have been fully initialized after a reload.
|
||||||
|
/// </summary>
|
||||||
|
bool FieldsInitialized { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the Viewer is providing extra flexibility or not.
|
||||||
|
/// </summary>
|
||||||
|
bool HaX { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the Viewer's controls are changing their values and should avoid triggering other updates.
|
||||||
|
/// </summary>
|
||||||
|
bool ChangingFields { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches the currently loaded <see cref="PKM"/> data from the viewer by finishing any pending changes or auto-modifications.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="click">Cause the viewer to do extra actions to force validation of its children.</param>
|
||||||
|
/// <returns>Prepared <see cref="PKM"/> data from the viewer.</returns>
|
||||||
|
PKM PreparePKM(bool click = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a given <see cref="PKM"/> data to the viewer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pk">Pokémon data to load.</param>
|
||||||
|
/// <param name="focus">Cause the viewer to give focus to itself.</param>
|
||||||
|
/// <param name="skipConversionCheck">Cause the viewer to skip converting the data. Faster if it is known that the format is the same as the previous format.</param>
|
||||||
|
void PopulateFields(PKM pk, bool focus = true, bool skipConversionCheck = false);
|
||||||
|
}
|
||||||
|
}
|
10
PKHeX.Core/Editing/IPlugin.cs
Normal file
10
PKHeX.Core/Editing/IPlugin.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
public interface IPlugin
|
||||||
|
{
|
||||||
|
string Name { get; }
|
||||||
|
void Initialize(params object[] args);
|
||||||
|
void NotifySaveLoaded();
|
||||||
|
ISaveFileProvider SaveFileEditor { get; }
|
||||||
|
}
|
||||||
|
}
|
23
PKHeX.Core/Editing/ISaveFileProvider.cs
Normal file
23
PKHeX.Core/Editing/ISaveFileProvider.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
namespace PKHeX.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple interface representing a Save File viewer.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISaveFileProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the save file the <see cref="ISaveFileProvider"/> has control over.
|
||||||
|
/// </summary>
|
||||||
|
SaveFile SAV { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the current box the <see cref="ISaveFileProvider"/> has control over.
|
||||||
|
/// </summary>
|
||||||
|
int CurrentBox { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers a refresh of any individual <see cref="PKM"/> view slots.
|
||||||
|
/// </summary>
|
||||||
|
void ReloadSlots();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,15 +2,9 @@ using PKHeX.Core;
|
||||||
|
|
||||||
namespace PKHeX.WinForms.Controls
|
namespace PKHeX.WinForms.Controls
|
||||||
{
|
{
|
||||||
public interface IMainEditor
|
public interface IMainEditor : IPKMView
|
||||||
{
|
{
|
||||||
bool Unicode { get; }
|
|
||||||
bool FieldsInitialized { get; }
|
|
||||||
bool ChangingFields { get; set; }
|
|
||||||
bool HaX { get; }
|
|
||||||
|
|
||||||
PKM pkm { get; }
|
|
||||||
|
|
||||||
void UpdateIVsGB(bool skipForm);
|
void UpdateIVsGB(bool skipForm);
|
||||||
|
PKM pkm { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -62,6 +62,7 @@ namespace PKHeX.WinForms.Controls
|
||||||
public bool HaX { get; set; }
|
public bool HaX { get; set; }
|
||||||
public byte[] LastData { private get; set; }
|
public byte[] LastData { private get; set; }
|
||||||
|
|
||||||
|
public PKM Data { get => pkm; set => pkm = value; }
|
||||||
public PKM pkm { get; private set; }
|
public PKM pkm { get; private set; }
|
||||||
public bool FieldsInitialized { get; private set; }
|
public bool FieldsInitialized { get; private set; }
|
||||||
public bool FieldsLoaded { get; private set; }
|
public bool FieldsLoaded { get; private set; }
|
||||||
|
|
|
@ -13,9 +13,10 @@ using static PKHeX.Core.MessageStrings;
|
||||||
|
|
||||||
namespace PKHeX.WinForms.Controls
|
namespace PKHeX.WinForms.Controls
|
||||||
{
|
{
|
||||||
public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>
|
public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>, ISaveFileProvider
|
||||||
{
|
{
|
||||||
public SaveFile SAV;
|
public SaveFile SAV { get; set; }
|
||||||
|
public int CurrentBox => Box.CurrentBox;
|
||||||
public SlotChangeManager M { get; }
|
public SlotChangeManager M { get; }
|
||||||
public readonly Stack<SlotChange> UndoStack = new Stack<SlotChange>();
|
public readonly Stack<SlotChange> UndoStack = new Stack<SlotChange>();
|
||||||
public readonly Stack<SlotChange> RedoStack = new Stack<SlotChange>();
|
public readonly Stack<SlotChange> RedoStack = new Stack<SlotChange>();
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace PKHeX.WinForms
|
||||||
"中文", // CHN
|
"中文", // CHN
|
||||||
"Português", // Portuguese
|
"Português", // Portuguese
|
||||||
};
|
};
|
||||||
|
private static readonly List<IPlugin> Plugins = new List<IPlugin>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Path Variables
|
#region Path Variables
|
||||||
|
@ -92,6 +93,7 @@ namespace PKHeX.WinForms
|
||||||
public static string MGDatabasePath => Path.Combine(WorkingDirectory, "mgdb");
|
public static string MGDatabasePath => Path.Combine(WorkingDirectory, "mgdb");
|
||||||
public static string BackupPath => Path.Combine(WorkingDirectory, "bak");
|
public static string BackupPath => Path.Combine(WorkingDirectory, "bak");
|
||||||
private static string TemplatePath => Path.Combine(WorkingDirectory, "template");
|
private static string TemplatePath => Path.Combine(WorkingDirectory, "template");
|
||||||
|
private static string PluginPath => Path.Combine(WorkingDirectory, "plugins");
|
||||||
private const string ThreadPath = "https://projectpokemon.org/pkhex/";
|
private const string ThreadPath = "https://projectpokemon.org/pkhex/";
|
||||||
private const string VersionPath = "https://raw.githubusercontent.com/kwsch/PKHeX/master/PKHeX.WinForms/Resources/text/version.txt";
|
private const string VersionPath = "https://raw.githubusercontent.com/kwsch/PKHeX/master/PKHeX.WinForms/Resources/text/version.txt";
|
||||||
|
|
||||||
|
@ -125,6 +127,8 @@ namespace PKHeX.WinForms
|
||||||
WinFormsUtil.Error(MsgSettingsLoadFail, e);
|
WinFormsUtil.Error(MsgSettingsLoadFail, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormLoadPlugins();
|
||||||
|
|
||||||
PKME_Tabs.InitializeFields();
|
PKME_Tabs.InitializeFields();
|
||||||
PKME_Tabs.TemplateFields(LoadTemplate(C_SAV.SAV));
|
PKME_Tabs.TemplateFields(LoadTemplate(C_SAV.SAV));
|
||||||
}
|
}
|
||||||
|
@ -246,6 +250,14 @@ namespace PKHeX.WinForms
|
||||||
|
|
||||||
Settings.Version = Resources.ProgramVersion;
|
Settings.Version = Resources.ProgramVersion;
|
||||||
}
|
}
|
||||||
|
private void FormLoadPlugins()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(PluginPath))
|
||||||
|
return;
|
||||||
|
Plugins.AddRange(PluginLoader.LoadPlugins<IPlugin>(PluginPath));
|
||||||
|
foreach (var p in Plugins)
|
||||||
|
p.Initialize(C_SAV, PKME_Tabs, menuStrip1);
|
||||||
|
}
|
||||||
private static void DeleteConfig(string settingsFilename)
|
private static void DeleteConfig(string settingsFilename)
|
||||||
{
|
{
|
||||||
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSettingsResetCorrupt, MsgSettingsResetPrompt);
|
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSettingsResetCorrupt, MsgSettingsResetPrompt);
|
||||||
|
@ -746,6 +758,8 @@ namespace PKHeX.WinForms
|
||||||
PKME_Tabs.FlickerInterface();
|
PKME_Tabs.FlickerInterface();
|
||||||
|
|
||||||
PKME_Tabs.TemplateFields(LoadTemplate(sav));
|
PKME_Tabs.TemplateFields(LoadTemplate(sav));
|
||||||
|
foreach (var p in Plugins)
|
||||||
|
p.NotifySaveLoaded();
|
||||||
sav.Edited = false;
|
sav.Edited = false;
|
||||||
}
|
}
|
||||||
private static string GetProgramTitle()
|
private static string GetProgramTitle()
|
||||||
|
|
39
PKHeX.WinForms/MainWindow/PluginLoader.cs
Normal file
39
PKHeX.WinForms/MainWindow/PluginLoader.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace PKHeX.WinForms
|
||||||
|
{
|
||||||
|
public static class PluginLoader
|
||||||
|
{
|
||||||
|
public static IEnumerable<T> LoadPlugins<T>(string pluginPath)
|
||||||
|
{
|
||||||
|
var dllFileNames = Directory.EnumerateFiles(pluginPath, "*.dll", SearchOption.AllDirectories);
|
||||||
|
var assemblies = GetAssemblies(dllFileNames);
|
||||||
|
var pluginTypes = GetPluginsOfType<T>(assemblies);
|
||||||
|
return LoadPlugins<T>(pluginTypes);
|
||||||
|
}
|
||||||
|
private static IEnumerable<T> LoadPlugins<T>(IEnumerable<Type> pluginTypes)
|
||||||
|
{
|
||||||
|
return pluginTypes.Select(type => (T)Activator.CreateInstance(type));
|
||||||
|
}
|
||||||
|
private static IEnumerable<Assembly> GetAssemblies(IEnumerable<string> dllFileNames)
|
||||||
|
{
|
||||||
|
return dllFileNames.Select(AssemblyName.GetAssemblyName).Select(Assembly.Load);
|
||||||
|
}
|
||||||
|
private static IEnumerable<Type> GetPluginsOfType<T>(IEnumerable<Assembly> assemblies)
|
||||||
|
{
|
||||||
|
var pluginType = typeof(T);
|
||||||
|
foreach (var type in assemblies.Where(z => z != null).SelectMany(a => a.GetTypes()))
|
||||||
|
{
|
||||||
|
if (type.IsInterface || type.IsAbstract)
|
||||||
|
continue;
|
||||||
|
if (type.GetInterface(pluginType.FullName) == null)
|
||||||
|
continue;
|
||||||
|
yield return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -245,6 +245,7 @@
|
||||||
<Compile Include="Controls\PKM Editor\PKMEditor.Designer.cs">
|
<Compile Include="Controls\PKM Editor\PKMEditor.Designer.cs">
|
||||||
<DependentUpon>PKMEditor.cs</DependentUpon>
|
<DependentUpon>PKMEditor.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="MainWindow\PluginLoader.cs" />
|
||||||
<Compile Include="Misc\About.cs">
|
<Compile Include="Misc\About.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
Loading…
Reference in a new issue