GUI: Implement all exports
This commit is contained in:
@@ -183,6 +183,8 @@
|
|||||||
|
|
||||||
<!-- Output configuration -->
|
<!-- Output configuration -->
|
||||||
<DockPanel Name="pnlOutputSettings" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2">
|
<DockPanel Name="pnlOutputSettings" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2">
|
||||||
|
|
||||||
|
<!-- Show preferences only when an image is selected -->
|
||||||
<DockPanel.Style>
|
<DockPanel.Style>
|
||||||
<Style>
|
<Style>
|
||||||
<Setter Property="DockPanel.Visibility" Value="Visible"/>
|
<Setter Property="DockPanel.Visibility" Value="Visible"/>
|
||||||
@@ -195,7 +197,17 @@
|
|||||||
</DockPanel.Style>
|
</DockPanel.Style>
|
||||||
|
|
||||||
<!-- Export button -->
|
<!-- Export button -->
|
||||||
<Button Name="btnExport" DockPanel.Dock="Bottom" Margin="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Style="{StaticResource LightBoxButton}" FontSize="18" Width="120">Export</Button>
|
<Button Name="btnExport" Click="BtnExport_OnClick" DockPanel.Dock="Bottom" Margin="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" FontSize="18" Width="120" Content="Export">
|
||||||
|
<Button.Style>
|
||||||
|
<Style BasedOn="{StaticResource LightBoxButton}" TargetType="{x:Type Button}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding ElementName=areaBusyIndicator, Path=Visibility}" Value="Visible">
|
||||||
|
<Setter Property="Button.IsEnabled" Value="False"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
|
||||||
<DockPanel DockPanel.Dock="Top">
|
<DockPanel DockPanel.Dock="Top">
|
||||||
<!-- List of namespaces to export -->
|
<!-- List of namespaces to export -->
|
||||||
@@ -240,7 +252,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<CheckBox Margin="2" Content="Don't nest folders (flatten hierarchy)">
|
<CheckBox Name="cbFlattenHierarchy" Margin="2" Content="Don't nest folders (flatten hierarchy)">
|
||||||
<CheckBox.Style>
|
<CheckBox.Style>
|
||||||
<Style>
|
<Style>
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
@@ -274,13 +286,13 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</GroupBox.Style>
|
</GroupBox.Style>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<RadioButton IsChecked="True">Alphabetical</RadioButton>
|
<RadioButton Name="rdoSortName" IsChecked="True">Alphabetical</RadioButton>
|
||||||
<RadioButton>Type definition index</RadioButton>
|
<RadioButton Name="rdoSortIndex">Type definition index</RadioButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<CheckBox Margin="2">Suppress pointer, offset and index metadata comments</CheckBox>
|
<CheckBox Name="cbSuppressMetadata" Margin="2">Suppress pointer, offset and index metadata comments</CheckBox>
|
||||||
<CheckBox Margin="2" Content="Attempt to generate output that compiles">
|
<CheckBox Name="cbMustCompile" Margin="2" Content="Attempt to generate output that compiles">
|
||||||
<CheckBox.Style>
|
<CheckBox.Style>
|
||||||
<Style>
|
<Style>
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
@@ -293,7 +305,7 @@
|
|||||||
</CheckBox.Style>
|
</CheckBox.Style>
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
|
||||||
<CheckBox Margin="2" Content="Place assembly-level attributes in separate files">
|
<CheckBox Name="cbSeparateAttributes" Margin="2" Content="Place assembly-level attributes in separate files">
|
||||||
<CheckBox.Style>
|
<CheckBox.Style>
|
||||||
<Style>
|
<Style>
|
||||||
<Setter Property="CheckBox.IsChecked" Value="True"/>
|
<Setter Property="CheckBox.IsChecked" Value="True"/>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ using System.Windows.Navigation;
|
|||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using Il2CppInspector;
|
using Il2CppInspector;
|
||||||
|
using Il2CppInspector.Outputs;
|
||||||
using Il2CppInspector.Reflection;
|
using Il2CppInspector.Reflection;
|
||||||
using Ookii.Dialogs.Wpf;
|
using Ookii.Dialogs.Wpf;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
@@ -194,9 +195,7 @@ namespace Il2CppInspectorGUI
|
|||||||
openFolderDialog.UseDescriptionForTitle = true;
|
openFolderDialog.UseDescriptionForTitle = true;
|
||||||
|
|
||||||
while (openFolderDialog.ShowDialog() == true) {
|
while (openFolderDialog.ShowDialog() == true) {
|
||||||
if (!File.Exists(openFolderDialog.SelectedPath + @"\Editor\Data\Managed\UnityEditor.dll"))
|
if (ValidateUnityPath(openFolderDialog.SelectedPath)) {
|
||||||
MessageBox.Show(this, "Could not find Unity installation in this folder. Ensure the 'Editor' folder is a child of the selected folder and try again.", "Unity installation not found", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
else {
|
|
||||||
txtUnityPath.Text = openFolderDialog.SelectedPath;
|
txtUnityPath.Text = openFolderDialog.SelectedPath;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -215,14 +214,160 @@ namespace Il2CppInspectorGUI
|
|||||||
openFolderDialog.UseDescriptionForTitle = true;
|
openFolderDialog.UseDescriptionForTitle = true;
|
||||||
|
|
||||||
while (openFolderDialog.ShowDialog() == true) {
|
while (openFolderDialog.ShowDialog() == true) {
|
||||||
if (!File.Exists(openFolderDialog.SelectedPath + @"\UnityEngine.UI.dll"))
|
if (ValidateUnityAssembliesPath(openFolderDialog.SelectedPath)) {
|
||||||
MessageBox.Show(this, "Could not find Unity assemblies in this folder. Ensure the selected folder contains UnityEngine.UI.dll and try again.", "Unity assemblies not found", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
else {
|
|
||||||
txtUnityScriptPath.Text = openFolderDialog.SelectedPath;
|
txtUnityScriptPath.Text = openFolderDialog.SelectedPath;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ValidateUnityPath(string path) {
|
||||||
|
if (File.Exists(path + @"\Editor\Data\Managed\UnityEditor.dll"))
|
||||||
|
return true;
|
||||||
|
MessageBox.Show(this, "Could not find Unity installation in this folder. Ensure the 'Editor' folder is a child of the selected folder and try again.", "Unity installation not found", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidateUnityAssembliesPath(string path) {
|
||||||
|
if (File.Exists(path + @"\UnityEngine.UI.dll"))
|
||||||
|
return true;
|
||||||
|
MessageBox.Show(this, "Could not find Unity assemblies in this folder. Ensure the selected folder contains UnityEngine.UI.dll and try again.", "Unity assemblies not found", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perform export
|
||||||
|
/// </summary>
|
||||||
|
private void BtnExport_OnClick(object sender, RoutedEventArgs e) {
|
||||||
|
var app = (App) Application.Current;
|
||||||
|
var model = (Il2CppModel) lstImages.SelectedItem;
|
||||||
|
|
||||||
|
var unityPath = txtUnityPath.Text;
|
||||||
|
var unityAssembliesPath = txtUnityScriptPath.Text;
|
||||||
|
|
||||||
|
var sortOrder = rdoSortIndex.IsChecked == true ? "index" :
|
||||||
|
rdoSortName.IsChecked == true ? "name" :
|
||||||
|
"unknown";
|
||||||
|
var layout = rdoLayoutSingle.IsChecked == true? "single" :
|
||||||
|
rdoLayoutAssembly.IsChecked == true? "assembly" :
|
||||||
|
rdoLayoutNamespace.IsChecked == true? "namespace" :
|
||||||
|
rdoLayoutClass.IsChecked == true? "class" :
|
||||||
|
rdoLayoutTree.IsChecked == true? "tree" :
|
||||||
|
"unknown";
|
||||||
|
|
||||||
|
switch (this) {
|
||||||
|
// C# prototypes and Visual Studio solution
|
||||||
|
case { rdoOutputCSharp: var r, rdoOutputSolution: var s } when r.IsChecked == true || s.IsChecked == true:
|
||||||
|
|
||||||
|
var createSolution = rdoOutputSolution.IsChecked == true;
|
||||||
|
|
||||||
|
if (createSolution) {
|
||||||
|
if (!ValidateUnityPath(unityPath))
|
||||||
|
return;
|
||||||
|
if (!ValidateUnityAssembliesPath(unityAssembliesPath))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get options
|
||||||
|
var excludedNamespaces = constructExcludedNamespaces((IEnumerable<CheckboxNode>) trvNamespaces.ItemsSource);
|
||||||
|
|
||||||
|
var writer = new CSharpCodeStubs(model) {
|
||||||
|
ExcludedNamespaces = excludedNamespaces.ToList(),
|
||||||
|
SuppressMetadata = cbSuppressMetadata.IsChecked == true,
|
||||||
|
MustCompile = cbMustCompile.IsChecked == true
|
||||||
|
};
|
||||||
|
|
||||||
|
var flattenHierarchy = cbFlattenHierarchy.IsChecked == true;
|
||||||
|
var separateAssemblyAttributesFiles = cbSeparateAttributes.IsChecked == true;
|
||||||
|
|
||||||
|
// Determine if we need a filename or a folder - file for single file, folder for everything else
|
||||||
|
var needsFolder = rdoOutputCSharp.IsChecked == false || rdoLayoutSingle.IsChecked == false;
|
||||||
|
|
||||||
|
var saveFolderDialog = new VistaFolderBrowserDialog {
|
||||||
|
Description = "Select save location",
|
||||||
|
UseDescriptionForTitle = true
|
||||||
|
};
|
||||||
|
var saveFileDialog = new SaveFileDialog {
|
||||||
|
Filter = "C# source files (*.cs)|*.cs|All files (*.*)|*.*",
|
||||||
|
CheckFileExists = false,
|
||||||
|
OverwritePrompt = true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (needsFolder && saveFolderDialog.ShowDialog() == false)
|
||||||
|
return;
|
||||||
|
if (!needsFolder && saveFileDialog.ShowDialog() == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var outPath = needsFolder ? saveFolderDialog.SelectedPath : saveFileDialog.FileName;
|
||||||
|
|
||||||
|
if (createSolution)
|
||||||
|
writer.WriteSolution(outPath, unityPath, unityAssembliesPath);
|
||||||
|
|
||||||
|
else
|
||||||
|
switch (layout, sortOrder) {
|
||||||
|
case ("single", "index"):
|
||||||
|
writer.WriteSingleFile(outPath, t => t.Index);
|
||||||
|
break;
|
||||||
|
case ("single", "name"):
|
||||||
|
writer.WriteSingleFile(outPath, t => t.Name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ("namespace", "index"):
|
||||||
|
writer.WriteFilesByNamespace(outPath, t => t.Index, flattenHierarchy);
|
||||||
|
break;
|
||||||
|
case ("namespace", "name"):
|
||||||
|
writer.WriteFilesByNamespace(outPath, t => t.Name, flattenHierarchy);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ("assembly", "index"):
|
||||||
|
writer.WriteFilesByAssembly(outPath, t => t.Index, separateAssemblyAttributesFiles);
|
||||||
|
break;
|
||||||
|
case ("assembly", "name"):
|
||||||
|
writer.WriteFilesByAssembly(outPath, t => t.Name, separateAssemblyAttributesFiles);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ("class", _):
|
||||||
|
writer.WriteFilesByClass(outPath, flattenHierarchy);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ("tree", _):
|
||||||
|
writer.WriteFilesByClassTree(outPath, separateAssemblyAttributesFiles);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// IDA Python script
|
||||||
|
case { rdoOutputIDA: var r } when r.IsChecked == true:
|
||||||
|
|
||||||
|
var scriptSaveFileDialog = new SaveFileDialog {
|
||||||
|
Filter = "Python scripts (*.py)|*.py|All files (*.*)|*.*",
|
||||||
|
CheckFileExists = false,
|
||||||
|
OverwritePrompt = true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (scriptSaveFileDialog.ShowDialog() == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var outFile = scriptSaveFileDialog.FileName;
|
||||||
|
|
||||||
|
var idaWriter = new IDAPythonScript(model);
|
||||||
|
idaWriter.WriteScriptToFile(outFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> constructExcludedNamespaces(IEnumerable<CheckboxNode> nodes) {
|
||||||
|
var ns = new List<string>();
|
||||||
|
|
||||||
|
foreach (var node in nodes) {
|
||||||
|
if (node.IsChecked == false)
|
||||||
|
ns.Add(node.FullName);
|
||||||
|
|
||||||
|
else if (node.Children != null)
|
||||||
|
ns.AddRange(constructExcludedNamespaces(node.Children));
|
||||||
|
}
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replacement for TreeViewItem that includes checkbox state
|
// Replacement for TreeViewItem that includes checkbox state
|
||||||
@@ -242,6 +387,8 @@ namespace Il2CppInspectorGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string FullName => (parent != null ? parent.FullName + "." : "") + Name;
|
||||||
|
|
||||||
public IEnumerable<CheckboxNode> Children {
|
public IEnumerable<CheckboxNode> Children {
|
||||||
get => children;
|
get => children;
|
||||||
set {
|
set {
|
||||||
|
|||||||
Reference in New Issue
Block a user