Plugins/GUI: Tidy up
This commit is contained in:
@@ -20,6 +20,13 @@ using Il2CppInspector.PluginAPI.V100;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
public enum OptionBehaviour
|
||||
{
|
||||
None,
|
||||
IgnoreInvalid,
|
||||
NoValidation
|
||||
}
|
||||
|
||||
// Internal settings for a plugin
|
||||
public class ManagedPlugin
|
||||
{
|
||||
@@ -40,6 +47,34 @@ namespace Il2CppInspector
|
||||
|
||||
// The current stack trace of the plugin
|
||||
internal Stack<string> StackTrace = new Stack<string>();
|
||||
|
||||
// Get options as dictionary
|
||||
public Dictionary<string, object> GetOptions()
|
||||
=> Plugin.Options.ToDictionary(o => o.Name, o => o.Value);
|
||||
|
||||
// Set options to values with optional validation behaviour
|
||||
public void SetOptions(Dictionary<string, object> options, OptionBehaviour behaviour = OptionBehaviour.None) {
|
||||
foreach (var option in options)
|
||||
// Throw an exception on the first invalid option
|
||||
if (behaviour == OptionBehaviour.None)
|
||||
this[option.Key] = option.Value;
|
||||
|
||||
// Don't set invalid options but don't throw an exception either
|
||||
else if (behaviour == OptionBehaviour.IgnoreInvalid)
|
||||
try {
|
||||
this[option.Key] = option.Value;
|
||||
} catch { }
|
||||
|
||||
// Force set options with no validation
|
||||
else if (behaviour == OptionBehaviour.NoValidation) {
|
||||
if (Plugin.Options.FirstOrDefault(o => o.Name == option.Key) is IPluginOption target) {
|
||||
var validationCondition = target.If;
|
||||
target.If = () => false;
|
||||
target.Value = option.Value;
|
||||
target.If = validationCondition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Event arguments for error handler
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace Il2CppInspectorGUI
|
||||
public List<IPluginOption> Options { get; set; }
|
||||
};
|
||||
|
||||
// Save state for plugin options
|
||||
private class PluginOptionState : IPluginOption
|
||||
{
|
||||
public string Name { get; set; }
|
||||
@@ -139,6 +140,7 @@ namespace Il2CppInspectorGUI
|
||||
var loadedPlugins = PluginManager.AsInstance.ManagedPlugins;
|
||||
foreach (var savedState in savedPluginState.Reverse()) {
|
||||
if (loadedPlugins.FirstOrDefault(p => p.Plugin.Id == savedState.Plugin.Id) is ManagedPlugin managedPlugin) {
|
||||
|
||||
// Re-order to match saved order
|
||||
loadedPlugins.Remove(managedPlugin);
|
||||
loadedPlugins.Insert(0, managedPlugin);
|
||||
@@ -147,27 +149,23 @@ namespace Il2CppInspectorGUI
|
||||
managedPlugin.Enabled = savedState.Enabled;
|
||||
|
||||
// Set options
|
||||
if (savedState.Plugin.Options != null)
|
||||
if (savedState.Plugin.Options != null) {
|
||||
var options = new Dictionary<string, object>();
|
||||
|
||||
foreach (var savedOption in savedState.Plugin.Options)
|
||||
if (managedPlugin.Plugin.Options.FirstOrDefault(o => o.Name == savedOption.Name) is IPluginOption option) {
|
||||
try {
|
||||
// Ignore validation
|
||||
var cond = option.If;
|
||||
option.If = () => false;
|
||||
if (savedOption.Value == null)
|
||||
option.Value = null;
|
||||
options.Add(option.Name, null);
|
||||
else
|
||||
option.Value = (savedOption.Value, ((JsonElement) savedOption.Value).ValueKind) switch {
|
||||
options.Add(option.Name, (savedOption.Value, ((JsonElement) savedOption.Value).ValueKind) switch {
|
||||
(var v, JsonValueKind.String) => v.ToString(),
|
||||
(var v, JsonValueKind.Number) => Convert.ChangeType(v.ToString(), option.Value.GetType()),
|
||||
(var v, JsonValueKind.True) => true,
|
||||
(var v, JsonValueKind.False) => false,
|
||||
_ => throw new ArgumentException("Unsupported JSON type")
|
||||
};
|
||||
option.If = cond;
|
||||
});
|
||||
}
|
||||
// Ignore invalid values
|
||||
catch { }
|
||||
managedPlugin.SetOptions(options, OptionBehaviour.NoValidation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +184,7 @@ namespace Il2CppInspectorGUI
|
||||
|
||||
private Metadata metadata;
|
||||
|
||||
// True if we extracted from an APK, IPA, zip file etc.
|
||||
// True if we extracted the current workload from an APK, IPA, zip file etc.
|
||||
private bool isExtractedFromPackage;
|
||||
public bool IsExtractedFromPackage {
|
||||
get => isExtractedFromPackage;
|
||||
@@ -197,10 +195,14 @@ namespace Il2CppInspectorGUI
|
||||
}
|
||||
}
|
||||
|
||||
// Load options for the current image
|
||||
public LoadOptions ImageLoadOptions { get; private set; }
|
||||
|
||||
// Application models for the current image
|
||||
public List<AppModel> AppModels { get; } = new List<AppModel>();
|
||||
|
||||
// The last exception thrown
|
||||
// Reading the exception clears it
|
||||
private Exception _lastException;
|
||||
public Exception LastException {
|
||||
get {
|
||||
@@ -236,6 +238,7 @@ namespace Il2CppInspectorGUI
|
||||
PluginManager.StatusHandler += (s, e) => StatusUpdate(e.Plugin, "[" + e.Plugin.Name + "]\n" + e.Text);
|
||||
}
|
||||
|
||||
// Reset image load options to their defaults
|
||||
public void ResetLoadOptions() {
|
||||
ImageLoadOptions = new LoadOptions {
|
||||
ImageBase = 0xffffffff_ffffffff,
|
||||
|
||||
@@ -117,6 +117,9 @@ namespace Il2CppInspectorGUI
|
||||
ValidateAllOptions();
|
||||
}
|
||||
|
||||
// Force each ListBoxItem to set its source property
|
||||
// This will force errors to appear in the dialog box when exceptions are thrown
|
||||
// Only needed when the window first opens or the plugin object changes
|
||||
private void ValidateAllOptions() {
|
||||
// Adapted from https://stackoverflow.com/a/18008545
|
||||
foreach (var item in lstOptions.Items) {
|
||||
@@ -145,17 +148,12 @@ namespace Il2CppInspectorGUI
|
||||
ManagedPlugin = plugin;
|
||||
|
||||
// Copy current options
|
||||
OriginalOptions = new Dictionary<string, object>(Plugin.Options.ToDictionary(o => o.Name, o => o.Value));
|
||||
OriginalOptions = plugin.GetOptions();
|
||||
|
||||
// Validate options once they have loaded
|
||||
lstOptions.ItemContainerGenerator.StatusChanged += OptionsListBoxStatusChanged;
|
||||
}
|
||||
|
||||
private void okButton_Click(object sender, RoutedEventArgs e) {
|
||||
// Close dialog box but call OnClosing first to validate all the options
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
// Select a file path
|
||||
private void btnFilePathSelector_Click(object sender, RoutedEventArgs e) {
|
||||
|
||||
@@ -217,6 +215,34 @@ namespace Il2CppInspectorGUI
|
||||
e.Handled = !Regex.IsMatch(e.Text, @"[A-Fa-f0-9]");
|
||||
}
|
||||
|
||||
// Reset a plugin's settings
|
||||
private void resetButton_Click(object sender, RoutedEventArgs e) {
|
||||
// Replace plugin object with a new one (updates ManagedPlugin.Plugin)
|
||||
PluginManager.Reset(Plugin);
|
||||
|
||||
// Validate options once they have loaded
|
||||
lstOptions.ItemContainerGenerator.StatusChanged += OptionsListBoxStatusChanged;
|
||||
|
||||
// Replace options in ListBox
|
||||
lstOptions.ItemsSource = Plugin.Options;
|
||||
}
|
||||
|
||||
// Close dialog box but call OnClosing first to validate all the options
|
||||
private void okButton_Click(object sender, RoutedEventArgs e) {
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
// Close dialog box, reverting changes
|
||||
private void cancelButton_Click(object sender, RoutedEventArgs e) {
|
||||
// Revert changes
|
||||
ManagedPlugin.SetOptions(OriginalOptions, OptionBehaviour.IgnoreInvalid);
|
||||
|
||||
// Replace options in ListBox
|
||||
lstOptions.ItemsSource = Plugin.Options;
|
||||
|
||||
DialogResult = false;
|
||||
}
|
||||
|
||||
// Check options validity before allowing the dialog to close either by clicking OK or the close icon
|
||||
private void Window_Closing(object sender, CancelEventArgs e) {
|
||||
|
||||
@@ -236,18 +262,6 @@ namespace Il2CppInspectorGUI
|
||||
e.Cancel = true;
|
||||
}
|
||||
|
||||
// Reset a plugin's settings
|
||||
private void resetButton_Click(object sender, RoutedEventArgs e) {
|
||||
// Get new context (updates ManagedPlugin)
|
||||
PluginManager.Reset(Plugin);
|
||||
|
||||
// Validate options once they have loaded
|
||||
lstOptions.ItemContainerGenerator.StatusChanged += OptionsListBoxStatusChanged;
|
||||
|
||||
// Replace options in ListBox
|
||||
lstOptions.ItemsSource = Plugin.Options;
|
||||
}
|
||||
|
||||
// Force all the If evaluations on each option to be re-evaluated each time an option is changed
|
||||
private void valueControl_Changed(object sender, RoutedEventArgs e) {
|
||||
// Ignore changes when listbox is first populated
|
||||
@@ -268,18 +282,5 @@ namespace Il2CppInspectorGUI
|
||||
ValidateAllOptions();
|
||||
}
|
||||
|
||||
private void cancelButton_Click(object sender, RoutedEventArgs e) {
|
||||
|
||||
// Revert changes
|
||||
foreach (var option in OriginalOptions)
|
||||
try {
|
||||
ManagedPlugin[option.Key] = option.Value;
|
||||
} catch { }
|
||||
|
||||
// Replace options in ListBox
|
||||
lstOptions.ItemsSource = Plugin.Options;
|
||||
|
||||
DialogResult = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Window x:Class="Il2CppInspector.GUI.PluginManagerDialog"
|
||||
<Window x:Class="Il2CppInspectorGUI.PluginManagerDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
@@ -6,7 +6,8 @@
|
||||
xmlns:local="clr-namespace:Il2CppInspector.GUI"
|
||||
mc:Ignorable="d"
|
||||
Title="Plugin Manager" Height="450" Width="800"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Closing="Window_Closing">
|
||||
<Window.Resources>
|
||||
<!-- Configure ListBox to display plugins nicely -->
|
||||
<Style x:Key="ConfigItemStyle" TargetType="{x:Type ListBoxItem}">
|
||||
|
||||
@@ -17,8 +17,9 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using Il2CppInspector;
|
||||
|
||||
namespace Il2CppInspector.GUI
|
||||
namespace Il2CppInspectorGUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for PluginManagerDialog.xaml
|
||||
@@ -33,10 +34,13 @@ namespace Il2CppInspector.GUI
|
||||
lstPlugins_SelectionChanged(null, null);
|
||||
}
|
||||
|
||||
// Save options whether the user clicked OK or the close icon
|
||||
private void Window_Closing(object sender, CancelEventArgs e) {
|
||||
((Il2CppInspectorGUI.App) Application.Current).SaveOptions();
|
||||
}
|
||||
|
||||
private void okButton_Click(object sender, RoutedEventArgs e) {
|
||||
DialogResult = true;
|
||||
|
||||
((Il2CppInspectorGUI.App) Application.Current).SaveOptions();
|
||||
}
|
||||
|
||||
// Reload list of plugins and reset settings
|
||||
|
||||
Reference in New Issue
Block a user