2019-11-14 05:28:27 +00:00
|
|
|
|
using System;
|
2019-12-14 03:44:27 +00:00
|
|
|
|
using System.IO;
|
2019-11-14 05:28:27 +00:00
|
|
|
|
using System.Linq;
|
2019-11-16 23:10:17 +00:00
|
|
|
|
using System.Reactive.Disposables;
|
|
|
|
|
using System.Reactive.Linq;
|
2019-11-14 05:28:27 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2019-11-17 00:41:59 +00:00
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
using DynamicData.Binding;
|
2019-11-14 05:28:27 +00:00
|
|
|
|
using ReactiveUI;
|
2019-11-16 23:10:17 +00:00
|
|
|
|
using ReactiveUI.Fody.Helpers;
|
|
|
|
|
using Wabbajack.Common;
|
2020-01-03 17:22:50 +00:00
|
|
|
|
using Wabbajack.Common.StoreHandlers;
|
2019-11-14 05:28:27 +00:00
|
|
|
|
using Wabbajack.Lib;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack
|
|
|
|
|
{
|
|
|
|
|
public class VortexCompilerVM : ViewModel, ISubCompilerVM
|
|
|
|
|
{
|
2019-12-14 03:44:27 +00:00
|
|
|
|
public CompilerVM Parent { get; }
|
|
|
|
|
|
2019-11-17 12:42:31 +00:00
|
|
|
|
private readonly VortexCompilationSettings _settings;
|
2019-11-14 05:28:27 +00:00
|
|
|
|
|
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>(
|
2019-11-17 00:41:59 +00:00
|
|
|
|
EnumExt.GetValues<Game>()
|
2019-12-03 02:38:33 +00:00
|
|
|
|
.Where(g => VortexCompiler.IsActiveVortexGame(g))
|
2019-11-17 12:36:07 +00:00
|
|
|
|
.Select(g => new GameVM(g))
|
|
|
|
|
.OrderBy(g => g.DisplayName));
|
2019-11-17 00:41:59 +00:00
|
|
|
|
|
2019-11-17 12:42:31 +00:00
|
|
|
|
public ObservableCollectionExtended<GameVM> GameOptions => _gameOptions;
|
2019-11-17 00:41:59 +00:00
|
|
|
|
|
2019-11-21 05:15:47 +00:00
|
|
|
|
[Reactive]
|
|
|
|
|
public ACompiler ActiveCompilation { get; private set; }
|
|
|
|
|
|
2019-11-16 23:10:17 +00:00
|
|
|
|
[Reactive]
|
2019-11-17 12:36:07 +00:00
|
|
|
|
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; }
|
|
|
|
|
|
2019-11-17 01:42:42 +00:00
|
|
|
|
public ICommand FindGameInSteamCommand { get; }
|
|
|
|
|
|
|
|
|
|
public ICommand FindGameInGogCommand { get; }
|
|
|
|
|
|
2019-11-17 07:59:00 +00:00
|
|
|
|
[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)
|
|
|
|
|
{
|
2019-12-14 03:44:27 +00:00
|
|
|
|
Parent = parent;
|
2019-11-17 12:36:07 +00:00
|
|
|
|
GameLocation = new FilePickerVM()
|
2019-11-16 23:10:17 +00:00
|
|
|
|
{
|
2019-12-14 20:11:39 +00:00
|
|
|
|
ExistCheckOption = FilePickerVM.CheckOptions.On,
|
2019-11-16 23:10:17 +00:00
|
|
|
|
PathType = FilePickerVM.PathTypeOptions.Folder,
|
|
|
|
|
PromptTitle = "Select Game Folder Location"
|
|
|
|
|
};
|
2019-11-17 12:36:07 +00:00
|
|
|
|
DownloadsLocation = new FilePickerVM()
|
2019-11-16 23:10:17 +00:00
|
|
|
|
{
|
2019-12-14 20:11:39 +00:00
|
|
|
|
ExistCheckOption = FilePickerVM.CheckOptions.On,
|
2019-11-16 23:10:17 +00:00
|
|
|
|
PathType = FilePickerVM.PathTypeOptions.Folder,
|
|
|
|
|
PromptTitle = "Select Downloads Folder"
|
|
|
|
|
};
|
2019-11-17 12:36:07 +00:00
|
|
|
|
StagingLocation = new FilePickerVM()
|
2019-11-16 23:10:17 +00:00
|
|
|
|
{
|
2019-12-14 20:11:39 +00:00
|
|
|
|
ExistCheckOption = FilePickerVM.CheckOptions.On,
|
2019-11-16 23:10:17 +00:00
|
|
|
|
PathType = FilePickerVM.PathTypeOptions.Folder,
|
|
|
|
|
PromptTitle = "Select Staging Folder"
|
|
|
|
|
};
|
|
|
|
|
|
2019-12-14 20:11:39 +00:00
|
|
|
|
// Load custom ModList settings when game type changes
|
2019-12-19 01:14:21 +00:00
|
|
|
|
_modListSettings = (this).WhenAny(x => x.SelectedGame)
|
2019-12-14 20:11:39 +00:00
|
|
|
|
.Select(game =>
|
|
|
|
|
{
|
2019-12-14 23:43:54 +00:00
|
|
|
|
if (game == null) return null;
|
2019-12-14 20:11:39 +00:00
|
|
|
|
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)
|
2020-01-17 04:48:54 +00:00
|
|
|
|
.ToGuiProperty(this, nameof(ModlistSettings));
|
2019-12-14 20:11:39 +00:00
|
|
|
|
|
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 =>
|
|
|
|
|
{
|
2019-11-17 01:42:42 +00:00
|
|
|
|
// 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
|
|
|
|
}
|
2019-11-17 01:42:42 +00:00
|
|
|
|
|
|
|
|
|
// Load new
|
2019-11-17 12:42:31 +00:00
|
|
|
|
GameLocation.TargetPath = current?.GameLocation;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(GameLocation.TargetPath))
|
2019-11-17 01:42:42 +00:00
|
|
|
|
{
|
2019-11-17 12:42:31 +00:00
|
|
|
|
SetGameToSteamLocation();
|
2019-11-17 01:42:42 +00:00
|
|
|
|
}
|
2019-11-17 12:42:31 +00:00
|
|
|
|
if (string.IsNullOrWhiteSpace(GameLocation.TargetPath))
|
2019-11-17 01:42:42 +00:00
|
|
|
|
{
|
2019-11-17 12:42:31 +00:00
|
|
|
|
SetGameToGogLocation();
|
2019-11-17 01:42:42 +00:00
|
|
|
|
}
|
2019-11-17 12:42:31 +00:00
|
|
|
|
DownloadsLocation.TargetPath = current?.DownloadLocation;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(DownloadsLocation.TargetPath))
|
2019-11-17 03:09:46 +00:00
|
|
|
|
{
|
2019-11-17 12:42:31 +00:00
|
|
|
|
DownloadsLocation.TargetPath = VortexCompiler.RetrieveDownloadLocation(SelectedGame.Game);
|
2019-11-17 03:09:46 +00:00
|
|
|
|
}
|
2019-11-17 12:42:31 +00:00
|
|
|
|
StagingLocation.TargetPath = current?.StagingLocation;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(StagingLocation.TargetPath))
|
2019-11-17 03:09:46 +00:00
|
|
|
|
{
|
2019-11-17 12:42:31 +00:00
|
|
|
|
StagingLocation.TargetPath = VortexCompiler.RetrieveStagingLocation(SelectedGame.Game);
|
2019-11-17 03:09:46 +00:00
|
|
|
|
}
|
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
|
|
|
|
|
2019-11-17 01:42:42 +00:00
|
|
|
|
// Find game commands
|
2019-11-17 12:42:31 +00:00
|
|
|
|
FindGameInSteamCommand = ReactiveCommand.Create(SetGameToSteamLocation);
|
|
|
|
|
FindGameInGogCommand = ReactiveCommand.Create(SetGameToGogLocation);
|
2019-11-17 03:09:46 +00:00
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
2019-11-17 01:42:42 +00:00
|
|
|
|
|
|
|
|
|
private void SetGameToSteamLocation()
|
|
|
|
|
{
|
2020-01-03 17:22:50 +00:00
|
|
|
|
GameLocation.TargetPath = StoreHandler.Instance.GetGamePath(SelectedGame.Game, StoreType.STEAM);
|
2019-11-17 01:42:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetGameToGogLocation()
|
|
|
|
|
{
|
2020-01-03 17:22:50 +00:00
|
|
|
|
GameLocation.TargetPath = StoreHandler.Instance.GetGamePath(SelectedGame.Game, StoreType.GOG);
|
2019-11-17 01:42:42 +00:00
|
|
|
|
}
|
2019-12-19 01:14:21 +00:00
|
|
|
|
|
2020-01-18 21:53:10 +00:00
|
|
|
|
public async Task<bool> Compile()
|
2019-12-19 01:14:21 +00:00
|
|
|
|
{
|
2020-01-20 01:49:12 +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
|
|
|
|
|
{
|
2020-01-10 04:55:57 +00:00
|
|
|
|
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,
|
2020-01-10 04:55:57 +00:00
|
|
|
|
})
|
|
|
|
|
{
|
|
|
|
|
Parent.MWVM.Settings.Performance.AttachToBatchProcessor(ActiveCompilation);
|
2020-01-18 21:53:10 +00:00
|
|
|
|
return await ActiveCompilation.Begin();
|
2020-01-10 04:55:57 +00:00
|
|
|
|
}
|
2019-12-19 01:14:21 +00:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
StatusTracker = null;
|
|
|
|
|
ActiveCompilation.Dispose();
|
|
|
|
|
ActiveCompilation = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-14 05:28:27 +00:00
|
|
|
|
}
|
2019-11-21 05:15:47 +00:00
|
|
|
|
}
|