From 8adeab1ba5e591e15309ea00fad3989915d3563b Mon Sep 17 00:00:00 2001 From: Adam <893184+NotAdam@users.noreply.github.com> Date: Wed, 6 Jan 2021 20:03:11 +1100 Subject: [PATCH] fix #11, reshuffled some UI and added a button to the main menu/lobby --- Penumbra/Configuration.cs | 4 + Penumbra/Game/GameUtils.cs | 50 ++++ Penumbra/Importer/ImporterState.cs | 10 + ...cTempFileStreamManagerAndDeleterFuckery.cs | 26 ++ Penumbra/Importer/TexToolsImport.cs | 82 ++++-- Penumbra/Models/ModMeta.cs | 4 + Penumbra/Mods/ModCollection.cs | 10 +- Penumbra/Mods/ModManager.cs | 53 +++- Penumbra/Penumbra.json | 3 +- Penumbra/Plugin.cs | 21 +- Penumbra/ResourceLoader.cs | 35 --- Penumbra/UI/SettingsInterface.cs | 235 +++++++++++++----- 12 files changed, 399 insertions(+), 134 deletions(-) create mode 100644 Penumbra/Game/GameUtils.cs create mode 100644 Penumbra/Importer/ImporterState.cs create mode 100644 Penumbra/Importer/MagicTempFileStreamManagerAndDeleterFuckery.cs diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index 5970a141..7a7d50b2 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -12,6 +12,10 @@ namespace Penumbra public bool IsEnabled { get; set; } = true; + public bool ShowAdvanced { get; set; } = false; + + public bool DisableFileSystemNotifications { get; set; } = false; + public string CurrentCollection { get; set; } = @"D:/ffxiv/fs_mods/"; public List< string > ModCollections { get; set; } = new(); diff --git a/Penumbra/Game/GameUtils.cs b/Penumbra/Game/GameUtils.cs new file mode 100644 index 00000000..7d8ce358 --- /dev/null +++ b/Penumbra/Game/GameUtils.cs @@ -0,0 +1,50 @@ +using System; +using System.Runtime.InteropServices; +using Dalamud.Plugin; +using Reloaded.Hooks.Definitions.X64; + +namespace Penumbra.Game +{ + public class GameUtils + { + private readonly DalamudPluginInterface _pluginInterface; + + [Function( CallingConventions.Microsoft )] + public unsafe delegate void* LoadPlayerResourcesPrototype( IntPtr pResourceManager ); + + [Function( CallingConventions.Microsoft )] + public unsafe delegate void* UnloadPlayerResourcesPrototype( IntPtr pResourceManager ); + + + public LoadPlayerResourcesPrototype LoadPlayerResources { get; private set; } + public UnloadPlayerResourcesPrototype UnloadPlayerResources { get; private set; } + + // Object addresses + private IntPtr _playerResourceManagerAddress; + public IntPtr PlayerResourceManagerPtr => Marshal.ReadIntPtr( _playerResourceManagerAddress ); + + public GameUtils( DalamudPluginInterface pluginInterface ) + { + _pluginInterface = pluginInterface; + + var scanner = _pluginInterface.TargetModuleScanner; + + var loadPlayerResourcesAddress = + scanner.ScanText( + "E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? BA ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? 48 8B 48 30 48 8B 01 FF 50 10 48 85 C0 74 0A " ); + var unloadPlayerResourcesAddress = + scanner.ScanText( "41 55 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4C 8B E9 48 83 C1 08" ); + + _playerResourceManagerAddress = scanner.GetStaticAddressFromSig( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05" ); + + LoadPlayerResources = Marshal.GetDelegateForFunctionPointer< LoadPlayerResourcesPrototype >( loadPlayerResourcesAddress ); + UnloadPlayerResources = Marshal.GetDelegateForFunctionPointer< UnloadPlayerResourcesPrototype >( unloadPlayerResourcesAddress ); + } + + public unsafe void ReloadPlayerResources() + { + UnloadPlayerResources( PlayerResourceManagerPtr ); + LoadPlayerResources( PlayerResourceManagerPtr ); + } + } +} \ No newline at end of file diff --git a/Penumbra/Importer/ImporterState.cs b/Penumbra/Importer/ImporterState.cs new file mode 100644 index 00000000..c8615d90 --- /dev/null +++ b/Penumbra/Importer/ImporterState.cs @@ -0,0 +1,10 @@ +namespace Penumbra.Importer +{ + public enum ImporterState + { + None, + WritingPackToDisk, + ExtractingModFiles, + Done + } +} \ No newline at end of file diff --git a/Penumbra/Importer/MagicTempFileStreamManagerAndDeleterFuckery.cs b/Penumbra/Importer/MagicTempFileStreamManagerAndDeleterFuckery.cs new file mode 100644 index 00000000..68f12965 --- /dev/null +++ b/Penumbra/Importer/MagicTempFileStreamManagerAndDeleterFuckery.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; +using Lumina.Data; + +namespace Penumbra.Importer +{ + public class MagicTempFileStreamManagerAndDeleterFuckery : SqPackStream, IDisposable + { + private readonly FileStream _fileStream; + + public MagicTempFileStreamManagerAndDeleterFuckery( FileStream stream ) : base( stream ) + { + _fileStream = stream; + } + + public new void Dispose() + { + var filePath = _fileStream.Name; + + base.Dispose(); + _fileStream.Dispose(); + + File.Delete( filePath ); + } + } +} \ No newline at end of file diff --git a/Penumbra/Importer/TexToolsImport.cs b/Penumbra/Importer/TexToolsImport.cs index 49ef3c63..2a785994 100644 --- a/Penumbra/Importer/TexToolsImport.cs +++ b/Penumbra/Importer/TexToolsImport.cs @@ -16,13 +16,40 @@ namespace Penumbra.Importer { private readonly DirectoryInfo _outDirectory; + private const string TempFileName = "textools-import"; + private readonly string _resolvedTempFilePath = null; + + public ImporterState State { get; private set; } + + public long TotalProgress { get; private set; } + public long CurrentProgress { get; private set; } + + public float Progress + { + get + { + if( CurrentProgress != 0 ) + { + // ReSharper disable twice RedundantCast + return ( float )CurrentProgress / ( float )TotalProgress; + } + + return 0; + } + } + + public string CurrentModPack { get; private set; } + public TexToolsImport( DirectoryInfo outDirectory ) { _outDirectory = outDirectory; + _resolvedTempFilePath = Path.Combine( _outDirectory.FullName, TempFileName ); } public void ImportModPack( FileInfo modPackFile ) { + CurrentModPack = modPackFile.Name; + switch( modPackFile.Extension ) { case ".ttmp": @@ -33,6 +60,29 @@ namespace Penumbra.Importer ImportV2ModPack( modPackFile ); return; } + + State = ImporterState.Done; + } + + private void WriteZipEntryToTempFile( Stream s ) + { + var fs = new FileStream( _resolvedTempFilePath, FileMode.Create ); + s.CopyTo( fs ); + fs.Close(); + } + + private SqPackStream GetMagicSqPackDeleterStream( ZipFile file, string entryName ) + { + State = ImporterState.WritingPackToDisk; + + // write shitty zip garbage to disk + var entry = file.GetEntry( entryName ); + using var s = file.GetInputStream( entry ); + + WriteZipEntryToTempFile( s ); + + var fs = new FileStream( _resolvedTempFilePath, FileMode.Open ); + return new MagicTempFileStreamManagerAndDeleterFuckery( fs ); } private void ImportV1ModPack( FileInfo modPackFile ) @@ -59,8 +109,7 @@ namespace Penumbra.Importer }; // Open the mod data file from the modpack as a SqPackStream - var mpd = extractedModPack.GetEntry( "TTMPD.mpd" ); - var modData = GetSqPackStreamFromZipEntry( extractedModPack, mpd ); + using var modData = GetMagicSqPackDeleterStream( extractedModPack, "TTMPD.mpd" ); var newModFolder = new DirectoryInfo( Path.Combine( _outDirectory.FullName, @@ -115,8 +164,7 @@ namespace Penumbra.Importer }; // Open the mod data file from the modpack as a SqPackStream - var mpd = extractedModPack.GetEntry( "TTMPD.mpd" ); - var modData = GetSqPackStreamFromZipEntry( extractedModPack, mpd ); + using var modData = GetMagicSqPackDeleterStream( extractedModPack, "TTMPD.mpd" ); var newModFolder = new DirectoryInfo( Path.Combine( _outDirectory.FullName, Path.GetFileNameWithoutExtension( modList.Name ) ) ); @@ -142,12 +190,12 @@ namespace Penumbra.Importer Name = modList.Name, Description = string.IsNullOrEmpty( modList.Description ) ? "Mod imported from TexTools mod pack" - : modList.Description + : modList.Description, + Version = modList.Version }; // Open the mod data file from the modpack as a SqPackStream - var mpd = extractedModPack.GetEntry( "TTMPD.mpd" ); - var modData = GetSqPackStreamFromZipEntry( extractedModPack, mpd ); + using var modData = GetMagicSqPackDeleterStream( extractedModPack, "TTMPD.mpd" ); var newModFolder = new DirectoryInfo( Path.Combine( _outDirectory.FullName, @@ -187,13 +235,24 @@ namespace Penumbra.Importer private void ExtractSimpleModList( DirectoryInfo outDirectory, IEnumerable< SimpleMod > mods, SqPackStream dataStream ) { + State = ImporterState.ExtractingModFiles; + + // haha allocation go brr + var wtf = mods.ToList(); + + TotalProgress = wtf.LongCount(); + // Extract each SimpleMod into the new mod folder - foreach( var simpleMod in mods ) + foreach( var simpleMod in wtf ) { if( simpleMod == null ) + { + // do we increment here too???? can this even happen????? continue; - + } + ExtractMod( outDirectory, simpleMod, dataStream ); + CurrentProgress++; } } @@ -228,10 +287,5 @@ namespace Penumbra.Importer s.CopyTo( ms ); return encoding.GetString( ms.ToArray() ); } - - private static SqPackStream GetSqPackStreamFromZipEntry( ZipFile file, ZipEntry entry ) - { - return new( GetStreamFromZipEntry( file, entry ) ); - } } } \ No newline at end of file diff --git a/Penumbra/Models/ModMeta.cs b/Penumbra/Models/ModMeta.cs index 79c84c67..08b00750 100644 --- a/Penumbra/Models/ModMeta.cs +++ b/Penumbra/Models/ModMeta.cs @@ -7,6 +7,10 @@ namespace Penumbra.Models public string Name { get; set; } public string Author { get; set; } public string Description { get; set; } + + public string Version { get; set; } + + public string Website { get; set; } public Dictionary< string, string > FileSwaps { get; } = new(); } diff --git a/Penumbra/Mods/ModCollection.cs b/Penumbra/Mods/ModCollection.cs index f988508c..cfbfd7dd 100644 --- a/Penumbra/Mods/ModCollection.cs +++ b/Penumbra/Mods/ModCollection.cs @@ -15,6 +15,7 @@ namespace Penumbra.Mods public List< ModInfo > ModSettings { get; set; } public ResourceMod[] EnabledMods { get; set; } + public ModCollection( DirectoryInfo basePath ) { _basePath = basePath; @@ -117,7 +118,7 @@ namespace Penumbra.Mods public void ReorderMod( ModInfo info, bool up ) { // todo: certified fucked tier - + var prio = info.Priority; var swapPrio = up ? prio + 1 : prio - 1; var swapMeta = ModSettings.FirstOrDefault( x => x.Priority == swapPrio ); @@ -126,10 +127,10 @@ namespace Penumbra.Mods { return; } - + info.Priority = swapPrio; swapMeta.Priority = prio; - + // reorder mods list ModSettings = ModSettings.OrderBy( x => x.Priority ).ToList(); EnabledMods = GetOrderedAndEnabledModList().ToArray(); @@ -137,8 +138,7 @@ namespace Penumbra.Mods // save new prios Save(); } - - + public ModInfo FindModSettings( string name ) { diff --git a/Penumbra/Mods/ModManager.cs b/Penumbra/Mods/ModManager.cs index cec6f677..dc19677b 100644 --- a/Penumbra/Mods/ModManager.cs +++ b/Penumbra/Mods/ModManager.cs @@ -1,10 +1,11 @@ +using System; using System.Collections.Generic; using System.IO; using Penumbra.Models; namespace Penumbra.Mods { - public class ModManager + public class ModManager : IDisposable { public readonly Dictionary< string, FileInfo > ResolvedFiles = new(); public readonly Dictionary< string, string > SwappedFiles = new(); @@ -23,6 +24,33 @@ namespace Penumbra.Mods DiscoverMods( _basePath ); } +// private void FileSystemWatcherOnChanged( object sender, FileSystemEventArgs e ) +// { +// #if DEBUG +// PluginLog.Verbose( "file changed: {FullPath}", e.FullPath ); +// #endif +// +// if( _plugin.ImportInProgress ) +// { +// return; +// } +// +// if( _plugin.Configuration.DisableFileSystemNotifications ) +// { +// return; +// } +// +// var file = e.FullPath; +// +// if( !ResolvedFiles.Any( x => x.Value.FullName == file ) ) +// { +// return; +// } +// +// PluginLog.Log( "a loaded file has been modified - file: {FullPath}", file ); +// _plugin.GameUtils.ReloadPlayerResources(); +// } + public void DiscoverMods( string basePath ) { DiscoverMods( new DirectoryInfo( basePath ) ); @@ -43,7 +71,21 @@ namespace Penumbra.Mods _basePath = basePath; - ResolvedFiles.Clear(); + // haha spaghet + // _fileSystemWatcher?.Dispose(); + // _fileSystemWatcher = new FileSystemWatcher( _basePath.FullName ) + // { + // NotifyFilter = NotifyFilters.LastWrite | + // NotifyFilters.FileName | + // NotifyFilters.DirectoryName, + // IncludeSubdirectories = true, + // EnableRaisingEvents = true + // }; + // + // _fileSystemWatcher.Changed += FileSystemWatcherOnChanged; + // _fileSystemWatcher.Created += FileSystemWatcherOnChanged; + // _fileSystemWatcher.Deleted += FileSystemWatcherOnChanged; + // _fileSystemWatcher.Renamed += FileSystemWatcherOnChanged; Mods = new ModCollection( basePath ); Mods.Load(); @@ -62,7 +104,7 @@ namespace Penumbra.Mods foreach( var mod in Mods.GetOrderedAndEnabledModList() ) { mod.FileConflicts?.Clear(); - + // fixup path var baseDir = mod.ModBasePath.FullName; @@ -138,5 +180,10 @@ namespace Penumbra.Mods return GetCandidateForGameFile( gameResourcePath )?.FullName ?? GetSwappedFilePath( gameResourcePath ); } + + public void Dispose() + { + // _fileSystemWatcher?.Dispose(); + } } } \ No newline at end of file diff --git a/Penumbra/Penumbra.json b/Penumbra/Penumbra.json index 8c348d17..bd28f0a5 100644 --- a/Penumbra/Penumbra.json +++ b/Penumbra/Penumbra.json @@ -7,5 +7,6 @@ "RepoUrl": "https://github.com/xivdev/Penumbra", "ApplicableVersion": "any", "Tags": [ "modding" ], - "DalamudApiLevel": 69420 + "DalamudApiLevel": 69420, + "LoadPriority": 69420 } \ No newline at end of file diff --git a/Penumbra/Plugin.cs b/Penumbra/Plugin.cs index 02f5ff35..b0ec5a91 100644 --- a/Penumbra/Plugin.cs +++ b/Penumbra/Plugin.cs @@ -1,11 +1,6 @@ -using System; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Runtime.InteropServices; using Dalamud.Game.Command; using Dalamud.Plugin; -using Penumbra.Extensions; +using Penumbra.Game; using Penumbra.Mods; using Penumbra.UI; @@ -18,6 +13,7 @@ namespace Penumbra private const string CommandName = "/penumbra"; public DalamudPluginInterface PluginInterface { get; set; } + public Configuration Configuration { get; set; } public ResourceLoader ResourceLoader { get; set; } @@ -26,21 +22,26 @@ namespace Penumbra public SettingsInterface SettingsInterface { get; set; } + public GameUtils GameUtils { get; set; } + public string PluginDebugTitleStr { get; private set; } + public bool ImportInProgress => SettingsInterface?.IsImportRunning ?? true; + public void Initialize( DalamudPluginInterface pluginInterface ) { PluginInterface = pluginInterface; - + Configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); Configuration.Initialize( PluginInterface ); + GameUtils = new GameUtils( PluginInterface ); + ModManager = new ModManager(); ModManager.DiscoverMods( Configuration.CurrentCollection ); ResourceLoader = new ResourceLoader( this ); - PluginInterface.CommandManager.AddHandler( CommandName, new CommandInfo( OnCommand ) { HelpMessage = "/penumbra - toggle ui\n/penumbra reload - reload mod file lists & discover any new mods" @@ -48,7 +49,7 @@ namespace Penumbra ResourceLoader.Init(); ResourceLoader.Enable(); - + SettingsInterface = new SettingsInterface( this ); PluginInterface.UiBuilder.OnBuildUi += SettingsInterface.Draw; @@ -57,6 +58,8 @@ namespace Penumbra public void Dispose() { + ModManager?.Dispose(); + PluginInterface.UiBuilder.OnBuildUi -= SettingsInterface.Draw; PluginInterface.CommandManager.RemoveHandler( CommandName ); diff --git a/Penumbra/ResourceLoader.cs b/Penumbra/ResourceLoader.cs index 31ed1f2c..86cf2b44 100644 --- a/Penumbra/ResourceLoader.cs +++ b/Penumbra/ResourceLoader.cs @@ -36,13 +36,6 @@ namespace Penumbra public unsafe delegate void* GetResourceAsyncPrototype( IntPtr pFileManager, uint* pCategoryId, char* pResourceType, uint* pResourceHash, char* pPath, void* pUnknown, bool isUnknown ); - [Function( CallingConventions.Microsoft )] - public unsafe delegate void* LoadPlayerResourcesPrototype( IntPtr pResourceManager ); - - [Function( CallingConventions.Microsoft )] - public unsafe delegate void* UnloadPlayerResourcesPrototype( IntPtr pResourceManager ); - - // Hooks public IHook< GetResourceSyncPrototype > GetResourceSyncHook { get; private set; } public IHook< GetResourceAsyncPrototype > GetResourceAsyncHook { get; private set; } @@ -52,14 +45,6 @@ namespace Penumbra public ReadFilePrototype ReadFile { get; private set; } - public LoadPlayerResourcesPrototype LoadPlayerResources { get; private set; } - public UnloadPlayerResourcesPrototype UnloadPlayerResources { get; private set; } - - // Object addresses - private IntPtr _playerResourceManagerAddress; - public IntPtr PlayerResourceManagerPtr => Marshal.ReadIntPtr( _playerResourceManagerAddress ); - - public bool LogAllFiles = false; @@ -91,20 +76,6 @@ namespace Penumbra GetResourceAsyncHook = new Hook< GetResourceAsyncPrototype >( GetResourceAsyncHandler, ( long )getResourceAsyncAddress ); ReadFile = Marshal.GetDelegateForFunctionPointer< ReadFilePrototype >( readFileAddress ); - - ///// - - var loadPlayerResourcesAddress = - scanner.ScanText( - "E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? BA ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? 48 8B 48 30 48 8B 01 FF 50 10 48 85 C0 74 0A " ); - var unloadPlayerResourcesAddress = - scanner.ScanText( "41 55 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4C 8B E9 48 83 C1 08" ); - - _playerResourceManagerAddress = scanner.GetStaticAddressFromSig( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05" ); - - LoadPlayerResources = Marshal.GetDelegateForFunctionPointer< LoadPlayerResourcesPrototype >( loadPlayerResourcesAddress ); - UnloadPlayerResources = Marshal.GetDelegateForFunctionPointer< UnloadPlayerResourcesPrototype >( unloadPlayerResourcesAddress ); - ReadFile = Marshal.GetDelegateForFunctionPointer< ReadFilePrototype >( readFileAddress ); } @@ -215,12 +186,6 @@ namespace Penumbra return ReadFile( pFileHandler, pFileDesc, priority, isSync ); } - public unsafe void ReloadPlayerResource() - { - UnloadPlayerResources( PlayerResourceManagerPtr ); - LoadPlayerResources( PlayerResourceManagerPtr ); - } - public void Enable() { if( IsEnabled ) diff --git a/Penumbra/UI/SettingsInterface.cs b/Penumbra/UI/SettingsInterface.cs index 21daedb2..01db3657 100644 --- a/Penumbra/UI/SettingsInterface.cs +++ b/Penumbra/UI/SettingsInterface.cs @@ -32,7 +32,8 @@ namespace Penumbra.UI private int? _selectedModDeleteIndex; private ModInfo _selectedMod; - private bool _isImportRunning = false; + public bool IsImportRunning = false; + private TexToolsImport _texToolsImport = null!; public SettingsInterface( Plugin plugin ) { @@ -72,6 +73,39 @@ namespace Penumbra.UI ImGui.EndMainMenuBar(); } + if( !_plugin.PluginInterface.ClientState.Condition.Any() && !Visible ) + { + // draw mods button on da menu :DDD + var ss = ImGui.GetIO().DisplaySize; + var padding = 50; + var width = 200; + var height = 45; + + // magic numbers + ImGui.SetNextWindowPos( new Vector2( ss.X - padding - width, ss.Y - padding - height ), ImGuiCond.Always ); + + if( + ImGui.Begin( + "Penumbra Menu Buttons", + ImGuiWindowFlags.AlwaysAutoResize | + ImGuiWindowFlags.NoBackground | + ImGuiWindowFlags.NoDecoration | + ImGuiWindowFlags.NoMove | + ImGuiWindowFlags.NoScrollbar | + ImGuiWindowFlags.NoResize | + ImGuiWindowFlags.NoSavedSettings + ) + ) + { + if( ImGui.Button( "Manage Mods", new Vector2( width, height ) ) ) + { + Visible = !Visible; + } + + ImGui.End(); + } + } + if( !Visible ) { return; @@ -91,11 +125,19 @@ namespace Penumbra.UI ImGui.BeginTabBar( "PenumbraSettings" ); DrawSettingsTab(); + DrawImportTab(); - if( !_isImportRunning ) + + if( !IsImportRunning ) { - DrawResourceMods(); - DrawEffectiveFileList(); + DrawModBrowser(); + + DrawInstalledMods(); + + if( _plugin.Configuration.ShowAdvanced ) + { + DrawEffectiveFileList(); + } DrawDeleteModal(); } @@ -105,6 +147,105 @@ namespace Penumbra.UI ImGui.End(); } + void DrawImportTab() + { + var ret = ImGui.BeginTabItem( "Import Mods" ); + if( !ret ) + { + return; + } + + if( !IsImportRunning ) + { + if( ImGui.Button( "Import TexTools Modpacks" ) ) + { + IsImportRunning = true; + + Task.Run( async () => + { + var picker = new OpenFileDialog + { + Multiselect = true, + Filter = "TexTools TTMP Modpack (*.ttmp2)|*.ttmp*|All files (*.*)|*.*", + CheckFileExists = true, + Title = "Pick one or more modpacks." + }; + + var result = await picker.ShowDialogAsync(); + + if( result == DialogResult.OK ) + { + foreach( var fileName in picker.FileNames ) + { + PluginLog.Log( "-> {0} START", fileName ); + + try + { + _texToolsImport = new TexToolsImport( new DirectoryInfo( _plugin.Configuration.CurrentCollection ) ); + _texToolsImport.ImportModPack( new FileInfo( fileName ) ); + } + catch( Exception ex ) + { + PluginLog.LogError( ex, "Could not import one or more modpacks." ); + } + + PluginLog.Log( "-> {0} OK!", fileName ); + } + + _texToolsImport = null; + ReloadMods(); + } + + IsImportRunning = false; + } ); + } + } + else + { + ImGui.Button( "Import in progress..." ); + + if( _texToolsImport != null ) + { + switch( _texToolsImport.State ) + { + case ImporterState.None: + break; + case ImporterState.WritingPackToDisk: + ImGui.Text( "Writing modpack to disk before extracting..." ); + break; + case ImporterState.ExtractingModFiles: + { + var str = + $"{_texToolsImport.CurrentModPack} - {_texToolsImport.CurrentProgress} of {_texToolsImport.TotalProgress} files"; + + ImGui.ProgressBar( _texToolsImport.Progress, new Vector2( -1, 0 ), str ); + break; + } + case ImporterState.Done: + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + ImGui.EndTabItem(); + } + + [Conditional( "DEBUG" )] + void DrawModBrowser() + { + var ret = ImGui.BeginTabItem( "Available Mods" ); + if( !ret ) + { + return; + } + + ImGui.Text( "woah" ); + + ImGui.EndTabItem(); + } + void DrawSettingsTab() { var ret = ImGui.BeginTabItem( "Settings" ); @@ -113,11 +254,14 @@ namespace Penumbra.UI return; } + bool dirty = false; + // FUCKKKKK var basePath = _plugin.Configuration.CurrentCollection; if( ImGui.InputText( "Root Folder", ref basePath, 255 ) ) { _plugin.Configuration.CurrentCollection = basePath; + dirty = true; } if( ImGui.Button( "Rediscover Mods" ) ) @@ -134,77 +278,34 @@ namespace Penumbra.UI ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 15 ); -#if DEBUG - - ImGui.Text( "debug shit" ); - - if( ImGui.Button( "Reload Player Resource" ) ) + var showAdvanced = _plugin.Configuration.ShowAdvanced; + if( ImGui.Checkbox( "Show Advanced Settings", ref showAdvanced ) ) { - _plugin.ResourceLoader.ReloadPlayerResource(); + _plugin.Configuration.ShowAdvanced = showAdvanced; + dirty = true; } - if( _plugin.ResourceLoader != null ) + if( _plugin.Configuration.ShowAdvanced ) { - ImGui.Checkbox( "DEBUG Log all loaded files", ref _plugin.ResourceLoader.LogAllFiles ); - } - - ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 15 ); -#endif - - if( !_isImportRunning ) - { - if( ImGui.Button( "Import TexTools Modpacks" ) ) + if( _plugin.ResourceLoader != null ) { - _isImportRunning = true; + ImGui.Checkbox( "Log all loaded files", ref _plugin.ResourceLoader.LogAllFiles ); + } - Task.Run( async () => - { - var picker = new OpenFileDialog - { - Multiselect = true, - Filter = "TexTools TTMP Modpack (*.ttmp2)|*.ttmp*|All files (*.*)|*.*", - CheckFileExists = true, - Title = "Pick one or more modpacks." - }; + var fswatch = _plugin.Configuration.DisableFileSystemNotifications; + if( ImGui.Checkbox( "Disable filesystem change notifications", ref fswatch ) ) + { + _plugin.Configuration.DisableFileSystemNotifications = fswatch; + dirty = true; + } - var result = await picker.ShowDialogAsync(); - - if( result == DialogResult.OK ) - { - try - { - var importer = - new TexToolsImport( new DirectoryInfo( _plugin.Configuration.CurrentCollection ) ); - - foreach( var fileName in picker.FileNames ) - { - PluginLog.Log( "-> {0} START", fileName ); - - importer.ImportModPack( new FileInfo( fileName ) ); - - PluginLog.Log( "-> {0} OK!", fileName ); - } - - ReloadMods(); - } - catch( Exception ex ) - { - PluginLog.LogError( ex, "Could not import one or more modpacks." ); - } - } - - _isImportRunning = false; - } ); + if( ImGui.Button( "Reload Player Resource" ) ) + { + _plugin.GameUtils.ReloadPlayerResources(); } } - else - { - ImGui.Button( "Import in progress..." ); - } - ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 15 ); - - if( ImGui.Button( "Save Settings" ) ) + if( dirty ) { _plugin.Configuration.Save(); } @@ -385,9 +486,9 @@ namespace Penumbra.UI ImGui.EndPopup(); } - void DrawResourceMods() + void DrawInstalledMods() { - var ret = ImGui.BeginTabItem( "Mods" ); + var ret = ImGui.BeginTabItem( "Installed Mods" ); if( !ret ) { return;