diff --git a/Penumbra/Importer/TexToolsImport.cs b/Penumbra/Importer/TexToolsImport.cs index 0a724f6f..fbbd4fc4 100644 --- a/Penumbra/Importer/TexToolsImport.cs +++ b/Penumbra/Importer/TexToolsImport.cs @@ -55,13 +55,14 @@ namespace Penumbra.Importer private static DirectoryInfo NewOptionDirectory( DirectoryInfo baseDir, string optionName ) => new( Path.Combine( baseDir.FullName, optionName.ReplaceBadXivSymbols() ) ); - public void ImportModPack( FileInfo modPackFile ) + public DirectoryInfo ImportModPack( FileInfo modPackFile ) { CurrentModPack = modPackFile.Name; - VerifyVersionAndImport( modPackFile ); + var dir = VerifyVersionAndImport( modPackFile ); State = ImporterState.Done; + return dir; } private void WriteZipEntryToTempFile( Stream s ) @@ -106,7 +107,7 @@ namespace Penumbra.Importer return new MagicTempFileStreamManagerAndDeleter( fs ); } - private void VerifyVersionAndImport( FileInfo modPackFile ) + private DirectoryInfo VerifyVersionAndImport( FileInfo modPackFile ) { using var zfs = modPackFile.OpenRead(); using var extractedModPack = new ZipFile( zfs ); @@ -127,7 +128,7 @@ namespace Penumbra.Importer PluginLog.Warning( $"File {modPackFile.FullName} seems to be a V2 TTMP, but has the wrong extension." ); } - ImportV2ModPack( modPackFile, extractedModPack, modRaw ); + return ImportV2ModPack( modPackFile, extractedModPack, modRaw ); } else { @@ -136,11 +137,11 @@ namespace Penumbra.Importer PluginLog.Warning( $"File {modPackFile.FullName} seems to be a V1 TTMP, but has the wrong extension." ); } - ImportV1ModPack( modPackFile, extractedModPack, modRaw ); + return ImportV1ModPack( modPackFile, extractedModPack, modRaw ); } } - private void ImportV1ModPack( FileInfo modPackFile, ZipFile extractedModPack, string modRaw ) + private DirectoryInfo ImportV1ModPack( FileInfo modPackFile, ZipFile extractedModPack, string modRaw ) { PluginLog.Log( " -> Importing V1 ModPack" ); @@ -170,28 +171,31 @@ namespace Penumbra.Importer ); ExtractSimpleModList( ExtractedDirectory, modList, modData ); + + return ExtractedDirectory; } - private void ImportV2ModPack( FileInfo modPackFile, ZipFile extractedModPack, string modRaw ) + private DirectoryInfo ImportV2ModPack( FileInfo modPackFile, ZipFile extractedModPack, string modRaw ) { var modList = JsonConvert.DeserializeObject< SimpleModPack >( modRaw ); if( modList?.TTMPVersion == null ) { PluginLog.Error( "Could not extract V2 Modpack. No version given." ); - return; + return new DirectoryInfo( "" ); } if( modList.TTMPVersion.EndsWith( "s" ) ) { - ImportSimpleV2ModPack( extractedModPack, modList ); - return; + return ImportSimpleV2ModPack( extractedModPack, modList ); } if( modList.TTMPVersion.EndsWith( "w" ) ) { - ImportExtendedV2ModPack( extractedModPack, modRaw ); + return ImportExtendedV2ModPack( extractedModPack, modRaw ); } + + return new DirectoryInfo( "" ); } public static DirectoryInfo CreateModFolder( DirectoryInfo outDirectory, string modListName ) @@ -219,7 +223,7 @@ namespace Penumbra.Importer return newModFolder; } - private void ImportSimpleV2ModPack( ZipFile extractedModPack, SimpleModPack modList ) + private DirectoryInfo ImportSimpleV2ModPack( ZipFile extractedModPack, SimpleModPack modList ) { PluginLog.Log( " -> Importing Simple V2 ModPack" ); @@ -242,9 +246,10 @@ namespace Penumbra.Importer JsonConvert.SerializeObject( modMeta ) ); ExtractSimpleModList( ExtractedDirectory, modList.SimpleModsList ?? Enumerable.Empty< SimpleMod >(), modData ); + return ExtractedDirectory; } - private void ImportExtendedV2ModPack( ZipFile extractedModPack, string modRaw ) + private DirectoryInfo ImportExtendedV2ModPack( ZipFile extractedModPack, string modRaw ) { PluginLog.Log( " -> Importing Extended V2 ModPack" ); @@ -273,7 +278,7 @@ namespace Penumbra.Importer if( modList.ModPackPages == null ) { - return; + return ExtractedDirectory; } // Iterate through all pages @@ -307,6 +312,7 @@ namespace Penumbra.Importer Path.Combine( ExtractedDirectory.FullName, "meta.json" ), JsonConvert.SerializeObject( modMeta, Formatting.Indented ) ); + return ExtractedDirectory; } private static void AddMeta( DirectoryInfo baseFolder, DirectoryInfo groupFolder, ModGroup group, ModMeta meta ) diff --git a/Penumbra/UI/MenuTabs/TabImport.cs b/Penumbra/UI/MenuTabs/TabImport.cs index e0166852..6680947b 100644 --- a/Penumbra/UI/MenuTabs/TabImport.cs +++ b/Penumbra/UI/MenuTabs/TabImport.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; @@ -35,6 +36,8 @@ namespace Penumbra.UI private readonly SettingsInterface _base; private readonly ModManager _manager; + public readonly HashSet< string > NewMods = new(); + public TabImport( SettingsInterface ui ) { _base = ui; @@ -72,7 +75,11 @@ namespace Penumbra.UI try { _texToolsImport = new TexToolsImport( _manager.BasePath ); - _texToolsImport.ImportModPack( new FileInfo( fileName ) ); + var dir = _texToolsImport.ImportModPack( new FileInfo( fileName ) ); + if( dir.Name.Any() ) + { + NewMods.Add( dir.Name ); + } PluginLog.Information( $"-> {fileName} OK!" ); } diff --git a/Penumbra/UI/MenuTabs/TabInstalled/ModFilter.cs b/Penumbra/UI/MenuTabs/TabInstalled/ModFilter.cs index 590ffff0..a90f620c 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/ModFilter.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/ModFilter.cs @@ -18,11 +18,13 @@ namespace Penumbra.UI HasNoConfig = 1 << 10, HasNoFiles = 1 << 11, HasFiles = 1 << 12, + IsNew = 1 << 13, + NotNew = 1 << 14, }; public static class ModFilterExtensions { - public const ModFilter UnfilteredStateMods = ( ModFilter )( ( 1 << 13 ) - 1 ); + public const ModFilter UnfilteredStateMods = ( ModFilter )( ( 1 << 15 ) - 1 ); public static string ToName( this ModFilter filter ) => filter switch @@ -40,6 +42,8 @@ namespace Penumbra.UI ModFilter.HasConfig => "Configuration", ModFilter.HasNoFiles => "No Files", ModFilter.HasFiles => "Files", + ModFilter.IsNew => "Newly Imported", + ModFilter.NotNew => "Not Newly Imported", _ => throw new ArgumentOutOfRangeException( nameof( filter ), filter, null ), }; } diff --git a/Penumbra/UI/MenuTabs/TabInstalled/ModListCache.cs b/Penumbra/UI/MenuTabs/TabInstalled/ModListCache.cs index ba1e3127..6d4adbd5 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/ModListCache.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/ModListCache.cs @@ -8,6 +8,7 @@ namespace Penumbra.UI { public class ModListCache : IDisposable { + public const uint NewModColor = 0xFF66DD66u; public const uint DisabledModColor = 0xFF666666u; public const uint ConflictingModColor = 0xFFAAAAFFu; public const uint HandledConflictModColor = 0xFF88DDDDu; @@ -17,6 +18,7 @@ namespace Penumbra.UI private readonly List< Mod.Mod > _modsInOrder = new(); private readonly List< (bool visible, uint color) > _visibleMods = new(); private readonly Dictionary< ModFolder, (bool visible, bool enabled) > _visibleFolders = new(); + private readonly IReadOnlySet< string > _newMods; private string _modFilter = string.Empty; private string _modFilterChanges = string.Empty; @@ -40,9 +42,10 @@ namespace Penumbra.UI } } - public ModListCache( ModManager manager ) + public ModListCache( ModManager manager, IReadOnlySet< string > newMods ) { _manager = manager; + _newMods = newMods; ResetModList(); ModFileSystem.ModFileSystemChanged += TriggerListReset; } @@ -225,6 +228,7 @@ namespace Penumbra.UI private (bool, uint) CheckFilters( Mod.Mod mod ) { var ret = ( false, 0u ); + if( _modFilter.Any() && !mod.Data.Meta.LowerName.Contains( _modFilter ) ) { return ret; @@ -261,6 +265,12 @@ namespace Penumbra.UI return ret; } + var isNew = _newMods.Contains( mod.Data.BasePath.Name ); + if( CheckFlags( isNew ? 1 : 0, ModFilter.IsNew, ModFilter.NotNew ) ) + { + return ret; + } + if( !mod.Settings.Enabled ) { if( !StateFilter.HasFlag( ModFilter.Disabled ) || !StateFilter.HasFlag( ModFilter.NoConflict ) ) @@ -303,6 +313,11 @@ namespace Penumbra.UI } ret.Item1 = true; + if( isNew ) + { + ret.Item2 = NewModColor; + } + SetFolderAndParentsVisible( mod.Data.SortOrder.ParentFolder ); return ret; } diff --git a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalled.cs b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalled.cs index ae1764b5..f3769ae6 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalled.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalled.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using ImGuiNET; using Penumbra.Mods; using Penumbra.UI.Custom; @@ -15,10 +16,10 @@ namespace Penumbra.UI public readonly Selector Selector; public readonly ModPanel ModPanel; - public TabInstalled( SettingsInterface ui ) + public TabInstalled( SettingsInterface ui, HashSet< string > newMods ) { - Selector = new Selector( ui ); - ModPanel = new ModPanel( ui, Selector ); + Selector = new Selector( ui, newMods ); + ModPanel = new ModPanel( ui, Selector, newMods ); _modManager = Service< ModManager >.Get(); } diff --git a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledModPanel.cs b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledModPanel.cs index bbc2c42a..e2e819bf 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledModPanel.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledModPanel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Numerics; @@ -50,16 +51,18 @@ namespace Penumbra.UI private readonly SettingsInterface _base; private readonly Selector _selector; private readonly ModManager _modManager; + private readonly HashSet< string > _newMods; public readonly PluginDetails Details; private bool _editMode; private string _currentWebsite; private bool _validWebsite; - public ModPanel( SettingsInterface ui, Selector s ) + public ModPanel( SettingsInterface ui, Selector s, HashSet< string > newMods ) { _base = ui; _selector = s; + _newMods = newMods; Details = new PluginDetails( _base, _selector ); _currentWebsite = Meta?.Website ?? ""; _modManager = Service< ModManager >.Get(); @@ -216,7 +219,11 @@ namespace Penumbra.UI if( ImGui.Checkbox( LabelModEnabled, ref enabled ) ) { Mod.Settings.Enabled = enabled; - if( !enabled ) + if( enabled ) + { + _newMods.Remove( Mod.Data.BasePath.Name ); + } + else { Mod.Cache.ClearConflicts(); } diff --git a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledSelector.cs b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledSelector.cs index 4e430298..e8e0e283 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledSelector.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledSelector.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; @@ -196,7 +197,7 @@ namespace Penumbra.UI private static void DrawModHelpPopup() { ImGui.SetNextWindowPos( ImGui.GetMainViewport().GetCenter(), ImGuiCond.Appearing, Vector2.One / 2 ); - ImGui.SetNextWindowSize( new Vector2( 5 * SelectorPanelWidth, 33 * ImGui.GetTextLineHeightWithSpacing() ), + ImGui.SetNextWindowSize( new Vector2( 5 * SelectorPanelWidth, 34 * ImGui.GetTextLineHeightWithSpacing() ), ImGuiCond.Appearing ); var _ = true; if( !ImGui.BeginPopupModal( LabelModHelpPopup, ref _, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove ) ) @@ -219,6 +220,10 @@ namespace Penumbra.UI ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.DisabledModColor ), "Disabled in the current collection." ); ImGui.Bullet(); ImGui.SameLine(); + ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.NewModColor ), + "Newly imported during this session. Will go away when first enabling a mod or when Penumbra is reloaded." ); + ImGui.Bullet(); + ImGui.SameLine(); ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.HandledConflictModColor ), "Enabled and conflicting with another enabled Mod, but on different priorities (i.e. the conflict is solved)." ); ImGui.Bullet(); @@ -582,11 +587,11 @@ namespace Penumbra.UI private float _selectorScalingFactor = 1; - public Selector( SettingsInterface ui ) + public Selector( SettingsInterface ui, IReadOnlySet< string > newMods ) { _base = ui; _modManager = Service< ModManager >.Get(); - Cache = new ModListCache( _modManager ); + Cache = new ModListCache( _modManager, newMods ); } private void DrawCollectionButton( string label, string tooltipLabel, float size, ModCollection collection ) diff --git a/Penumbra/UI/SettingsMenu.cs b/Penumbra/UI/SettingsMenu.cs index 7a3ec8ab..43e7bd49 100644 --- a/Penumbra/UI/SettingsMenu.cs +++ b/Penumbra/UI/SettingsMenu.cs @@ -30,7 +30,7 @@ namespace Penumbra.UI _settingsTab = new TabSettings( _base ); _importTab = new TabImport( _base ); _browserTab = new TabBrowser(); - InstalledTab = new TabInstalled( _base ); + InstalledTab = new TabInstalled( _base, _importTab.NewMods ); CollectionsTab = new TabCollections( InstalledTab.Selector ); _effectiveTab = new TabEffective(); _changedItems = new TabChangedItems( _base );