diff --git a/Penumbra/Api/IpcTester.cs b/Penumbra/Api/IpcTester.cs index d6b0b51c..6c48fd2a 100644 --- a/Penumbra/Api/IpcTester.cs +++ b/Penumbra/Api/IpcTester.cs @@ -13,6 +13,8 @@ using Penumbra.Api.Enums; using Penumbra.Api.Helpers; using Penumbra.String; using Penumbra.String.Classes; +using Swan; +using Penumbra.Meta.Manipulations; namespace Penumbra.Api; @@ -1132,6 +1134,17 @@ public class IpcTester : IDisposable _tempManipulation.Length > 0 ? _tempManipulation : string.Empty, int.MaxValue ); } + DrawIntro( Ipc.CreateTemporaryCollection.Label, "Copy Existing Collection" ); + if( ImGuiUtil.DrawDisabledButton( "Copy##Collection", Vector2.Zero, "Copies the effective list from the collection named in Temporary Mod Name...", + !Penumbra.CollectionManager.ByName( _tempModName, out var copyCollection ) ) + && copyCollection is { HasCache: true } ) + { + var files = copyCollection.ResolvedFiles.ToDictionary( kvp => kvp.Key.ToString(), kvp => kvp.Value.Path.ToString() ); + var manips = Functions.ToCompressedBase64( copyCollection.MetaCache?.Manipulations.ToArray() ?? Array.Empty< MetaManipulation >(), + MetaManipulation.CurrentVersion ); + _lastTempError = Ipc.AddTemporaryMod.Subscriber( _pi ).Invoke( _tempModName, _tempCollectionName, files, manips, 999 ); + } + DrawIntro( Ipc.AddTemporaryModAll.Label, "Add Temporary Mod to all Collections" ); if( ImGui.Button( "Add##All" ) ) { @@ -1154,7 +1167,7 @@ public class IpcTester : IDisposable public void DrawCollections() { - using var collTree = ImRaii.TreeNode( "Collections" ); + using var collTree = ImRaii.TreeNode( "Collections##TempCollections" ); if( !collTree ) { return; @@ -1166,27 +1179,25 @@ public class IpcTester : IDisposable return; } - foreach( var (character, collection) in Penumbra.TempMods.Collections ) + foreach( var collection in Penumbra.TempMods.CustomCollections.Values ) { ImGui.TableNextColumn(); - ImGui.TextUnformatted( character ); - ImGui.TableNextColumn(); - ImGui.TextUnformatted( collection.Name ); - ImGui.TableNextColumn(); - ImGui.TextUnformatted( collection.ResolvedFiles.Count.ToString() ); - ImGui.TableNextColumn(); - ImGui.TextUnformatted( collection.MetaCache?.Count.ToString() ?? "0" ); - ImGui.TableNextColumn(); - if( ImGui.Button( $"Save##{character}" ) ) + var character = Penumbra.TempMods.Collections.Where( p => p.Collection == collection ).Select( p => p.DisplayName ).FirstOrDefault() ?? "Unknown"; + if( ImGui.Button( $"Save##{collection.Name}" ) ) { Mod.TemporaryMod.SaveTempCollection( collection, character ); } + + ImGuiUtil.DrawTableColumn( collection.Name ); + ImGuiUtil.DrawTableColumn( collection.ResolvedFiles.Count.ToString() ); + ImGuiUtil.DrawTableColumn( collection.MetaCache?.Count.ToString() ?? "0" ); + ImGuiUtil.DrawTableColumn( string.Join( ", ", Penumbra.TempMods.Collections.Where( p => p.Collection == collection ).Select( c => c.DisplayName ) ) ); } } public void DrawMods() { - using var modTree = ImRaii.TreeNode( "Mods" ); + using var modTree = ImRaii.TreeNode( "Mods##TempMods" ); if( !modTree ) { return; diff --git a/Penumbra/Api/TempModManager.cs b/Penumbra/Api/TempModManager.cs index db087f9d..650b476e 100644 --- a/Penumbra/Api/TempModManager.cs +++ b/Penumbra/Api/TempModManager.cs @@ -37,7 +37,7 @@ public class TempModManager => _customCollections; public bool CollectionByName( string name, [NotNullWhen( true )] out ModCollection? collection ) - => _customCollections.TryGetValue( name, out collection ); + => _customCollections.TryGetValue( name.ToLowerInvariant(), out collection ); // These functions to check specific redirections or meta manipulations for existence are currently unused. //public bool IsRegistered( string tag, ModCollection? collection, Utf8GamePath gamePath, out FullPath? fullPath, out int priority ) @@ -154,18 +154,18 @@ public class TempModManager public string CreateTemporaryCollection( string tag, string customName ) { var collection = ModCollection.CreateNewTemporary( tag, customName ); - if( _customCollections.ContainsKey( collection.Name ) ) + if( _customCollections.TryAdd( collection.Name.ToLowerInvariant(), collection ) ) { - collection.ClearCache(); - return string.Empty; + return collection.Name; } - _customCollections.Add( collection.Name, collection ); - return collection.Name; + + collection.ClearCache(); + return string.Empty; } public bool RemoveTemporaryCollection( string collectionName ) { - if( !_customCollections.Remove( collectionName, out var collection ) ) + if( !_customCollections.Remove( collectionName.ToLowerInvariant(), out var collection ) ) { return false; } @@ -197,7 +197,7 @@ public class TempModManager public bool AddIdentifier( string collectionName, params ActorIdentifier[] identifiers ) { - if( !_customCollections.TryGetValue( collectionName, out var collection ) ) + if( !_customCollections.TryGetValue( collectionName.ToLowerInvariant(), out var collection ) ) { return false; } diff --git a/Penumbra/UI/ConfigWindow.Changelog.cs b/Penumbra/UI/ConfigWindow.Changelog.cs index a5f6204a..4a6ab8b1 100644 --- a/Penumbra/UI/ConfigWindow.Changelog.cs +++ b/Penumbra/UI/ConfigWindow.Changelog.cs @@ -50,6 +50,7 @@ public partial class ConfigWindow .RegisterEntry( "Try to use Unicode normalization before replacing invalid path symbols on import for somewhat nicer paths." ) .RegisterEntry( "Improved interface for group settings (minimally)." ) .RegisterEntry( "Prevent a bug that allowed IPC to add Mods from outside the Penumbra root folder." ) + .RegisterEntry( "New Special or Individual Assignments now default to your current Base assignment instead of None." ) .RegisterEntry( "Improved Support Info somewhat." ) .RegisterEntry( "Fixed a bug when dragging options during mod edit." ) .RegisterEntry( "Fixed a bug where sometimes the valid folder check caused issues." ) diff --git a/Penumbra/UI/ConfigWindow.Tutorial.cs b/Penumbra/UI/ConfigWindow.Tutorial.cs index 5826d3f1..6c10f740 100644 --- a/Penumbra/UI/ConfigWindow.Tutorial.cs +++ b/Penumbra/UI/ConfigWindow.Tutorial.cs @@ -128,8 +128,8 @@ public partial class ConfigWindow + "The more specific the condition, the higher its priority (i.e. Your Character > Player Characters > Race).\n\n" + $"{IndividualAssignments} always take precedence before groups." ) .Register( IndividualAssignments, - "Collections assigned here are used only for individual characters or NPCs that have the specified name.\n\n" - + "They may also apply to objects 'owned' by those characters, e.g. minions or mounts - see the general settings for options on this.\n\n" ) + "Collections assigned here are used only for individual players or NPCs that fulfill the given criteria.\n\n" + + "They may also apply to objects 'owned' by those characters implicitly, e.g. minions or mounts - see the general settings for options on this.\n\n" ) .Register( "Initial Setup, Step 8: Mods", "Our last stop is the Mods tab, where you can import and setup your mods.\n\n" + $"Please go there after verifying that your {SelectedCollection} and {DefaultCollection} are setup to your liking." ) .Register( "Initial Setup, Step 9: Mod Import",