mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Add other profiles and always enabled to Compiler screen
This commit is contained in:
parent
8cceacf78d
commit
695e7ede8b
@ -55,6 +55,7 @@ namespace Wabbajack
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger<CompilerVM> _logger;
|
||||
private readonly ResourceMonitor _resourceMonitor;
|
||||
private readonly CompilerSettingsInferencer _inferencer;
|
||||
|
||||
[Reactive]
|
||||
public CompilerState State { get; set; }
|
||||
@ -86,6 +87,7 @@ namespace Wabbajack
|
||||
[Reactive] public bool IsMO2Compilation { get; set; }
|
||||
|
||||
[Reactive] public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty<RelativePath>();
|
||||
|
||||
[Reactive] public string[] OtherProfiles { get; set; } = Array.Empty<string>();
|
||||
|
||||
[Reactive] public AbsolutePath Source { get; set; }
|
||||
@ -99,7 +101,8 @@ namespace Wabbajack
|
||||
public ReadOnlyObservableCollection<CPUDisplayVM> StatusList => _resourceMonitor.Tasks;
|
||||
|
||||
public CompilerVM(ILogger<CompilerVM> logger, DTOSerializer dtos, SettingsManager settingsManager,
|
||||
IServiceProvider serviceProvider, LogStream loggerProvider, ResourceMonitor resourceMonitor) : base(logger)
|
||||
IServiceProvider serviceProvider, LogStream loggerProvider, ResourceMonitor resourceMonitor,
|
||||
CompilerSettingsInferencer inferencer) : base(logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_dtos = dtos;
|
||||
@ -107,6 +110,7 @@ namespace Wabbajack
|
||||
_serviceProvider = serviceProvider;
|
||||
LoggerProvider = loggerProvider;
|
||||
_resourceMonitor = resourceMonitor;
|
||||
_inferencer = inferencer;
|
||||
|
||||
BackCommand =
|
||||
ReactiveCommand.CreateFromTask(async () =>
|
||||
@ -160,69 +164,26 @@ namespace Wabbajack
|
||||
});
|
||||
}
|
||||
|
||||
private async Task InferModListFromLocation(AbsolutePath settingsFile)
|
||||
private async Task InferModListFromLocation(AbsolutePath path)
|
||||
{
|
||||
if (settingsFile == default) return;
|
||||
using var _ = LoadingLock.WithLoading();
|
||||
if (path == default || path.FileName != "modlist.txt".ToRelativePath())
|
||||
return;
|
||||
|
||||
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"];
|
||||
var downloadLocation = settings["download_directory"].FromMO2Ini().ToAbsolutePath();
|
||||
|
||||
if (downloadLocation == default)
|
||||
downloadLocation = Source.Combine("downloads");
|
||||
|
||||
DownloadLocation.TargetPath = downloadLocation;
|
||||
IsMO2Compilation = true;
|
||||
|
||||
|
||||
|
||||
AlwaysEnabled = Array.Empty<RelativePath>();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
var settings = await _inferencer.InferModListFromLocation(path);
|
||||
if (settings == null) return;
|
||||
|
||||
BaseGame = settings.Game;
|
||||
ModListName = settings.ModListName;
|
||||
Source = settings.Source;
|
||||
DownloadLocation.TargetPath = settings.Downloads;
|
||||
OutputLocation.TargetPath = settings.OutputFile;
|
||||
SelectedProfile = settings.Profile;
|
||||
OtherProfiles = settings.OtherProfiles;
|
||||
AlwaysEnabled = settings.AlwaysEnabled;
|
||||
}
|
||||
|
||||
|
||||
private async Task StartCompilation()
|
||||
{
|
||||
var tsk = Task.Run(async () =>
|
||||
@ -306,5 +267,29 @@ namespace Wabbajack
|
||||
OtherProfiles = OtherProfiles.ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
#region ListOps
|
||||
|
||||
public void AddOtherProfile(string profile)
|
||||
{
|
||||
OtherProfiles = (OtherProfiles ?? Array.Empty<string>()).Append(profile).Distinct().ToArray();
|
||||
}
|
||||
|
||||
public void RemoveProfile(string profile)
|
||||
{
|
||||
OtherProfiles = OtherProfiles.Where(p => p != profile).ToArray();
|
||||
}
|
||||
|
||||
public void AddAlwaysEnabled(RelativePath path)
|
||||
{
|
||||
AlwaysEnabled = (AlwaysEnabled ?? Array.Empty<RelativePath>()).Append(path).Distinct().ToArray();
|
||||
}
|
||||
|
||||
public void RemoveAlwaysEnabled(RelativePath path)
|
||||
{
|
||||
AlwaysEnabled = AlwaysEnabled.Where(p => p != path).ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
<reactiveUi:ReactiveUserControl x:Class="Wabbajack.View_Models.Controls.RemovableItemView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Wabbajack.View_Models.Controls"
|
||||
|
||||
x:TypeArguments="controls:RemovableItemViewModel"
|
||||
xmlns:reactiveUi="http://reactiveui.net"
|
||||
xmlns:controls="clr-namespace:Wabbajack.View_Models.Controls"
|
||||
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="28" d:DesignWidth="300">
|
||||
<Grid Margin="4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0" Name="DeleteButton">
|
||||
<iconPacks:Material Kind="Delete"></iconPacks:Material>
|
||||
</Button>
|
||||
<TextBlock Margin="10, 0, 0, 0" Grid.Column="1" Name="DisplayText" VerticalAlignment="Center"></TextBlock>
|
||||
</Grid>
|
||||
</reactiveUi:ReactiveUserControl>
|
@ -0,0 +1,23 @@
|
||||
using System.Reactive.Disposables;
|
||||
using System.Windows.Controls;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Wabbajack.View_Models.Controls;
|
||||
|
||||
public partial class RemovableItemView : ReactiveUserControl<RemovableItemViewModel>
|
||||
{
|
||||
public RemovableItemView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindStrict(ViewModel, vm => vm.Text, view => view.DisplayText.Text)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
|
||||
});
|
||||
|
||||
DeleteButton.Command = ReactiveCommand.Create(() => ViewModel.RemoveFn());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace Wabbajack.View_Models.Controls;
|
||||
|
||||
public class RemovableItemViewModel : ViewModel
|
||||
{
|
||||
|
||||
public string Text { get; }
|
||||
|
||||
public Action RemoveFn { get; }
|
||||
|
||||
public RemovableItemViewModel(string text, Action removeFn)
|
||||
{
|
||||
Text = text;
|
||||
RemoveFn = removeFn;
|
||||
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:rxui="http://reactiveui.net"
|
||||
xmlns:wabbacommon="clr-namespace:Wabbajack.Common;assembly=Wabbajack.Common"
|
||||
xmlns:controls1="clr-namespace:Wabbajack.View_Models.Controls"
|
||||
d:DataContext="{d:DesignInstance local:CompilerVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
@ -142,6 +143,36 @@
|
||||
Text="MachineUrl"
|
||||
ToolTip="If this box has a value the modlist will be published to this MachineUrl after compilation" />
|
||||
<TextBox x:Name="MachineUrl" Style="{StaticResource ValueStyle}" />
|
||||
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Name="AddOtherProfile">
|
||||
<icon:Material Kind="Plus"></icon:Material>
|
||||
</Button>
|
||||
<Label>Other Profiles</Label>
|
||||
</StackPanel>
|
||||
<ListBox x:Name="OtherProfiles">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls1:RemovableItemView ViewModel="{Binding}" ></controls1:RemovableItemView>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Name="AddAlwaysEnabled">
|
||||
<icon:Material Kind="Plus"></icon:Material>
|
||||
</Button>
|
||||
<Label>Always Enabled Mods</Label>
|
||||
</StackPanel>
|
||||
<ListBox x:Name="AlwaysEnabled">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls1:RemovableItemView ViewModel="{Binding}" ></controls1:RemovableItemView>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<Border Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5"
|
||||
|
@ -1,11 +1,18 @@
|
||||
using System.Linq;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using ReactiveUI;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using DynamicData;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Wabbajack.View_Models.Controls;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
@ -98,9 +105,99 @@ namespace Wabbajack
|
||||
this.Bind(ViewModel, vm => vm.MachineUrl, view => view.MachineUrl.Text)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
ViewModel.WhenAnyValue(vm => vm.AlwaysEnabled)
|
||||
.WhereNotNull()
|
||||
.Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveAlwaysEnabled(itm))).ToArray())
|
||||
.BindToStrict(this, view => view.AlwaysEnabled.ItemsSource)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
AddAlwaysEnabled.Command = ReactiveCommand.CreateFromTask(async () => await AddAlwaysEnabledCommand());
|
||||
|
||||
ViewModel.WhenAnyValue(vm => vm.OtherProfiles)
|
||||
.WhereNotNull()
|
||||
.Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveProfile(itm))).ToArray())
|
||||
.BindToStrict(this, view => view.OtherProfiles.ItemsSource)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
AddOtherProfile.Command = ReactiveCommand.CreateFromTask(async () => await AddOtherProfileCommand());
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public async Task AddAlwaysEnabledCommand()
|
||||
{
|
||||
AbsolutePath dirPath;
|
||||
|
||||
if (ViewModel!.Source != default && ViewModel.Source.Combine("mods").DirectoryExists())
|
||||
{
|
||||
dirPath = ViewModel.Source.Combine("mods");
|
||||
}
|
||||
else
|
||||
{
|
||||
dirPath = ViewModel.Source;
|
||||
}
|
||||
|
||||
var dlg = new CommonOpenFileDialog
|
||||
{
|
||||
Title = "Please select a folder",
|
||||
IsFolderPicker = true,
|
||||
InitialDirectory = dirPath.ToString(),
|
||||
AddToMostRecentlyUsedList = false,
|
||||
AllowNonFileSystemItems = false,
|
||||
DefaultDirectory = dirPath.ToString(),
|
||||
EnsureFileExists = true,
|
||||
EnsurePathExists = true,
|
||||
EnsureReadOnly = false,
|
||||
EnsureValidNames = true,
|
||||
Multiselect = false,
|
||||
ShowPlacesList = true,
|
||||
};
|
||||
|
||||
if (dlg.ShowDialog() != CommonFileDialogResult.Ok) return;
|
||||
var selectedPath = dlg.FileNames.First().ToAbsolutePath();
|
||||
|
||||
if (!selectedPath.InFolder(ViewModel.Source)) return;
|
||||
|
||||
ViewModel.AddAlwaysEnabled(selectedPath.RelativeTo(ViewModel.Source));
|
||||
}
|
||||
|
||||
public async Task AddOtherProfileCommand()
|
||||
{
|
||||
AbsolutePath dirPath;
|
||||
|
||||
if (ViewModel!.Source != default && ViewModel.Source.Combine("mods").DirectoryExists())
|
||||
{
|
||||
dirPath = ViewModel.Source.Combine("mods");
|
||||
}
|
||||
else
|
||||
{
|
||||
dirPath = ViewModel.Source;
|
||||
}
|
||||
|
||||
var dlg = new CommonOpenFileDialog
|
||||
{
|
||||
Title = "Please select a profile folder",
|
||||
IsFolderPicker = true,
|
||||
InitialDirectory = dirPath.ToString(),
|
||||
AddToMostRecentlyUsedList = false,
|
||||
AllowNonFileSystemItems = false,
|
||||
DefaultDirectory = dirPath.ToString(),
|
||||
EnsureFileExists = true,
|
||||
EnsurePathExists = true,
|
||||
EnsureReadOnly = false,
|
||||
EnsureValidNames = true,
|
||||
Multiselect = false,
|
||||
ShowPlacesList = true,
|
||||
};
|
||||
|
||||
if (dlg.ShowDialog() != CommonFileDialogResult.Ok) return;
|
||||
var selectedPath = dlg.FileNames.First().ToAbsolutePath();
|
||||
|
||||
if (!selectedPath.InFolder(ViewModel.Source.Combine("profiles"))) return;
|
||||
|
||||
ViewModel.AddOtherProfile(selectedPath.FileName.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
84
Wabbajack.Compiler/CompilerSettingsInferencer.cs
Normal file
84
Wabbajack.Compiler/CompilerSettingsInferencer.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.Installer;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
|
||||
namespace Wabbajack.Compiler;
|
||||
|
||||
/// <summary>
|
||||
/// Given a modlist.txt file, infer as much of CompilerSettings as possible
|
||||
/// </summary>
|
||||
public class CompilerSettingsInferencer
|
||||
{
|
||||
private readonly ILogger<CompilerSettingsInferencer> _logger;
|
||||
|
||||
public CompilerSettingsInferencer(ILogger<CompilerSettingsInferencer> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
|
||||
}
|
||||
|
||||
public async Task<CompilerSettings?> InferModListFromLocation(AbsolutePath settingsFile)
|
||||
{
|
||||
var cs = new CompilerSettings();
|
||||
|
||||
if (settingsFile.FileName == "modlist.txt".ToRelativePath() && settingsFile.Depth > 3)
|
||||
{
|
||||
_logger.LogInformation("Inferencing basic settings");
|
||||
var mo2Folder = settingsFile.Parent.Parent.Parent;
|
||||
var mo2Ini = mo2Folder.Combine(Consts.MO2IniName);
|
||||
if (mo2Ini.FileExists())
|
||||
{
|
||||
var iniData = mo2Ini.LoadIniFile();
|
||||
|
||||
var general = iniData["General"];
|
||||
|
||||
cs.Game = GameRegistry.GetByFuzzyName(general["gameName"].FromMO2Ini()).Game;
|
||||
cs.Source = mo2Folder;
|
||||
|
||||
var selectedProfile = general["selected_profile"].FromMO2Ini();
|
||||
//cs.GamePath = general["gamePath"].FromMO2Ini().ToAbsolutePath();
|
||||
cs.ModListName = selectedProfile;
|
||||
|
||||
cs.OutputFile = cs.Source.Parent;
|
||||
|
||||
var settings = iniData["Settings"];
|
||||
cs.Downloads = settings["download_directory"].FromMO2Ini().ToAbsolutePath();
|
||||
|
||||
if (cs.Downloads == default)
|
||||
cs.Downloads = cs.Source.Combine("downloads");
|
||||
|
||||
_logger.LogInformation("Finding Always Enabled mods");
|
||||
cs.AlwaysEnabled = Array.Empty<RelativePath>();
|
||||
// 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))
|
||||
cs.AlwaysEnabled = cs.AlwaysEnabled.Append(modFolder.RelativeTo(mo2Folder)).ToArray();
|
||||
}
|
||||
|
||||
_logger.LogInformation("Finding other profiles");
|
||||
var otherProfilesFile = settingsFile.Parent.Combine("otherprofiles.txt");
|
||||
if (otherProfilesFile.FileExists())
|
||||
{
|
||||
cs.OtherProfiles = await otherProfilesFile.ReadAllLinesAsync().ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -154,6 +154,7 @@ public static class ServiceExtensions
|
||||
service.AddScoped<StandardInstaller>();
|
||||
service.AddScoped<MO2CompilerSettings>();
|
||||
service.AddScoped<MO2Compiler>();
|
||||
service.AddSingleton<CompilerSettingsInferencer>();
|
||||
|
||||
// Application Info
|
||||
var version =
|
||||
|
Loading…
Reference in New Issue
Block a user