From f75f93086c522a875d7c0899fb5f2ed72d467203 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Wed, 5 Jan 2022 06:59:30 -0700 Subject: [PATCH] Start to wire up the picker boxes --- Wabbajack.App.Wpf/Consts.cs | 1 + Wabbajack.App.Wpf/Settings.cs | 8 - .../View Models/Compilers/CompilerVM.cs | 155 +++++++++++++++++- .../Views/Compilers/CompilerView.xaml | 26 +-- .../Views/Compilers/CompilerView.xaml.cs | 32 ++++ .../Compilers/MO2CompilerConfigView.xaml | 5 +- Wabbajack.Compiler/CompilerSettings.cs | 4 + Wabbajack.Compiler/MO2CompilerSettings.cs | 4 +- 8 files changed, 196 insertions(+), 39 deletions(-) diff --git a/Wabbajack.App.Wpf/Consts.cs b/Wabbajack.App.Wpf/Consts.cs index f93ff405..bec5a30f 100644 --- a/Wabbajack.App.Wpf/Consts.cs +++ b/Wabbajack.App.Wpf/Consts.cs @@ -6,6 +6,7 @@ namespace Wabbajack; public static class Consts { + public static RelativePath MO2IniName = "ModOrganizer.ini".ToRelativePath(); public static string AppName = "Wabbajack"; public static Uri WabbajackBuildServerUri => new("https://build.wabbajack.org"); public static Version CurrentMinimumWabbajackVersion { get; set; } = Version.Parse("2.3.0.0"); diff --git a/Wabbajack.App.Wpf/Settings.cs b/Wabbajack.App.Wpf/Settings.cs index 9c2f65f2..68a9d89a 100644 --- a/Wabbajack.App.Wpf/Settings.cs +++ b/Wabbajack.App.Wpf/Settings.cs @@ -87,14 +87,6 @@ namespace Wabbajack public bool AutomaticallyOverrideExistingInstall { get; set; } } - [JsonName("CompilerSettings")] - public class CompilerSettings - { - public ModManager LastCompiledModManager { get; set; } - public AbsolutePath OutputLocation { get; set; } - public MO2CompilationSettings MO2Compilation { get; } = new MO2CompilationSettings(); - } - [JsonName("FiltersSettings")] [JsonObject(MemberSerialization.OptOut)] public class FiltersSettings : ViewModel diff --git a/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs b/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs index 61219196..c164f246 100644 --- a/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs @@ -1,5 +1,7 @@ using System; using System.Collections.ObjectModel; +using System.IO; +using System.Linq; using System.Reactive; using System.Windows.Media.Imaging; using Microsoft.Extensions.Logging; @@ -10,16 +12,167 @@ using Wabbajack.RateLimiter; using ReactiveUI; using System.Reactive.Disposables; using System.Reactive.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using System.Windows.Media; using DynamicData.Binding; using ReactiveUI.Fody.Helpers; +using Wabbajack.Common; +using Wabbajack.Compiler; +using Wabbajack.DTOs; using Wabbajack.DTOs.Interventions; +using Wabbajack.DTOs.JsonConverters; +using Wabbajack.Installer; +using Wabbajack.Paths; +using Wabbajack.Paths.IO; namespace Wabbajack { + public enum CompilerState + { + Configuration, + Compiling, + Completed, + Errored + } public class CompilerVM : BackNavigatingVM { - public CompilerVM(ILogger logger) : base(logger) + private readonly DTOSerializer _dtos; + + [Reactive] + public CompilerState State { get; set; } + + [Reactive] + public ISubCompilerVM SubCompilerVM { get; set; } + + // Paths + public FilePickerVM ModlistLocation { get; } = new(); + public FilePickerVM DownloadLocation { get; } = new(); + public FilePickerVM OutputLocation { get; } = new(); + + // Modlist Settings + + [Reactive] public string ModListName { get; set; } + [Reactive] public string Version { get; set; } + [Reactive] public string Author { get; set; } + [Reactive] public string Description { get; set; } + public FilePickerVM ModListImagePath { get; } = new(); + [Reactive] public ImageSource ModListImage { get; set; } + [Reactive] public string Website { get; set; } + [Reactive] public string Readme { get; set; } + [Reactive] public bool IsNSFW { get; set; } + [Reactive] public bool PublishUpdate { get; set; } + [Reactive] public string MachineUrl { get; set; } + [Reactive] public Game BaseGame { get; set; } + [Reactive] public string SelectedProfile { get; set; } + [Reactive] public AbsolutePath GamePath { get; set; } + [Reactive] public bool IsMO2Compilation { get; set; } + + [Reactive] public RelativePath[] AlwaysEnabled { get; set; } + [Reactive] public string[] OtherProfiles { get; set; } + + [Reactive] public AbsolutePath Source { get; set; } + + public AbsolutePath SettingsOutputLocation => ModlistLocation.TargetPath.Combine(ModListName) + .WithExtension(IsMO2Compilation ? Ext.MO2CompilerSettings : Ext.CompilerSettings); + + public CompilerVM(ILogger logger, DTOSerializer dtos) : base(logger) { + _dtos = dtos; + SubCompilerVM = new MO2CompilerVM(this); + + this.WhenActivated(disposables => + { + State = CompilerState.Configuration; + Disposable.Empty.DisposeWith(disposables); + + ModlistLocation.WhenAnyValue(vm => vm.TargetPath) + .Subscribe(p => InferModListFromLocation(p).FireAndForget()) + .DisposeWith(disposables); + }); + } + + private async Task InferModListFromLocation(AbsolutePath settingsFile) + { + using var ll = LoadingLock.WithLoading(); + if (settingsFile.FileName == "modlist.txt".ToRelativePath() && settingsFile.Depth > 3) + { + var mo2Folder = settingsFile.Parent.Parent.Parent; + var mo2Ini = mo2Folder.Combine(Consts.MO2IniName); + if (mo2Ini.FileExists()) + { + var iniData = mo2Ini.LoadIniFile(); + + var general = iniData["General"]; + + BaseGame = GameRegistry.GetByFuzzyName(general["gameName"].FromMO2Ini()).Game; + Source = mo2Folder; + + SelectedProfile = general["selected_profile"].FromMO2Ini(); + GamePath = general["gamePath"].FromMO2Ini().ToAbsolutePath(); + ModListName = SelectedProfile; + + var settings = iniData["Settings"]; + DownloadLocation.TargetPath = settings["download_directory"].FromMO2Ini().ToAbsolutePath(); + IsMO2Compilation = true; + + + + AlwaysEnabled = Array.Empty(); + // Find Always Enabled mods + foreach (var modFolder in mo2Folder.Combine("mods").EnumerateDirectories()) + { + var iniFile = modFolder.Combine("meta.ini"); + if (!iniFile.FileExists()) continue; + + var data = iniFile.LoadIniFile(); + var generalModData = data["General"]; + if ((generalModData["notes"]?.Contains("WABBAJACK_ALWAYS_ENABLE") ?? false) || + (generalModData["comments"]?.Contains("WABBAJACK_ALWAYS_ENABLE") ?? false)) + AlwaysEnabled = AlwaysEnabled.Append(modFolder.RelativeTo(mo2Folder)).ToArray(); + } + + var otherProfilesFile = settingsFile.Parent.Combine("otherprofiles.txt"); + if (otherProfilesFile.FileExists()) + { + OtherProfiles = await otherProfilesFile.ReadAllLinesAsync().ToArray(); + } + + if (mo2Folder.Depth > 1) + OutputLocation.TargetPath = mo2Folder.Parent; + + await SaveSettingsFile(); + ModlistLocation.TargetPath = SettingsOutputLocation; + } + } + + } + + private async Task SaveSettingsFile() + { + await using var st = SettingsOutputLocation.Open(FileMode.Create, FileAccess.Write, FileShare.None); + if (IsMO2Compilation) + await JsonSerializer.SerializeAsync(st, (MO2CompilerSettings) GetSettings(), _dtos.Options); + else + await JsonSerializer.SerializeAsync(st, GetSettings(), _dtos.Options); + } + + + private CompilerSettings GetSettings() + { + return new CompilerSettings + { + ModListName = ModListName, + ModListAuthor = Author, + Downloads = DownloadLocation.TargetPath, + Source = ModlistLocation.TargetPath, + Game = BaseGame, + Profile = SelectedProfile, + UseGamePaths = true, + OutputFile = OutputLocation.TargetPath.Combine(SelectedProfile).WithExtension(Ext.Wabbajack), + AlwaysEnabled = AlwaysEnabled.ToArray(), + OtherProfiles = OtherProfiles.ToArray() + }; } } } diff --git a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml index f8add2a5..8747618b 100644 --- a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml +++ b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml @@ -166,31 +166,7 @@ - - - - - - - - - - - - - - - - - - + diff --git a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs index 2a8d99e8..f3b6c35b 100644 --- a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs @@ -18,6 +18,38 @@ namespace Wabbajack { InitializeComponent(); + this.WhenActivated(disposables => + { + ViewModel.WhenAnyValue(vm => vm.State) + .Select(v => v == CompilerState.Configuration ? Visibility.Visible : Visibility.Collapsed) + .BindToStrict(this, view => view.BottomCompilerSettingsGrid.Visibility) + .DisposeWith(disposables); + + ViewModel.WhenAnyValue(vm => vm.State) + .Select(v => v != CompilerState.Configuration ? Visibility.Visible : Visibility.Collapsed) + .BindToStrict(this, view => view.LogView.Visibility) + .DisposeWith(disposables); + + ViewModel.WhenAnyValue(vm => vm.State) + .Select(v => v == CompilerState.Compiling ? Visibility.Visible : Visibility.Collapsed) + .BindToStrict(this, view => view.CpuView.Visibility) + .DisposeWith(disposables); + + ViewModel.WhenAnyValue(vm => vm.State) + .Select(v => v == CompilerState.Completed ? Visibility.Visible : Visibility.Collapsed) + .BindToStrict(this, view => view.CompilationComplete.Visibility) + .DisposeWith(disposables); + + ViewModel.WhenAnyValue(vm => vm.ModlistLocation) + .BindToStrict(this, view => view.CompilerConfigView.ModListLocation.PickerVM) + .DisposeWith(disposables); + + UserInterventionsControl.Visibility = Visibility.Collapsed; + + + + }); + } } } diff --git a/Wabbajack.App.Wpf/Views/Compilers/MO2CompilerConfigView.xaml b/Wabbajack.App.Wpf/Views/Compilers/MO2CompilerConfigView.xaml index fd4da5a3..f8cc4efa 100644 --- a/Wabbajack.App.Wpf/Views/Compilers/MO2CompilerConfigView.xaml +++ b/Wabbajack.App.Wpf/Views/Compilers/MO2CompilerConfigView.xaml @@ -27,11 +27,12 @@ Text="Modlist Location" TextAlignment="Center" ToolTip="The MO2 modlist.txt file you want to use as your source" /> - public RelativePath[] Include { get; set; } = Array.Empty(); + + public string Profile { get; set; } = ""; + public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty(); + public string[] OtherProfiles { get; set; } } \ No newline at end of file diff --git a/Wabbajack.Compiler/MO2CompilerSettings.cs b/Wabbajack.Compiler/MO2CompilerSettings.cs index ce3ac65d..8efc2ccb 100644 --- a/Wabbajack.Compiler/MO2CompilerSettings.cs +++ b/Wabbajack.Compiler/MO2CompilerSettings.cs @@ -5,7 +5,5 @@ namespace Wabbajack.Compiler; public class MO2CompilerSettings : CompilerSettings { - public string Profile { get; set; } = ""; - public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty(); - public string[] OtherProfiles { get; set; } + } \ No newline at end of file