wabbajack/Wabbajack/View Models/Compilers/VortexCompilerVM.cs

220 lines
8.9 KiB
C#
Raw Normal View History

using System;
using System.IO;
using System.Linq;
2019-11-16 23:10:17 +00:00
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using DynamicData.Binding;
using ReactiveUI;
2019-11-16 23:10:17 +00:00
using ReactiveUI.Fody.Helpers;
using Wabbajack.Common;
using Wabbajack.Common.StoreHandlers;
using Wabbajack.Lib;
namespace Wabbajack
{
public class VortexCompilerVM : ViewModel, ISubCompilerVM
{
public CompilerVM Parent { get; }
2019-11-17 12:42:31 +00:00
private readonly VortexCompilationSettings _settings;
2019-11-17 12:42:31 +00:00
private readonly ObservableAsPropertyHelper<ModlistSettingsEditorVM> _modListSettings;
public ModlistSettingsEditorVM ModlistSettings => _modListSettings.Value;
2019-11-16 23:10:17 +00:00
2019-11-17 12:42:31 +00:00
private static readonly ObservableCollectionExtended<GameVM> _gameOptions = new ObservableCollectionExtended<GameVM>(
EnumExt.GetValues<Game>()
2019-12-03 02:38:33 +00:00
.Where(g => VortexCompiler.IsActiveVortexGame(g))
.Select(g => new GameVM(g))
.OrderBy(g => g.DisplayName));
2019-11-17 12:42:31 +00:00
public ObservableCollectionExtended<GameVM> GameOptions => _gameOptions;
2019-11-21 05:15:47 +00:00
[Reactive]
public ACompiler ActiveCompilation { get; private set; }
2019-11-16 23:10:17 +00:00
[Reactive]
public GameVM SelectedGame { get; set; }
2019-11-16 23:10:17 +00:00
[Reactive]
public FilePickerVM GameLocation { get; set; }
[Reactive]
public FilePickerVM DownloadsLocation { get; set; }
[Reactive]
public FilePickerVM StagingLocation { get; set; }
public ICommand FindGameInSteamCommand { get; }
public ICommand FindGameInGogCommand { get; }
[Reactive]
public StatusUpdateTracker StatusTracker { get; private set; }
2019-12-19 01:14:21 +00:00
public IObservable<bool> CanCompile { get; }
2019-11-16 23:10:17 +00:00
public VortexCompilerVM(CompilerVM parent)
{
Parent = parent;
GameLocation = new FilePickerVM()
2019-11-16 23:10:17 +00:00
{
ExistCheckOption = FilePickerVM.CheckOptions.On,
2019-11-16 23:10:17 +00:00
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Game Folder Location"
};
DownloadsLocation = new FilePickerVM()
2019-11-16 23:10:17 +00:00
{
ExistCheckOption = FilePickerVM.CheckOptions.On,
2019-11-16 23:10:17 +00:00
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Downloads Folder"
};
StagingLocation = new FilePickerVM()
2019-11-16 23:10:17 +00:00
{
ExistCheckOption = FilePickerVM.CheckOptions.On,
2019-11-16 23:10:17 +00:00
PathType = FilePickerVM.PathTypeOptions.Folder,
PromptTitle = "Select Staging Folder"
};
// Load custom ModList settings when game type changes
2019-12-19 01:14:21 +00:00
_modListSettings = (this).WhenAny(x => x.SelectedGame)
.Select(game =>
{
2019-12-14 23:43:54 +00:00
if (game == null) return null;
var gameSettings = _settings.ModlistSettings.TryCreate(game.Game);
return new ModlistSettingsEditorVM(gameSettings.ModlistSettings);
})
// Interject and save old while loading new
.Pairwise()
.Do(pair =>
{
var (previous, current) = pair;
previous?.Save();
current?.Init();
})
.Select(x => x.Current)
.ToGuiProperty(this, nameof(ModlistSettings));
2019-12-19 01:14:21 +00:00
CanCompile = Observable.CombineLatest(
this.WhenAny(x => x.GameLocation.InError),
this.WhenAny(x => x.DownloadsLocation.InError),
this.WhenAny(x => x.StagingLocation.InError),
this.WhenAny(x => x.ModlistSettings)
.Select(x => x?.InError ?? Observable.Return(false))
.Switch(),
(g, d, s, ml) => !g && !d && !s && !ml)
.Publish()
.RefCount();
2019-11-16 23:10:17 +00:00
// Load settings
2019-11-17 12:42:31 +00:00
_settings = parent.MWVM.Settings.Compiler.VortexCompilation;
SelectedGame = _gameOptions.FirstOrDefault(x => x.Game == _settings.LastCompiledGame) ?? _gameOptions[0];
2019-11-16 23:10:17 +00:00
parent.MWVM.Settings.SaveSignal
.Subscribe(_ => Unload())
2019-11-17 12:42:31 +00:00
.DisposeWith(CompositeDisposable);
2019-11-16 23:10:17 +00:00
// Load custom game settings when game type changes
2019-12-19 01:14:21 +00:00
(this).WhenAny(x => x.SelectedGame)
2019-11-17 12:42:31 +00:00
.Select(game => _settings.ModlistSettings.TryCreate(game.Game))
2019-11-16 23:10:17 +00:00
.Pairwise()
.Subscribe(pair =>
{
// Save old
2019-11-17 12:42:31 +00:00
var (previous, current) = pair;
if (previous != null)
2019-11-16 23:10:17 +00:00
{
2019-11-17 12:42:31 +00:00
previous.GameLocation = GameLocation.TargetPath;
2019-11-16 23:10:17 +00:00
}
// Load new
2019-11-17 12:42:31 +00:00
GameLocation.TargetPath = current?.GameLocation;
if (string.IsNullOrWhiteSpace(GameLocation.TargetPath))
{
2019-11-17 12:42:31 +00:00
SetGameToSteamLocation();
}
2019-11-17 12:42:31 +00:00
if (string.IsNullOrWhiteSpace(GameLocation.TargetPath))
{
2019-11-17 12:42:31 +00:00
SetGameToGogLocation();
}
2019-11-17 12:42:31 +00:00
DownloadsLocation.TargetPath = current?.DownloadLocation;
if (string.IsNullOrWhiteSpace(DownloadsLocation.TargetPath))
{
2019-11-17 12:42:31 +00:00
DownloadsLocation.TargetPath = VortexCompiler.RetrieveDownloadLocation(SelectedGame.Game);
}
2019-11-17 12:42:31 +00:00
StagingLocation.TargetPath = current?.StagingLocation;
if (string.IsNullOrWhiteSpace(StagingLocation.TargetPath))
{
2019-11-17 12:42:31 +00:00
StagingLocation.TargetPath = VortexCompiler.RetrieveStagingLocation(SelectedGame.Game);
}
2019-11-16 23:10:17 +00:00
})
2019-11-17 12:42:31 +00:00
.DisposeWith(CompositeDisposable);
2019-11-16 23:10:17 +00:00
// Find game commands
2019-11-17 12:42:31 +00:00
FindGameInSteamCommand = ReactiveCommand.Create(SetGameToSteamLocation);
FindGameInGogCommand = ReactiveCommand.Create(SetGameToGogLocation);
// Add additional criteria to download/staging folders
2019-11-17 12:42:31 +00:00
DownloadsLocation.AdditionalError = this.WhenAny(x => x.DownloadsLocation.TargetPath)
.Select(path => path == null ? ErrorResponse.Success : VortexCompiler.IsValidDownloadsFolder(path));
StagingLocation.AdditionalError = this.WhenAny(x => x.StagingLocation.TargetPath)
.Select(path => path == null ? ErrorResponse.Success : VortexCompiler.IsValidBaseStagingFolder(path));
2019-11-16 23:10:17 +00:00
}
public void Unload()
{
2019-11-17 12:42:31 +00:00
_settings.LastCompiledGame = SelectedGame.Game;
ModlistSettings?.Save();
2019-11-16 23:10:17 +00:00
}
private void SetGameToSteamLocation()
{
GameLocation.TargetPath = StoreHandler.Instance.GetGamePath(SelectedGame.Game, StoreType.STEAM);
}
private void SetGameToGogLocation()
{
GameLocation.TargetPath = StoreHandler.Instance.GetGamePath(SelectedGame.Game, StoreType.GOG);
}
2019-12-19 01:14:21 +00:00
public async Task<GetResponse<ModList>> Compile()
2019-12-19 01:14:21 +00:00
{
string outputFile = $"{ModlistSettings.ModListName}{Consts.ModListExtension}";
2019-12-19 01:14:21 +00:00
if (!string.IsNullOrWhiteSpace(Parent.OutputLocation.TargetPath))
{
outputFile = Path.Combine(Parent.OutputLocation.TargetPath, outputFile);
}
try
{
using (ActiveCompilation = new VortexCompiler(
2019-12-19 01:14:21 +00:00
game: SelectedGame.Game,
gamePath: GameLocation.TargetPath,
vortexFolder: VortexCompiler.TypicalVortexFolder(),
downloadsFolder: DownloadsLocation.TargetPath,
stagingFolder: StagingLocation.TargetPath,
outputFile: outputFile)
{
ModListName = ModlistSettings.ModListName,
ModListAuthor = ModlistSettings.AuthorText,
ModListDescription = ModlistSettings.Description,
ModListImage = ModlistSettings.ImagePath.TargetPath,
ModListWebsite = ModlistSettings.Website,
2019-12-20 07:14:43 +00:00
ModListReadme = ModlistSettings.ReadmeIsWebsite ? ModlistSettings.ReadmeWebsite : ModlistSettings.ReadmeFilePath.TargetPath,
ReadmeIsWebsite = ModlistSettings.ReadmeIsWebsite,
})
{
Parent.MWVM.Settings.Performance.AttachToBatchProcessor(ActiveCompilation);
var success = await ActiveCompilation.Begin();
return GetResponse<ModList>.Create(success, ActiveCompilation.ModList);
}
2019-12-19 01:14:21 +00:00
}
finally
{
StatusTracker = null;
ActiveCompilation.Dispose();
ActiveCompilation = null;
}
}
}
2019-11-21 05:15:47 +00:00
}