Refactor right click commands

This commit is contained in:
LongerWarrior 2026-03-16 21:47:08 +02:00
parent 639f21e574
commit 36ad881a8d
8 changed files with 161 additions and 204 deletions

View File

@ -107,6 +107,7 @@ public enum EBulkType
Animations = 1 << 4,
Audio = 1 << 5,
Code = 1 << 6,
Raw = 1 << 7,
}
public enum EAssetCategory : uint

View File

@ -598,6 +598,9 @@ public class CUE4ParseViewModel : ViewModel
foreach (var f in folder.Folders) ExportFolder(cancellationToken, f);
}
public void ExtractFolder(CancellationToken cancellationToken, TreeItem folder, EBulkType bulk)
=> BulkFolder(cancellationToken, folder, asset => Extract(cancellationToken, asset, TabControl.HasNoTabs, bulk));
public void ExtractFolder(CancellationToken cancellationToken, TreeItem folder)
=> BulkFolder(cancellationToken, folder, asset => Extract(cancellationToken, asset, TabControl.HasNoTabs));

View File

@ -1,7 +1,10 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Threading;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.Utils;
using FModel.Framework;
using FModel.Services;
using FModel.Settings;
@ -17,6 +20,21 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
{
}
private enum EAction
{
Show,
Export,
}
private enum EShowAssetType
{
None,
JSON,
Metadata,
References,
Decompile,
}
public override async void Execute(ApplicationViewModel contextViewModel, object parameter)
{
if (parameter is not object[] parameters || parameters[0] is not string trigger)
@ -26,188 +44,123 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
if (param.Length == 0) return;
var folders = param.OfType<TreeItem>().ToArray();
var assets = param.SelectMany(item => item switch
{
GameFile gf => new[] { gf }, // search view passes GameFile directly
GameFileViewModel gvm => new[] { gvm.Asset },
_ => []
}).ToArray();
var assets = param
.Select(static item => item switch
{
GameFile gf => gf,
GameFileViewModel gvm => gvm.Asset,
_ => null
})
.Where(static gf => gf is not null).ToArray();
if (folders.Length == 0 && assets.Length == 0)
return;
var updateUi = assets.Length > 1 ? EBulkType.Auto : EBulkType.None;
var assetsGroups = assets.GroupBy(static gf => gf.Directory);
var (action, showtype, bulktype) = trigger switch
{
"Assets_Extract_New_Tab" => (EAction.Show, EShowAssetType.JSON, EBulkType.None),
"Assets_Show_Metadata" => (EAction.Show, EShowAssetType.Metadata, EBulkType.None),
"Assets_Show_References" => (EAction.Show, EShowAssetType.References, EBulkType.None),
"Assets_Decompile" => (EAction.Show, EShowAssetType.Decompile, EBulkType.Code),
"Save_Data" => (EAction.Export, EShowAssetType.None, EBulkType.Raw),
"Save_Properties" => (EAction.Export, EShowAssetType.None, EBulkType.Properties),
"Save_Textures" => (EAction.Export, EShowAssetType.None, EBulkType.Textures),
"Save_Models" => (EAction.Export, EShowAssetType.None, EBulkType.Meshes),
"Save_Animations" => (EAction.Export, EShowAssetType.None, EBulkType.Animations),
"Save_Audio" => (EAction.Export, EShowAssetType.None, EBulkType.Audio),
_ => throw new ArgumentOutOfRangeException("Unsupported asset action."),
};
await _threadWorkerView.Begin(cancellationToken =>
{
switch (trigger)
if (action is EAction.Show)
{
#region Asset Commands
case "Assets_Extract_New_Tab":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Extract(cancellationToken, entry, true);
}
break;
case "Assets_Show_Metadata":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.ShowMetadata(entry);
}
break;
case "Assets_Show_References":
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.FindReferences(assets.FirstOrDefault());
}
break;
case "Assets_Decompile":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Decompile(entry);
}
break;
case "Assets_Export_Data":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.ExportData(entry);
}
break;
case "Assets_Save_Properties":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Extract(cancellationToken, entry, false, EBulkType.Properties | updateUi);
}
break;
case "Assets_Save_Textures":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Extract(cancellationToken, entry, false, EBulkType.Textures | updateUi);
}
break;
case "Assets_Save_Models":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Extract(cancellationToken, entry, false, EBulkType.Meshes | updateUi);
}
break;
case "Assets_Save_Animations":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Extract(cancellationToken, entry, false, EBulkType.Animations | updateUi);
}
break;
case "Assets_Save_Audio":
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.Extract(cancellationToken, entry, false, EBulkType.Audio | updateUi);
}
break;
#endregion
if (showtype is EShowAssetType.References)
assets = [assets.FirstOrDefault()];
#region Folder Commands
case "Folders_Export_Data":
foreach (var folder in folders)
{
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.ExportFolder(cancellationToken, folder);
Action<GameFile> entryAction = showtype switch
{
EShowAssetType.JSON => entry => contextViewModel.CUE4Parse.Extract(cancellationToken, entry, true),
EShowAssetType.Metadata => entry => contextViewModel.CUE4Parse.ShowMetadata(entry),
EShowAssetType.Decompile => entry => contextViewModel.CUE4Parse.Decompile(entry),
EShowAssetType.References => entry => contextViewModel.CUE4Parse.FindReferences(entry),
_ => throw new ArgumentOutOfRangeException("Unsupported asset action type."),
};
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully exported ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.RawDataDirectory, true);
});
}
break;
case "Folders_Save_Properties":
foreach (var folder in folders)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.SaveFolder(cancellationToken, folder);
foreach (var entry in assets)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
entryAction(entry);
}
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.PropertiesDirectory, true);
});
}
break;
case "Folders_Save_Textures":
foreach (var folder in folders)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.TextureFolder(cancellationToken, folder);
return;
}
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved textures from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.TextureDirectory, true);
});
}
break;
case "Folders_Save_Models":
foreach (var folder in folders)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.ModelFolder(cancellationToken, folder);
var (dirType, filetype) = bulktype switch
{
EBulkType.Raw => (UserSettings.Default.RawDataDirectory, "files"),
EBulkType.Properties => (UserSettings.Default.PropertiesDirectory, "json files"),
EBulkType.Textures => (UserSettings.Default.TextureDirectory, "textures"),
EBulkType.Meshes => (UserSettings.Default.ModelDirectory, "models"),
EBulkType.Animations => (UserSettings.Default.ModelDirectory, "animations"),
EBulkType.Audio => (UserSettings.Default.AudioDirectory, "audio files"),
_ => (null, null),
};
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved models from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.ModelDirectory, true);
});
}
break;
case "Folders_Save_Animations":
foreach (var folder in folders)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.AnimationFolder(cancellationToken, folder);
if (string.IsNullOrEmpty(dirType))
return;
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved animations from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.ModelDirectory, true);
});
}
break;
case "Folders_Save_Audio":
foreach (var folder in folders)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
contextViewModel.CUE4Parse.AudioFolder(cancellationToken, folder);
Action<TreeItem> folderAction = bulktype switch
{
EBulkType.Raw => folder => contextViewModel.CUE4Parse.ExportFolder(cancellationToken, folder),
_ => folder => contextViewModel.CUE4Parse.ExtractFolder(cancellationToken, folder, bulktype | EBulkType.Auto),
};
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved audio from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.AudioDirectory, true);
});
}
break;
#endregion
foreach (var folder in folders)
{
cancellationToken.ThrowIfCancellationRequested();
folderAction(folder);
var path = Path.Combine(dirType, UserSettings.Default.KeepDirectoryStructure ? folder.PathAtThisPoint : folder.PathAtThisPoint.SubstringAfterLast('/')).Replace('\\', '/');
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully exported {filetype} from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, path, true);
});
}
Action<GameFile, EBulkType, bool> fileAction = bulktype switch
{
EBulkType.Raw => (entry, _, update) => contextViewModel.CUE4Parse.ExportData(entry, !update),
_ => (entry, bulk, update) => contextViewModel.CUE4Parse.Extract(cancellationToken, entry, false, bulk),
};
foreach (var group in assetsGroups)
{
var directory = group.Key;
var list = group.ToArray();
var update = list.Length > 1;
var bulk = bulktype | (update ? EBulkType.Auto : EBulkType.None);
foreach (var entry in list)
{
Thread.Yield();
cancellationToken.ThrowIfCancellationRequested();
fileAction(entry, bulk, update);
}
if (update)
{
var path = Path.Combine(dirType, UserSettings.Default.KeepDirectoryStructure ? directory : directory.SubstringAfterLast('/')).Replace('\\', '/');
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully exported {list.Length} {filetype} from ", Constants.WHITE);
FLogger.Link(directory, path, true);
});
}
}
});
}

