mirror of
https://github.com/4sval/FModel.git
synced 2026-09-15 04:56:49 -05:00
FModel v4.0
This commit is contained in:
@@ -1,559 +1,237 @@
|
||||
using FModel.Discord;
|
||||
using FModel.Grabber.Aes;
|
||||
using FModel.Grabber.Cdn;
|
||||
using FModel.Grabber.Paks;
|
||||
using FModel.Logger;
|
||||
using FModel.Utils;
|
||||
using FModel.ViewModels.AvalonEdit;
|
||||
using FModel.ViewModels.Buttons;
|
||||
using FModel.ViewModels.ImageBox;
|
||||
using FModel.ViewModels.ListBox;
|
||||
using FModel.ViewModels.MenuItem;
|
||||
using FModel.ViewModels.StatusBar;
|
||||
using FModel.ViewModels.TabControl;
|
||||
using FModel.ViewModels.Treeview;
|
||||
using FModel.Windows.About;
|
||||
using FModel.Windows.AESManager;
|
||||
using FModel.Windows.AvalonEditFindReplace;
|
||||
using FModel.Windows.CustomNotifier;
|
||||
using FModel.Windows.DarkMessageBox;
|
||||
using FModel.Windows.ImagesMerger;
|
||||
using FModel.Windows.Launcher;
|
||||
using FModel.Windows.Search;
|
||||
using FModel.Windows.Settings;
|
||||
using FModel.Windows.SoundPlayer;
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using FModel.Grabber.Mappings;
|
||||
using AdonisUI.Controls;
|
||||
using FModel.Extensions;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels;
|
||||
using FModel.Views;
|
||||
using FModel.Views.Resources.Controls;
|
||||
using ICSharpCode.AvalonEdit.Editing;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
public partial class MainWindow
|
||||
{
|
||||
public static MainWindow YesWeCats;
|
||||
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
|
||||
private ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
|
||||
private DiscordHandler _discordHandler => DiscordService.DiscordHandler;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoExportData", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoExportData.Key, UserSettings.Default.AutoExportData.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveProps", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveProps.Key, UserSettings.Default.AutoSaveProps.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveTextures", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveTextures.Key, UserSettings.Default.AutoSaveTextures.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveMaterials", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveMaterials.Key, UserSettings.Default.AutoSaveMaterials.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveMeshes", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveMeshes.Key, UserSettings.Default.AutoSaveMeshes.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoOpenSounds", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoOpenSounds.Key, UserSettings.Default.AutoOpenSounds.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("ReloadMappings", typeof(MainWindow), new InputGestureCollection {new KeyGesture(Key.F12)}), OnMappingsReload));
|
||||
CommandBindings.Add(new CommandBinding(ApplicationCommands.Find, (s, e) => OnOpenAvalonFinder()));
|
||||
|
||||
DataContext = _applicationView;
|
||||
InitializeComponent();
|
||||
FConsole.fConsoleControl = FModel_Console;
|
||||
|
||||
FLogger.Logger = LogRtbName;
|
||||
YesWeCats = this;
|
||||
}
|
||||
|
||||
private async void OnClosing(object sender, CancelEventArgs e)
|
||||
private void OnClosing(object sender, CancelEventArgs e)
|
||||
{
|
||||
Globals.gNotifier.Dispose();
|
||||
Tasks.TokenSource?.Dispose();
|
||||
DiscordIntegration.Dispose();
|
||||
DebugHelper.Logger.AsyncWrite = false;
|
||||
await Properties.Settings.SaveToFile().ConfigureAwait(false);
|
||||
_applicationView.CustomDirectories.Save();
|
||||
_discordHandler.Dispose();
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
FModelVersion_TxtBlck.Text += Assembly.GetExecutingAssembly().GetName().Version?.ToString();
|
||||
FModel_StsBar.DataContext = StatusBarVm.statusBarViewModel;
|
||||
FModel_AvalonEdit.DataContext = AvalonEditVm.avalonEditViewModel;
|
||||
FModel_ImgBox.DataContext = ImageBoxVm.imageBoxViewModel;
|
||||
FModel_PakProps.DataContext = PakPropertiesVm.pakPropertiesViewModel;
|
||||
FModel_AssetProps.DataContext = AssetPropertiesVm.assetPropertiesViewModel;
|
||||
FModel_Extract_Btn.DataContext = ExtractStopVm.extractViewModel;
|
||||
FModel_Stop_Btn.DataContext = ExtractStopVm.stopViewModel;
|
||||
FModel_MI_Files_PAK.ItemsSource = MenuItems.pakFiles;
|
||||
FModel_MI_Files_Backups.ItemsSource = MenuItems.backupFiles;
|
||||
FModel_MI_Assets_GoTo.ItemsSource = MenuItems.customGoTos;
|
||||
FModel_AssetsPathTree.ItemsSource = SortedTreeviewVm.gameFilesPath.ChildrensView;
|
||||
|
||||
if (!Properties.Settings.Default.SkipVersion) Updater.CheckForUpdate();
|
||||
DebugHelper.WriteUserSettings();
|
||||
Folders.CheckWatermarks();
|
||||
|
||||
await Task.WhenAll(Init()).ContinueWith(t =>
|
||||
{
|
||||
Keys.NoKeyGoodBye();
|
||||
MenuItems.FeedCustomGoTos();
|
||||
AeConfiguration();
|
||||
|
||||
if (t.Exception != null) Tasks.TaskCompleted(t.Exception);
|
||||
else StatusBarVm.statusBarViewModel.Set($"{Properties.Resources.Hello} {Environment.UserName}!", Properties.Resources.State);
|
||||
|
||||
App.StartTimer.Stop();
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Startup Time]", $"{App.StartTimer.ElapsedMilliseconds}ms");
|
||||
},
|
||||
TaskScheduler.FromCurrentSynchronizationContext());
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
await PaksGrabber.PopulateMenu().ConfigureAwait(false);
|
||||
await AesGrabber.Load(Properties.Settings.Default.ReloadAesKeys).ConfigureAwait(false);
|
||||
await MappingsGrabber.Load().ConfigureAwait(false);
|
||||
await CdnDataGrabber.DoCDNStuff().ConfigureAwait(false);
|
||||
await Folders.DownloadAndExtractVgm().ConfigureAwait(false);
|
||||
if (Properties.Settings.Default.UseDiscordRpc) DiscordIntegration.StartClient();
|
||||
}
|
||||
|
||||
public async void ReloadMappings(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (await MappingsGrabber.Load(true).ConfigureAwait(false))
|
||||
ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(UserSettings.Default.UpdateMode);
|
||||
|
||||
switch (UserSettings.Default.AesReload)
|
||||
{
|
||||
Globals.gNotifier.ShowCustomMessage("Mappings", "Reloaded successfully");
|
||||
case EAesReload.Always:
|
||||
await _applicationView.CUE4Parse.RefreshAes();
|
||||
break;
|
||||
case EAesReload.OncePerDay when UserSettings.Default.LastAesReload != DateTime.Today:
|
||||
UserSettings.Default.LastAesReload = DateTime.Today;
|
||||
await _applicationView.CUE4Parse.RefreshAes();
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
await _applicationView.CUE4Parse.InitInformation();
|
||||
await _applicationView.CUE4Parse.Initialize();
|
||||
await _applicationView.AesManager.InitAes();
|
||||
await _applicationView.AesManager.UpdateProvider(true);
|
||||
await _applicationView.CUE4Parse.InitBenMappings();
|
||||
await _applicationView.InitVgmStream();
|
||||
|
||||
if (UserSettings.Default.DiscordRpc == EDiscordRpc.Always)
|
||||
_discordHandler.Initialize(_applicationView.CUE4Parse.Game);
|
||||
}
|
||||
|
||||
private void OnGridSplitterDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
RootGrid.ColumnDefinitions[0].Width = GridLength.Auto;
|
||||
}
|
||||
|
||||
private void OnWindowKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is TextArea or TextBox)
|
||||
return;
|
||||
|
||||
if (_threadWorkerView.CanBeCanceled && e.Key == Key.Escape)
|
||||
{
|
||||
Globals.gNotifier.ShowCustomMessage("Mappings", "Failed to reload");
|
||||
_applicationView.Status = EStatusKind.Stopping;
|
||||
_threadWorkerView.Cancel();
|
||||
}
|
||||
else if (_applicationView.IsReady && e.Key == Key.F && Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
|
||||
OnSearchViewClick(null, null);
|
||||
else if (UserSettings.Default.AssetAddTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.AddTab();
|
||||
else if (UserSettings.Default.AssetRemoveTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.RemoveTab();
|
||||
else if (UserSettings.Default.AssetLeftTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.GoLeftTab();
|
||||
else if (UserSettings.Default.AssetRightTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.GoRightTab();
|
||||
else if (UserSettings.Default.DirLeftTab.IsTriggered(e.Key) && LeftTabControl.SelectedIndex > 0)
|
||||
LeftTabControl.SelectedIndex--;
|
||||
else if (UserSettings.Default.DirRightTab.IsTriggered(e.Key) && LeftTabControl.SelectedIndex < LeftTabControl.Items.Count - 1)
|
||||
LeftTabControl.SelectedIndex++;
|
||||
}
|
||||
|
||||
private void OnSearchViewClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Helper.OpenWindow<AdonisWindow>("Search View", () => new SearchView().Show());
|
||||
}
|
||||
|
||||
private void OnTabItemChange(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is not TabControl tabControl)
|
||||
return;
|
||||
|
||||
(tabControl.SelectedItem as System.Windows.Controls.TabItem)?.Focus();
|
||||
}
|
||||
|
||||
private async void OnMappingsReload(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
await _applicationView.CUE4Parse.InitBenMappings();
|
||||
}
|
||||
|
||||
private void OnAutoTriggerExecuted(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
switch ((e.Command as RoutedCommand)?.Name)
|
||||
{
|
||||
case "AutoExportData":
|
||||
UserSettings.Default.IsAutoExportData = !UserSettings.Default.IsAutoExportData;
|
||||
break;
|
||||
case "AutoSaveProps":
|
||||
UserSettings.Default.IsAutoSaveProps = !UserSettings.Default.IsAutoSaveProps;
|
||||
break;
|
||||
case "AutoSaveTextures":
|
||||
UserSettings.Default.IsAutoSaveTextures = !UserSettings.Default.IsAutoSaveTextures;
|
||||
break;
|
||||
case "AutoSaveMaterials":
|
||||
UserSettings.Default.IsAutoSaveMaterials = !UserSettings.Default.IsAutoSaveMaterials;
|
||||
break;
|
||||
case "AutoSaveMeshes":
|
||||
UserSettings.Default.IsAutoSaveMeshes = !UserSettings.Default.IsAutoSaveMeshes;
|
||||
break;
|
||||
case "AutoOpenSounds":
|
||||
UserSettings.Default.IsAutoOpenSounds = !UserSettings.Default.IsAutoOpenSounds;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AeConfiguration()
|
||||
private void OnOpenAvalonFinder()
|
||||
{
|
||||
AvalonEditFindReplaceHelper Frm = new AvalonEditFindReplaceHelper
|
||||
_applicationView.CUE4Parse.TabControl.SelectedTab.HasSearchOpen = true;
|
||||
AvalonEditor.YesWeSearch.Focus();
|
||||
AvalonEditor.YesWeSearch.SelectAll();
|
||||
}
|
||||
|
||||
private void OnAssetsTreeMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is not TreeView {SelectedItem: TreeItem treeItem} || treeItem.Folders.Count > 0) return;
|
||||
|
||||
LeftTabControl.SelectedIndex++;
|
||||
}
|
||||
|
||||
private async void OnAssetsListMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is not ListBox listBox) return;
|
||||
|
||||
var selectedItems = listBox.SelectedItems.Cast<AssetItem>().ToList();
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractSelected(cancellationToken, selectedItems); });
|
||||
}
|
||||
|
||||
private async void OnFolderExtractClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
CurrentEditor = new AvalonEditVm.TextEditorAdapter(FModel_AvalonEdit),
|
||||
ShowSearchIn = false,
|
||||
OwnerWindow = this
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderExportClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExportFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderSaveClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.SaveFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSaveDirectoryClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is not TreeItem folder) return;
|
||||
|
||||
_applicationView.CustomDirectories.Add(new CustomDirectory(folder.Header, folder.PathAtThisPoint));
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Successfully saved '{folder.PathAtThisPoint}' as a new custom directory", Constants.WHITE, true);
|
||||
}
|
||||
|
||||
private void OnCopyDirectoryPathClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is not TreeItem folder) return;
|
||||
Clipboard.SetText(folder.PathAtThisPoint);
|
||||
}
|
||||
|
||||
private void OnDeleteSearchClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AssetsSearchName.Text = string.Empty;
|
||||
AssetsListName.ScrollIntoView(AssetsListName.SelectedItem);
|
||||
}
|
||||
|
||||
private void OnFilterTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (sender is not TextBox textBox || AssetsFolderName.SelectedItem is not TreeItem folder)
|
||||
return;
|
||||
|
||||
var filters = textBox.Text.Trim().Split(' ');
|
||||
folder.AssetsList.AssetsView.Filter = o =>
|
||||
{
|
||||
return o is AssetItem assetItem && filters.All(x => assetItem.FullPath.SubstringAfterLast('/').Contains(x, StringComparison.OrdinalIgnoreCase));
|
||||
};
|
||||
CommandBindings.Add(Frm.FindBinding);
|
||||
}
|
||||
|
||||
#region MENU ITEMS
|
||||
|
||||
private void OnAutoShortcutPressed(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (e is ExecutedRoutedEventArgs r && r.Command is RoutedUICommand command)
|
||||
{
|
||||
string name = string.Empty;
|
||||
string state = string.Empty;
|
||||
string[] states = {Properties.Resources.Enabled, Properties.Resources.Disabled};
|
||||
switch (command.Name)
|
||||
{
|
||||
case "AutoExport":
|
||||
{
|
||||
bool b = Properties.Settings.Default.AutoExport;
|
||||
Properties.Settings.Default.AutoExport = !b;
|
||||
name = Properties.Resources.Export;
|
||||
state = states[Convert.ToInt32(b)];
|
||||
break;
|
||||
}
|
||||
case "AutoSave":
|
||||
{
|
||||
bool b = Properties.Settings.Default.AutoSave;
|
||||
Properties.Settings.Default.AutoSave = !b;
|
||||
name = Properties.Resources.Save;
|
||||
state = states[Convert.ToInt32(b)];
|
||||
break;
|
||||
}
|
||||
case "AutoSaveImage":
|
||||
{
|
||||
bool b = Properties.Settings.Default.AutoSaveImage;
|
||||
Properties.Settings.Default.AutoSaveImage = !b;
|
||||
name = Properties.Resources.SaveImage;
|
||||
state = states[Convert.ToInt32(b)];
|
||||
break;
|
||||
}
|
||||
case "AutoOpenSounds":
|
||||
{
|
||||
bool b = Properties.Settings.Default.AutoOpenSounds;
|
||||
Properties.Settings.Default.AutoOpenSounds = !b;
|
||||
name = Properties.Resources.OpenSounds;
|
||||
state = states[Convert.ToInt32(b)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
Globals.gNotifier.ShowCustomMessage(Properties.Resources.Auto, $"{name} 🠞 {state}");
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Files_AES_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening AES Manager");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.AES))
|
||||
{
|
||||
new AESManager().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.AES).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Assets_Search_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening Searcher");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.Search))
|
||||
{
|
||||
new Search().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Window openedWindow = FWindows.GetOpenedWindow<Window>(Properties.Resources.Search);
|
||||
if (openedWindow.WindowState == WindowState.Minimized)
|
||||
openedWindow.WindowState = WindowState.Normal;
|
||||
else openedWindow.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Assets_AudioPlayer_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening Audio Player");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.AudioPlayer))
|
||||
{
|
||||
new AudioPlayer(); //no need to show, Show() is already in the constructor
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.AudioPlayer).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private async void FModel_MI_Assets_Export_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0 &&
|
||||
FModel_AssetsList.SelectedItem is ListBoxViewModel selectedItem)
|
||||
{
|
||||
bool autoExport = FModel_AssetsList.SelectedItems.Count > 1;
|
||||
if (!autoExport) Assets.Export(selectedItem.ReaderEntry, false); // manual export if one
|
||||
else
|
||||
{
|
||||
bool ret = Properties.Settings.Default.AutoExport;
|
||||
Properties.Settings.Default.AutoExport = autoExport;
|
||||
|
||||
await Assets.GetUserSelection(FModel_AssetsList.SelectedItems); // auto export if multiple
|
||||
|
||||
Properties.Settings.Default.AutoExport = ret;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
else Globals.gNotifier.ShowCustomMessage(Properties.Resources.Error, Properties.Resources.NoDataToExport);
|
||||
}
|
||||
|
||||
private void FModel_MI_Assets_Save_Click(object sender, RoutedEventArgs e) => AvalonEditVm.avalonEditViewModel.Save(false);
|
||||
|
||||
private void FModel_MI_Assets_CopyImage_Click(object sender, RoutedEventArgs e) => ImageBoxVm.imageBoxViewModel.Copy();
|
||||
|
||||
private void FModel_MI_Assets_SaveImage_Click(object sender, RoutedEventArgs e) => ImageBoxVm.imageBoxViewModel.Save(false);
|
||||
|
||||
private void FModel_MI_Assets_OpenOutputFolder_Click(object sender, RoutedEventArgs e) => Process.Start(new ProcessStartInfo {FileName = Properties.Settings.Default.OutputPath, UseShellExecute = true});
|
||||
|
||||
private void FModel_MI_Assets_ImageMerger_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening Images Merger Settings");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.ImagesMerger))
|
||||
{
|
||||
new ImagesMerger().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.ImagesMerger).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Settings_General_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening General Settings");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.GeneralSettings))
|
||||
{
|
||||
new General().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.GeneralSettings).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Settings_IconCreator_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening Icon Creator Settings");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.IconCreator))
|
||||
{
|
||||
new IconCreator().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.IconCreator).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Settings_ThemeCreator_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening Challenge Bundles Creator Settings");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.ChallengesThemeCreator))
|
||||
{
|
||||
new ChallengeBundlesCreator().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.ChallengesThemeCreator).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Settings_RestoreLayout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Properties.Settings.Default.GridParentTop = "11*";
|
||||
Properties.Settings.Default.GridParentBottom = "10*";
|
||||
Properties.Settings.Default.GridChildTopLeft = "2*";
|
||||
Properties.Settings.Default.GridChildTopCenter = "3*";
|
||||
Properties.Settings.Default.GridChildTopRight = "2*";
|
||||
Properties.Settings.Default.GridChildBottomLeft = "6*";
|
||||
Properties.Settings.Default.GridChildBottomCenter = "11*";
|
||||
Properties.Settings.Default.GridChildBottomRight = "6*";
|
||||
}
|
||||
|
||||
private void FModel_MI_Settings_ChangeGame_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var launcher = new FLauncher();
|
||||
if ((bool) launcher.ShowDialog())
|
||||
{
|
||||
if (Properties.Settings.Default.PakPath != launcher.Path)
|
||||
{
|
||||
Properties.Settings.Default.PakPath = launcher.Path;
|
||||
|
||||
DarkMessageBoxHelper.Show(Properties.Resources.PathChangedRestart, Properties.Resources.PathChanged, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Restarting]", "Path(s) changed");
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
Process.Start(Process.GetCurrentProcess().MainModule.FileName);
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FModel_MI_Help_Trello_Click(object sender, RoutedEventArgs e) => Process.Start(new ProcessStartInfo {FileName = "https://trello.com/b/DfmzkVQB/fmodel", UseShellExecute = true});
|
||||
|
||||
private void FModel_MI_Help_Donate_Click(object sender, RoutedEventArgs e) => Process.Start(new ProcessStartInfo {FileName = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EP9SSWG8MW4UC&source=url", UseShellExecute = true});
|
||||
|
||||
private void FModel_MI_Help_Changelog_Click(object sender, RoutedEventArgs e) => Process.Start(new ProcessStartInfo {FileName = "https://github.com/iAmAsval/FModel/releases/latest", UseShellExecute = true});
|
||||
|
||||
private void FModel_MI_Help_BugsReport_Click(object sender, RoutedEventArgs e) => Process.Start(new ProcessStartInfo {FileName = "https://github.com/iAmAsval/FModel/issues/new", UseShellExecute = true});
|
||||
|
||||
private void FModel_MI_Help_Discord_Click(object sender, RoutedEventArgs e) => Process.Start(new ProcessStartInfo {FileName = "https://discord.gg/fdkNYYQ", UseShellExecute = true});
|
||||
|
||||
private void FModel_MI_Help_About_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", "Opening About");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.AboutF))
|
||||
{
|
||||
new FAbout().Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
FWindows.GetOpenedWindow<Window>(Properties.Resources.AboutF).Focus();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TREEVIEW
|
||||
|
||||
private void OnSelectedPathChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
AssetFilter_TxtBox.Text = string.Empty;
|
||||
AssetPropertiesVm.assetPropertiesViewModel.Reset();
|
||||
if (sender is TreeView s && s.SelectedItem is TreeviewViewModel selectedItem)
|
||||
{
|
||||
string path = selectedItem.GetFullPath().Substring(1);
|
||||
if (selectedItem.GameFiles.ContainsKey(path))
|
||||
{
|
||||
FModel_AssetsList.ItemsSource = // re-assigning ListBoxes.gameFiles delete the bind so we set it again
|
||||
ListBoxVm.gameFiles = selectedItem.GameFiles[path]; // this might not be the best solution but idk what to do instead
|
||||
|
||||
if (Globals.bSearch && !string.IsNullOrEmpty(Globals.sSearch))
|
||||
{
|
||||
var selected = ListBoxVm.gameFiles.FirstOrDefault(x => x.Content.Equals(Globals.sSearch));
|
||||
FModel_AssetsList.SelectedIndex = ListBoxVm.gameFiles.IndexOf(selected);
|
||||
FModel_AssetsList.ScrollIntoView(selected);
|
||||
Globals.bSearch = false;
|
||||
Globals.sSearch = string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
FModel_AssetsList.ItemsSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LISTBOX
|
||||
|
||||
private void OnSelectedItemChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ListBox listBox && listBox.SelectedItem is ListBoxViewModel selectedItem)
|
||||
{
|
||||
FModel_TabCtrl.SelectedIndex = 1;
|
||||
ExtractStopVm.extractViewModel.IsEnabled = true;
|
||||
AssetPropertiesVm.assetPropertiesViewModel.Set(selectedItem.ReaderEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
FModel_TabCtrl.SelectedIndex = 0;
|
||||
ExtractStopVm.extractViewModel.IsEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is ListBox listBox && listBox.SelectedIndex >= 0)
|
||||
await Assets.GetUserSelection(listBox.SelectedItems);
|
||||
}
|
||||
|
||||
private void OnDeleteFilterClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AssetFilter_TxtBox.Text = string.Empty;
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0 && FModel_AssetsList.SelectedItem is ListBoxViewModel selectedItem)
|
||||
FModel_AssetsList.ScrollIntoView(selectedItem);
|
||||
}
|
||||
|
||||
private async void OnFilterTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (sender is TextBox textBox)
|
||||
{
|
||||
string[] filters = textBox.Text.Trim().Split(' ');
|
||||
if (!string.IsNullOrEmpty(filters[0]))
|
||||
{
|
||||
FilterDelete_Img.Visibility = Visibility.Visible;
|
||||
var filtered = new ObservableSortedList<ListBoxViewModel>();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
foreach (ListBoxViewModel item in ListBoxVm.gameFiles)
|
||||
{
|
||||
bool bSearch = false;
|
||||
if (filters.Length > 1)
|
||||
{
|
||||
foreach (string filter in filters)
|
||||
{
|
||||
Assets.Filter(filter, item.Content, out bSearch);
|
||||
if (!bSearch)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assets.Filter(filters[0], item.Content, out bSearch);
|
||||
}
|
||||
|
||||
if (bSearch)
|
||||
filtered.Add(item);
|
||||
}
|
||||
}).ContinueWith(t =>
|
||||
{
|
||||
if (t.Exception != null) Tasks.TaskCompleted(t.Exception);
|
||||
else FModel_AssetsList.ItemsSource = filtered;
|
||||
},
|
||||
TaskScheduler.FromCurrentSynchronizationContext());
|
||||
}
|
||||
else
|
||||
{
|
||||
FilterDelete_Img.Visibility = Visibility.Hidden;
|
||||
FModel_AssetsList.ItemsSource = ListBoxVm.gameFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BUTTONS
|
||||
|
||||
private void OnImageOpenClick(object sender, RoutedEventArgs e) => ImageBoxVm.imageBoxViewModel.OpenImage();
|
||||
|
||||
private void OnStopClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Tasks.TokenSource != null)
|
||||
{
|
||||
Tasks.TokenSource.Cancel();
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Thread]", "Canceled by user");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnExtractClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.SelectedIndex >= 0)
|
||||
await Assets.GetUserSelection(FModel_AssetsList.SelectedItems);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RIGHT CLICK MENUS
|
||||
|
||||
private async void FModel_MI_Directory_Extract_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsPathTree.HasItems && FModel_AssetsPathTree.SelectedItem is TreeviewViewModel treeItem)
|
||||
await SortedTreeviewVm.ExtractFolder(treeItem).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async void FModel_MI_Directory_Export_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsPathTree.HasItems && FModel_AssetsPathTree.SelectedItem is TreeviewViewModel treeItem)
|
||||
await SortedTreeviewVm.ExportFolder(treeItem).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private void FModel_MI_Directory_Save_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsPathTree.HasItems && FModel_AssetsPathTree.SelectedItem is TreeviewViewModel treeItem)
|
||||
MenuItems.AddCustomGoTo(treeItem.Header, treeItem.GetFullPath().Substring(1) + "/");
|
||||
}
|
||||
|
||||
private async void CM_Asset_Save_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0 && FModel_AssetsList.SelectedItem is ListBoxViewModel selectedItem)
|
||||
{
|
||||
if (selectedItem.Content.Equals(AvalonEditVm.avalonEditViewModel.OwnerName)) // if selected item is actually displayed, just save
|
||||
AvalonEditVm.avalonEditViewModel.Save(false);
|
||||
else // extract (aka display) and save
|
||||
{
|
||||
bool autoSave = FModel_AssetsList.SelectedItems.Count > 1;
|
||||
bool ret = Properties.Settings.Default.AutoSave;
|
||||
|
||||
Properties.Settings.Default.AutoSave = autoSave;
|
||||
await Assets.GetUserSelection(FModel_AssetsList.SelectedItems); // auto save if multiple
|
||||
if (!autoSave) AvalonEditVm.avalonEditViewModel.Save(false); // manual save if one
|
||||
|
||||
Properties.Settings.Default.AutoSave = ret;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
else Globals.gNotifier.ShowCustomMessage(Properties.Resources.Error, Properties.Resources.NoDataToSave);
|
||||
}
|
||||
|
||||
private void CM_Copy_DPath_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsPathTree.HasItems && FModel_AssetsPathTree.SelectedItem is TreeviewViewModel treeItem)
|
||||
Assets.Copy(treeItem.GetFullPath().Substring(1) + "/");
|
||||
else if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0)
|
||||
Assets.Copy(FModel_AssetsList.SelectedItems, ECopy.PathNoFile);
|
||||
}
|
||||
|
||||
private void CM_Copy_FPath_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0)
|
||||
Assets.Copy(FModel_AssetsList.SelectedItems, ECopy.Path);
|
||||
}
|
||||
|
||||
private void CM_Copy_FName_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0)
|
||||
Assets.Copy(FModel_AssetsList.SelectedItems, ECopy.File);
|
||||
}
|
||||
|
||||
private void CM_Copy_FPath_NoExt_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0)
|
||||
Assets.Copy(FModel_AssetsList.SelectedItems, ECopy.PathNoExt);
|
||||
}
|
||||
|
||||
private void CM_Copy_FName_NoExt_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FModel_AssetsList.HasItems && FModel_AssetsList.SelectedIndex >= 0)
|
||||
Assets.Copy(FModel_AssetsList.SelectedItems, ECopy.FileNoExt);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user