Bulk Blueprint Decompilation on folders

This commit is contained in:
Krowe Moh 2026-03-24 20:48:59 +11:00
parent ceb6d08268
commit 01c19f9a84
8 changed files with 78 additions and 4 deletions

View File

@ -92,6 +92,12 @@ public partial class App
UserSettings.Default.AudioDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
}
if (!Directory.Exists(UserSettings.Default.CodeDirectory))
{
createMe = true;
UserSettings.Default.CodeDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
}
if (!Directory.Exists(UserSettings.Default.ModelDirectory))
{
createMe = true;

View File

@ -119,6 +119,13 @@ namespace FModel.Settings
set => SetProperty(ref _audioDirectory, value);
}
private string _codeDirectory;
public string CodeDirectory
{
get => _codeDirectory;
set => SetProperty(ref _codeDirectory, value);
}
private string _modelDirectory;
public string ModelDirectory
{

View File

@ -628,6 +628,9 @@ public class CUE4ParseViewModel : ViewModel
public void AudioFolder(CancellationToken cancellationToken, TreeItem folder)
=> BulkFolder(cancellationToken, folder, asset => Extract(cancellationToken, asset, TabControl.HasNoTabs, EBulkType.Audio | EBulkType.Auto));
public void CodeFolder(CancellationToken cancellationToken, TreeItem folder)
=> BulkFolder(cancellationToken, folder, asset => Extract(cancellationToken, asset, TabControl.HasNoTabs, EBulkType.Code | EBulkType.Auto));
public void Extract(CancellationToken cancellationToken, GameFile entry, bool addNewTab = false, EBulkType bulk = EBulkType.None)
{
ApplicationService.ApplicationView.IsAssetsExplorerVisible = false;
@ -641,6 +644,7 @@ public class CUE4ParseViewModel : ViewModel
var saveProperties = HasFlag(bulk, EBulkType.Properties);
var saveTextures = HasFlag(bulk, EBulkType.Textures);
var saveAudio = HasFlag(bulk, EBulkType.Audio);
var saveDecompiled = HasFlag(bulk, EBulkType.Code);
switch (entry.Extension)
{
case "uasset":
@ -655,6 +659,13 @@ public class CUE4ParseViewModel : ViewModel
if (saveProperties) break; // do not search for viewable exports if we are dealing with jsons
}
if (saveDecompiled)
{
if (Decompile(entry, false))
TabControl.SelectedTab.SaveDecompiled(updateUi);
break;
}
for (var i = result.InclusiveStart; i < result.ExclusiveEnd; i++)
{
if (CheckExport(cancellationToken, result.Package, i, bulk))
@ -1364,11 +1375,13 @@ public class CUE4ParseViewModel : ViewModel
}
public void Decompile(GameFile entry)
public bool Decompile(GameFile entry, bool AddTab = true)
{
ApplicationService.ApplicationView.IsAssetsExplorerVisible = false;
if (TabControl.CanAddTabs) TabControl.AddTab(entry);
if (TabControl.CanAddTabs && AddTab)
{
ApplicationService.ApplicationView.IsAssetsExplorerVisible = false;
TabControl.AddTab(entry);
}
else TabControl.SelectedTab.SoftReset(entry);
TabControl.SelectedTab.TitleExtra = "Decompiled";
@ -1410,6 +1423,7 @@ public class CUE4ParseViewModel : ViewModel
cpp = Regex.Replace(cpp, @"K2Node_([A-Za-z0-9_]+)", "$1");
TabControl.SelectedTab.SetDocumentText(cpp, false, false);
return cpp.Length > 0;
}
private void SaveAndPlaySound(CancellationToken cancellationToken, string fullPath, string ext, byte[] data, bool isBulk, bool updateUi)

View File

@ -207,6 +207,20 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
});
}
break;
case "Folders_Save_Code":
foreach (var folder in folders)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.CodeFolder(cancellationToken, folder);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved decompiled blueprints from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.CodeDirectory, true);
});
}
break;
#endregion
}
});

View File

@ -195,6 +195,7 @@ public class SettingsViewModel : ViewModel
private string _propertiesSnapshot;
private string _textureSnapshot;
private string _audioSnapshot;
private string _codeSnapshot;
private string _modelSnapshot;
private string _gameSnapshot;
private ETexturePlatform _uePlatformSnapshot;
@ -227,6 +228,7 @@ public class SettingsViewModel : ViewModel
_propertiesSnapshot = UserSettings.Default.PropertiesDirectory;
_textureSnapshot = UserSettings.Default.TextureDirectory;
_audioSnapshot = UserSettings.Default.AudioDirectory;
_codeSnapshot = UserSettings.Default.CodeDirectory;
_modelSnapshot = UserSettings.Default.ModelDirectory;
_gameSnapshot = UserSettings.Default.GameDirectory;
_uePlatformSnapshot = UserSettings.Default.CurrentDir.TexturePlatform;

View File

@ -407,7 +407,17 @@ public class TabItem : ViewModel
Application.Current.Dispatcher.Invoke(() => File.WriteAllText(directory, Document.Text));
SaveCheck(directory, fileName, updateUi);
}
public void SaveDecompiled(bool updateUi)
{
var fileName = Path.ChangeExtension(Entry.Name, ".cpp");
var directory = Path.Combine(UserSettings.Default.PropertiesDirectory,
UserSettings.Default.KeepDirectoryStructure ? Entry.Directory : "", fileName).Replace('\\', '/');
Directory.CreateDirectory(directory.SubstringBeforeLast('/'));
Application.Current.Dispatcher.Invoke(() => File.WriteAllText(directory, Document.Text));
SaveCheck(directory, fileName, updateUi);
}
private void SaveCheck(string path, string fileName, bool updateUi)
{
if (File.Exists(path))

View File

@ -65,6 +65,26 @@
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Folder's Decompiled Blueprints"
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Save_Code" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>
<MenuItem.Icon>
<Viewbox Width="16"
Height="16">
<Canvas Width="24"
Height="24">
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}"
Data="{StaticResource CodeIcon}" />
</Canvas>
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Folder's Packages Models"
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>

View File

@ -76,6 +76,7 @@ public partial class SettingsView
UserSettings.Default.PropertiesDirectory = path;
UserSettings.Default.TextureDirectory = path;
UserSettings.Default.AudioDirectory = path;
UserSettings.Default.CodeDirectory = path;
}
private void OnBrowseDirectories(object sender, RoutedEventArgs e)