add slideshow

This commit is contained in:
Timothy Baldridge 2019-09-25 21:18:36 -06:00
parent 37c6af9a6a
commit 825929b119
8 changed files with 257 additions and 14 deletions

View File

@ -10,6 +10,7 @@
* Add unit/integration tests.
* Don't assume *everyone* has LOOT
* Added support for `.exe` installers
* Rework UI to support a slideshow of used mods during installation and compilation
#### Version 0.9.2 - 9/18/2013
* Fixed a bug with BSA string encoding

View File

@ -1,5 +1,6 @@
using System;
using Wabbajack.Common;
using Microsoft.Win32;
namespace VirtualFileSystem.Test
{
@ -7,6 +8,8 @@ namespace VirtualFileSystem.Test
{
private static void Main(string[] args)
{
var result = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\7-zip\");
Utils.SetLoggerFn(s => Console.WriteLine(s));
Utils.SetStatusFn((s, i) => Console.Write(s + "\r"));
WorkQueue.Init((a, b, c) => { },

View File

@ -4,12 +4,15 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Wabbajack.Common;
using Wabbajack.Properties;
namespace Wabbajack
{
@ -37,6 +40,8 @@ namespace Wabbajack
private int _queueProgress;
private ICommand _showReportCommand;
private ICommand _visitNexusSiteCommand;
private readonly DateTime _startTime;
public volatile bool Dirty;
@ -45,6 +50,16 @@ namespace Wabbajack
public AppState(Dispatcher d, string mode)
{
var image = new BitmapImage();
image.BeginInit();
image.StreamSource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Wabbajack.banner.png");
image.EndInit();
_wabbajackLogo = image;
_splashScreenImage = image;
SetupSlideshow();
if (Assembly.GetEntryAssembly().Location.ToLower().Contains("\\downloads\\"))
{
MessageBox.Show(
@ -75,6 +90,19 @@ namespace Wabbajack
th.Start();
}
private void SetupSlideshow()
{
var files = NexusAPI.CachedSlideShow;
if (files.Any())
{
SlideShowElements = files.ToList();
}
}
public Random _random = new Random();
public List<NexusAPI.SlideShowItem> SlideShowElements = new List<NexusAPI.SlideShowItem>();
private DateTime _lastSlideShowUpdate = new DateTime();
public ObservableCollection<string> Log { get; }
public ObservableCollection<CPUStatus> Status { get; }
@ -207,6 +235,26 @@ namespace Wabbajack
}
}
public ICommand VisitNexusSiteCommand
{
get
{
if (_visitNexusSiteCommand == null) _visitNexusSiteCommand = new LambdaCommand(() => true, () => VisitNexusSite());
return _visitNexusSiteCommand;
}
}
private string _nexusSiteURL = null;
private void VisitNexusSite()
{
if (_nexusSiteURL != null && _nexusSiteURL.StartsWith("https://"))
{
Process.Start(_nexusSiteURL);
}
}
private bool _uiReady = false;
public bool UIReady
{
@ -218,6 +266,51 @@ namespace Wabbajack
}
}
private BitmapImage _wabbajackLogo = null;
private BitmapImage _splashScreenImage = null;
public BitmapImage SplashScreenImage
{
get => _splashScreenImage;
set
{
_splashScreenImage = value;
OnPropertyChanged("SplashScreenImage");
}
}
public string _splashScreenModName = "Wabbajack";
public string SplashScreenModName
{
get => _splashScreenModName;
set
{
_splashScreenModName = value;
OnPropertyChanged("SplashScreenModName");
}
}
public string _splashScreenAuthorName = "Halgari & the Wabbajack Team";
public string SplashScreenAuthorName
{
get => _splashScreenAuthorName;
set
{
_splashScreenAuthorName = value;
OnPropertyChanged("SplashScreenAuthorName");
}
}
public string _splashScreenSummary = "";
public string SplashScreenSummary
{
get => _splashScreenSummary;
set
{
_splashScreenSummary = value;
OnPropertyChanged("SplashScreenSummary");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
@ -244,6 +337,24 @@ namespace Wabbajack
Dirty = false;
}
if (SlideShowElements.Any())
{
if (DateTime.Now - _lastSlideShowUpdate > TimeSpan.FromSeconds(10))
{
dispatcher.Invoke(() =>
{
var element = SlideShowElements[_random.Next(0, SlideShowElements.Count)];
SplashScreenImage = new BitmapImage(new Uri(element.ImageURL));
SplashScreenModName = element.ModName;
SplashScreenAuthorName = element.AuthorName;
SplashScreenSummary = element.ModSummary;
_nexusSiteURL = element.ModURL;
_lastSlideShowUpdate = DateTime.Now;
});
}
}
Thread.Sleep(1000);
}
}
@ -255,6 +366,15 @@ namespace Wabbajack
ModListName = _modList.Name;
HTMLReport = _modList.ReportHTML;
Location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
SlideShowElements = modlist.Archives.OfType<NexusMod>().Select(m => new NexusAPI.SlideShowItem
{
ModName = NexusAPI.FixupSummary(m.ModName),
AuthorName = NexusAPI.FixupSummary(m.Author),
ModSummary = NexusAPI.FixupSummary(m.Summary),
ImageURL = m.SlideShowPic,
ModURL = m.NexusURL,
}).ToList();
}
public void LogMsg(string msg)
@ -353,6 +473,7 @@ namespace Wabbajack
if (Mode == "Installing")
{
var installer = new Installer(_modList, Location, msg => LogMsg(msg));
installer.IgnoreMissingFiles = IgnoreMissingFiles;
installer.DownloadFolder = DownloadLocation;
var th = new Thread(() =>
@ -408,6 +529,8 @@ namespace Wabbajack
}
}
public class CPUStatus
{
public int Progress { get; internal set; }

View File

@ -234,7 +234,7 @@ namespace Wabbajack
Info("Getting nexus api_key please click authorize if a browser window appears");
if (IndexedArchives.OfType<NexusMod>().Any())
if (IndexedArchives.Any(a => a.IniData?.General?.gameName != null))
{
NexusKey = GetNexusAPIKey();
User = GetUserStatus(NexusKey);
@ -473,6 +473,11 @@ namespace Wabbajack
nm.Author = info.author;
nm.UploadedBy = info.uploaded_by;
nm.UploaderProfile = info.uploaded_users_profile_url;
nm.ModName = info.name;
nm.SlideShowPic = info.picture_url;
nm.NexusURL = NexusAPI.GetModURL(info.game_name, info.mod_id);
nm.Summary = info.summary;
result = nm;
}
else if (general.manualURL != null)

View File

@ -192,6 +192,10 @@ namespace Wabbajack
public string UploadedBy;
public string UploaderProfile;
public string Version;
public string SlideShowPic;
public string ModName;
public string NexusURL;
public string Summary;
}
[Serializable]

View File

@ -5,14 +5,14 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Wabbajack"
mc:Ignorable="d"
Title="Wabbajack" Height="800" Width="800"
Title="Wabbajack" Height="960" Width="1448"
Style="{StaticResource {x:Type Window}}" Icon="square_transparent_icon.ico" WindowStyle="ToolWindow"
ResizeMode="NoResize"
Closing="Window_Closing">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="460"/>
<RowDefinition Height="10" />
<RowDefinition Height="Auto" />
<RowDefinition />
@ -20,12 +20,40 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="700"></ColumnDefinition>
<ColumnDefinition Width="700"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0, 16, 0, 16">
<TextBlock Text="{Binding Mode}" FontSize="16" FontWeight="Bold" />
<TextBlock Text=" : " FontSize="16" />
<TextBlock Text="{Binding ModListName}" FontSize="16" />
</StackPanel>
<Grid HorizontalAlignment="Stretch" Grid.Row="1" Margin="0, 10, 0, 10">
<!-- Slideshow -->
<Image Grid.Row="1" Grid.Column="0" Source="{Binding SplashScreenImage}" Stretch="Uniform" Margin="5"></Image>
<Grid Grid.Row="1" Grid.Column="1" Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="{Binding SplashScreenModName}" Grid.Row="0" FontSize="30" FontWeight="Bold"></TextBlock>
<TextBlock Text="{Binding SplashScreenAuthorName}" Grid.Row="1" FontSize="15" FontWeight="Bold"></TextBlock>
<TextBlock Text="{Binding SplashScreenSummary}" TextWrapping="Wrap" Grid.Row="2" FontSize="15" FontWeight="Bold"></TextBlock>
<Button Height="30" Grid.Row="3" Grid.Column="1" Command="{Binding VisitNexusSiteCommand}">
<TextBlock Text="View Nexus Site" FontSize="15" FontWeight="Bold"></TextBlock>
</Button>
</Grid>
<!-- End Slideshow-->
<TextBlock Text="Log:" Grid.Row="3" FontSize="14" Margin="0, 16, 0, 8" />
<ListBox local:AutoScrollBehavior.ScrollOnNewItem="True" Grid.Row="4" ItemsSource="{Binding Log}" />
<Grid HorizontalAlignment="Stretch" Grid.Row="5" Grid.Column="0" Grid.RowSpan="2" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
@ -43,7 +71,14 @@
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding DownloadLocation}" IsEnabled="{Binding UIReady}"/>
<Button Grid.Row="2" Content="Select" MinWidth="80" Grid.Column="2" Command="{Binding ChangeDownloadPath}" IsEnabled="{Binding UIReady}"/>
</Grid>
<ListBox Grid.Row="2" ItemsSource="{Binding Status}" Width="Auto" HorizontalAlignment="Stretch">
<!-- Work Queue Start -->
<ProgressBar Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Value="{Binding QueueProgress}" Minimum="0" Maximum="100" Background="#444444" />
<TextBlock Text="Work Queue:" Grid.Row="3" Grid.Column="1" FontSize="14" Margin="0, 16, 0, 8" />
<ListBox Grid.Row="4" Grid.Column="1" ItemsSource="{Binding Status}" Width="Auto" HorizontalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
@ -75,12 +110,11 @@
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ProgressBar Grid.Row="3" Value="{Binding QueueProgress}" Minimum="0" Maximum="100" Background="#444444" />
<TextBlock Text="Log:" Grid.Row="4" FontSize="14" Margin="0, 16, 0, 8" />
<ListBox local:AutoScrollBehavior.ScrollOnNewItem="True" Grid.Row="5" ItemsSource="{Binding Log}" />
<Button Content="View Modlist Contents" Grid.Row="6" Height="30" Visibility="{Binding ShowReportButton}"
Command="{Binding ShowReportCommand}" />
<Button Content="Begin" Grid.Row="7" Height="30" Command="{Binding Begin}" IsEnabled="{Binding UIReady}"/>
<CheckBox Content="Ignore Missing Files" Grid.Row="8" Height="20" IsChecked="{Binding IgnoreMissingFiles}" IsEnabled="{Binding UIReady}" Visibility="Collapsed"/>
<!-- Work Queue End-->
<Button Content="View Modlist Contents" Grid.Row="5" Grid.Column="1" Height="30" Visibility="{Binding ShowReportButton}"
Command="{Binding ShowReportCommand}" Margin="10" />
<Button Content="Begin" Grid.Row="6" Height="30" Grid.Column="1" Command="{Binding Begin}" IsEnabled="{Binding UIReady}" Margin="10"/>
<CheckBox Content="Ignore Missing Files" Grid.Row="7" Height="20" IsChecked="{Binding IgnoreMissingFiles}" IsEnabled="{Binding UIReady}" Visibility="Collapsed"/>
</Grid>
</Window>

View File

@ -7,8 +7,10 @@ using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Authentication;
using System.Threading.Tasks;
using System.Windows.Media.TextFormatting;
using Wabbajack.Common;
using WebSocketSharp;
@ -126,16 +128,27 @@ namespace Wabbajack
}
}
private const int CACHED_VERSION_NUMBER = 1;
public static ModInfo GetModInfo(NexusMod archive, string apikey)
{
if (!Directory.Exists(Consts.NexusCacheDirectory))
Directory.CreateDirectory(Consts.NexusCacheDirectory);
TOP:
var path = Path.Combine(Consts.NexusCacheDirectory, $"mod-info-{archive.GameName}-{archive.ModID}.json");
try
{
if (File.Exists(path))
return path.FromJSON<ModInfo>();
{
var result = path.FromJSON<ModInfo>();
if (result._internal_version != CACHED_VERSION_NUMBER)
{
File.Delete(path);
goto TOP;
}
return result;
}
}
catch (Exception)
{
@ -150,6 +163,9 @@ namespace Wabbajack
using (var s = client.GetStreamSync(url))
{
var result = s.FromJSON<ModInfo>();
result.game_name = archive.GameName;
result.mod_id = archive.ModID;
result._internal_version = CACHED_VERSION_NUMBER;
result.ToJSON(path);
return result;
}
@ -209,9 +225,63 @@ namespace Wabbajack
public class ModInfo
{
public uint _internal_version;
public string game_name;
public string mod_id;
public string name;
public string summary;
public string author;
public string uploaded_by;
public string uploaded_users_profile_url;
public string picture_url;
}
public class SlideShowItem
{
public string ImageURL;
public string ModName;
public string ModSummary;
public string AuthorName;
public string ModURL;
}
public static IEnumerable<SlideShowItem> CachedSlideShow
{
get
{
if (!Directory.Exists(Consts.NexusCacheDirectory)) return new SlideShowItem[]{};
return Directory.EnumerateFiles(Consts.NexusCacheDirectory)
.Where(f => f.EndsWith(".json"))
.Select(f => f.FromJSON<ModInfo>())
.Where(m => m._internal_version == CACHED_VERSION_NUMBER && m.picture_url != null)
.Select(m => new SlideShowItem
{
ImageURL = m.picture_url,
ModName = FixupSummary(m.name),
AuthorName = FixupSummary(m.author),
ModURL = GetModURL(m.game_name, m.mod_id),
ModSummary = FixupSummary(m.summary)
});
}
}
public static string GetModURL(string argGameName, string argModId)
{
return $"https://nexusmods.com/{ConvertGameName(argGameName)}/mods/{argModId}";
}
public static string FixupSummary(string argSummary)
{
if (argSummary != null)
{
return argSummary.Replace("&#39;", "'")
.Replace("<br/>", "\n\n")
.Replace("<br />", "\n\n")
.Replace("&#33;", "!");
}
return argSummary;
}
}

View File

@ -265,6 +265,9 @@
<ItemGroup>
<Resource Include="square_transparent_icon.ico" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="banner.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.5.1.1\build\Fody.targets" Condition="Exists('..\packages\Fody.5.1.1\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">