From 4bb76c57eff22ac55ef7896cd9b32028a4a9fa25 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Sun, 10 Nov 2019 00:39:40 -0600 Subject: [PATCH 01/14] Compiler Source radio button setup --- Wabbajack/Converters/EqualsToBoolConverter.cs | 24 +++++ Wabbajack/Resources/MO2Button.png | Bin 0 -> 60047 bytes Wabbajack/Resources/VortexButton.png | Bin 0 -> 45252 bytes Wabbajack/Themes/Styles.xaml | 1 + Wabbajack/View Models/CompilerVM.cs | 9 ++ Wabbajack/{ => Views}/BorderFadeDownView.xaml | 0 .../{ => Views}/BorderFadeDownView.xaml.cs | 0 Wabbajack/Views/CompilerView.xaml | 82 +++++++++++++++--- Wabbajack/Views/RadioButtonView.xaml | 67 ++++++++++++++ Wabbajack/Views/RadioButtonView.xaml.cs | 57 ++++++++++++ Wabbajack/Wabbajack.csproj | 16 +++- 11 files changed, 240 insertions(+), 16 deletions(-) create mode 100644 Wabbajack/Converters/EqualsToBoolConverter.cs create mode 100644 Wabbajack/Resources/MO2Button.png create mode 100644 Wabbajack/Resources/VortexButton.png rename Wabbajack/{ => Views}/BorderFadeDownView.xaml (100%) rename Wabbajack/{ => Views}/BorderFadeDownView.xaml.cs (100%) create mode 100644 Wabbajack/Views/RadioButtonView.xaml create mode 100644 Wabbajack/Views/RadioButtonView.xaml.cs diff --git a/Wabbajack/Converters/EqualsToBoolConverter.cs b/Wabbajack/Converters/EqualsToBoolConverter.cs new file mode 100644 index 00000000..1fd143f7 --- /dev/null +++ b/Wabbajack/Converters/EqualsToBoolConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace Wabbajack +{ + public class EqualsToBoolConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return object.Equals(value, parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return parameter; + } + } +} diff --git a/Wabbajack/Resources/MO2Button.png b/Wabbajack/Resources/MO2Button.png new file mode 100644 index 0000000000000000000000000000000000000000..ac97254e7ae2e4421182ee73af8b18f6b51ef0be GIT binary patch literal 60047 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 NMOoFiRnlg`{|6o1zt#W% literal 0 HcmV?d00001 diff --git a/Wabbajack/Resources/VortexButton.png b/Wabbajack/Resources/VortexButton.png new file mode 100644 index 0000000000000000000000000000000000000000..ee4978cc6b6b705c936ce7e55b936cb6f99af9f8 GIT binary patch literal 45252 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 Gh5j#V4HSz2 literal 0 HcmV?d00001 diff --git a/Wabbajack/Themes/Styles.xaml b/Wabbajack/Themes/Styles.xaml index 558363dd..b9cb0511 100644 --- a/Wabbajack/Themes/Styles.xaml +++ b/Wabbajack/Themes/Styles.xaml @@ -12,6 +12,7 @@ + #121212 diff --git a/Wabbajack/View Models/CompilerVM.cs b/Wabbajack/View Models/CompilerVM.cs index 3362eb0b..7ac9fd1a 100644 --- a/Wabbajack/View Models/CompilerVM.cs +++ b/Wabbajack/View Models/CompilerVM.cs @@ -13,6 +13,12 @@ using Wabbajack.Lib; namespace Wabbajack { + public enum CompilerType + { + MO2, + Vortex + } + public class CompilerVM : ViewModel { public MainWindowVM MWVM { get; } @@ -54,6 +60,9 @@ namespace Wabbajack public IReactiveCommand BeginCommand { get; } + [Reactive] + public CompilerType SelectedCompilerType { get; set; } + public CompilerVM(MainWindowVM mainWindowVM, string source) { this.MWVM = mainWindowVM; diff --git a/Wabbajack/BorderFadeDownView.xaml b/Wabbajack/Views/BorderFadeDownView.xaml similarity index 100% rename from Wabbajack/BorderFadeDownView.xaml rename to Wabbajack/Views/BorderFadeDownView.xaml diff --git a/Wabbajack/BorderFadeDownView.xaml.cs b/Wabbajack/Views/BorderFadeDownView.xaml.cs similarity index 100% rename from Wabbajack/BorderFadeDownView.xaml.cs rename to Wabbajack/Views/BorderFadeDownView.xaml.cs diff --git a/Wabbajack/Views/CompilerView.xaml b/Wabbajack/Views/CompilerView.xaml index b8c5550e..db94a316 100644 --- a/Wabbajack/Views/CompilerView.xaml +++ b/Wabbajack/Views/CompilerView.xaml @@ -60,7 +60,7 @@ + + + + - + + + + + + + + + + + + + + + + + TextAlignment="Center" + ToolTip="The MO2 modlist.txt file you want to use as your source" /> + FontSize="14" + ToolTip="The MO2 modlist.txt file you want to use as your source" /> + TextAlignment="Center" + ToolTip="The folder where MO2 downloads your mods." /> + FontSize="14" + ToolTip="The folder where MO2 downloads your mods." /> + + diff --git a/Wabbajack/Views/RadioButtonView.xaml b/Wabbajack/Views/RadioButtonView.xaml new file mode 100644 index 00000000..dd704842 --- /dev/null +++ b/Wabbajack/Views/RadioButtonView.xaml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + diff --git a/Wabbajack/Views/RadioButtonView.xaml.cs b/Wabbajack/Views/RadioButtonView.xaml.cs new file mode 100644 index 00000000..dfda9a8d --- /dev/null +++ b/Wabbajack/Views/RadioButtonView.xaml.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Wabbajack +{ + /// + /// Interaction logic for ImageRadioButtonView.xaml + /// + public partial class ImageRadioButtonView : UserControl + { + public bool IsChecked + { + get => (bool)GetValue(IsCheckedProperty); + set => SetValue(IsCheckedProperty, value); + } + public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(nameof(IsChecked), typeof(bool), typeof(ImageRadioButtonView), + new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); + + public BitmapImage Image + { + get => (BitmapImage)GetValue(ImageProperty); + set => SetValue(ImageProperty, value); + } + public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(nameof(Image), typeof(BitmapImage), typeof(ImageRadioButtonView), + new FrameworkPropertyMetadata(default(BitmapImage))); + + public ICommand Command + { + get => (ICommand)GetValue(CommandProperty); + set => SetValue(CommandProperty, value); + } + public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(ImageRadioButtonView), + new FrameworkPropertyMetadata(default(ICommand))); + + public ImageRadioButtonView() + { + InitializeComponent(); + } + + private void Button_Click(object sender, RoutedEventArgs e) + { + this.IsChecked = true; + } + } +} diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index 8fd62a5d..d9b44eac 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -161,11 +161,15 @@ MSBuild:Compile Designer - + + BorderFadeDownView.xaml + + RadioButtonView.xaml + BeginButton.xaml @@ -216,7 +220,11 @@ TextViewer.xaml - + + Designer + MSBuild:Compile + + Designer MSBuild:Compile @@ -450,5 +458,9 @@ + + + + \ No newline at end of file From 6aa2908078a3dd00212888540d23dbfd52ad14da Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 20:25:01 -0600 Subject: [PATCH 02/14] Reverted GUI portions. Will readd manually --- Wabbajack/View Models/CompilerVM.cs | 68 ++++-------- Wabbajack/View Models/InstallerVM.cs | 149 ++++++-------------------- Wabbajack/Views/InstallationView.xaml | 127 ++++++++-------------- 3 files changed, 98 insertions(+), 246 deletions(-) diff --git a/Wabbajack/View Models/CompilerVM.cs b/Wabbajack/View Models/CompilerVM.cs index 8693e717..7ac9fd1a 100644 --- a/Wabbajack/View Models/CompilerVM.cs +++ b/Wabbajack/View Models/CompilerVM.cs @@ -205,30 +205,9 @@ namespace Wabbajack private async Task ExecuteBegin() { - if (false) + Compiler compiler; + try { - string[] args = Environment.GetCommandLineArgs(); - var compiler = new VortexCompiler(args[1], args[2]); - await Task.Run(() => - { - Compiling = true; - try - { - compiler.Compile(); - } - catch (Exception ex) - { - while (ex.InnerException != null) ex = ex.InnerException; - Utils.Log($"Can't continue: {ex.ExceptionToString()}"); - } - finally - { - Compiling = false; - } - }); - }else{ - Compiler compiler; - try { compiler = new Compiler(this.Mo2Folder) { MO2Profile = this.MOProfile, @@ -239,35 +218,34 @@ namespace Wabbajack ModListWebsite = this.Website, ModListReadme = this.ReadMeText.TargetPath, }; + } + catch (Exception ex) + { + while (ex.InnerException != null) ex = ex.InnerException; + Utils.Log($"Compiler error: {ex.ExceptionToString()}"); + return; + } + await Task.Run(() => + { + Compiling = true; + try + { + compiler.Compile(); + if (compiler.ModList?.ReportHTML != null) + { + this.HTMLReport = compiler.ModList.ReportHTML; + } } catch (Exception ex) { while (ex.InnerException != null) ex = ex.InnerException; Utils.Log($"Compiler error: {ex.ExceptionToString()}"); - return; } - await Task.Run(() => + finally { - Compiling = true; - try - { - compiler.Compile(); - if (compiler.ModList?.ReportHTML != null) - { - this.HTMLReport = compiler.ModList.ReportHTML; - } - } - catch (Exception ex) - { - while (ex.InnerException != null) ex = ex.InnerException; - Utils.Log($"Compiler error: {ex.ExceptionToString()}"); - } - finally - { - Compiling = false; - } - }); - } + Compiling = false; + } + }); } } } diff --git a/Wabbajack/View Models/InstallerVM.cs b/Wabbajack/View Models/InstallerVM.cs index 1a0728b1..1da55b24 100644 --- a/Wabbajack/View Models/InstallerVM.cs +++ b/Wabbajack/View Models/InstallerVM.cs @@ -1,4 +1,4 @@ - using Syroot.Windows.IO; +using Syroot.Windows.IO; using System; using ReactiveUI; using System.Diagnostics; @@ -50,15 +50,10 @@ namespace Wabbajack [Reactive] public bool InstallingMode { get; set; } - [Reactive] - public bool IsMO2ModList { get; set; } - public FilePickerVM Location { get; } public FilePickerVM DownloadLocation { get; } - public FilePickerVM StagingLocation { get; } - private readonly ObservableAsPropertyHelper _ProgressPercent; public float ProgressPercent => _ProgressPercent.Value; @@ -119,25 +114,15 @@ namespace Wabbajack this.DownloadLocation.AdditionalError = this.WhenAny(x => x.DownloadLocation.TargetPath) .Select(x => Utils.IsDirectoryPathValid(x)); - StagingLocation = new FilePickerVM - { - DoExistsCheck = true, - PathType = FilePickerVM.PathTypeOptions.Folder, - PromptTitle = "Select your Vortex Staging Folder", - AdditionalError = this.WhenAny(x => x.StagingLocation.TargetPath) - .Select(Utils.IsDirectoryPathValid) - }; - // Load settings - var settings = MWVM.Settings.InstallationSettings.TryCreate(source); + InstallationSettings settings = this.MWVM.Settings.InstallationSettings.TryCreate(source); + this.Location.TargetPath = settings.InstallationLocation; + this.DownloadLocation.TargetPath = settings.DownloadLocation; this.MWVM.Settings.SaveSignal .Subscribe(_ => { - settings.DownloadLocation = DownloadLocation.TargetPath; - if (IsMO2ModList) - settings.InstallationLocation = Location.TargetPath; - else - settings.StagingLocation = StagingLocation.TargetPath; + settings.InstallationLocation = this.Location.TargetPath; + settings.DownloadLocation = this.DownloadLocation.TargetPath; }) .DisposeWith(this.CompositeDisposable); @@ -163,38 +148,6 @@ namespace Wabbajack }); return default(ModListVM); } - if (modList.ModManager == ModManager.Vortex) - { - IsMO2ModList = false; - StagingLocation.TargetPath = settings.StagingLocation; - - var vortexFolder = - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "Vortex"); - var stagingFolder = Path.Combine(vortexFolder, GameRegistry.Games[modList.GameType].NexusName, - "mods"); - var downloadFolder = Path.Combine(vortexFolder, "downloads", - GameRegistry.Games[modList.GameType].NexusName); - MessageBox.Show( - "The ModList you are about to install was compiled from a Vortex installation. " + - "Vortex support is still very bleeding edge and installing this ModList WILL OVERRIDE your existing mods. " + - "If you encounter any errors during installation go to our discord and ping erri120#2285 with your error and a log file.", - "Important information regarding Vortex support", MessageBoxButton.OK, MessageBoxImage.Stop); - - if (!Directory.Exists(vortexFolder)) return new ModListVM(modList, modListPath); - if (Directory.Exists(stagingFolder) && - File.Exists(Path.Combine(stagingFolder, "__vortex_staging_folder"))) - StagingLocation.TargetPath = stagingFolder; - if (Directory.Exists(Path.Combine(vortexFolder, "downloads")) && - File.Exists(Path.Combine(vortexFolder, "downloads", "__vortex_downloads_folder"))) - DownloadLocation.TargetPath = downloadFolder; - } - else - { - Location.TargetPath = settings.InstallationLocation; - DownloadLocation.TargetPath = settings.DownloadLocation; - IsMO2ModList = true; - } return new ModListVM(modList, modListPath); }) .ObserveOnGuiThread() @@ -266,13 +219,10 @@ namespace Wabbajack this.WhenAny(x => x.Installing), this.WhenAny(x => x.Location.InError), this.WhenAny(x => x.DownloadLocation.InError), - this.WhenAny(x => x.StagingLocation.InError), - resultSelector: (installing, loc, download, staging) => + resultSelector: (installing, loc, download) => { if (installing) return false; - if (IsMO2ModList) - return !loc && !download; - return !staging && !download; + return !loc && !download; }) .ObserveOnGuiThread()); this.VisitWebsiteCommand = ReactiveCommand.Create( @@ -288,7 +238,7 @@ namespace Wabbajack { if (string.IsNullOrWhiteSpace(this.DownloadLocation.TargetPath)) { - this.DownloadLocation.TargetPath = Path.Combine(installPath, "downloads"); + this.DownloadLocation.TargetPath = Path.Combine(installPath, "downloads"); } }) .DisposeWith(this.CompositeDisposable); @@ -339,68 +289,35 @@ namespace Wabbajack private void ExecuteBegin() { - Installing = true; - InstallingMode = true; - if (ModList.ModManager == ModManager.Vortex) + this.Installing = true; + this.InstallingMode = true; + var installer = new Installer(this.ModListPath, this.ModList.SourceModList, Location.TargetPath) { - var installer = new VortexInstaller(ModListPath, ModList.SourceModList) - { - StagingFolder = StagingLocation.TargetPath, - DownloadFolder = DownloadLocation.TargetPath - }; - var th = new Thread(() => - { - try - { - installer.Install(); - } - catch (Exception ex) - { - while (ex.InnerException != null) ex = ex.InnerException; - Utils.Log(ex.StackTrace); - Utils.Log(ex.ToString()); - Utils.Log($"{ex.Message} - Can't continue"); - } - finally - { - Installing = false; - } - }) - { - Priority = ThreadPriority.BelowNormal - }; - th.Start(); - } - else + DownloadFolder = DownloadLocation.TargetPath + }; + var th = new Thread(() => { - var installer = new Installer(this.ModListPath, this.ModList.SourceModList, Location.TargetPath) + try { - DownloadFolder = DownloadLocation.TargetPath - }; - var th = new Thread(() => + installer.Install(); + } + catch (Exception ex) + { + while (ex.InnerException != null) ex = ex.InnerException; + Utils.Log(ex.StackTrace); + Utils.Log(ex.ToString()); + Utils.Log($"{ex.Message} - Can't continue"); + } + finally { - try - { - installer.Install(); - } - catch (Exception ex) - { - while (ex.InnerException != null) ex = ex.InnerException; - Utils.Log(ex.StackTrace); - Utils.Log(ex.ToString()); - Utils.Log($"{ex.Message} - Can't continue"); - } - finally - { - this.Installing = false; - } - }) - { - Priority = ThreadPriority.BelowNormal - }; - th.Start(); - } + this.Installing = false; + } + }) + { + Priority = ThreadPriority.BelowNormal + }; + th.Start(); } } } \ No newline at end of file diff --git a/Wabbajack/Views/InstallationView.xaml b/Wabbajack/Views/InstallationView.xaml index f5ba65a4..3e850853 100644 --- a/Wabbajack/Views/InstallationView.xaml +++ b/Wabbajack/Views/InstallationView.xaml @@ -27,10 +27,17 @@ - + Grid.RowSpan="2"> + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Date: Wed, 13 Nov 2019 23:28:27 -0600 Subject: [PATCH 03/14] Lots of compiler backend changes to support multiple CompilerVM is lightweight now, with sub view models per mod manager mode --- Wabbajack.Common/Extensions/RxExt.cs | 11 + Wabbajack/Settings.cs | 37 ++- Wabbajack/View Models/CompilerVM.cs | 251 ------------------ Wabbajack/View Models/Compilers/CompilerVM.cs | 82 ++++++ .../View Models/Compilers/ISubCompilerVM.cs | 17 ++ .../View Models/Compilers/MO2CompilerVM.cs | 191 +++++++++++++ .../Compilers/ModlistSettingsEditorVM.cs | 83 ++++++ .../View Models/Compilers/VortexCompilerVM.cs | 19 ++ Wabbajack/View Models/InstallerVM.cs | 2 +- Wabbajack/View Models/MainWindowVM.cs | 2 +- Wabbajack/Views/CompilerView.xaml | 5 +- Wabbajack/Views/ModeSelectionWindow.xaml.cs | 49 ++-- Wabbajack/Wabbajack.csproj | 6 +- 13 files changed, 462 insertions(+), 293 deletions(-) delete mode 100644 Wabbajack/View Models/CompilerVM.cs create mode 100644 Wabbajack/View Models/Compilers/CompilerVM.cs create mode 100644 Wabbajack/View Models/Compilers/ISubCompilerVM.cs create mode 100644 Wabbajack/View Models/Compilers/MO2CompilerVM.cs create mode 100644 Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs create mode 100644 Wabbajack/View Models/Compilers/VortexCompilerVM.cs diff --git a/Wabbajack.Common/Extensions/RxExt.cs b/Wabbajack.Common/Extensions/RxExt.cs index 4457261b..20ce19f1 100644 --- a/Wabbajack.Common/Extensions/RxExt.cs +++ b/Wabbajack.Common/Extensions/RxExt.cs @@ -173,5 +173,16 @@ namespace Wabbajack { return source.Select(x => !x); } + + public static IObservable<(T Previous, T Current)> Pairwise(this IObservable source) + { + T prevStorage = default; + return source.Select(i => + { + var prev = prevStorage; + prevStorage = i; + return (prev, i); + }); + } } } diff --git a/Wabbajack/Settings.cs b/Wabbajack/Settings.cs index c2b2a28d..37eca284 100644 --- a/Wabbajack/Settings.cs +++ b/Wabbajack/Settings.cs @@ -10,6 +10,7 @@ using System.Reactive.Subjects; using System.Reflection; using System.Text; using System.Threading.Tasks; +using Wabbajack.Common; namespace Wabbajack { @@ -22,10 +23,8 @@ namespace Wabbajack public double PosY { get; set; } public double Height { get; set; } public double Width { get; set; } - public string LastInstalledListLocation { get; set; } - public Dictionary InstallationSettings { get; } = new Dictionary(); - public string LastCompiledProfileLocation { get; set; } - public Dictionary CompilationSettings { get; } = new Dictionary(); + public InstallerSettings Installer { get; set; } = new InstallerSettings(); + public CompilerSettings Compiler { get; set; } = new CompilerSettings(); [JsonIgnoreAttribute] private Subject _saveSignal = new Subject(); @@ -50,14 +49,27 @@ namespace Wabbajack } } - public class InstallationSettings + public class InstallerSettings + { + public string LastInstalledListLocation { get; set; } + public Dictionary ModlistSettings { get; } = new Dictionary(); + } + + public class ModlistInstallationSettings { public string InstallationLocation { get; set; } public string StagingLocation { get; set; } public string DownloadLocation { get; set; } } - public class CompilationSettings + public class CompilerSettings + { + public ModManager LastCompiledModManager { get; set; } + public MO2CompilationSettings MO2Compilation { get; } = new MO2CompilationSettings(); + public VortexCompilationSettings VortexCompilation { get; } = new VortexCompilationSettings(); + } + + public class CompilationModlistSettings { public string ModListName { get; set; } public string Author { get; set; } @@ -65,6 +77,19 @@ namespace Wabbajack public string Website { get; set; } public string Readme { get; set; } public string SplashScreen { get; set; } + } + + public class MO2CompilationSettings + { public string DownloadLocation { get; set; } + public string LastCompiledProfileLocation { get; set; } + public Dictionary ModlistSettings { get; } = new Dictionary(); + } + + public class VortexCompilationSettings + { + public string StagingLocation { get; set; } + public Game LastCompiledGame { get; set; } + public Dictionary ModlistSettings { get; } = new Dictionary(); } } diff --git a/Wabbajack/View Models/CompilerVM.cs b/Wabbajack/View Models/CompilerVM.cs deleted file mode 100644 index 7ac9fd1a..00000000 --- a/Wabbajack/View Models/CompilerVM.cs +++ /dev/null @@ -1,251 +0,0 @@ -using Microsoft.WindowsAPICodePack.Dialogs; -using ReactiveUI; -using ReactiveUI.Fody.Helpers; -using System; -using System.IO; -using System.Linq; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using System.Threading.Tasks; -using System.Windows.Media.Imaging; -using Wabbajack.Common; -using Wabbajack.Lib; - -namespace Wabbajack -{ - public enum CompilerType - { - MO2, - Vortex - } - - public class CompilerVM : ViewModel - { - public MainWindowVM MWVM { get; } - - private readonly ObservableAsPropertyHelper _Mo2Folder; - public string Mo2Folder => _Mo2Folder.Value; - - private readonly ObservableAsPropertyHelper _MOProfile; - public string MOProfile => _MOProfile.Value; - - [Reactive] - public string ModListName { get; set; } - - public FilePickerVM ModlistLocation { get; } - - [Reactive] - public bool Compiling { get; set; } - - [Reactive] - public string AuthorText { get; set; } - - [Reactive] - public string Description { get; set; } - - public FilePickerVM ImagePath { get; } - - private readonly ObservableAsPropertyHelper _Image; - public BitmapImage Image => _Image.Value; - - [Reactive] - public string Website { get; set; } - - public FilePickerVM ReadMeText { get; } - - [Reactive] - public string HTMLReport { get; set; } - - public FilePickerVM DownloadLocation { get; } - - public IReactiveCommand BeginCommand { get; } - - [Reactive] - public CompilerType SelectedCompilerType { get; set; } - - public CompilerVM(MainWindowVM mainWindowVM, string source) - { - this.MWVM = mainWindowVM; - this.ModlistLocation = new FilePickerVM() - { - TargetPath = source, - DoExistsCheck = true, - PathType = FilePickerVM.PathTypeOptions.File, - PromptTitle = "Select Modlist" - }; - this.DownloadLocation = new FilePickerVM() - { - DoExistsCheck = true, - PathType = FilePickerVM.PathTypeOptions.Folder, - PromptTitle = "Select Download Location", - }; - this.ImagePath = new FilePickerVM() - { - DoExistsCheck = false, - PathType = FilePickerVM.PathTypeOptions.File, - Filters = - { - new CommonFileDialogFilter("Banner image", "*.png") - } - }; - this.ReadMeText = new FilePickerVM() - { - PathType = FilePickerVM.PathTypeOptions.File, - DoExistsCheck = true, - }; - - this.BeginCommand = ReactiveCommand.CreateFromTask( - execute: this.ExecuteBegin, - canExecute: Observable.CombineLatest( - this.WhenAny(x => x.Compiling), - this.WhenAny(x => x.ModlistLocation.InError), - this.WhenAny(x => x.DownloadLocation.InError), - resultSelector: (c, ml, down) => !c && !ml && !down) - .ObserveOnGuiThread()); - - this._Image = this.WhenAny(x => x.ImagePath.TargetPath) - .Select(path => - { - if (string.IsNullOrWhiteSpace(path)) return UIUtils.BitmapImageFromResource("Wabbajack.Resources.Banner_Dark.png"); - if (UIUtils.TryGetBitmapImageFromFile(path, out var image)) - { - return image; - } - return UIUtils.BitmapImageFromResource("Wabbajack.Resources.none.png"); - }) - .ToProperty(this, nameof(this.Image)); - - this._Mo2Folder = this.WhenAny(x => x.ModlistLocation.TargetPath) - .Select(loc => - { - try - { - var profile_folder = Path.GetDirectoryName(loc); - return Path.GetDirectoryName(Path.GetDirectoryName(profile_folder)); - } - catch (Exception) - { - return null; - } - }) - .ToProperty(this, nameof(this.Mo2Folder)); - this._MOProfile = this.WhenAny(x => x.ModlistLocation.TargetPath) - .Select(loc => - { - try - { - var profile_folder = Path.GetDirectoryName(loc); - return Path.GetFileName(profile_folder); - } - catch (Exception) - { - return null; - } - }) - .ToProperty(this, nameof(this.MOProfile)); - - // If Mo2 folder changes and download location is empty, set it for convenience - this.WhenAny(x => x.Mo2Folder) - .Where(x => Directory.Exists(x)) - .Subscribe(x => - { - try - { - var tmp_compiler = new Compiler(this.Mo2Folder); - this.DownloadLocation.TargetPath = tmp_compiler.MO2DownloadsFolder; - } - catch (Exception ex) - { - Utils.Log($"Error setting default download location {ex}"); - } - }) - .DisposeWith(this.CompositeDisposable); - - // Wire missing Mo2Folder to signal error state for Modlist Location - this.ModlistLocation.AdditionalError = this.WhenAny(x => x.Mo2Folder) - .Select(moFolder => - { - if (Directory.Exists(moFolder)) return ErrorResponse.Success; - return ErrorResponse.Fail($"MO2 Folder could not be located from the given modlist location.{Environment.NewLine}Make sure your modlist is inside a valid MO2 distribution."); - }); - - // Load settings - CompilationSettings settings = this.MWVM.Settings.CompilationSettings.TryCreate(source); - this.AuthorText = settings.Author; - if (string.IsNullOrWhiteSpace(settings.ModListName)) - { - // Set ModlistName initially off just the MO2Profile - this.ModListName = this.MOProfile; - } - else - { - this.ModListName = settings.ModListName; - } - this.Description = settings.Description; - this.ReadMeText.TargetPath = settings.Readme; - this.ImagePath.TargetPath = settings.SplashScreen; - this.Website = settings.Website; - if (!string.IsNullOrWhiteSpace(settings.DownloadLocation)) - { - this.DownloadLocation.TargetPath = settings.DownloadLocation; - } - this.MWVM.Settings.SaveSignal - .Subscribe(_ => - { - settings.Author = this.AuthorText; - settings.ModListName = this.ModListName; - settings.Description = this.Description; - settings.Readme = this.ReadMeText.TargetPath; - settings.SplashScreen = this.ImagePath.TargetPath; - settings.Website = this.Website; - settings.DownloadLocation = this.DownloadLocation.TargetPath; - }) - .DisposeWith(this.CompositeDisposable); - } - - private async Task ExecuteBegin() - { - Compiler compiler; - try - { - compiler = new Compiler(this.Mo2Folder) - { - MO2Profile = this.MOProfile, - ModListName = this.ModListName, - ModListAuthor = this.AuthorText, - ModListDescription = this.Description, - ModListImage = this.ImagePath.TargetPath, - ModListWebsite = this.Website, - ModListReadme = this.ReadMeText.TargetPath, - }; - } - catch (Exception ex) - { - while (ex.InnerException != null) ex = ex.InnerException; - Utils.Log($"Compiler error: {ex.ExceptionToString()}"); - return; - } - await Task.Run(() => - { - Compiling = true; - try - { - compiler.Compile(); - if (compiler.ModList?.ReportHTML != null) - { - this.HTMLReport = compiler.ModList.ReportHTML; - } - } - catch (Exception ex) - { - while (ex.InnerException != null) ex = ex.InnerException; - Utils.Log($"Compiler error: {ex.ExceptionToString()}"); - } - finally - { - Compiling = false; - } - }); - } - } -} diff --git a/Wabbajack/View Models/Compilers/CompilerVM.cs b/Wabbajack/View Models/Compilers/CompilerVM.cs new file mode 100644 index 00000000..4e8e87d3 --- /dev/null +++ b/Wabbajack/View Models/Compilers/CompilerVM.cs @@ -0,0 +1,82 @@ +using Microsoft.WindowsAPICodePack.Dialogs; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using System; +using System.IO; +using System.Linq; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Wabbajack.Common; +using Wabbajack.Lib; + +namespace Wabbajack +{ + public class CompilerVM : ViewModel + { + public MainWindowVM MWVM { get; } + + [Reactive] + public bool Compiling { get; set; } + + private readonly ObservableAsPropertyHelper _Image; + public BitmapImage Image => _Image.Value; + + [Reactive] + public ModManager SelectedCompilerType { get; set; } + + private readonly ObservableAsPropertyHelper _Compiler; + public ISubCompilerVM Compiler => _Compiler.Value; + + private readonly ObservableAsPropertyHelper _CurrentModlistSettings; + public ModlistSettingsEditorVM CurrentModlistSettings => _CurrentModlistSettings.Value; + + public CompilerVM(MainWindowVM mainWindowVM) + { + this.MWVM = mainWindowVM; + + // Load settings + CompilerSettings settings = this.MWVM.Settings.Compiler; + this.SelectedCompilerType = settings.LastCompiledModManager; + this.MWVM.Settings.SaveSignal + .Subscribe(_ => + { + settings.LastCompiledModManager = this.SelectedCompilerType; + }) + .DisposeWith(this.CompositeDisposable); + + // Swap to proper sub VM based on selected type + this._Compiler = this.WhenAny(x => x.SelectedCompilerType) + .Select(type => + { + switch (type) + { + case ModManager.MO2: + return new MO2CompilerVM(this); + case ModManager.Vortex: + return new VortexCompilerVM(); + default: + return null; + } + }) + .ToProperty(this, nameof(this.Compiler)); + + // Let sub VM determine what settings we're displaying and when + this._CurrentModlistSettings = this.WhenAny(x => x.Compiler.ModlistSettings) + .ToProperty(this, nameof(this.CurrentModlistSettings)); + + this._Image = this.WhenAny(x => x.CurrentModlistSettings.ImagePath.TargetPath) + .Select(path => + { + if (string.IsNullOrWhiteSpace(path)) return UIUtils.BitmapImageFromResource("Wabbajack.Resources.Banner_Dark.png"); + if (UIUtils.TryGetBitmapImageFromFile(path, out var image)) + { + return image; + } + return UIUtils.BitmapImageFromResource("Wabbajack.Resources.none.png"); + }) + .ToProperty(this, nameof(this.Image)); + } + } +} diff --git a/Wabbajack/View Models/Compilers/ISubCompilerVM.cs b/Wabbajack/View Models/Compilers/ISubCompilerVM.cs new file mode 100644 index 00000000..1319e61a --- /dev/null +++ b/Wabbajack/View Models/Compilers/ISubCompilerVM.cs @@ -0,0 +1,17 @@ +using ReactiveUI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace Wabbajack +{ + public interface ISubCompilerVM + { + IReactiveCommand BeginCommand { get; } + bool Compiling { get; } + ModlistSettingsEditorVM ModlistSettings { get; } + } +} diff --git a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs new file mode 100644 index 00000000..14362a57 --- /dev/null +++ b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs @@ -0,0 +1,191 @@ +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reactive; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Text; +using System.Threading.Tasks; +using Wabbajack.Common; +using Wabbajack.Lib; + +namespace Wabbajack +{ + public class MO2CompilerVM : ViewModel, ISubCompilerVM + { + private readonly ObservableAsPropertyHelper _Mo2Folder; + public string Mo2Folder => _Mo2Folder.Value; + + private readonly ObservableAsPropertyHelper _MOProfile; + public string MOProfile => _MOProfile.Value; + + public FilePickerVM DownloadLocation { get; } + + public FilePickerVM ModlistLocation { get; } + + public IReactiveCommand BeginCommand { get; } + + private readonly ObservableAsPropertyHelper _Compiling; + public bool Compiling => _Compiling.Value; + + private readonly ObservableAsPropertyHelper _ModlistSettings; + public ModlistSettingsEditorVM ModlistSettings => _ModlistSettings.Value; + + public MO2CompilerVM(CompilerVM parent) + { + this.ModlistLocation = new FilePickerVM() + { + DoExistsCheck = true, + PathType = FilePickerVM.PathTypeOptions.File, + PromptTitle = "Select Modlist" + }; + this.DownloadLocation = new FilePickerVM() + { + DoExistsCheck = true, + PathType = FilePickerVM.PathTypeOptions.Folder, + PromptTitle = "Select Download Location", + }; + + this._Mo2Folder = this.WhenAny(x => x.ModlistLocation.TargetPath) + .Select(loc => + { + try + { + var profile_folder = Path.GetDirectoryName(loc); + return Path.GetDirectoryName(Path.GetDirectoryName(profile_folder)); + } + catch (Exception) + { + return null; + } + }) + .ToProperty(this, nameof(this.Mo2Folder)); + this._MOProfile = this.WhenAny(x => x.ModlistLocation.TargetPath) + .Select(loc => + { + try + { + var profile_folder = Path.GetDirectoryName(loc); + return Path.GetFileName(profile_folder); + } + catch (Exception) + { + return null; + } + }) + .ToProperty(this, nameof(this.MOProfile)); + + // If Mo2 folder changes and download location is empty, set it for convenience + this.WhenAny(x => x.Mo2Folder) + .Where(x => Directory.Exists(x)) + .Subscribe(x => + { + try + { + var tmp_compiler = new Compiler(this.Mo2Folder); + this.DownloadLocation.TargetPath = tmp_compiler.MO2DownloadsFolder; + } + catch (Exception ex) + { + Utils.Log($"Error setting default download location {ex}"); + } + }) + .DisposeWith(this.CompositeDisposable); + + // Wire missing Mo2Folder to signal error state for Modlist Location + this.ModlistLocation.AdditionalError = this.WhenAny(x => x.Mo2Folder) + .Select(moFolder => + { + if (Directory.Exists(moFolder)) return ErrorResponse.Success; + return ErrorResponse.Fail($"MO2 Folder could not be located from the given modlist location.{Environment.NewLine}Make sure your modlist is inside a valid MO2 distribution."); + }); + + // Wire start command + this.BeginCommand = ReactiveCommand.CreateFromTask( + canExecute: Observable.CombineLatest( + this.WhenAny(x => x.ModlistLocation.InError), + this.WhenAny(x => x.DownloadLocation.InError), + resultSelector: (ml, down) => !ml && !down) + .ObserveOnGuiThread(), + execute: async () => + { + Compiler compiler; + try + { + compiler = new Compiler(this.Mo2Folder) + { + MO2Profile = this.MOProfile, + ModListName = this.ModlistSettings.ModListName, + ModListAuthor = this.ModlistSettings.AuthorText, + ModListDescription = this.ModlistSettings.Description, + ModListImage = this.ModlistSettings.ImagePath.TargetPath, + ModListWebsite = this.ModlistSettings.Website, + ModListReadme = this.ModlistSettings.ReadMeText.TargetPath, + }; + } + catch (Exception ex) + { + while (ex.InnerException != null) ex = ex.InnerException; + Utils.Log($"Compiler error: {ex.ExceptionToString()}"); + return; + } + await Task.Run(() => + { + try + { + compiler.Compile(); + } + catch (Exception ex) + { + while (ex.InnerException != null) ex = ex.InnerException; + Utils.Log($"Compiler error: {ex.ExceptionToString()}"); + } + }); + }); + this._Compiling = this.BeginCommand.IsExecuting + .ToProperty(this, nameof(this.Compiling)); + + // Load settings + var settings = parent.MWVM.Settings.Compiler.MO2Compilation; + if (!string.IsNullOrWhiteSpace(settings.DownloadLocation)) + { + this.DownloadLocation.TargetPath = settings.DownloadLocation; + } + parent.MWVM.Settings.SaveSignal + .Subscribe(_ => + { + settings.DownloadLocation = this.DownloadLocation.TargetPath; + this.ModlistSettings?.Save(); + }) + .DisposeWith(this.CompositeDisposable); + + // Load custom modlist settings per MO2 profile + this._ModlistSettings = Observable.CombineLatest( + this.WhenAny(x => x.ModlistLocation.ErrorState), + this.WhenAny(x => x.ModlistLocation.TargetPath), + resultSelector: (State, Path) => (State, Path)) + // A short throttle is a quick hack to make the above changes "atomic" + .Throttle(TimeSpan.FromMilliseconds(25)) + .Select(u => + { + if (u.State.Failed) return null; + var modlistSettings = settings.ModlistSettings.TryCreate(u.Path); + return new ModlistSettingsEditorVM(modlistSettings, this.MOProfile); + }) + // Interject and save old while loading new + .Pairwise() + .Do(pair => + { + pair.Previous?.Save(); + pair.Current?.Init(); + }) + .Select(x => x.Current) + // Save to property + .ObserveOnGuiThread() + .ToProperty(this, nameof(this.ModlistSettings)); + } + } +} diff --git a/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs b/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs new file mode 100644 index 00000000..ff5a0a42 --- /dev/null +++ b/Wabbajack/View Models/Compilers/ModlistSettingsEditorVM.cs @@ -0,0 +1,83 @@ +using Microsoft.WindowsAPICodePack.Dialogs; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Wabbajack.Lib; + +namespace Wabbajack +{ + public class ModlistSettingsEditorVM : ViewModel + { + private CompilationModlistSettings settings; + private string mo2Profile; + + [Reactive] + public string ModListName { get; set; } + + [Reactive] + public string AuthorText { get; set; } + + [Reactive] + public string Description { get; set; } + + public FilePickerVM ImagePath { get; } + + public FilePickerVM ReadMeText { get; } + + [Reactive] + public string Website { get; set; } + + public ModlistSettingsEditorVM(CompilationModlistSettings settings, string mo2Profile) + { + this.settings = settings; + this.mo2Profile = mo2Profile; + this.ImagePath = new FilePickerVM() + { + DoExistsCheck = false, + PathType = FilePickerVM.PathTypeOptions.File, + Filters = + { + new CommonFileDialogFilter("Banner image", "*.png") + } + }; + this.ReadMeText = new FilePickerVM() + { + PathType = FilePickerVM.PathTypeOptions.File, + DoExistsCheck = true, + }; + } + + public void Init() + { + this.AuthorText = settings.Author; + if (string.IsNullOrWhiteSpace(settings.ModListName)) + { + // Set ModlistName initially off just the MO2Profile + this.ModListName = mo2Profile; + } + else + { + this.ModListName = settings.ModListName; + } + this.Description = settings.Description; + this.ReadMeText.TargetPath = settings.Readme; + this.ImagePath.TargetPath = settings.SplashScreen; + this.Website = settings.Website; + } + + public void Save() + { + settings.Author = this.AuthorText; + settings.ModListName = this.ModListName; + settings.Description = this.Description; + settings.Readme = this.ReadMeText.TargetPath; + settings.SplashScreen = this.ImagePath.TargetPath; + settings.Website = this.Website; + } + } +} diff --git a/Wabbajack/View Models/Compilers/VortexCompilerVM.cs b/Wabbajack/View Models/Compilers/VortexCompilerVM.cs new file mode 100644 index 00000000..c6d78cd1 --- /dev/null +++ b/Wabbajack/View Models/Compilers/VortexCompilerVM.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ReactiveUI; +using Wabbajack.Lib; + +namespace Wabbajack +{ + public class VortexCompilerVM : ViewModel, ISubCompilerVM + { + public IReactiveCommand BeginCommand => throw new NotImplementedException(); + + public bool Compiling => throw new NotImplementedException(); + + public ModlistSettingsEditorVM ModlistSettings => throw new NotImplementedException(); + } +} diff --git a/Wabbajack/View Models/InstallerVM.cs b/Wabbajack/View Models/InstallerVM.cs index 1da55b24..1f62ded0 100644 --- a/Wabbajack/View Models/InstallerVM.cs +++ b/Wabbajack/View Models/InstallerVM.cs @@ -115,7 +115,7 @@ namespace Wabbajack .Select(x => Utils.IsDirectoryPathValid(x)); // Load settings - InstallationSettings settings = this.MWVM.Settings.InstallationSettings.TryCreate(source); + ModlistInstallationSettings settings = this.MWVM.Settings.Installer.ModlistSettings.TryCreate(source); this.Location.TargetPath = settings.InstallationLocation; this.DownloadLocation.TargetPath = settings.DownloadLocation; this.MWVM.Settings.SaveSignal diff --git a/Wabbajack/View Models/MainWindowVM.cs b/Wabbajack/View Models/MainWindowVM.cs index 5ed7e1f3..5c18f7c2 100644 --- a/Wabbajack/View Models/MainWindowVM.cs +++ b/Wabbajack/View Models/MainWindowVM.cs @@ -50,7 +50,7 @@ namespace Wabbajack this.MainWindow = mainWindow; this.Settings = settings; this._Installer = new Lazy(() => new InstallerVM(this, source)); - this._Compiler = new Lazy(() => new CompilerVM(this, source)); + this._Compiler = new Lazy(() => new CompilerVM(this)); // Set up logging Utils.LogMessages diff --git a/Wabbajack/Views/CompilerView.xaml b/Wabbajack/Views/CompilerView.xaml index db94a316..607c0f71 100644 --- a/Wabbajack/Views/CompilerView.xaml +++ b/Wabbajack/Views/CompilerView.xaml @@ -6,6 +6,7 @@ xmlns:local="clr-namespace:Wabbajack" xmlns:mahapps="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:wabbacommon="clr-namespace:Wabbajack.Common;assembly=Wabbajack.Common" d:DataContext="{d:DesignInstance local:CompilerVM}" d:DesignHeight="450" d:DesignWidth="800" @@ -177,7 +178,7 @@ Grid.Row="0" Height="35" Margin="4" - IsChecked="{Binding SelectedCompilerType, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static local:CompilerType.MO2}}"> + IsChecked="{Binding SelectedCompilerType, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static wabbacommon:ModManager.MO2}}"> @@ -186,7 +187,7 @@ Grid.Row="1" Height="35" Margin="4" - IsChecked="{Binding SelectedCompilerType, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static local:CompilerType.Vortex}}"> + IsChecked="{Binding SelectedCompilerType, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static wabbacommon:ModManager.Vortex}}"> diff --git a/Wabbajack/Views/ModeSelectionWindow.xaml.cs b/Wabbajack/Views/ModeSelectionWindow.xaml.cs index d65760e9..ecee2390 100644 --- a/Wabbajack/Views/ModeSelectionWindow.xaml.cs +++ b/Wabbajack/Views/ModeSelectionWindow.xaml.cs @@ -37,42 +37,37 @@ namespace Wabbajack private void CreateModlist_Click(object sender, RoutedEventArgs e) { - OpenMainWindow( - RunMode.Compile, - UIUtils.OpenFileDialog( - "MO2 Modlist(modlist.txt)|modlist.txt", - initialDirectory: settings.LastCompiledProfileLocation)); + ShutdownOnClose = false; + var window = new MainWindow(RunMode.Compile, null, settings); + window.Left = this.Left; + window.Top = this.Top; + window.Show(); + Close(); } private void InstallModlist_Click(object sender, RoutedEventArgs e) { - //OpenMainWindow( - // RunMode.Install, - // UIUtils.OpenFileDialog($"Wabbajack Modlist (*{Consts.ModlistExtension})|*{Consts.ModlistExtension}")); - var result = ((ModeSelectionWindowVM)DataContext).Download(); if (result != null) { - OpenMainWindow(RunMode.Install, result); + OpenMainWindowInstall(result); } } - private void OpenMainWindow(RunMode mode, string file) + private void InstallFromList_Click(object sender, RoutedEventArgs e) + { + OpenMainWindowInstall( + UIUtils.OpenFileDialog( + $"*{ExtensionManager.Extension}|*{ExtensionManager.Extension}", + initialDirectory: settings.Installer.LastInstalledListLocation)); + } + + private void OpenMainWindowInstall(string file) { if (file == null) return; ShutdownOnClose = false; - switch (mode) - { - case RunMode.Compile: - settings.LastCompiledProfileLocation = Path.GetDirectoryName(file); - break; - case RunMode.Install: - settings.LastInstalledListLocation = Path.GetDirectoryName(file); - break; - default: - break; - } - var window = new MainWindow(mode, file, settings); + settings.Installer.LastInstalledListLocation = Path.GetDirectoryName(file); + var window = new MainWindow(RunMode.Install, file, settings); window.Left = this.Left; window.Top = this.Top; window.Show(); @@ -101,13 +96,5 @@ namespace Wabbajack { Process.Start("https://discord.gg/zgbrkmA"); } - - private void InstallFromList_Click(object sender, RoutedEventArgs e) - { - OpenMainWindow(RunMode.Install, - UIUtils.OpenFileDialog( - $"*{ExtensionManager.Extension}|*{ExtensionManager.Extension}", - initialDirectory: settings.LastInstalledListLocation)); - } } } diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index 7c9ca9d3..b084363d 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -162,6 +162,10 @@ Designer + + + + BorderFadeDownView.xaml @@ -201,7 +205,7 @@ InstallationView.xaml - + LogCpuView.xaml From 320761fbcd10dc4df960972c091f06d4ce109c08 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Wed, 13 Nov 2019 23:30:26 -0600 Subject: [PATCH 04/14] Restructured View folder --- Wabbajack/View Models/Compilers/CompilerVM.cs | 3 -- Wabbajack/Views/{ => Common}/BeginButton.xaml | 0 .../Views/{ => Common}/BeginButton.xaml.cs | 0 .../{ => Common}/BorderFadeDownView.xaml | 0 .../{ => Common}/BorderFadeDownView.xaml.cs | 0 .../Views/{ => Common}/DetailImageView.xaml | 0 .../{ => Common}/DetailImageView.xaml.cs | 0 Wabbajack/Views/{ => Common}/FilePicker.xaml | 0 .../Views/{ => Common}/FilePicker.xaml.cs | 0 Wabbajack/Views/{ => Common}/LogCpuView.xaml | 0 .../Views/{ => Common}/LogCpuView.xaml.cs | 0 .../Views/{ => Common}/RadioButtonView.xaml | 0 .../{ => Common}/RadioButtonView.xaml.cs | 0 .../Views/{ => Common}/TopProgressView.xaml | 0 .../{ => Common}/TopProgressView.xaml.cs | 0 .../Views/{ => Compilers}/CompilerView.xaml | 0 .../{ => Compilers}/CompilerView.xaml.cs | 0 Wabbajack/Wabbajack.csproj | 32 +++++++++---------- 18 files changed, 16 insertions(+), 19 deletions(-) rename Wabbajack/Views/{ => Common}/BeginButton.xaml (100%) rename Wabbajack/Views/{ => Common}/BeginButton.xaml.cs (100%) rename Wabbajack/Views/{ => Common}/BorderFadeDownView.xaml (100%) rename Wabbajack/Views/{ => Common}/BorderFadeDownView.xaml.cs (100%) rename Wabbajack/Views/{ => Common}/DetailImageView.xaml (100%) rename Wabbajack/Views/{ => Common}/DetailImageView.xaml.cs (100%) rename Wabbajack/Views/{ => Common}/FilePicker.xaml (100%) rename Wabbajack/Views/{ => Common}/FilePicker.xaml.cs (100%) rename Wabbajack/Views/{ => Common}/LogCpuView.xaml (100%) rename Wabbajack/Views/{ => Common}/LogCpuView.xaml.cs (100%) rename Wabbajack/Views/{ => Common}/RadioButtonView.xaml (100%) rename Wabbajack/Views/{ => Common}/RadioButtonView.xaml.cs (100%) rename Wabbajack/Views/{ => Common}/TopProgressView.xaml (100%) rename Wabbajack/Views/{ => Common}/TopProgressView.xaml.cs (100%) rename Wabbajack/Views/{ => Compilers}/CompilerView.xaml (100%) rename Wabbajack/Views/{ => Compilers}/CompilerView.xaml.cs (100%) diff --git a/Wabbajack/View Models/Compilers/CompilerVM.cs b/Wabbajack/View Models/Compilers/CompilerVM.cs index 4e8e87d3..70cc770f 100644 --- a/Wabbajack/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack/View Models/Compilers/CompilerVM.cs @@ -17,9 +17,6 @@ namespace Wabbajack { public MainWindowVM MWVM { get; } - [Reactive] - public bool Compiling { get; set; } - private readonly ObservableAsPropertyHelper _Image; public BitmapImage Image => _Image.Value; diff --git a/Wabbajack/Views/BeginButton.xaml b/Wabbajack/Views/Common/BeginButton.xaml similarity index 100% rename from Wabbajack/Views/BeginButton.xaml rename to Wabbajack/Views/Common/BeginButton.xaml diff --git a/Wabbajack/Views/BeginButton.xaml.cs b/Wabbajack/Views/Common/BeginButton.xaml.cs similarity index 100% rename from Wabbajack/Views/BeginButton.xaml.cs rename to Wabbajack/Views/Common/BeginButton.xaml.cs diff --git a/Wabbajack/Views/BorderFadeDownView.xaml b/Wabbajack/Views/Common/BorderFadeDownView.xaml similarity index 100% rename from Wabbajack/Views/BorderFadeDownView.xaml rename to Wabbajack/Views/Common/BorderFadeDownView.xaml diff --git a/Wabbajack/Views/BorderFadeDownView.xaml.cs b/Wabbajack/Views/Common/BorderFadeDownView.xaml.cs similarity index 100% rename from Wabbajack/Views/BorderFadeDownView.xaml.cs rename to Wabbajack/Views/Common/BorderFadeDownView.xaml.cs diff --git a/Wabbajack/Views/DetailImageView.xaml b/Wabbajack/Views/Common/DetailImageView.xaml similarity index 100% rename from Wabbajack/Views/DetailImageView.xaml rename to Wabbajack/Views/Common/DetailImageView.xaml diff --git a/Wabbajack/Views/DetailImageView.xaml.cs b/Wabbajack/Views/Common/DetailImageView.xaml.cs similarity index 100% rename from Wabbajack/Views/DetailImageView.xaml.cs rename to Wabbajack/Views/Common/DetailImageView.xaml.cs diff --git a/Wabbajack/Views/FilePicker.xaml b/Wabbajack/Views/Common/FilePicker.xaml similarity index 100% rename from Wabbajack/Views/FilePicker.xaml rename to Wabbajack/Views/Common/FilePicker.xaml diff --git a/Wabbajack/Views/FilePicker.xaml.cs b/Wabbajack/Views/Common/FilePicker.xaml.cs similarity index 100% rename from Wabbajack/Views/FilePicker.xaml.cs rename to Wabbajack/Views/Common/FilePicker.xaml.cs diff --git a/Wabbajack/Views/LogCpuView.xaml b/Wabbajack/Views/Common/LogCpuView.xaml similarity index 100% rename from Wabbajack/Views/LogCpuView.xaml rename to Wabbajack/Views/Common/LogCpuView.xaml diff --git a/Wabbajack/Views/LogCpuView.xaml.cs b/Wabbajack/Views/Common/LogCpuView.xaml.cs similarity index 100% rename from Wabbajack/Views/LogCpuView.xaml.cs rename to Wabbajack/Views/Common/LogCpuView.xaml.cs diff --git a/Wabbajack/Views/RadioButtonView.xaml b/Wabbajack/Views/Common/RadioButtonView.xaml similarity index 100% rename from Wabbajack/Views/RadioButtonView.xaml rename to Wabbajack/Views/Common/RadioButtonView.xaml diff --git a/Wabbajack/Views/RadioButtonView.xaml.cs b/Wabbajack/Views/Common/RadioButtonView.xaml.cs similarity index 100% rename from Wabbajack/Views/RadioButtonView.xaml.cs rename to Wabbajack/Views/Common/RadioButtonView.xaml.cs diff --git a/Wabbajack/Views/TopProgressView.xaml b/Wabbajack/Views/Common/TopProgressView.xaml similarity index 100% rename from Wabbajack/Views/TopProgressView.xaml rename to Wabbajack/Views/Common/TopProgressView.xaml diff --git a/Wabbajack/Views/TopProgressView.xaml.cs b/Wabbajack/Views/Common/TopProgressView.xaml.cs similarity index 100% rename from Wabbajack/Views/TopProgressView.xaml.cs rename to Wabbajack/Views/Common/TopProgressView.xaml.cs diff --git a/Wabbajack/Views/CompilerView.xaml b/Wabbajack/Views/Compilers/CompilerView.xaml similarity index 100% rename from Wabbajack/Views/CompilerView.xaml rename to Wabbajack/Views/Compilers/CompilerView.xaml diff --git a/Wabbajack/Views/CompilerView.xaml.cs b/Wabbajack/Views/Compilers/CompilerView.xaml.cs similarity index 100% rename from Wabbajack/Views/CompilerView.xaml.cs rename to Wabbajack/Views/Compilers/CompilerView.xaml.cs diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index b084363d..329d7141 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -166,30 +166,30 @@ - + BorderFadeDownView.xaml - + RadioButtonView.xaml - + BeginButton.xaml - + DetailImageView.xaml - + TopProgressView.xaml - + CompilerView.xaml @@ -199,7 +199,7 @@ - + FilePicker.xaml @@ -207,7 +207,7 @@ - + LogCpuView.xaml @@ -223,27 +223,27 @@ TextViewer.xaml - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -251,7 +251,7 @@ Designer MSBuild:Compile - + MSBuild:Compile Designer @@ -259,7 +259,7 @@ Designer MSBuild:Compile - + MSBuild:Compile Designer From f8366c838adb82d3f1805adbe23e5489a3ffb852 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Wed, 13 Nov 2019 23:57:14 -0600 Subject: [PATCH 05/14] View work to get a basic MO2 compilation working again --- Wabbajack/Views/Compilers/CompilerView.xaml | 86 +++++-------------- .../Compilers/MO2CompilerConfigView.xaml | 75 ++++++++++++++++ .../Compilers/MO2CompilerConfigView.xaml.cs | 28 ++++++ Wabbajack/Wabbajack.csproj | 7 ++ 4 files changed, 131 insertions(+), 65 deletions(-) create mode 100644 Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml create mode 100644 Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml.cs diff --git a/Wabbajack/Views/Compilers/CompilerView.xaml b/Wabbajack/Views/Compilers/CompilerView.xaml index 607c0f71..20e983ca 100644 --- a/Wabbajack/Views/Compilers/CompilerView.xaml +++ b/Wabbajack/Views/Compilers/CompilerView.xaml @@ -33,12 +33,12 @@ Grid.RowSpan="2" Grid.Column="4" /> + Visibility="{Binding Compiler.Compiling, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}"> - - - + - - @@ -180,7 +177,7 @@ Margin="4" IsChecked="{Binding SelectedCompilerType, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static wabbacommon:ModManager.MO2}}"> - + - + - - - - - - + Content="{Binding Compiler}"> + + + + + + + Command="{Binding Compiler.BeginCommand}" /> + Visibility="{Binding Compiler.Compiling, Converter={StaticResource bool2VisibilityConverter}, FallbackValue=Hidden}"> diff --git a/Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml b/Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml new file mode 100644 index 00000000..fe698b30 --- /dev/null +++ b/Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml.cs b/Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml.cs new file mode 100644 index 00000000..f5ce67a4 --- /dev/null +++ b/Wabbajack/Views/Compilers/MO2CompilerConfigView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Wabbajack +{ + /// + /// Interaction logic for MO2CompilerConfigView.xaml + /// + public partial class MO2CompilerConfigView : UserControl + { + public MO2CompilerConfigView() + { + InitializeComponent(); + } + } +} diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index 329d7141..f06955a1 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -162,6 +162,9 @@ Designer + + MO2CompilerConfigView.xaml + @@ -223,6 +226,10 @@ TextViewer.xaml + + Designer + MSBuild:Compile + Designer MSBuild:Compile From fd94df0f108506477b146dde8738ac2a9e6cc9c6 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 22:55:27 -0600 Subject: [PATCH 06/14] FilePickerVM optimization for initial values Was debouncing off its initial value of null, so any initial value set by settings wouldn't take immediate effect until later. --- Wabbajack/View Models/FilePickerVM.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Wabbajack/View Models/FilePickerVM.cs b/Wabbajack/View Models/FilePickerVM.cs index c804453f..c216cdb7 100644 --- a/Wabbajack/View Models/FilePickerVM.cs +++ b/Wabbajack/View Models/FilePickerVM.cs @@ -77,7 +77,9 @@ namespace Wabbajack this.WhenAny(x => x.DoExistsCheck), this.WhenAny(x => x.PathType), this.WhenAny(x => x.TargetPath) - .Throttle(TimeSpan.FromMilliseconds(200)), + // Dont want to debounce the initial value, because we know it's null + .Skip(1) + .Debounce(TimeSpan.FromMilliseconds(200)), resultSelector: (_, DoExists, Type, Path) => (DoExists, Type, Path)) // Refresh exists .Select(t => @@ -95,6 +97,7 @@ namespace Wabbajack return true; } }) + .StartWith(false) .DistinctUntilChanged() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, nameof(this.Exists)); From 80f96433bc27e74dd1e8e2ec39c2fac3d9edd20f Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 22:54:18 -0600 Subject: [PATCH 07/14] MO2 compiler target path saving was missing --- Wabbajack/View Models/Compilers/MO2CompilerVM.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs index 14362a57..44484b27 100644 --- a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs +++ b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs @@ -1,4 +1,4 @@ -using ReactiveUI; +using ReactiveUI; using ReactiveUI.Fody.Helpers; using System; using System.Collections.Generic; @@ -150,6 +150,7 @@ namespace Wabbajack // Load settings var settings = parent.MWVM.Settings.Compiler.MO2Compilation; + this.ModlistLocation.TargetPath = settings.LastCompiledProfileLocation; if (!string.IsNullOrWhiteSpace(settings.DownloadLocation)) { this.DownloadLocation.TargetPath = settings.DownloadLocation; @@ -158,6 +159,7 @@ namespace Wabbajack .Subscribe(_ => { settings.DownloadLocation = this.DownloadLocation.TargetPath; + settings.LastCompiledProfileLocation = this.ModlistLocation.TargetPath; this.ModlistSettings?.Save(); }) .DisposeWith(this.CompositeDisposable); From 52517dc3e4270cd5f34b4b806b2c74358e140a7c Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 22:54:34 -0600 Subject: [PATCH 08/14] Some compiler VM startup optimizations --- Wabbajack.Common/Extensions/RxExt.cs | 20 ++++++++- Wabbajack/View Models/Compilers/CompilerVM.cs | 6 ++- .../View Models/Compilers/MO2CompilerVM.cs | 42 +++++++++++-------- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/Wabbajack.Common/Extensions/RxExt.cs b/Wabbajack.Common/Extensions/RxExt.cs index 20ce19f1..25ac87b2 100644 --- a/Wabbajack.Common/Extensions/RxExt.cs +++ b/Wabbajack.Common/Extensions/RxExt.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reactive; @@ -184,5 +184,23 @@ namespace Wabbajack return (prev, i); }); } + + public static IObservable DelayInitial(this IObservable source, TimeSpan delay) + { + return source.FilterSwitch( + Observable.Return(System.Reactive.Unit.Default) + .Delay(delay) + .Select(_ => true) + .StartWith(false)); + } + + public static IObservable DelayInitial(this IObservable source, TimeSpan delay, IScheduler scheduler) + { + return source.FilterSwitch( + Observable.Return(System.Reactive.Unit.Default) + .Delay(delay, scheduler) + .Select(_ => true) + .StartWith(false)); + } } } diff --git a/Wabbajack/View Models/Compilers/CompilerVM.cs b/Wabbajack/View Models/Compilers/CompilerVM.cs index 70cc770f..9a8f32e9 100644 --- a/Wabbajack/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack/View Models/Compilers/CompilerVM.cs @@ -1,4 +1,4 @@ -using Microsoft.WindowsAPICodePack.Dialogs; +using Microsoft.WindowsAPICodePack.Dialogs; using ReactiveUI; using ReactiveUI.Fody.Helpers; using System; @@ -45,6 +45,8 @@ namespace Wabbajack // Swap to proper sub VM based on selected type this._Compiler = this.WhenAny(x => x.SelectedCompilerType) + // Delay so the initial VM swap comes in immediately, subVM comes right after + .DelayInitial(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler) .Select(type => { switch (type) @@ -64,6 +66,8 @@ namespace Wabbajack .ToProperty(this, nameof(this.CurrentModlistSettings)); this._Image = this.WhenAny(x => x.CurrentModlistSettings.ImagePath.TargetPath) + // Delay so the initial VM swap comes in immediately, image comes right after + .DelayInitial(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler) .Select(path => { if (string.IsNullOrWhiteSpace(path)) return UIUtils.BitmapImageFromResource("Wabbajack.Resources.Banner_Dark.png"); diff --git a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs index 44484b27..0a0d3311 100644 --- a/Wabbajack/View Models/Compilers/MO2CompilerVM.cs +++ b/Wabbajack/View Models/Compilers/MO2CompilerVM.cs @@ -1,4 +1,4 @@ -using ReactiveUI; +using ReactiveUI; using ReactiveUI.Fody.Helpers; using System; using System.Collections.Generic; @@ -78,23 +78,6 @@ namespace Wabbajack }) .ToProperty(this, nameof(this.MOProfile)); - // If Mo2 folder changes and download location is empty, set it for convenience - this.WhenAny(x => x.Mo2Folder) - .Where(x => Directory.Exists(x)) - .Subscribe(x => - { - try - { - var tmp_compiler = new Compiler(this.Mo2Folder); - this.DownloadLocation.TargetPath = tmp_compiler.MO2DownloadsFolder; - } - catch (Exception ex) - { - Utils.Log($"Error setting default download location {ex}"); - } - }) - .DisposeWith(this.CompositeDisposable); - // Wire missing Mo2Folder to signal error state for Modlist Location this.ModlistLocation.AdditionalError = this.WhenAny(x => x.Mo2Folder) .Select(moFolder => @@ -188,6 +171,29 @@ namespace Wabbajack // Save to property .ObserveOnGuiThread() .ToProperty(this, nameof(this.ModlistSettings)); + + // If Mo2 folder changes and download location is empty, set it for convenience + this.WhenAny(x => x.Mo2Folder) + .DelayInitial(TimeSpan.FromMilliseconds(100)) + .Where(x => Directory.Exists(x)) + .FilterSwitch( + this.WhenAny(x => x.DownloadLocation.Exists) + .Invert()) + .Subscribe(x => + { + try + { + var tmp_compiler = new Compiler(this.Mo2Folder); + this.DownloadLocation.TargetPath = tmp_compiler.MO2DownloadsFolder; + } + catch (Exception ex) + { + Utils.Log($"Error setting default download location {ex}"); + } + }) + .DisposeWith(this.CompositeDisposable); + + } } } From 9fd06e4c67d65f08d1bc096a119cc498ac4c61e6 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 22:59:59 -0600 Subject: [PATCH 09/14] Removed none.jpg null bitmaps should just be used --- Wabbajack/Resources/none.jpg | Bin 20794 -> 0 bytes Wabbajack/View Models/Compilers/CompilerVM.cs | 4 ++-- Wabbajack/Wabbajack.csproj | 3 --- 3 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 Wabbajack/Resources/none.jpg diff --git a/Wabbajack/Resources/none.jpg b/Wabbajack/Resources/none.jpg deleted file mode 100644 index 55ae0bad2e951e2b26b6aff0da9a22b064b12e67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20794 zcmeIwOH30%7zglgc4pgcHKEH(#e-5n3Wp|zijRW^kSZjYfP&(QqEyR)2v(^k9zc9? zFu}K;#JAp1QQ;&CsNC=gc(Fdw6ZqE4I$KRmI2k#a{AcscPIhJ|`=9+8!^U%Rl=zB$ z#2BM$d65yJKv6gtASx}TY$DP~uoP0|h{;;QX2-@p<{}<_uEsJXKzyZ z(0F=oO=FAAo;+jbtdxv-nXasC@BF+43l}XeTvp^;zM{Bf)#{4MHEXNZt=~`^*tjWJ zwTgJJ<}_=G1??T3y|%R6^6{ja#vyxhx;K(BVMdE4`@3K* z|CB5i>`$&yn$DU0d0eNZbfC?3N#=zsgO} diff --git a/Wabbajack/View Models/Compilers/CompilerVM.cs b/Wabbajack/View Models/Compilers/CompilerVM.cs index 9a8f32e9..d6454a1a 100644 --- a/Wabbajack/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack/View Models/Compilers/CompilerVM.cs @@ -1,4 +1,4 @@ -using Microsoft.WindowsAPICodePack.Dialogs; +using Microsoft.WindowsAPICodePack.Dialogs; using ReactiveUI; using ReactiveUI.Fody.Helpers; using System; @@ -75,7 +75,7 @@ namespace Wabbajack { return image; } - return UIUtils.BitmapImageFromResource("Wabbajack.Resources.none.png"); + return null; }) .ToProperty(this, nameof(this.Image)); } diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index f06955a1..35c0c7c5 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -374,9 +374,6 @@ - - - From cefe52f42e0eac8504522d47ffa55f81372c41b2 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 23:31:46 -0600 Subject: [PATCH 10/14] CompilerVM image throttles input, and is distinct --- Wabbajack/View Models/Compilers/CompilerVM.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Wabbajack/View Models/Compilers/CompilerVM.cs b/Wabbajack/View Models/Compilers/CompilerVM.cs index d6454a1a..4e2106e7 100644 --- a/Wabbajack/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack/View Models/Compilers/CompilerVM.cs @@ -66,8 +66,9 @@ namespace Wabbajack .ToProperty(this, nameof(this.CurrentModlistSettings)); this._Image = this.WhenAny(x => x.CurrentModlistSettings.ImagePath.TargetPath) - // Delay so the initial VM swap comes in immediately, image comes right after - .DelayInitial(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler) + // Throttle so that it only loads image after any sets of swaps have completed + .Throttle(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler) + .DistinctUntilChanged() .Select(path => { if (string.IsNullOrWhiteSpace(path)) return UIUtils.BitmapImageFromResource("Wabbajack.Resources.Banner_Dark.png"); From 9f86f3466d36051782b862897508ac0545aae258 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 23:43:58 -0600 Subject: [PATCH 11/14] Made GameMetaData Games dictionary readonly --- Wabbajack.Common/GameMetaData.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Wabbajack.Common/GameMetaData.cs b/Wabbajack.Common/GameMetaData.cs index 203d24a4..e865665f 100644 --- a/Wabbajack.Common/GameMetaData.cs +++ b/Wabbajack.Common/GameMetaData.cs @@ -71,8 +71,7 @@ namespace Wabbajack.Common return Games.Values.FirstOrDefault(g => g.NexusName == gameName.ToLower()); } - - public static Dictionary Games = new Dictionary + public static IReadOnlyDictionary Games = new Dictionary { /*{ Game.Morrowind, new GameMetaData() From deafaf5ebdcda487068bf61b7718e15089dbed1e Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 23:45:02 -0600 Subject: [PATCH 12/14] Adjusted Game enum capitalization C# standard is camel case, and the other enum values were that way, too. KOTOR kept as is, as it's an acronym --- Wabbajack.Common/GameMetaData.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Wabbajack.Common/GameMetaData.cs b/Wabbajack.Common/GameMetaData.cs index e865665f..5440e722 100644 --- a/Wabbajack.Common/GameMetaData.cs +++ b/Wabbajack.Common/GameMetaData.cs @@ -22,9 +22,9 @@ namespace Wabbajack.Common Starbound, SWKOTOR, SWKOTOR2, - WITCHER, - WITCHER2, - WITCHER3 + Witcher, + Witcher2, + Witcher3 } public class GameMetaData @@ -241,30 +241,30 @@ namespace Wabbajack.Common } }, { - Game.WITCHER, new GameMetaData + Game.Witcher, new GameMetaData { SupportedModManager = ModManager.Vortex, - Game = Game.WITCHER, + Game = Game.Witcher, NexusName = "witcher", SteamIDs = new List{20900}, GOGIDs = new List{1207658924} } }, { - Game.WITCHER2, new GameMetaData + Game.Witcher2, new GameMetaData { SupportedModManager = ModManager.Vortex, - Game = Game.WITCHER2, + Game = Game.Witcher2, NexusName = "witcher2", SteamIDs = new List{20920}, GOGIDs = new List{1207658930} } }, { - Game.WITCHER3, new GameMetaData + Game.Witcher3, new GameMetaData { SupportedModManager = ModManager.Vortex, - Game = Game.WITCHER3, + Game = Game.Witcher3, NexusName = "witcher3", SteamIDs = new List{292030, 499450}, // normal and GotY GOGIDs = new List{1207664643, 1495134320, 1207664663, 1640424747} // normal, GotY and both in packages From 9580301a4f4ac740a6b8c4b854aa8d14638b785d Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 23:47:31 -0600 Subject: [PATCH 13/14] Moved some trivial member instantiations to in-line No need to make every sub compiler create these --- Wabbajack.Lib/ACompiler.cs | 14 +++++++------- Wabbajack.Lib/Compiler.cs | 9 --------- Wabbajack.Lib/VortexCompiler.cs | 7 ------- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/Wabbajack.Lib/ACompiler.cs b/Wabbajack.Lib/ACompiler.cs index 9c9c8561..279fe296 100644 --- a/Wabbajack.Lib/ACompiler.cs +++ b/Wabbajack.Lib/ACompiler.cs @@ -18,13 +18,13 @@ namespace Wabbajack.Lib public string ModListOutputFolder; public string ModListOutputFile; - public List SelectedArchives; - public List InstallDirectives; - public List AllFiles; - public ModList ModList; - public VirtualFileSystem VFS; - public List IndexedArchives; - public Dictionary> IndexedFiles; + public List SelectedArchives = new List(); + public List InstallDirectives = new List(); + public List AllFiles = new List(); + public ModList ModList = new ModList(); + public VirtualFileSystem VFS = VirtualFileSystem.VFS; + public List IndexedArchives = new List(); + public Dictionary> IndexedFiles = new Dictionary>(); public abstract void Info(string msg); public abstract void Status(string msg); diff --git a/Wabbajack.Lib/Compiler.cs b/Wabbajack.Lib/Compiler.cs index 3f395c63..1af2779e 100644 --- a/Wabbajack.Lib/Compiler.cs +++ b/Wabbajack.Lib/Compiler.cs @@ -50,15 +50,6 @@ namespace Wabbajack.Lib ModListOutputFolder = "output_folder"; ModListOutputFile = MO2Profile + ExtensionManager.Extension; - - SelectedArchives = new List(); - InstallDirectives = new List(); - AllFiles = new List(); - ModList = new ModList(); - - VFS = VirtualFileSystem.VFS; - IndexedArchives = new List(); - IndexedFiles = new Dictionary>(); } public dynamic MO2Ini { get; } diff --git a/Wabbajack.Lib/VortexCompiler.cs b/Wabbajack.Lib/VortexCompiler.cs index d650c3c2..80aa5789 100644 --- a/Wabbajack.Lib/VortexCompiler.cs +++ b/Wabbajack.Lib/VortexCompiler.cs @@ -55,13 +55,6 @@ namespace Wabbajack.Lib // TODO: add custom modlist name ModListOutputFile = $"VORTEX_TEST_MODLIST{ExtensionManager.Extension}"; - - VFS = VirtualFileSystem.VFS; - - SelectedArchives = new List(); - AllFiles = new List(); - IndexedArchives = new List(); - IndexedFiles = new Dictionary>(); } public override void Info(string msg) From 22d1f29a8d1c26015843fe3903f1c4931d374cfb Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Thu, 14 Nov 2019 23:49:00 -0600 Subject: [PATCH 14/14] Removed duplicate member --- Wabbajack.Lib/Compiler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Wabbajack.Lib/Compiler.cs b/Wabbajack.Lib/Compiler.cs index 1af2779e..bb8d4214 100644 --- a/Wabbajack.Lib/Compiler.cs +++ b/Wabbajack.Lib/Compiler.cs @@ -53,7 +53,6 @@ namespace Wabbajack.Lib } public dynamic MO2Ini { get; } - public string GamePath { get; } public bool ShowReportWhenFinished { get; set; } = true;