View File

@ -34,34 +34,34 @@ public class TabCommand : ViewModelCommand<TabItem>
case "Find_References":
_applicationView.CUE4Parse.FindReferences(tabViewModel.Entry);
break;
case "Asset_Export_Data":
case "Save_Data":
await _threadWorkerView.Begin(_ => _applicationView.CUE4Parse.ExportData(tabViewModel.Entry));
break;
case "Asset_Save_Properties":
case "Save_Properties":
await _threadWorkerView.Begin(cancellationToken =>
{
_applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Properties);
});
break;
case "Asset_Save_Textures":
case "Save_Textures":
await _threadWorkerView.Begin(cancellationToken =>
{
_applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Textures);
});
break;
case "Asset_Save_Models":
case "Save_Models":
await _threadWorkerView.Begin(cancellationToken =>
{
_applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Meshes);
});
break;
case "Asset_Save_Animations":
case "Save_Animations":
await _threadWorkerView.Begin(cancellationToken =>
{
_applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Animations);
});
break;
case "Asset_Save_Audio":
case "Save_Audio":
await _threadWorkerView.Begin(cancellationToken =>
{
_applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Audio);

View File

@ -120,7 +120,7 @@
</MenuItem.Header>
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Export_Data" />
<Binding Source="Save_Data" />
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -135,7 +135,7 @@
<MenuItem Header="Save Properties (.json)" Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Properties" />
<Binding Source="Save_Properties" />
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -150,7 +150,7 @@
<MenuItem Header="Save Texture" Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Textures" />
<Binding Source="Save_Textures" />
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -176,7 +176,7 @@
<MenuItem Header="Save Model" Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Models" />
<Binding Source="Save_Models" />
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -202,7 +202,7 @@
<MenuItem Header="Save Animation" Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Animations" />
<Binding Source="Save_Animations" />
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -228,7 +228,7 @@
<MenuItem Header="Save Audio" Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Audio" />
<Binding Source="Save_Audio" />
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
</MenuItem.CommandParameter>

View File

@ -9,7 +9,7 @@
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Export_Data" />
<Binding Source="Save_Data" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
@ -29,7 +29,7 @@
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Save_Properties" />
<Binding Source="Save_Properties" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
@ -49,7 +49,7 @@
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Save_Textures" />
<Binding Source="Save_Textures" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
@ -69,7 +69,7 @@
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Save_Models" />
<Binding Source="Save_Models" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
@ -89,7 +89,7 @@
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Save_Animations" />
<Binding Source="Save_Animations" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>
@ -109,7 +109,7 @@
Command="{Binding RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Folders_Save_Audio" />
<Binding Source="Save_Audio" />
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
</MultiBinding>

View File

@ -926,7 +926,7 @@
</MenuItem.IsEnabled>
</MenuItem>
<Separator />
<MenuItem Command="{Binding TabCommand}" CommandParameter="Asset_Export_Data">
<MenuItem Command="{Binding TabCommand}" CommandParameter="Save_Data">
<MenuItem.Header>
<TextBlock Text="{Binding Entry.Extension, FallbackValue='Export Raw Data', StringFormat='Export Raw Data (.{0})'}" />
</MenuItem.Header>
@ -938,7 +938,7 @@
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Properties (.json)" Command="{Binding TabCommand}" CommandParameter="Asset_Save_Properties">
<MenuItem Header="Save Properties (.json)" Command="{Binding TabCommand}" CommandParameter="Save_Properties">
<MenuItem.Icon>
<Viewbox Width="16" Height="16">
<Canvas Width="24" Height="24">
@ -947,7 +947,7 @@
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Texture" Command="{Binding TabCommand}" CommandParameter="Asset_Save_Textures">
<MenuItem Header="Save Texture" Command="{Binding TabCommand}" CommandParameter="Save_Textures">
<MenuItem.Icon>
<Viewbox Width="16" Height="16">
<Canvas Width="24" Height="24">
@ -956,7 +956,7 @@
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Model" Command="{Binding TabCommand}" CommandParameter="Asset_Save_Models">
<MenuItem Header="Save Model" Command="{Binding TabCommand}" CommandParameter="Save_Models">
<MenuItem.Icon>
<Viewbox Width="16" Height="16">
<Canvas Width="24" Height="24">
@ -965,7 +965,7 @@
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Animation" Command="{Binding TabCommand}" CommandParameter="Asset_Save_Animations">
<MenuItem Header="Save Animation" Command="{Binding TabCommand}" CommandParameter="Save_Animations">
<MenuItem.Icon>
<Viewbox Width="16" Height="16">
<Canvas Width="24" Height="24">
@ -974,7 +974,7 @@
</Viewbox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save Audio" Command="{Binding TabCommand}" CommandParameter="Asset_Save_Audio">
<MenuItem Header="Save Audio" Command="{Binding TabCommand}" CommandParameter="Save_Audio">
<MenuItem.Icon>
<Viewbox Width="16" Height="16">
<Canvas Width="24" Height="24">

View File

@ -216,7 +216,7 @@
</MenuItem.Header>
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Export_Data" />
<Binding Source="Save_Data" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -231,7 +231,7 @@
<MenuItem Header="Save Properties (.json)" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Properties" />
<Binding Source="Save_Properties" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -246,7 +246,7 @@
<MenuItem Header="Save Texture" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Textures" />
<Binding Source="Save_Textures" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -261,7 +261,7 @@
<MenuItem Header="Save Model" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Models" />
<Binding Source="Save_Models" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -276,7 +276,7 @@
<MenuItem Header="Save Animation" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Animations" />
<Binding Source="Save_Animations" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -291,7 +291,7 @@
<MenuItem Header="Save Audio" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Audio" />
<Binding Source="Save_Audio" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -561,7 +561,7 @@
</MenuItem.Header>
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Export_Data" />
<Binding Source="Save_Data" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -576,7 +576,7 @@
<MenuItem Header="Save Properties (.json)" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Properties" />
<Binding Source="Save_Properties" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -591,7 +591,7 @@
<MenuItem Header="Save Texture" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Textures" />
<Binding Source="Save_Textures" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -606,7 +606,7 @@
<MenuItem Header="Save Model" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Models" />
<Binding Source="Save_Models" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -621,7 +621,7 @@
<MenuItem Header="Save Animation" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Animations" />
<Binding Source="Save_Animations" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>
@ -636,7 +636,7 @@
<MenuItem Header="Save Audio" Command="{Binding DataContext.mainApplication.RightClickMenuCommand}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Save_Audio" />
<Binding Source="Save_Audio" />
<Binding Path="SelectedItems" />
</MultiBinding>
</MenuItem.CommandParameter>