mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
Option for bulk audio conversion (#646)
Some checks failed
FModel QA Builder / build (push) Has been cancelled
Some checks failed
FModel QA Builder / build (push) Has been cancelled
This commit is contained in:
parent
1c48a27f8e
commit
500fa59f85
|
|
@ -1 +1 @@
|
|||
Subproject commit a451f8e3140c806da8b438e9b44dafe4c1c0a37b
|
||||
Subproject commit 1861416d2ab765cde91eec6f46305fc316dfae6e
|
||||
|
|
@ -266,6 +266,13 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _readShaderMaps, value);
|
||||
}
|
||||
|
||||
private bool _convertAudioOnBulkExport;
|
||||
public bool ConvertAudioOnBulkExport
|
||||
{
|
||||
get => _convertAudioOnBulkExport;
|
||||
set => SetProperty(ref _convertAudioOnBulkExport, value);
|
||||
}
|
||||
|
||||
private IDictionary<string, DirectorySettings> _perDirectory = new Dictionary<string, DirectorySettings>();
|
||||
public IDictionary<string, DirectorySettings> PerDirectory
|
||||
{
|
||||
|
|
|
|||
|
|
@ -655,7 +655,7 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable
|
|||
}
|
||||
|
||||
private bool TryConvert(out string wavFilePath) => TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, out wavFilePath);
|
||||
private bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath)
|
||||
public static bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath)
|
||||
{
|
||||
wavFilePath = string.Empty;
|
||||
var vgmFilePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", "test.exe");
|
||||
|
|
|
|||
|
|
@ -780,7 +780,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
case "bank":
|
||||
{
|
||||
var archive = entry.CreateReader();
|
||||
if (!FModProvider.TryLoadBank(archive, entry.NameWithoutExtension, out var fmodReader))
|
||||
if (!FmodProvider.TryLoadBank(archive, entry.NameWithoutExtension, out var fmodReader))
|
||||
{
|
||||
Log.Error($"Failed to load FMOD bank {entry.Path}");
|
||||
break;
|
||||
|
|
@ -792,7 +792,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var directory = Path.GetDirectoryName(entry.Path) ?? "/FMOD/Desktop/";
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -807,7 +807,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var medias = WwiseProvider.ExtractBankSounds(wwise);
|
||||
foreach (var media in medias)
|
||||
{
|
||||
SaveAndPlaySound(media.OutputPath, media.Extension, media.Data, saveAudio);
|
||||
SaveAndPlaySound(media.OutputPath, media.Extension, media.Data, saveAudio, updateUi);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -823,7 +823,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var extractedSounds = CriWareProvider.ExtractCriWareSounds(awbReader, archive.Name);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -839,7 +839,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var extractedSounds = CriWareProvider.ExtractCriWareSounds(acbReader, archive.Name);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -854,7 +854,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
// todo: CSCore.MediaFoundation.MediaFoundationException The byte stream type of the given URL is unsupported. case "aif":
|
||||
{
|
||||
var data = Provider.SaveAsset(entry);
|
||||
SaveAndPlaySound(entry.PathWithoutExtension, entry.Extension, data, saveAudio);
|
||||
SaveAndPlaySound(entry.PathWithoutExtension, entry.Extension, data, saveAudio, updateUi);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -1114,7 +1114,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
case UExternalSource when (isNone || saveAudio) && pointer.Object.Value is UExternalSource externalSource:
|
||||
{
|
||||
var audioName = Path.GetFileNameWithoutExtension(externalSource.ExternalSourcePath);
|
||||
SaveAndPlaySound(audioName, "wem", externalSource.Data?.WemFile ?? [], saveAudio);
|
||||
SaveAndPlaySound(audioName, "wem", externalSource.Data?.WemFile ?? [], saveAudio, updateUi);
|
||||
return false;
|
||||
}
|
||||
case UAkAudioEvent when (isNone || saveAudio) && pointer.Object.Value is UAkAudioEvent audioEvent:
|
||||
|
|
@ -1122,7 +1122,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var extractedSounds = WwiseProvider.ExtractAudioEventSounds(audioEvent);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1132,7 +1132,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var directory = Path.GetDirectoryName(fmodEvent.Owner?.Name) ?? "/FMOD/Desktop/";
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1142,7 +1142,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var directory = Path.GetDirectoryName(fmodBank.Owner?.Name) ?? "/FMOD/Desktop/";
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name), sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1161,7 +1161,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
directory = Path.GetDirectoryName(atomObject.Owner.Provider.FixPath(directory));
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name).Replace("\\", "/"), sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(Path.Combine(directory, sound.Name).Replace("\\", "/"), sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1181,7 +1181,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
return false;
|
||||
}
|
||||
|
||||
SaveAndPlaySound(TabControl.SelectedTab.Entry.PathWithoutExtension.Replace('\\', '/'), audioFormat, data, saveAudio);
|
||||
SaveAndPlaySound(TabControl.SelectedTab.Entry.PathWithoutExtension.Replace('\\', '/'), audioFormat, data, saveAudio, updateUi);
|
||||
return false;
|
||||
}
|
||||
case UAkMediaAsset when (isNone || saveAudio) && pointer.Object.Value is UAkMediaAsset akMediaAsset:
|
||||
|
|
@ -1192,7 +1192,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var shouldDecompress = UserSettings.Default.CompressedAudioMode is ECompressedAudio.PlayDecompressed;
|
||||
akMediaAssetData.Decode(shouldDecompress, out var audioFormat, out var data);
|
||||
|
||||
SaveAndPlaySound(audioName, audioFormat, data, saveAudio);
|
||||
SaveAndPlaySound(audioName, audioFormat, data, saveAudio, updateUi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1208,7 +1208,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var audioName = akMediaAsset.MediaName ?? $"{akAudioEventData.Outer.Name} ({akMediaAsset.ID})";
|
||||
akMediaAssetData.Decode(shouldDecompress, out var audioFormat, out var data);
|
||||
|
||||
SaveAndPlaySound(audioName, audioFormat, data, saveAudio);
|
||||
SaveAndPlaySound(audioName, audioFormat, data, saveAudio, updateUi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1225,7 +1225,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var extractedSounds = WwiseProvider.ExtractAudioEventBorderlands4(faceFXAnimData.ID.Name, false);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1239,7 +1239,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
var extractedSounds = WwiseProvider.ExtractAudioEventBorderlands4(eventName, useSoundTag);
|
||||
foreach (var sound in extractedSounds)
|
||||
{
|
||||
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio);
|
||||
SaveAndPlaySound(sound.OutputPath, sound.Extension, sound.Data, saveAudio, updateUi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1379,7 +1379,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
TabControl.SelectedTab.SetDocumentText(cpp, false, false);
|
||||
}
|
||||
|
||||
private void SaveAndPlaySound(string fullPath, string ext, byte[] data, bool isBulk)
|
||||
private void SaveAndPlaySound(string fullPath, string ext, byte[] data, bool isBulk, bool updateUi)
|
||||
{
|
||||
if (fullPath.StartsWith('/')) fullPath = fullPath[1..];
|
||||
var savedAudioPath = Path.Combine(UserSettings.Default.AudioDirectory,
|
||||
|
|
@ -1389,9 +1389,28 @@ public class CUE4ParseViewModel : ViewModel
|
|||
{
|
||||
Directory.CreateDirectory(savedAudioPath.SubstringBeforeLast('/'));
|
||||
using var stream = new FileStream(savedAudioPath, FileMode.Create, FileAccess.Write);
|
||||
using var writer = new BinaryWriter(stream);
|
||||
writer.Write(data);
|
||||
writer.Flush();
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
{
|
||||
writer.Write(data);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
if (UserSettings.Default.ConvertAudioOnBulkExport)
|
||||
{
|
||||
AudioPlayerViewModel.TryConvert(savedAudioPath, data, out string wavFilePath);
|
||||
savedAudioPath = wavFilePath;
|
||||
}
|
||||
|
||||
Log.Information("Successfully saved {FilePath}", savedAudioPath);
|
||||
if (updateUi)
|
||||
{
|
||||
FLogger.Append(ELog.Information, () =>
|
||||
{
|
||||
FLogger.Text("Successfully saved ", Constants.WHITE);
|
||||
FLogger.Link(Path.GetFileName(savedAudioPath), savedAudioPath, true);
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public class MenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
Process.Start(new ProcessStartInfo { FileName = Constants.DISCORD_LINK, UseShellExecute = true });
|
||||
break;
|
||||
case "ToolBox_Clear_Logs":
|
||||
FLogger.Logger.Text = string.Empty;
|
||||
FLogger.ClearLogs();
|
||||
break;
|
||||
case "ToolBox_Open_Output_Directory":
|
||||
Process.Start(new ProcessStartInfo { FileName = UserSettings.Default.OutputDirectory, UseShellExecute = true });
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using CUE4Parse.UE4.Assets.Exports.CustomizableObject;
|
|||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine.Font;
|
||||
using CUE4Parse.UE4.Assets.Exports.Fmod;
|
||||
using CUE4Parse.UE4.Assets.Exports.FMod;
|
||||
using CUE4Parse.UE4.Assets.Exports.Foliage;
|
||||
using CUE4Parse.UE4.Assets.Exports.Internationalization;
|
||||
using CUE4Parse.UE4.Assets.Exports.LevelSequence;
|
||||
|
|
@ -240,6 +241,10 @@ public class GameFileViewModel(GameFile asset) : ViewModel
|
|||
USoundAtomCue or UAkAudioEvent or USoundCue or UFMODEvent
|
||||
or UAkAssetData or UAkAssetPlatformData => (EAssetCategory.AudioEvent, EBulkType.Audio),
|
||||
|
||||
UFMODBankLookup => (EAssetCategory.Data, EBulkType.None),
|
||||
|
||||
UFMODBus or UFMODSnapshot or UFMODSnapshotReverb or UFMODVCA => (EAssetCategory.Audio, EBulkType.None),
|
||||
|
||||
UFMODBank or UAkAudioBank or UAtomWaveBank or UAkInitBank => (EAssetCategory.SoundBank, EBulkType.Audio),
|
||||
|
||||
UWwiseAssetLibrary or USoundBase or UAkMediaAssetData or UAtomCueSheet
|
||||
|
|
@ -320,7 +325,8 @@ public class GameFileViewModel(GameFile asset) : ViewModel
|
|||
private Task ResolveByExtensionAsync(EResolveCompute resolve)
|
||||
{
|
||||
Resolved |= EResolveCompute.Preview;
|
||||
switch (Asset.Extension)
|
||||
var lowercaseExtension = Asset.Extension.ToLowerInvariant();
|
||||
switch (lowercaseExtension)
|
||||
{
|
||||
case "uproject":
|
||||
case "uefnproject":
|
||||
|
|
@ -393,7 +399,7 @@ public class GameFileViewModel(GameFile asset) : ViewModel
|
|||
stream.Position = 0;
|
||||
|
||||
SKBitmap bitmap;
|
||||
if (Asset.Extension == "svg")
|
||||
if (lowercaseExtension == "svg")
|
||||
{
|
||||
var svg = new SKSvg();
|
||||
svg.Load(stream);
|
||||
|
|
@ -415,7 +421,7 @@ public class GameFileViewModel(GameFile asset) : ViewModel
|
|||
bitmap = SKBitmap.Decode(stream);
|
||||
}
|
||||
|
||||
using var image = bitmap.Encode(Asset.Extension == "jpg" ? SKEncodedImageFormat.Jpeg : SKEncodedImageFormat.Png, 100);
|
||||
using var image = bitmap.Encode(lowercaseExtension == "jpg" ? SKEncodedImageFormat.Jpeg : SKEncodedImageFormat.Png, 100);
|
||||
SetPreviewImage(image);
|
||||
|
||||
bitmap.Dispose();
|
||||
|
|
|
|||
|
|
@ -155,6 +155,12 @@ public class FLogger : ITextFormatter
|
|||
{
|
||||
new TextRange(document.ContentStart, document.ContentEnd).Text = text;
|
||||
}
|
||||
|
||||
public static void ClearLogs()
|
||||
{
|
||||
Logger.Document.Blocks.Clear();
|
||||
_previous = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomRichTextBox : RichTextBox
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
|
@ -157,7 +158,8 @@
|
|||
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="Keep Directory Structure" VerticalAlignment="Center" Margin="0 5 0 5" ToolTip="Auto-save packages following their game directory" />
|
||||
<CheckBox Grid.Row="9" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding KeepDirectoryStructure, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 0"/>
|
||||
IsChecked="{Binding KeepDirectoryStructure, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 0"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
|
||||
|
||||
<Separator Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="7" Style="{StaticResource CustomSeparator}" Tag="ADVANCED"></Separator>
|
||||
|
||||
|
|
@ -207,7 +209,8 @@
|
|||
<CheckBox Grid.Row="14" Grid.Column="2" Margin="0 5 0 10"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}"
|
||||
Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding SettingsView.MappingEndpoint.Overwrite, Mode=TwoWay}" />
|
||||
IsChecked="{Binding SettingsView.MappingEndpoint.Overwrite, Mode=TwoWay}"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
|
||||
|
||||
<TextBlock Grid.Row="15" Grid.Column="0" Text="Mapping File Path" VerticalAlignment="Center" Margin="0 0 0 5"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}"
|
||||
|
|
@ -221,29 +224,44 @@
|
|||
|
||||
<TextBlock Grid.Row="16" Grid.Column="0" Text="Serialize Script Bytecode" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<CheckBox Grid.Row="16" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding ReadScriptData, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"/>
|
||||
IsChecked="{Binding ReadScriptData, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
|
||||
|
||||
<TextBlock Grid.Row="17" Grid.Column="0" Text="Serialize Inlined Shader Maps" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<CheckBox Grid.Row="17" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding ReadShaderMaps, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"/>
|
||||
IsChecked="{Binding ReadShaderMaps, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
|
||||
|
||||
<TextBlock Grid.Row="18" Grid.Column="0" Text="Decompile Blueprint to Pseudo C++" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Adds a right click option to decompile UClass packages into a pseudo C++ friendly format" />
|
||||
<CheckBox Grid.Row="18" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding ShowDecompileOption, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"/>
|
||||
IsChecked="{Binding ShowDecompileOption, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
|
||||
|
||||
<TextBlock Grid.Row="19" Grid.Column="0" Text="Max Wwise Bank (.BNK) Prefetch" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<Slider Grid.Row="19" Grid.Column="2" Grid.ColumnSpan="5" TickPlacement="None" Minimum="0" Maximum="2048" Ticks="0,8,32,128,256,512,1024,2048"
|
||||
<TextBlock Grid.Row="19"
|
||||
Grid.Column="0"
|
||||
Text="Convert Audio During Export (.wav)"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 0 5" />
|
||||
<CheckBox Grid.Row="19"
|
||||
Grid.Column="2"
|
||||
Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding ConvertAudioOnBulkExport, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"
|
||||
Margin="0 5 0 10"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
|
||||
|
||||
<TextBlock Grid.Row="20" Grid.Column="0" Text="Max Wwise Bank (.BNK) Prefetch" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<Slider Grid.Row="20" Grid.Column="2" Grid.ColumnSpan="5" TickPlacement="None" Minimum="0" Maximum="2048" Ticks="0,8,32,128,256,512,1024,2048"
|
||||
AutoToolTipPlacement="BottomRight" IsMoveToPointEnabled="True" IsSnapToTickEnabled="True" Margin="0 5 0 5"
|
||||
Value="{Binding WwiseMaxBnkPrefetch, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="20"
|
||||
<TextBlock Grid.Row="21"
|
||||
Grid.Column="0"
|
||||
Text="CRIWARE Decryption Key"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 0 10" />
|
||||
|
||||
<TextBox x:Name="CriwareKeyBox"
|
||||
Grid.Row="20"
|
||||
Grid.Row="21"
|
||||
Grid.Column="2"
|
||||
Grid.ColumnSpan="5"
|
||||
Margin="0 5 0 10"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user