From 924c9b9f7e6ca61c4cd78d21fbece8475d384ca8 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Wed, 17 Sep 2025 18:05:07 +0200 Subject: [PATCH] Update to Luna state. --- .editorconfig | 67 +- Luna | 2 +- Penumbra.GameData | 2 +- Penumbra/Api/Api/CollectionApi.cs | 2 +- Penumbra/Api/Api/ModsApi.cs | 2 +- .../Api/IpcTester/CollectionsIpcTester.cs | 180 +- Penumbra/Api/IpcTester/IpcTester.cs | 7 +- Penumbra/Api/IpcTester/TemporaryIpcTester.cs | 2 +- Penumbra/Configuration.cs | 28 +- Penumbra/DebugConfiguration.cs | 6 +- .../Hooks/ResourceLoading/FileReadService.cs | 6 +- .../Hooks/ResourceLoading/ResourceService.cs | 6 +- .../PathResolving/CollectionResolver.cs | 5 - .../Interop/PathResolving/PathResolver.cs | 10 +- Penumbra/Mods/Editor/IMod.cs | 3 +- Penumbra/Mods/Editor/ModMerger.cs | 4 +- Penumbra/Mods/Manager/ModDataEditor.cs | 11 +- Penumbra/Mods/Manager/ModFileSystem.cs | 11 +- Penumbra/Mods/Manager/ModStorage.cs | 4 +- Penumbra/Mods/Mod.cs | 287 ++-- Penumbra/Mods/ModCreator.cs | 6 +- Penumbra/Mods/TemporaryMod.cs | 3 +- Penumbra/Services/PcpService.cs | 38 +- Penumbra/UI/AdvancedWindow/ItemSwapTab.cs | 14 +- .../Materials/MtrlTab.Constants.cs | 2 +- .../AdvancedWindow/ModEditWindow.Deformers.cs | 1 - .../UI/AdvancedWindow/ModEditWindow.Files.cs | 42 +- .../UI/AdvancedWindow/ModEditWindow.Models.cs | 2 +- .../AdvancedWindow/ModEditWindow.ShpkTab.cs | 2 +- Penumbra/UI/AdvancedWindow/ModEditWindow.cs | 9 +- Penumbra/UI/AdvancedWindow/ModMergeTab.cs | 6 +- .../UI/AdvancedWindow/ResourceTreeViewer.cs | 33 +- Penumbra/UI/ChangedItemDrawer.cs | 5 +- Penumbra/UI/Changelog.cs | 1525 +++++++++-------- Penumbra/UI/ConfigWindow.cs | 9 +- Penumbra/UI/ModsTab/ModFileSystemSelector.cs | 10 +- .../UI/ModsTab/ModPanelChangedItemsTab.cs | 11 +- Penumbra/UI/ModsTab/ModPanelConflictsTab.cs | 6 +- Penumbra/UI/ModsTab/ModPanelHeader.cs | 4 +- .../UI/ModsTab/ModSearchStringSplitter.cs | 18 +- Penumbra/UI/ModsTab/MultiModPanel.cs | 6 +- Penumbra/UI/ResourceWatcher/Record.cs | 2 +- .../ResourceWatcher/ResourceWatcherTable.cs | 2 +- Penumbra/UI/Tabs/ChangedItemsTab.cs | 14 +- Penumbra/UI/Tabs/Debug/DebugTab.cs | 44 +- Penumbra/UI/Tabs/EffectiveTab.cs | 25 +- Penumbra/UI/Tabs/SettingsTab.cs | 44 +- Penumbra/Util/PerformanceType.cs | 66 - 48 files changed, 1323 insertions(+), 1271 deletions(-) delete mode 100644 Penumbra/Util/PerformanceType.cs diff --git a/.editorconfig b/.editorconfig index f0328fd7..bf79c9d6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -59,9 +59,9 @@ csharp_space_between_method_declaration_parameter_list_parentheses=false csharp_space_between_parentheses=false csharp_space_between_square_brackets=false csharp_style_namespace_declarations= file_scoped:suggestion -csharp_style_var_elsewhere=true:suggestion -csharp_style_var_for_built_in_types=true:suggestion -csharp_style_var_when_type_is_apparent=true:suggestion +csharp_style_var_elsewhere= true:suggestion +csharp_style_var_for_built_in_types= true:suggestion +csharp_style_var_when_type_is_apparent= true:suggestion csharp_using_directive_placement= outside_namespace:silent dotnet_diagnostic.bc40000.severity=warning dotnet_diagnostic.bc400005.severity=warning @@ -348,16 +348,16 @@ dotnet_naming_symbols.type_parameters_symbols.applicable_accessibilities=* dotnet_naming_symbols.type_parameters_symbols.applicable_kinds=type_parameter dotnet_separate_import_directive_groups=false dotnet_sort_system_directives_first=true -dotnet_style_parentheses_in_arithmetic_binary_operators=never_if_unnecessary:suggestion -dotnet_style_parentheses_in_other_binary_operators=never_if_unnecessary:suggestion -dotnet_style_parentheses_in_relational_binary_operators=never_if_unnecessary:suggestion -dotnet_style_predefined_type_for_locals_parameters_members=true:suggestion -dotnet_style_predefined_type_for_member_access=true:suggestion -dotnet_style_qualification_for_event=false:suggestion -dotnet_style_qualification_for_field=false:suggestion -dotnet_style_qualification_for_method=false:suggestion -dotnet_style_qualification_for_property=false:suggestion -dotnet_style_require_accessibility_modifiers=for_non_interface_members:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators= never_if_unnecessary:suggestion +dotnet_style_parentheses_in_other_binary_operators= never_if_unnecessary:suggestion +dotnet_style_parentheses_in_relational_binary_operators= never_if_unnecessary:suggestion +dotnet_style_predefined_type_for_locals_parameters_members= true:suggestion +dotnet_style_predefined_type_for_member_access= true:suggestion +dotnet_style_qualification_for_event= false:suggestion +dotnet_style_qualification_for_field= false:suggestion +dotnet_style_qualification_for_method= false:suggestion +dotnet_style_qualification_for_property= false:suggestion +dotnet_style_require_accessibility_modifiers= always:suggestion file_header_template= # ReSharper properties @@ -3588,6 +3588,40 @@ csharp_style_deconstructed_variable_declaration = true:suggestion csharp_style_unused_value_assignment_preference = discard_variable:suggestion csharp_style_unused_value_expression_statement_preference = discard_variable:silent csharp_style_expression_bodied_properties = true:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_prefer_system_threading_lock = true:suggestion +csharp_style_prefer_simple_property_accessors = true:suggestion +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_prefer_static_anonymous_function = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion [*.{cshtml,htm,html,proto,razor}] indent_style=tab @@ -3635,3 +3669,10 @@ dotnet_style_prefer_compound_assignment = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion dotnet_style_namespace_match_folder = true:suggestion insert_final_newline = true +end_of_line = lf +dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent diff --git a/Luna b/Luna index f39b5143..15636cda 160000 --- a/Luna +++ b/Luna @@ -1 +1 @@ -Subproject commit f39b514304d8f30030310f75d83f99385105c271 +Subproject commit 15636cda90725e6af7071512cf9873dd273570fc diff --git a/Penumbra.GameData b/Penumbra.GameData index 2183dc78..3104cfee 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 2183dc78c46dd9b72fd2d95370e1bf223eff93a3 +Subproject commit 3104cfeefbdf0dd616a5886e07d1b615db15afd4 diff --git a/Penumbra/Api/Api/CollectionApi.cs b/Penumbra/Api/Api/CollectionApi.cs index 1a0562f2..e9d54676 100644 --- a/Penumbra/Api/Api/CollectionApi.cs +++ b/Penumbra/Api/Api/CollectionApi.cs @@ -40,7 +40,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : if (!c.Active.Current.ChangedItems.TryGetValue(s, out var d)) return []; - return d.Item1.Select(m => (m is Mod mod ? mod.Identifier : string.Empty, m.Name.Text)).ToArray(); + return d.Item1.Select(m => (m is Mod mod ? mod.Identifier : string.Empty, m.Name)).ToArray(); }; } diff --git a/Penumbra/Api/Api/ModsApi.cs b/Penumbra/Api/Api/ModsApi.cs index fecfb916..348dc250 100644 --- a/Penumbra/Api/Api/ModsApi.cs +++ b/Penumbra/Api/Api/ModsApi.cs @@ -58,7 +58,7 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable } public Dictionary GetModList() - => _modManager.ToDictionary(m => m.ModPath.Name, m => m.Name.Text); + => _modManager.ToDictionary(m => m.ModPath.Name, m => m.Name); public PenumbraApiEc InstallMod(string modFilePackagePath) { diff --git a/Penumbra/Api/IpcTester/CollectionsIpcTester.cs b/Penumbra/Api/IpcTester/CollectionsIpcTester.cs index 4fa450ae..f7df3fec 100644 --- a/Penumbra/Api/IpcTester/CollectionsIpcTester.cs +++ b/Penumbra/Api/IpcTester/CollectionsIpcTester.cs @@ -1,14 +1,10 @@ -using Dalamud.Bindings.ImGui; -using Dalamud.Interface; -using Dalamud.Interface.Utility; using Dalamud.Plugin; +using ImSharp; using OtterGui; -using OtterGui.Raii; using Penumbra.Api.Enums; using Penumbra.Api.IpcSubscribers; using Penumbra.Collections.Manager; using Penumbra.GameData.Data; -using ImGuiClip = OtterGui.ImGuiClip; namespace Penumbra.Api.IpcTester; @@ -28,89 +24,110 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : Luna.IUiService public void Draw() { - using var _ = ImRaii.TreeNode("Collections"); + using var _ = Im.Tree.Node("Collections"u8); if (!_) return; ImGuiUtil.GenericEnumCombo("Collection Type", 200, _type, out _type, t => ((CollectionType)t).ToName()); - ImGui.InputInt("Object Index##Collections", ref _objectIdx, 0, 0); - ImGuiUtil.GuidInput("Collection Id##Collections", "Collection Identifier...", string.Empty, ref _collectionId, ref _collectionIdString); - ImGui.Checkbox("Allow Assignment Creation", ref _allowCreation); - ImGui.SameLine(); - ImGui.Checkbox("Allow Assignment Deletion", ref _allowDeletion); - - using var table = ImRaii.Table(string.Empty, 4, ImGuiTableFlags.SizingFixedFit); - if (!table) - return; - - IpcTester.DrawIntro("Last Return Code", _returnCode.ToString()); - if (_oldCollection != null) - ImGui.TextUnformatted(!_oldCollection.HasValue ? "Created" : _oldCollection.ToString()); - - IpcTester.DrawIntro(GetCollectionsByIdentifier.Label, "Collection Identifier"); - var collectionList = new GetCollectionsByIdentifier(pi).Invoke(_collectionIdString); - if (collectionList.Count == 0) + Im.Input.Scalar("Object Index##Collections"u8, ref _objectIdx); + if (_collectionId.HasValue) { - DrawCollection(null); + if (ImEx.GuidInput("Collection Id##Collections"u8, $"{_collectionId.Value}", out var id)) + _collectionId = id; } else { - DrawCollection(collectionList[0]); + if (ImEx.GuidInput("Collection Id##Collections"u8, "Collection Identifier..."u8, out var id)) + _collectionId = id; + } + + Im.Checkbox("Allow Assignment Creation"u8, ref _allowCreation); + Im.Line.Same(); + Im.Checkbox("Allow Assignment Deletion"u8, ref _allowDeletion); + + using var table = Im.Table.Begin("table"u8, 4, TableFlags.SizingFixedFit); + if (!table) + return; + + table.DrawColumn("Last Return Code"u8); + table.DrawColumn($"{_returnCode}"); + if (_oldCollection is not null) + Im.Text(!_oldCollection.HasValue ? "Created" : _oldCollection.ToString()!); + + table.DrawColumn(GetCollectionsByIdentifier.Label); + table.DrawColumn("Collection Identifier"u8); + var collectionList = new GetCollectionsByIdentifier(pi).Invoke(_collectionIdString); + if (collectionList.Count == 0) + { + DrawCollection(table, null); + } + else + { + DrawCollection(table, collectionList[0]); foreach (var pair in collectionList.Skip(1)) { - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - DrawCollection(pair); + table.NextRow(); + table.NextColumn(); + table.NextColumn(); + table.NextColumn(); + DrawCollection(table, pair); } } - IpcTester.DrawIntro(GetCollection.Label, "Current Collection"); - DrawCollection(new GetCollection(pi).Invoke(ApiCollectionType.Current)); + table.DrawColumn(GetCollection.Label); + table.DrawColumn("Current Collection"u8); + DrawCollection(table, new GetCollection(pi).Invoke(ApiCollectionType.Current)); - IpcTester.DrawIntro(GetCollection.Label, "Default Collection"); - DrawCollection(new GetCollection(pi).Invoke(ApiCollectionType.Default)); + table.DrawColumn(GetCollection.Label); + table.DrawColumn("Default Collection"u8); + DrawCollection(table, new GetCollection(pi).Invoke(ApiCollectionType.Default)); - IpcTester.DrawIntro(GetCollection.Label, "Interface Collection"); - DrawCollection(new GetCollection(pi).Invoke(ApiCollectionType.Interface)); + table.DrawColumn(GetCollection.Label); + table.DrawColumn("Interface Collection"u8); + DrawCollection(table, new GetCollection(pi).Invoke(ApiCollectionType.Interface)); - IpcTester.DrawIntro(GetCollection.Label, "Special Collection"); - DrawCollection(new GetCollection(pi).Invoke(_type)); + table.DrawColumn(GetCollection.Label); + table.DrawColumn("Special Collection"u8); + DrawCollection(table, new GetCollection(pi).Invoke(_type)); - IpcTester.DrawIntro(GetCollections.Label, "Collections"); + table.DrawColumn(GetCollections.Label); + table.DrawColumn("Collections"u8); DrawCollectionPopup(); - if (ImGui.Button("Get##Collections")) + if (Im.Button("Get##Collections"u8)) { _collections = new GetCollections(pi).Invoke(); - ImGui.OpenPopup("Collections"); + Im.Popup.Open("Collections"u8); } - IpcTester.DrawIntro(GetCollectionForObject.Label, "Get Object Collection"); + table.DrawColumn(GetCollectionForObject.Label); + table.DrawColumn("Get Object Collection"u8); var (valid, individual, effectiveCollection) = new GetCollectionForObject(pi).Invoke(_objectIdx); - DrawCollection(effectiveCollection); - ImGui.SameLine(); - ImGui.TextUnformatted($"({(valid ? "Valid" : "Invalid")} Object{(individual ? ", Individual Assignment)" : ")")}"); + DrawCollection(table, effectiveCollection); + Im.Line.Same(); + Im.Text($"({(valid ? "Valid" : "Invalid")} Object{(individual ? ", Individual Assignment)" : ")")}"); - IpcTester.DrawIntro(SetCollection.Label, "Set Special Collection"); - if (ImGui.Button("Set##SpecialCollection")) + table.DrawColumn(SetCollection.Label); + table.DrawColumn("Set Special Collection"u8); + if (Im.Button("Set##SpecialCollection"u8)) (_returnCode, _oldCollection) = new SetCollection(pi).Invoke(_type, _collectionId.GetValueOrDefault(Guid.Empty), _allowCreation, _allowDeletion); - ImGui.TableNextColumn(); - if (ImGui.Button("Remove##SpecialCollection")) + table.NextColumn(); + if (Im.Button("Remove##SpecialCollection"u8)) (_returnCode, _oldCollection) = new SetCollection(pi).Invoke(_type, null, _allowCreation, _allowDeletion); - IpcTester.DrawIntro(SetCollectionForObject.Label, "Set Object Collection"); - if (ImGui.Button("Set##ObjectCollection")) + table.DrawColumn(SetCollectionForObject.Label); + table.DrawColumn("Set Object Collection"u8); + if (Im.Button("Set##ObjectCollection"u8)) (_returnCode, _oldCollection) = new SetCollectionForObject(pi).Invoke(_objectIdx, _collectionId.GetValueOrDefault(Guid.Empty), _allowCreation, _allowDeletion); - ImGui.TableNextColumn(); - if (ImGui.Button("Remove##ObjectCollection")) + table.NextColumn(); + if (Im.Button("Remove##ObjectCollection"u8)) (_returnCode, _oldCollection) = new SetCollectionForObject(pi).Invoke(_objectIdx, null, _allowCreation, _allowDeletion); - IpcTester.DrawIntro(GetChangedItemsForCollection.Label, "Changed Item List"); + table.DrawColumn(GetChangedItemsForCollection.Label); + table.DrawColumn("Changed Item List"u8); DrawChangedItemPopup(); - if (ImGui.Button("Get##ChangedItems")) + if (Im.Button("Get##ChangedItems"u8)) { var items = new GetChangedItemsForCollection(pi).Invoke(_collectionId.GetValueOrDefault(Guid.Empty)); _changedItems = items.Select(kvp => @@ -118,67 +135,70 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : Luna.IUiService var (type, id) = kvp.Value.ToApiObject(); return (kvp.Key, type, id); }).ToArray(); - ImGui.OpenPopup("Changed Item List"); + Im.Popup.Open("Changed Item List"u8); } } private void DrawChangedItemPopup() { - ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(500, 500)); - using var p = ImRaii.Popup("Changed Item List"); + Im.Window.SetNextSize(ImEx.ScaledVector(500)); + using var p = Im.Popup.Begin("Changed Item List"u8); if (!p) return; - using (var table = ImRaii.Table("##ChangedItems", 3, ImGuiTableFlags.SizingFixedFit)) + using (var table = Im.Table.Begin("##ChangedItems"u8, 3, TableFlags.SizingFixedFit)) { if (table) - ImGuiClip.ClippedDraw(_changedItems, t => + { + using var clipper = new Im.ListClipper(_changedItems.Length, Im.Style.TextHeightWithSpacing); + foreach (var item in clipper.Iterate(_changedItems)) { - ImGuiUtil.DrawTableColumn(t.Item1); - ImGuiUtil.DrawTableColumn(t.Item2.ToString()); - ImGuiUtil.DrawTableColumn(t.Item3.ToString()); - }, ImGui.GetTextLineHeightWithSpacing()); + table.DrawColumn(item.Item1); + table.DrawColumn($"{item.Item2}"); + table.DrawColumn($"{item.Item3}"); + } + } } - if (ImGui.Button("Close", -Vector2.UnitX) || !ImGui.IsWindowFocused()) - ImGui.CloseCurrentPopup(); + if (Im.Button("Close"u8, -Vector2.UnitX) || !Im.Window.Focused()) + Im.Popup.CloseCurrent(); } private void DrawCollectionPopup() { - ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(500, 500)); - using var p = ImRaii.Popup("Collections"); + Im.Window.SetNextSize(ImEx.ScaledVector(500)); + using var p = Im.Popup.Begin("Collections"u8); if (!p) return; - using (var t = ImRaii.Table("collections", 2, ImGuiTableFlags.SizingFixedFit)) + using (var t = Im.Table.Begin("collections"u8, 2, TableFlags.SizingFixedFit)) { if (t) foreach (var collection in _collections) { - ImGui.TableNextColumn(); - DrawCollection((collection.Key, collection.Value)); + t.NextColumn(); + DrawCollection(t, (collection.Key, collection.Value)); } } - if (ImGui.Button("Close", -Vector2.UnitX) || !ImGui.IsWindowFocused()) - ImGui.CloseCurrentPopup(); + if (Im.Button("Close"u8, -Vector2.UnitX) || !Im.Window.Focused()) + Im.Popup.CloseCurrent(); } - private static void DrawCollection((Guid Id, string Name)? collection) + private static void DrawCollection(Im.TableDisposable table, (Guid Id, string Name)? collection) { if (collection == null) { - ImGui.TextUnformatted(""); - ImGui.TableNextColumn(); + Im.Text(""u8); + table.NextColumn(); return; } - ImGui.TextUnformatted(collection.Value.Name); - ImGui.TableNextColumn(); - using (ImRaii.PushFont(UiBuilder.MonoFont)) + Im.Text(collection.Value.Name); + table.NextColumn(); + using (Im.Font.PushMono()) { - ImGuiUtil.CopyOnClickSelectable(collection.Value.Id.ToString()); + ImEx.CopyOnClickSelectable($"{collection.Value.Id}"); } } } diff --git a/Penumbra/Api/IpcTester/IpcTester.cs b/Penumbra/Api/IpcTester/IpcTester.cs index 6a99a810..654ee905 100644 --- a/Penumbra/Api/IpcTester/IpcTester.cs +++ b/Penumbra/Api/IpcTester/IpcTester.cs @@ -1,5 +1,6 @@ using Dalamud.Plugin.Services; using Dalamud.Bindings.ImGui; +using ImSharp; using Penumbra.Api.Api; namespace Penumbra.Api.IpcTester; @@ -54,13 +55,13 @@ public class IpcTester( } } - internal static void DrawIntro(string label, string info) + internal static void DrawIntro(Utf8StringHandler label, Utf8StringHandler info) { ImGui.TableNextRow(); ImGui.TableNextColumn(); - ImGui.TextUnformatted(label); + Im.Text(ref label); ImGui.TableNextColumn(); - ImGui.TextUnformatted(info); + Im.Text(ref info); ImGui.TableNextColumn(); } diff --git a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs index 64f1f6b6..14c0aa14 100644 --- a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs +++ b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs @@ -282,7 +282,7 @@ public class TemporaryIpcTester( foreach (var mod in list) { ImGui.TableNextColumn(); - ImGui.TextUnformatted(mod.Name.Text); + ImGui.TextUnformatted(mod.Name); ImGui.TableNextColumn(); ImGui.TextUnformatted(mod.Priority.ToString()); ImGui.TableNextColumn(); diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index 3c82d8f7..454963fb 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -3,7 +3,6 @@ using Dalamud.Interface.ImGuiNotification; using Luna; using Newtonsoft.Json; using OtterGui.Filesystem; -using OtterGui.Widgets; using Penumbra.Import.Structs; using Penumbra.Interop.Services; using Penumbra.Mods; @@ -23,6 +22,7 @@ public record PcpSettings public bool AllowIpc { get; set; } = true; public bool DisableHandling { get; set; } = false; public string FolderName { get; set; } = "PCP"; + public string PcpExtension { get; set; } = ".pcp"; } [Serializable] @@ -93,19 +93,19 @@ public class Configuration : IPluginConfiguration, ISavable, IService [JsonProperty(Order = int.MaxValue)] public ISortMode SortMode = ISortMode.FoldersFirst; - public bool OpenFoldersByDefault { get; set; } = false; - public int SingleGroupRadioMax { get; set; } = 2; - public string DefaultImportFolder { get; set; } = string.Empty; - public string QuickMoveFolder1 { get; set; } = string.Empty; - public string QuickMoveFolder2 { get; set; } = string.Empty; - public string QuickMoveFolder3 { get; set; } = string.Empty; - public OtterGui.Classes.DoubleModifier DeleteModModifier { get; set; } = new(OtterGui.Classes.ModifierHotkey.Control, OtterGui.Classes.ModifierHotkey.Shift); - public OtterGui.Classes.DoubleModifier IncognitoModifier { get; set; } = new(OtterGui.Classes.ModifierHotkey.Control); - public bool PrintSuccessfulCommandsToChat { get; set; } = true; - public bool AutoDeduplicateOnImport { get; set; } = true; - public bool AutoReduplicateUiOnImport { get; set; } = true; - public bool UseFileSystemCompression { get; set; } = true; - public bool EnableHttpApi { get; set; } = true; + public bool OpenFoldersByDefault { get; set; } = false; + public int SingleGroupRadioMax { get; set; } = 2; + public string DefaultImportFolder { get; set; } = string.Empty; + public string QuickMoveFolder1 { get; set; } = string.Empty; + public string QuickMoveFolder2 { get; set; } = string.Empty; + public string QuickMoveFolder3 { get; set; } = string.Empty; + public DoubleModifier DeleteModModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift); + public DoubleModifier IncognitoModifier { get; set; } = new(ModifierHotkey.Control); + public bool PrintSuccessfulCommandsToChat { get; set; } = true; + public bool AutoDeduplicateOnImport { get; set; } = true; + public bool AutoReduplicateUiOnImport { get; set; } = true; + public bool UseFileSystemCompression { get; set; } = true; + public bool EnableHttpApi { get; set; } = true; public bool MigrateImportedModelsToV6 { get; set; } = true; public bool MigrateImportedMaterialsToLegacy { get; set; } = true; diff --git a/Penumbra/DebugConfiguration.cs b/Penumbra/DebugConfiguration.cs index 3f9e8207..7b6a1ac9 100644 --- a/Penumbra/DebugConfiguration.cs +++ b/Penumbra/DebugConfiguration.cs @@ -1,7 +1,7 @@ -namespace Penumbra; - +namespace Penumbra; + public class DebugConfiguration { public static bool WriteImcBytesToLog = false; public static bool UseSkinMaterialProcessing = true; -} +} diff --git a/Penumbra/Interop/Hooks/ResourceLoading/FileReadService.cs b/Penumbra/Interop/Hooks/ResourceLoading/FileReadService.cs index 781a21ca..85255943 100644 --- a/Penumbra/Interop/Hooks/ResourceLoading/FileReadService.cs +++ b/Penumbra/Interop/Hooks/ResourceLoading/FileReadService.cs @@ -3,16 +3,14 @@ using Dalamud.Plugin.Services; using Dalamud.Utility.Signatures; using Penumbra.GameData; using Penumbra.Interop.Structs; -using Penumbra.Util; namespace Penumbra.Interop.Hooks.ResourceLoading; public unsafe class FileReadService : IDisposable, Luna.IRequiredService { - public FileReadService(PerformanceTracker performance, ResourceManagerService resourceManager, IGameInteropProvider interop) + public FileReadService(ResourceManagerService resourceManager, IGameInteropProvider interop) { _resourceManager = resourceManager; - _performance = performance; interop.InitializeFromAttributes(this); if (!HookOverrides.Instance.ResourceLoading.ReadSqPack) _readSqPackHook.Enable(); @@ -49,7 +47,6 @@ public unsafe class FileReadService : IDisposable, Luna.IRequiredService _readSqPackHook.Dispose(); } - private readonly PerformanceTracker _performance; private readonly ResourceManagerService _resourceManager; private delegate byte ReadSqPackPrototype(nint resourceManager, SeFileDescriptor* pFileDesc, int priority, bool isSync); @@ -59,7 +56,6 @@ public unsafe class FileReadService : IDisposable, Luna.IRequiredService private byte ReadSqPackDetour(nint resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync) { - using var performance = _performance.Measure(PerformanceType.ReadSqPack); byte? ret = null; _lastFileThreadResourceManager.Value = resourceManager; ReadSqPack?.Invoke(fileDescriptor, ref priority, ref isSync, ref ret); diff --git a/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs b/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs index 1e8f4ee3..6b6da89f 100644 --- a/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs +++ b/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs @@ -8,21 +8,18 @@ using Penumbra.Interop.SafeHandles; using Penumbra.Interop.Structs; using Penumbra.String; using Penumbra.String.Classes; -using Penumbra.Util; using CSResourceHandle = FFXIVClientStructs.FFXIV.Client.System.Resource.Handle.ResourceHandle; namespace Penumbra.Interop.Hooks.ResourceLoading; public unsafe class ResourceService : IDisposable, Luna.IRequiredService { - private readonly PerformanceTracker _performance; private readonly ResourceManagerService _resourceManager; private readonly ThreadLocal _currentGetResourcePath = new(() => Utf8GamePath.Empty); - public ResourceService(PerformanceTracker performance, ResourceManagerService resourceManager, IGameInteropProvider interop) + public ResourceService(ResourceManagerService resourceManager, IGameInteropProvider interop) { - _performance = performance; _resourceManager = resourceManager; interop.InitializeFromAttributes(this); _incRefHook = interop.HookFromAddress( @@ -108,7 +105,6 @@ public unsafe class ResourceService : IDisposable, Luna.IRequiredService private ResourceHandle* GetResourceHandler(bool isSync, ResourceManager* resourceManager, ResourceCategory* categoryId, ResourceType* resourceType, int* resourceHash, byte* path, GetResourceParameters* pGetResParams, byte isUnk, nint unk8, uint unk9) { - using var performance = _performance.Measure(PerformanceType.GetResourceHandler); if (!Utf8GamePath.FromPointer(path, MetaDataComputation.CiCrc32, out var gamePath)) { Penumbra.Log.Error("[ResourceService] Could not create GamePath from resource path."); diff --git a/Penumbra/Interop/PathResolving/CollectionResolver.cs b/Penumbra/Interop/PathResolving/CollectionResolver.cs index 1f046e09..c527a6da 100644 --- a/Penumbra/Interop/PathResolving/CollectionResolver.cs +++ b/Penumbra/Interop/PathResolving/CollectionResolver.cs @@ -10,7 +10,6 @@ using Penumbra.GameData.Enums; using Penumbra.GameData.Interop; using Penumbra.GameData.Structs; using Penumbra.String; -using Penumbra.Util; using Character = FFXIVClientStructs.FFXIV.Client.Game.Character.Character; using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; @@ -18,7 +17,6 @@ using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; namespace Penumbra.Interop.PathResolving; public sealed unsafe class CollectionResolver( - PerformanceTracker performance, IdentifiedCollectionCache cache, IClientState clientState, ObjectManager objects, @@ -38,7 +36,6 @@ public sealed unsafe class CollectionResolver( /// public ModCollection PlayerCollection() { - using var performance1 = performance.Measure(PerformanceType.IdentifyCollection); var gameObject = objects[0]; if (!gameObject.Valid) return collectionManager.Active.ByType(CollectionType.Yourself) @@ -55,8 +52,6 @@ public sealed unsafe class CollectionResolver( /// Identify the correct collection for a game object. public ResolveData IdentifyCollection(GameObject* gameObject, bool useCache) { - using var t = performance.Measure(PerformanceType.IdentifyCollection); - if (gameObject == null) return collectionManager.Active.Default.ToResolveData(); diff --git a/Penumbra/Interop/PathResolving/PathResolver.cs b/Penumbra/Interop/PathResolving/PathResolver.cs index 3e115c84..5fcf56a4 100644 --- a/Penumbra/Interop/PathResolving/PathResolver.cs +++ b/Penumbra/Interop/PathResolving/PathResolver.cs @@ -5,13 +5,11 @@ using Penumbra.Collections.Manager; using Penumbra.Interop.Hooks.ResourceLoading; using Penumbra.Interop.Processing; using Penumbra.String.Classes; -using Penumbra.Util; namespace Penumbra.Interop.PathResolving; public class PathResolver : IDisposable, Luna.IService { - private readonly PerformanceTracker _performance; private readonly Configuration _config; private readonly CollectionManager _collectionManager; private readonly ResourceLoader _loader; @@ -23,11 +21,10 @@ public class PathResolver : IDisposable, Luna.IService private readonly CollectionResolver _collectionResolver; private readonly GamePathPreProcessService _preprocessor; - public PathResolver(PerformanceTracker performance, Configuration config, CollectionManager collectionManager, ResourceLoader loader, + public PathResolver(Configuration config, CollectionManager collectionManager, ResourceLoader loader, SubfileHelper subfileHelper, PathState pathState, MetaState metaState, CollectionResolver collectionResolver, GameState gameState, GamePathPreProcessService preprocessor) { - _performance = performance; _config = config; _collectionManager = collectionManager; _subfileHelper = subfileHelper; @@ -75,10 +72,6 @@ public class PathResolver : IDisposable, Luna.IService // always use the default resolver for now, // except that common/font is conceptually more UI. ResourceCategory.Common => path.Path.StartsWith("common/font"u8) ? ResolveUi(path) : DefaultResolver(path), - ResourceCategory.BgCommon => DefaultResolver(path), - ResourceCategory.Bg => DefaultResolver(path), - ResourceCategory.Cut => DefaultResolver(path), - ResourceCategory.Music => DefaultResolver(path), _ => DefaultResolver(path), } }; @@ -99,7 +92,6 @@ public class PathResolver : IDisposable, Luna.IService public (FullPath?, ResolveData) Resolve(Utf8GamePath gamePath, ResourceType type) { - using var performance = _performance.Measure(PerformanceType.CharacterResolver); // Check if the path was marked for a specific collection, // or if it is a file loaded by a material, and if we are currently in a material load, // or if it is a face decal path and the current mod collection is set. diff --git a/Penumbra/Mods/Editor/IMod.cs b/Penumbra/Mods/Editor/IMod.cs index 3da38829..6f620b8c 100644 --- a/Penumbra/Mods/Editor/IMod.cs +++ b/Penumbra/Mods/Editor/IMod.cs @@ -1,4 +1,3 @@ -using OtterGui.Classes; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Groups; using Penumbra.Mods.Settings; @@ -15,7 +14,7 @@ public record struct AppliedModData( public interface IMod { - LowerString Name { get; } + public string Name { get; } public int Index { get; } public ModPriority Priority { get; } diff --git a/Penumbra/Mods/Editor/ModMerger.cs b/Penumbra/Mods/Editor/ModMerger.cs index 2c60250b..4b63de56 100644 --- a/Penumbra/Mods/Editor/ModMerger.cs +++ b/Penumbra/Mods/Editor/ModMerger.cs @@ -479,8 +479,8 @@ public class ModMerger : IDisposable, IService private void OnSelectionChange(in ModSelection.Arguments arguments) { - if (OptionGroupName == "Merges" && OptionName.Length == 0 || OptionName == arguments.OldSelection?.Name.Text) - OptionName = arguments.NewSelection?.Name.Text ?? string.Empty; + if (OptionGroupName == "Merges" && OptionName.Length == 0 || OptionName == arguments.OldSelection?.Name) + OptionName = arguments.NewSelection?.Name ?? string.Empty; if (MergeToMod == arguments.NewSelection) MergeToMod = null; diff --git a/Penumbra/Mods/Manager/ModDataEditor.cs b/Penumbra/Mods/Manager/ModDataEditor.cs index 04e743fa..1bbdb67f 100644 --- a/Penumbra/Mods/Manager/ModDataEditor.cs +++ b/Penumbra/Mods/Manager/ModDataEditor.cs @@ -1,5 +1,4 @@ using Dalamud.Utility; -using OtterGui.Classes; using Penumbra.Communication; using Penumbra.GameData.Data; using Penumbra.GameData.Structs; @@ -39,8 +38,8 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic string? website, params string[] tags) { var mod = new Mod(directory); - mod.Name = name.IsNullOrEmpty() ? mod.Name : new LowerString(name); - mod.Author = author != null ? new LowerString(author) : mod.Author; + mod.Name = name.IsNullOrEmpty() ? mod.Name : name; + mod.Author = author ?? mod.Author; mod.Description = description ?? mod.Description; mod.Version = version ?? mod.Version; mod.Website = website ?? mod.Website; @@ -50,13 +49,13 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic public void ChangeModName(Mod mod, string newName) { - if (mod.Name.Text == newName) + if (mod.Name == newName) return; var oldName = mod.Name; mod.Name = newName; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Name, mod, oldName.Text)); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Name, mod, oldName)); } public void ChangeModAuthor(Mod mod, string newAuthor) @@ -97,7 +96,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Website = newWebsite; saveService.QueueSave(new ModMeta(mod)); communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Website, mod, null)); - } + } public void ChangeRequiredFeatures(Mod mod, FeatureFlags flags) { diff --git a/Penumbra/Mods/Manager/ModFileSystem.cs b/Penumbra/Mods/Manager/ModFileSystem.cs index 7163b7b9..02aa9dc3 100644 --- a/Penumbra/Mods/Manager/ModFileSystem.cs +++ b/Penumbra/Mods/Manager/ModFileSystem.cs @@ -3,6 +3,7 @@ using Luna; using OtterGui.Filesystem; using Penumbra.Communication; using Penumbra.Services; +using FileSystemChangeType = OtterGui.Filesystem.FileSystemChangeType; namespace Penumbra.Mods.Manager; @@ -82,9 +83,9 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer if (!arguments.Type.HasFlag(ModDataChangeType.Name) || arguments.OldName == null || !TryGetValue(arguments.Mod, out var leaf)) return; - var old = arguments.OldName.FixName(); - if (old == leaf.Name || leaf.Name.IsDuplicateName(out var baseName, out _) && baseName == old) - RenameWithDuplicates(leaf, arguments.Mod.Name.Text); + var old = Extensions.FixName(arguments.OldName); + if (old == leaf.Name || Extensions.IsDuplicateName(leaf.Name, out var baseName, out _) && baseName == old) + RenameWithDuplicates(leaf, arguments.Mod.Name); } // Update the filesystem if a mod has been added or removed. @@ -107,7 +108,7 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer NotificationType.Warning); } - CreateDuplicateLeaf(parent, arguments.Mod.Name.Text, arguments.Mod); + CreateDuplicateLeaf(parent, arguments.Mod.Name, arguments.Mod); break; case ModPathChangeType.Deleted: if (TryGetValue(arguments.Mod, out var leaf)) @@ -128,7 +129,7 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer => mod.ModPath.Name; private static string ModToName(Mod mod) - => mod.Name.Text.FixName(); + => Extensions.FixName(mod.Name); // Return whether a mod has a custom path or is just a numbered default path. public static bool ModHasDefaultPath(Mod mod, string fullPath) diff --git a/Penumbra/Mods/Manager/ModStorage.cs b/Penumbra/Mods/Manager/ModStorage.cs index acb2c1ab..ea82582d 100644 --- a/Penumbra/Mods/Manager/ModStorage.cs +++ b/Penumbra/Mods/Manager/ModStorage.cs @@ -9,7 +9,7 @@ public class ModCombo(Func> generator) : FilterComboCache Items[globalIndex].Name.Contains(filter); protected override string ToString(Mod obj) - => obj.Name.Text; + => obj.Name; } public class ModStorage : IReadOnlyList @@ -60,7 +60,7 @@ public class ModStorage : IReadOnlyList /// Mods are removed when they are deleted or when they are toggled in any collection. /// Also gets cleared on mod rediscovery. /// - private readonly HashSet _newMods = new(); + private readonly HashSet _newMods = []; public bool IsNew(Mod mod) => _newMods.Contains(mod); diff --git a/Penumbra/Mods/Mod.cs b/Penumbra/Mods/Mod.cs index 56d7e729..0ef87b85 100644 --- a/Penumbra/Mods/Mod.cs +++ b/Penumbra/Mods/Mod.cs @@ -1,144 +1,143 @@ -using Luna; -using OtterGui.Classes; -using Penumbra.GameData.Data; -using Penumbra.GameData.Structs; -using Penumbra.Meta.Manipulations; -using Penumbra.Mods.Editor; -using Penumbra.Mods.Groups; -using Penumbra.Mods.Settings; -using Penumbra.Mods.SubMods; -using Penumbra.String.Classes; - -namespace Penumbra.Mods; - -[Flags] -public enum FeatureFlags : ulong -{ - None = 0, - Atch = 1ul << 0, - Shp = 1ul << 1, - Atr = 1ul << 2, - Invalid = 1ul << 62, -} - -public sealed class Mod : IMod -{ - public static readonly TemporaryMod ForcedFiles = new() - { - Name = "Forced Files", - Index = -1, - Priority = ModPriority.MaxValue, - }; - - // Main Data - public DirectoryInfo ModPath { get; internal set; } - - public string Identifier - => Index >= 0 ? ModPath.Name : Name; - - public int Index { get; internal set; } = -1; - - public bool IsTemporary - => Index < 0; - - /// Unused if Index is less than 0 but used for special temporary mods. - public ModPriority Priority - => ModPriority.Default; - - IReadOnlyList IMod.Groups - => Groups; - - internal Mod(DirectoryInfo modPath) - { - ModPath = modPath; - Default = new DefaultSubMod(this); - } - - public override string ToString() - => Name.Text; - - // Meta Data - public LowerString Name { get; internal set; } = "New Mod"; - public LowerString Author { get; internal set; } = LowerString.Empty; - public string Description { get; internal set; } = string.Empty; - public string Version { get; internal set; } = string.Empty; - public string Website { get; internal set; } = string.Empty; - public string Image { get; internal set; } = string.Empty; - public IReadOnlyList ModTags { get; internal set; } = []; - public HashSet DefaultPreferredItems { get; internal set; } = []; - public FeatureFlags RequiredFeatures { get; internal set; } = 0; - - - // Local Data - public long ImportDate { get; internal set; } = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds(); - public IReadOnlyList LocalTags { get; internal set; } = []; - public string Note { get; internal set; } = string.Empty; - public HashSet PreferredChangedItems { get; internal set; } = []; - public bool Favorite { get; internal set; } - - // Options - public readonly DefaultSubMod Default; - public readonly List Groups = []; - - /// Compute the required feature flags for this mod. - public FeatureFlags ComputeRequiredFeatures() - { - var flags = FeatureFlags.None; - foreach (var option in AllDataContainers) - { - if (option.Manipulations.Atch.Count > 0) - flags |= FeatureFlags.Atch; - if (option.Manipulations.Atr.Count > 0) - flags |= FeatureFlags.Atr; - if (option.Manipulations.Shp.Count > 0) - flags |= FeatureFlags.Shp; - } - - return flags; - } - - public AppliedModData GetData(ModSettings? settings = null) - { - if (settings is not { Enabled: true }) - return AppliedModData.Empty; - - var dictRedirections = new Dictionary(TotalFileCount); - var setManips = new MetaDictionary(); - foreach (var (groupIndex, group) in Groups.Index().Reverse().OrderByDescending(g => g.Item.Priority)) - { - var config = settings.Settings[groupIndex]; - group.AddData(config, dictRedirections, setManips); - } - - Default.AddTo(dictRedirections, setManips); - return new AppliedModData(dictRedirections, setManips); - } - - public IEnumerable AllDataContainers - => Groups.SelectMany(o => o.DataContainers).Prepend(Default); - - public List FindUnusedFiles() - { - var modFiles = AllDataContainers.SelectMany(o => o.Files) - .Select(p => p.Value) - .ToHashSet(); - return ModPath.EnumerateDirectories() - .Where(d => !d.IsHidden()) - .SelectMany(FileExtensions.EnumerateNonHiddenFiles) - .Select(f => new FullPath(f)) - .Where(f => !modFiles.Contains(f)) - .ToList(); - } - - // Cache - public readonly SortedList ChangedItems = new(); - - public string LowerChangedItemsString { get; internal set; } = string.Empty; - public string AllTagsLower { get; internal set; } = string.Empty; - - public int TotalFileCount { get; internal set; } - public int TotalSwapCount { get; internal set; } - public int TotalManipulations { get; internal set; } - public ushort LastChangedItemsUpdate { get; internal set; } - public bool HasOptions { get; internal set; } -} +using Luna; +using Penumbra.GameData.Data; +using Penumbra.GameData.Structs; +using Penumbra.Meta.Manipulations; +using Penumbra.Mods.Editor; +using Penumbra.Mods.Groups; +using Penumbra.Mods.Settings; +using Penumbra.Mods.SubMods; +using Penumbra.String.Classes; + +namespace Penumbra.Mods; + +[Flags] +public enum FeatureFlags : ulong +{ + None = 0, + Atch = 1ul << 0, + Shp = 1ul << 1, + Atr = 1ul << 2, + Invalid = 1ul << 62, +} + +public sealed class Mod : IMod +{ + public static readonly TemporaryMod ForcedFiles = new() + { + Name = "Forced Files", + Index = -1, + Priority = ModPriority.MaxValue, + }; + + // Main Data + public DirectoryInfo ModPath { get; internal set; } + + public string Identifier + => Index >= 0 ? ModPath.Name : Name; + + public int Index { get; internal set; } = -1; + + public bool IsTemporary + => Index < 0; + + /// Unused if Index is less than 0 but used for special temporary mods. + public ModPriority Priority + => ModPriority.Default; + + IReadOnlyList IMod.Groups + => Groups; + + internal Mod(DirectoryInfo modPath) + { + ModPath = modPath; + Default = new DefaultSubMod(this); + } + + public override string ToString() + => Name; + + // Meta Data + public string Name { get; internal set; } = "New Mod"; + public string Author { get; internal set; } = string.Empty; + public string Description { get; internal set; } = string.Empty; + public string Version { get; internal set; } = string.Empty; + public string Website { get; internal set; } = string.Empty; + public string Image { get; internal set; } = string.Empty; + public IReadOnlyList ModTags { get; internal set; } = []; + public HashSet DefaultPreferredItems { get; internal set; } = []; + public FeatureFlags RequiredFeatures { get; internal set; } = 0; + + + // Local Data + public long ImportDate { get; internal set; } = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds(); + public IReadOnlyList LocalTags { get; internal set; } = []; + public string Note { get; internal set; } = string.Empty; + public HashSet PreferredChangedItems { get; internal set; } = []; + public bool Favorite { get; internal set; } + + // Options + public readonly DefaultSubMod Default; + public readonly List Groups = []; + + /// Compute the required feature flags for this mod. + public FeatureFlags ComputeRequiredFeatures() + { + var flags = FeatureFlags.None; + foreach (var option in AllDataContainers) + { + if (option.Manipulations.Atch.Count > 0) + flags |= FeatureFlags.Atch; + if (option.Manipulations.Atr.Count > 0) + flags |= FeatureFlags.Atr; + if (option.Manipulations.Shp.Count > 0) + flags |= FeatureFlags.Shp; + } + + return flags; + } + + public AppliedModData GetData(ModSettings? settings = null) + { + if (settings is not { Enabled: true }) + return AppliedModData.Empty; + + var dictRedirections = new Dictionary(TotalFileCount); + var setManips = new MetaDictionary(); + foreach (var (groupIndex, group) in Groups.Index().Reverse().OrderByDescending(g => g.Item.Priority)) + { + var config = settings.Settings[groupIndex]; + group.AddData(config, dictRedirections, setManips); + } + + Default.AddTo(dictRedirections, setManips); + return new AppliedModData(dictRedirections, setManips); + } + + public IEnumerable AllDataContainers + => Groups.SelectMany(o => o.DataContainers).Prepend(Default); + + public List FindUnusedFiles() + { + var modFiles = AllDataContainers.SelectMany(o => o.Files) + .Select(p => p.Value) + .ToHashSet(); + return ModPath.EnumerateDirectories() + .Where(d => !d.IsHidden()) + .SelectMany(FileExtensions.EnumerateNonHiddenFiles) + .Select(f => new FullPath(f)) + .Where(f => !modFiles.Contains(f)) + .ToList(); + } + + // Cache + public readonly SortedList ChangedItems = new(); + + public string LowerChangedItemsString { get; internal set; } = string.Empty; + public string AllTagsLower { get; internal set; } = string.Empty; + + public int TotalFileCount { get; internal set; } + public int TotalSwapCount { get; internal set; } + public int TotalManipulations { get; internal set; } + public ushort LastChangedItemsUpdate { get; internal set; } + public bool HasOptions { get; internal set; } +} diff --git a/Penumbra/Mods/ModCreator.cs b/Penumbra/Mods/ModCreator.cs index fd6fc8f6..447a059b 100644 --- a/Penumbra/Mods/ModCreator.cs +++ b/Penumbra/Mods/ModCreator.cs @@ -23,7 +23,7 @@ public partial class ModCreator( Configuration config, ModDataEditor dataEditor, MetaFileManager metaFileManager, - GamePathParser gamePathParser) : Luna.IService + GamePathParser gamePathParser) : IService { public const FeatureFlags SupportedFeatures = FeatureFlags.Atch | FeatureFlags.Shp | FeatureFlags.Atr; public readonly Configuration Config = config; @@ -139,7 +139,7 @@ public partial class ModCreator( name = "_"; var newModFolderBase = NewOptionDirectory(outDirectory, name, onlyAscii); - var newModFolder = newModFolderBase.FullName.ObtainUniqueFile(); + var newModFolder = FileSystemUtility.ObtainUniqueFile(newModFolderBase.FullName); if (newModFolder.Length == 0) throw new IOException("Could not create mod folder: too many folders of the same name exist."); @@ -236,7 +236,7 @@ public partial class ModCreator( public static DirectoryInfo? NewSubFolderName(DirectoryInfo parentFolder, string subFolderName, bool onlyAscii) { var newModFolderBase = NewOptionDirectory(parentFolder, subFolderName, onlyAscii); - var newModFolder = newModFolderBase.FullName.ObtainUniqueFile(); + var newModFolder = FileSystemUtility.ObtainUniqueFile(newModFolderBase.FullName); return newModFolder.Length == 0 ? null : new DirectoryInfo(newModFolder); } diff --git a/Penumbra/Mods/TemporaryMod.cs b/Penumbra/Mods/TemporaryMod.cs index 8fdd09c5..28814b70 100644 --- a/Penumbra/Mods/TemporaryMod.cs +++ b/Penumbra/Mods/TemporaryMod.cs @@ -1,4 +1,3 @@ -using OtterGui.Classes; using Penumbra.Collections; using Penumbra.Interop.PathResolving; using Penumbra.Meta.Manipulations; @@ -14,7 +13,7 @@ namespace Penumbra.Mods; public class TemporaryMod : IMod { - public LowerString Name { get; init; } = LowerString.Empty; + public string Name { get; init; } = string.Empty; public int Index { get; init; } = -2; public ModPriority Priority { get; init; } = ModPriority.MaxValue; diff --git a/Penumbra/Services/PcpService.cs b/Penumbra/Services/PcpService.cs index 6174db19..d0aa4630 100644 --- a/Penumbra/Services/PcpService.cs +++ b/Penumbra/Services/PcpService.cs @@ -22,7 +22,8 @@ namespace Penumbra.Services; public class PcpService : IApiService, IDisposable { - public const string Extension = ".pcp"; + public string Extension + => _config.PcpSettings.PcpExtension; private readonly Configuration _config; private readonly SaveService _files; @@ -160,7 +161,7 @@ public class PcpService : IApiService, IDisposable public void Dispose() => _communicator.ModPathChanged.Unsubscribe(OnModPathChange); - public async Task<(bool, string)> CreatePcp(ObjectIndex objectIndex, string note = "", CancellationToken cancel = default) + public async Task<(bool, string)> CreatePcp(ObjectIndex objectIndex, string? modPath, string note = "", CancellationToken cancel = default) { try { @@ -188,7 +189,7 @@ public class PcpService : IApiService, IDisposable var modDirectory = CreateMod(identifier, note, time); await CreateDefaultMod(modDirectory, meta, tree, cancel); await CreateCollectionInfo(modDirectory, objectIndex, identifier, note, time, cancel); - var file = ZipUp(modDirectory); + var file = ZipUp(modDirectory, modPath, Extension); return (true, file); } catch (Exception ex) @@ -197,12 +198,15 @@ public class PcpService : IApiService, IDisposable } } - private static string ZipUp(DirectoryInfo directory) + private static string ZipUp(DirectoryInfo directory, string? path, string extension) { - var fileName = directory.FullName + Extension; - ZipFile.CreateFromDirectory(directory.FullName, fileName, CompressionLevel.Optimal, false); + if (path is null) + path = directory.FullName + extension; + else if (Path.GetExtension(path.AsSpan()).IsEmpty) + path += extension; + ZipFile.CreateFromDirectory(directory.FullName, path, CompressionLevel.Optimal, false); directory.Delete(true); - return fileName; + return path; } private async Task CreateCollectionInfo(DirectoryInfo directory, ObjectIndex index, ActorIdentifier actor, string note, DateTime time, @@ -220,7 +224,8 @@ public class PcpService : IApiService, IDisposable if (note.Length > 0) cancel.ThrowIfCancellationRequested(); if (_config.PcpSettings.AllowIpc) - await _framework.Framework.RunOnFrameworkThread(() => _communicator.PcpCreation.Invoke(new PcpCreation.Arguments(jObj, index.Index, directory.FullName))); + await _framework.Framework.RunOnFrameworkThread(() + => _communicator.PcpCreation.Invoke(new PcpCreation.Arguments(jObj, index.Index, directory.FullName))); var filePath = Path.Combine(directory.FullName, "character.json"); await using var file = File.Open(filePath, File.Exists(filePath) ? FileMode.Truncate : FileMode.CreateNew); await using var stream = new StreamWriter(file); @@ -233,17 +238,22 @@ public class PcpService : IApiService, IDisposable { var directory = _modExport.ExportDirectory; directory.Create(); - var actorName = actor.ToName(); - var authorName = _actors.GetCurrentPlayer().ToName(); - var suffix = note.Length > 0 - ? note - : time.ToString("yyyy-MM-ddTHH\\:mm", CultureInfo.InvariantCulture); - var modName = $"{actorName} - {suffix}"; + var actorName = actor.ToName(); + var modName = ModName(actorName, note, time); + var authorName = _actors.GetCurrentPlayer().ToName(); var description = $"On-Screen Data for {actorName} as snapshotted on {time}."; return _modCreator.CreateEmptyMod(directory, modName, description, authorName, "PCP") ?? throw new Exception($"Unable to create mod {modName} in {directory.FullName}."); } + public static string ModName(string actorName, string note, DateTime time) + { + var suffix = note.Length > 0 + ? note + : time.ToString("yyyy-MM-ddTHH_mm", CultureInfo.InvariantCulture); + return $"{actorName} - {suffix}"; + } + private async Task CreateDefaultMod(DirectoryInfo modDirectory, MetaDictionary meta, ResourceTree tree, CancellationToken cancel = default) { diff --git a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs index 636688a3..0636c98a 100644 --- a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs +++ b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs @@ -75,9 +75,9 @@ public class ItemSwapTab : IDisposable, ITab, IUiService if (mod == _mod && settings == _modSettings) return; - var oldDefaultName = $"{_mod?.Name.Text ?? "Unknown"} (Swapped)"; + var oldDefaultName = $"{_mod?.Name ?? "Unknown"} (Swapped)"; if (_newModName.Length == 0 || oldDefaultName == _newModName) - _newModName = $"{mod.Name.Text} (Swapped)"; + _newModName = $"{mod.Name} (Swapped)"; _mod = mod; _modSettings = settings; @@ -163,7 +163,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService : null; var ret = base.DrawSelectable(globalIdx, selected); if (inCollection.Count > 0) - ImUtf8.HoverTooltip(string.Join('\n', inCollection.Select(m => m.Name.Text))); + ImUtf8.HoverTooltip(string.Join('\n', inCollection.Select(m => m.Name))); return ret; } @@ -305,7 +305,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService private string OriginalAuthor() { - if (_mod!.Author.IsEmpty || _mod!.Author.Text is "TexTools User" or DefaultTexToolsData.Author) + if (_mod!.Author.Length is 0 || _mod!.Author is "TexTools User" or DefaultTexToolsData.Author) return "."; return $" by {_mod!.Author}."; @@ -313,11 +313,11 @@ public class ItemSwapTab : IDisposable, ITab, IUiService private string CreateAuthor() { - if (_mod!.Author.IsEmpty) + if (_mod!.Author.Length is 0) return _config.DefaultModAuthor; - if (_mod!.Author.Text == _config.DefaultModAuthor) + if (_mod!.Author == _config.DefaultModAuthor) return _config.DefaultModAuthor; - if (_mod!.Author.Text is "TexTools User" or DefaultTexToolsData.Author) + if (_mod!.Author is "TexTools User" or DefaultTexToolsData.Author) return _config.DefaultModAuthor; if (_config.DefaultModAuthor is DefaultTexToolsData.Author) return _mod!.Author; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs index 99669131..397c59b3 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Bindings.ImGui; +using Luna; using OtterGui; -using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Text.Widget.Editors; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs index 21d167aa..fc1b9ef2 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs @@ -8,7 +8,6 @@ using Penumbra.GameData.Data; using Penumbra.GameData.Enums; using Penumbra.GameData.Files; using Penumbra.UI.Classes; -using Notification = OtterGui.Classes.Notification; namespace Penumbra.UI.AdvancedWindow; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs index ee22655e..b538b2c9 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Bindings.ImGui; +using ImSharp; using OtterGui; -using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using Penumbra.Mods.Editor; @@ -15,7 +15,7 @@ public partial class ModEditWindow { private readonly HashSet _selectedFiles = new(256); private readonly HashSet _cutPaths = []; - private LowerString _fileFilter = LowerString.Empty; + private string _fileFilter = string.Empty; private bool _showGamePaths = true; private string _gamePathEdit = string.Empty; private int _fileIdx = -1; @@ -23,12 +23,12 @@ public partial class ModEditWindow private int _folderSkip; private bool _overviewMode; - private LowerString _fileOverviewFilter1 = LowerString.Empty; - private LowerString _fileOverviewFilter2 = LowerString.Empty; - private LowerString _fileOverviewFilter3 = LowerString.Empty; + private string _fileOverviewFilter1 = string.Empty; + private string _fileOverviewFilter2 = string.Empty; + private string _fileOverviewFilter3 = string.Empty; private bool CheckFilter(FileRegistry registry) - => _fileFilter.IsEmpty || registry.File.FullName.Contains(_fileFilter.Lower, StringComparison.OrdinalIgnoreCase); + => _fileFilter.Length is 0 || registry.File.FullName.Contains(_fileFilter, StringComparison.OrdinalIgnoreCase); private bool CheckFilter((int, FileRegistry) p) => CheckFilter(p.Item2); @@ -105,9 +105,9 @@ public partial class ModEditWindow } bool Filter((string, string, string, uint) data) - => _fileOverviewFilter1.IsContained(data.Item1) - && _fileOverviewFilter2.IsContained(data.Item2) - && _fileOverviewFilter3.IsContained(data.Item3); + => data.Item1.Contains(_fileOverviewFilter1, StringComparison.OrdinalIgnoreCase) + && data.Item2.Contains(_fileOverviewFilter2, StringComparison.OrdinalIgnoreCase) + && data.Item3.Contains(_fileOverviewFilter3, StringComparison.OrdinalIgnoreCase); var end = ImGuiClip.FilteredClippedDraw(files, skips, Filter, DrawLine); ImGuiClip.DrawEndDummy(end, height); @@ -252,7 +252,7 @@ public partial class ModEditWindow } } - private void PrintGamePath(int i, int j, FileRegistry registry, IModDataContainer subMod, Utf8GamePath gamePath) + private void PrintGamePath(int i, int j, FileRegistry registry, IModDataContainer _, Utf8GamePath gamePath) { using var id = ImRaii.PushId(j); ImGui.TableNextColumn(); @@ -290,16 +290,16 @@ public partial class ModEditWindow { ImGui.SameLine(); ImGui.SetCursorPosX(pos); - using (var font = ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); + using (ImRaii.PushFont(UiBuilder.IconFont)) + { + ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); } ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8); } } - private void PrintNewGamePath(int i, FileRegistry registry, IModDataContainer subMod) + private void PrintNewGamePath(int i, FileRegistry registry, IModDataContainer _) { var tmp = _fileIdx == i && _pathIdx == -1 ? _gamePathEdit : string.Empty; var pos = ImGui.GetCursorPosX() - ImGui.GetFrameHeight(); @@ -333,9 +333,9 @@ public partial class ModEditWindow { ImGui.SameLine(); ImGui.SetCursorPosX(pos); - using (var font = ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); + using (ImRaii.PushFont(UiBuilder.IconFont)) + { + ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); } ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8); @@ -404,7 +404,7 @@ public partial class ModEditWindow private void DrawFileManagementNormal() { ImGui.SetNextItemWidth(250 * UiHelpers.Scale); - LowerString.InputWithHint("##filter", "Filter paths...", ref _fileFilter, Utf8GamePath.MaxGamePathLength); + Im.Input.Text("##filter"u8, ref _fileFilter, "Filter paths..."u8); ImGui.SameLine(); ImGui.Checkbox("Show Game Paths", ref _showGamePaths); ImGui.SameLine(); @@ -437,12 +437,12 @@ public partial class ModEditWindow var width = ImGui.GetContentRegionAvail().X / 8; ImGui.SetNextItemWidth(width * 3); - LowerString.InputWithHint("##fileFilter", "Filter file...", ref _fileOverviewFilter1, Utf8GamePath.MaxGamePathLength); + Im.Input.Text("##fileFilter"u8, ref _fileOverviewFilter1, "Filter file..."u8); ImGui.SameLine(); ImGui.SetNextItemWidth(width * 3); - LowerString.InputWithHint("##pathFilter", "Filter path...", ref _fileOverviewFilter2, Utf8GamePath.MaxGamePathLength); + Im.Input.Text("##pathFilter"u8, ref _fileOverviewFilter2, "Filter path..."u8); ImGui.SameLine(); ImGui.SetNextItemWidth(width * 2); - LowerString.InputWithHint("##optionFilter", "Filter option...", ref _fileOverviewFilter3, Utf8GamePath.MaxGamePathLength); + Im.Input.Text("##optionFilter"u8, ref _fileOverviewFilter3, "Filter option..."u8); } } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs index 042b2760..7189181d 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs @@ -1,7 +1,7 @@ using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Lumina.Data.Parsing; -using Luna.Widgets; +using Luna; using OtterGui; using OtterGui.Custom; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShpkTab.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShpkTab.cs index 5cc6eb67..e81442bf 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShpkTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShpkTab.cs @@ -1,6 +1,6 @@ using Dalamud.Utility; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Classes; using Penumbra.GameData.Files; using Penumbra.GameData.Files.ShaderStructs; using Penumbra.GameData.Interop; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index 0ee7dae6..fea33e3e 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -26,7 +26,6 @@ using Penumbra.String.Classes; using Penumbra.UI.AdvancedWindow.Materials; using Penumbra.UI.AdvancedWindow.Meta; using Penumbra.UI.Classes; -using Penumbra.Util; using MdlMaterialEditor = Penumbra.Mods.Editor.MdlMaterialEditor; namespace Penumbra.UI.AdvancedWindow; @@ -35,7 +34,6 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService { private const string WindowBaseLabel = "###SubModEdit"; - private readonly PerformanceTracker _performance; private readonly ModEditor _editor; private readonly Configuration _config; private readonly ItemSwapTab _itemSwapTab; @@ -129,8 +127,6 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService if (IsLoading) return; - using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow); - var sb = new StringBuilder(256); var redirections = 0; @@ -195,8 +191,6 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService public override void Draw() { - using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow); - if (!_config.Ephemeral.AdvancedEditingOpen) { _config.Ephemeral.AdvancedEditingOpen = true; @@ -620,7 +614,7 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService return ret; } - public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, IDataManager gameData, + public ModEditWindow(FileDialogService fileDialog, ItemSwapTab itemSwapTab, IDataManager gameData, Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager, ActiveCollections activeCollections, ModMergeTab modMergeTab, CommunicatorService communicator, TextureManager textures, ModelManager models, IDragDropManager dragDropManager, @@ -629,7 +623,6 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService MtrlTabFactory mtrlTabFactory, ModSelection selection) : base(WindowBaseLabel) { - _performance = performance; _itemSwapTab = itemSwapTab; _gameData = gameData; _config = config; diff --git a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs index 672cfcc8..332e9a10 100644 --- a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs @@ -58,11 +58,11 @@ public class ModMergeTab(ModMerger modMerger) : Luna.IUiService if (size - textSize < minComboSize) { ImUtf8.Text("selected mod"u8, ColorId.FolderLine.Value()); - ImUtf8.HoverTooltip(modMerger.MergeFromMod!.Name.Text); + ImUtf8.HoverTooltip(modMerger.MergeFromMod!.Name); } else { - ImUtf8.Text(modMerger.MergeFromMod!.Name.Text, ColorId.FolderLine.Value()); + ImUtf8.Text(modMerger.MergeFromMod!.Name, ColorId.FolderLine.Value()); } ImGui.SameLine(0, 0); @@ -121,7 +121,7 @@ public class ModMergeTab(ModMerger modMerger) : Luna.IUiService private void DrawCombo(float width) { - _modCombo.Draw("##ModSelection", _modCombo.CurrentSelection?.Name.Text ?? "Select the target Mod...", string.Empty, width, + _modCombo.Draw("##ModSelection", _modCombo.CurrentSelection?.Name ?? "Select the target Mod...", string.Empty, width, ImGui.GetTextLineHeight()); modMerger.MergeToMod = _modCombo.CurrentSelection; } diff --git a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs index 9f6a9e83..762bb5b6 100644 --- a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs +++ b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs @@ -103,9 +103,8 @@ public class ResourceTreeViewer( if (ImUtf8.ButtonEx("Export Character Pack"u8, "Note that this recomputes the current data of the actor if it still exists, and does not use the cached data."u8)) { - pcpService.CreatePcp((ObjectIndex)tree.GameObjectIndex, _note).ContinueWith(t => + pcpService.CreatePcp((ObjectIndex)tree.GameObjectIndex, null, _note).ContinueWith(t => { - var (success, text) = t.Result; if (success) @@ -116,6 +115,27 @@ public class ResourceTreeViewer( _note = string.Empty; } + ImUtf8.SameLineInner(); + if (ImUtf8.ButtonEx("Export To..."u8, + "Note that this recomputes the current data of the actor if it still exists, and does not use the cached data."u8)) + fileDialog.OpenSavePicker("Export PCP...", $"Penumbra Mod Packs{{.pcp,.pmp}},{config.PcpSettings.PcpExtension},Any File{{.*}}", PcpService.ModName(tree.Name, _note, DateTime.Now), + config.PcpSettings.PcpExtension, + (selected, path) => + { + if (!selected) + return; + + pcpService.CreatePcp((ObjectIndex)tree.GameObjectIndex, path, _note).ContinueWith(t => + { + var (success, text) = t.Result; + + if (success) + Penumbra.Messager.NotificationMessage($"Created {text}.", NotificationType.Success, false); + else + Penumbra.Messager.NotificationMessage(text, NotificationType.Error, false); + }); + _note = string.Empty; + }, config.ExportDirectory, false); ImUtf8.SameLineInner(); ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); ImUtf8.InputText("##note"u8, ref _note, "Export note..."u8); @@ -434,7 +454,7 @@ public class ResourceTreeViewer( _writableCache.Add(resourceNode.FullPath, writable); } - + if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Export this file."u8, buttonSize, resourceNode.FullPath.FullName.Length is 0 || writable is null)) { @@ -442,7 +462,8 @@ public class ResourceTreeViewer( var ext = resourceNode.PossibleGamePaths.Length == 1 ? Path.GetExtension(resourceNode.GamePath.ToString()) : Path.GetExtension(fullPathStr); - fileDialog.OpenSavePicker($"Export {Path.GetFileName(fullPathStr)} to...", ext, Path.GetFileNameWithoutExtension(fullPathStr), ext, + fileDialog.OpenSavePicker($"Export {Path.GetFileName(fullPathStr)} to...", ext, Path.GetFileNameWithoutExtension(fullPathStr), + ext, (success, name) => { if (!success) @@ -458,7 +479,7 @@ public class ResourceTreeViewer( } }, null, false); } - + drawActions(resourceNode, writable, new Vector2(frameHeight)); } } @@ -524,7 +545,7 @@ public class ResourceTreeViewer( Visible = 1, DescendentsOnly = 2, } - + private record RawFileWritable(string Path) : IWritable { public bool Valid diff --git a/Penumbra/UI/ChangedItemDrawer.cs b/Penumbra/UI/ChangedItemDrawer.cs index 97aec626..c006c909 100644 --- a/Penumbra/UI/ChangedItemDrawer.cs +++ b/Penumbra/UI/ChangedItemDrawer.cs @@ -6,7 +6,6 @@ using Dalamud.Utility; using Dalamud.Bindings.ImGui; using Lumina.Data.Files; using OtterGui; -using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using Penumbra.Api.Enums; @@ -87,10 +86,10 @@ public class ChangedItemDrawer : IDisposable, Luna.IUiService } /// Check if a changed item should be drawn based on its category. - public bool FilterChangedItem(string name, IIdentifiedObjectData data, LowerString filter) + public bool FilterChangedItem(string name, IIdentifiedObjectData data, string filter) => (_config.Ephemeral.ChangedItemFilter == ChangedItemFlagExtensions.AllFlags || _config.Ephemeral.ChangedItemFilter.HasFlag(data.GetIcon().ToFlag())) - && (filter.IsEmpty || !data.IsFilteredOut(name, filter.Text)); + && (filter.Length is 0 || !data.IsFilteredOut(name, filter)); /// Draw the icon corresponding to the category of a changed item. public void DrawCategoryIcon(IIdentifiedObjectData data, float height) diff --git a/Penumbra/UI/Changelog.cs b/Penumbra/UI/Changelog.cs index 0bb4ca97..97d75906 100644 --- a/Penumbra/UI/Changelog.cs +++ b/Penumbra/UI/Changelog.cs @@ -1,8 +1,8 @@ -using OtterGui.Widgets; +using Luna; namespace Penumbra.UI; -public class PenumbraChangelog : Luna.IUiService +public class PenumbraChangelog : IUiService { public const int LastChangelogVersion = 0; @@ -63,1081 +63,1102 @@ public class PenumbraChangelog : Luna.IUiService Add1_4_0_0(Changelog); Add1_5_0_0(Changelog); Add1_5_1_0(Changelog); - } - + } + #region Changelogs private static void Add1_5_1_0(Changelog log) - => log.NextVersion("Version 1.5.1.0") - .RegisterHighlight("Added the option to export a characters current data as a .pcp modpack in the On-Screen tab.") - .RegisterEntry("Other plugins can attach to this functionality and package and interpret their own data.", 1) - .RegisterEntry("When a .pcp modpack is installed, it can create and assign collections for the corresponding character it was created for.", 1) - .RegisterEntry("This basically provides an easier way to manually synchronize other players, but does not contain any automation.", 1) - .RegisterEntry("The settings provide some fine control about what happens when a PCP is installed, as well as buttons to cleanup any PCP-created data.", 1) - .RegisterEntry("Added a warning message when the game's integrity is corrupted to the On-Screen tab.") - .RegisterEntry("Added .kdb files to the On-Screen tab and associated functionality (thanks Ny!).") - .RegisterEntry("Updated the creation of temporary collections to require a passed identity.") - .RegisterEntry("Added the option to change the skin material suffix in models using the stockings shader by adding specific attributes (thanks Ny!).") - .RegisterEntry("Added predefined tag utility to the multi-mod selection.") - .RegisterEntry("Fixed an issue with the automatic collection selection on character login when no mods are assigned.") + => log.NextVersion("Version 1.5.1.0"u8) + .RegisterHighlight("Added the option to export a characters current data as a .pcp modpack in the On-Screen tab."u8) + .RegisterEntry("Other plugins can attach to this functionality and package and interpret their own data."u8, 1) + .RegisterEntry( + "When a .pcp modpack is installed, it can create and assign collections for the corresponding character it was created for."u8, + 1) + .RegisterEntry( + "This basically provides an easier way to manually synchronize other players, but does not contain any automation."u8, 1) + .RegisterEntry( + "The settings provide some fine control about what happens when a PCP is installed, as well as buttons to cleanup any PCP-created data."u8, + 1) + .RegisterEntry("Added a warning message when the game's integrity is corrupted to the On-Screen tab."u8) + .RegisterEntry("Added .kdb files to the On-Screen tab and associated functionality (thanks Ny!)."u8) + .RegisterEntry("Updated the creation of temporary collections to require a passed identity."u8) + .RegisterEntry( + "Added the option to change the skin material suffix in models using the stockings shader by adding specific attributes (thanks Ny!)."u8) + .RegisterEntry("Added predefined tag utility to the multi-mod selection."u8) + .RegisterEntry("Fixed an issue with the automatic collection selection on character login when no mods are assigned."u8) .RegisterImportant( - "Fixed issue with new deformer data that makes modded deformers not containing this data work implicitly. Updates are still recommended (1.5.0.5).") - .RegisterEntry("Fixed various issues after patch (1.5.0.1 - 1.5.0.4)."); + "Fixed issue with new deformer data that makes modded deformers not containing this data work implicitly. Updates are still recommended (1.5.0.5)."u8) + .RegisterEntry("Fixed various issues after patch (1.5.0.1 - 1.5.0.4)."u8); private static void Add1_5_0_0(Changelog log) - => log.NextVersion("Version 1.5.0.0") - .RegisterImportant("Updated for game version 7.30 and Dalamud API13, which uses a new GUI backend. Some things may not work as expected. Please let me know any issues you encounter.") - .RegisterEntry("Added support for exporting models using two vertex color schemes (thanks zeroeightysix!).") - .RegisterEntry("Possibly improved the color accuracy of the basecolor texture created when exporting models (thanks zeroeightysix!).") - .RegisterEntry("Disabled enabling transparency for materials that use the characterstockings shader due to crashes (thanks zeroeightysix!).") - .RegisterEntry("Fixed some issues with model i/o and invalid tangents (thanks PassiveModding!)") - .RegisterEntry("Changed the behavior for default directory names when using the mod normalizer with combining groups.") - .RegisterEntry("Added jumping to specific mods to the HTTP API.") - .RegisterEntry("Fixed an issue with character sound modding (1.4.0.6).") - .RegisterHighlight("Added support for IMC-toggle attributes to accessories beyond the first toggle (1.4.0.5).") - .RegisterEntry("Fixed up some slot-specific attributes and shapes in models when swapping items between slots (1.4.0.5).") - .RegisterEntry("Added handling for human skin materials to the OnScreen tab and similar functionality (thanks Ny!) (1.4.0.5).") - .RegisterEntry("The OS thread ID a resource was loaded from was added to the resource logger (1.4.0.5).") - .RegisterEntry("A button linking to my (Ottermandias') Ko-Fi and Patreon was added in the settings tab. Feel free, but not pressured, to use it! :D ") - .RegisterHighlight("Mod setting combos now support mouse-wheel scrolling with Control and have filters (1.4.0.4).") - .RegisterEntry("Using the middle mouse button to toggle designs now works correctly with temporary settings (1.4.0.4).") - .RegisterEntry("Updated some BNPC associations (1.4.0.3).") - .RegisterEntry("Fixed further issues with shapes and attributes (1.4.0.4).") - .RegisterEntry("Penumbra now handles textures with MipMap offsets broken by TexTools on import and removes unnecessary MipMaps (1.4.0.3).") - .RegisterEntry("Updated the Mod Merger for the new group types (1.4.0.3).") - .RegisterEntry("Added querying Penumbra for supported features via IPC (1.4.0.3).") - .RegisterEntry("Shape names can now be edited in Penumbras model editor (1.4.0.2).") - .RegisterEntry("Attributes and Shapes can be fully toggled (1.4.0.2).") - .RegisterEntry("Fixed several issues with attributes and shapes (1.4.0.1)."); + => log.NextVersion("Version 1.5.0.0"u8) + .RegisterImportant( + "Updated for game version 7.30 and Dalamud API13, which uses a new GUI backend. Some things may not work as expected. Please let me know any issues you encounter."u8) + .RegisterEntry("Added support for exporting models using two vertex color schemes (thanks zeroeightysix!)."u8) + .RegisterEntry( + "Possibly improved the color accuracy of the basecolor texture created when exporting models (thanks zeroeightysix!)."u8) + .RegisterEntry( + "Disabled enabling transparency for materials that use the characterstockings shader due to crashes (thanks zeroeightysix!)."u8) + .RegisterEntry("Fixed some issues with model i/o and invalid tangents (thanks PassiveModding!)"u8) + .RegisterEntry("Changed the behavior for default directory names when using the mod normalizer with combining groups."u8) + .RegisterEntry("Added jumping to specific mods to the HTTP API."u8) + .RegisterEntry("Fixed an issue with character sound modding (1.4.0.6)."u8) + .RegisterHighlight("Added support for IMC-toggle attributes to accessories beyond the first toggle (1.4.0.5)."u8) + .RegisterEntry("Fixed up some slot-specific attributes and shapes in models when swapping items between slots (1.4.0.5)."u8) + .RegisterEntry("Added handling for human skin materials to the OnScreen tab and similar functionality (thanks Ny!) (1.4.0.5)."u8) + .RegisterEntry("The OS thread ID a resource was loaded from was added to the resource logger (1.4.0.5)."u8) + .RegisterEntry( + "A button linking to my (Ottermandias') Ko-Fi and Patreon was added in the settings tab. Feel free, but not pressured, to use it! :D "u8) + .RegisterHighlight("Mod setting combos now support mouse-wheel scrolling with Control and have filters (1.4.0.4)."u8) + .RegisterEntry("Using the middle mouse button to toggle designs now works correctly with temporary settings (1.4.0.4)."u8) + .RegisterEntry("Updated some BNPC associations (1.4.0.3)."u8) + .RegisterEntry("Fixed further issues with shapes and attributes (1.4.0.4)."u8) + .RegisterEntry( + "Penumbra now handles textures with MipMap offsets broken by TexTools on import and removes unnecessary MipMaps (1.4.0.3)."u8) + .RegisterEntry("Updated the Mod Merger for the new group types (1.4.0.3)."u8) + .RegisterEntry("Added querying Penumbra for supported features via IPC (1.4.0.3)."u8) + .RegisterEntry("Shape names can now be edited in Penumbras model editor (1.4.0.2)."u8) + .RegisterEntry("Attributes and Shapes can be fully toggled (1.4.0.2)."u8) + .RegisterEntry("Fixed several issues with attributes and shapes (1.4.0.1)."u8); private static void Add1_4_0_0(Changelog log) - => log.NextVersion("Version 1.4.0.0") - .RegisterHighlight("Added two types of new Meta Changes, SHP and ATR (Thanks Karou!).") - .RegisterEntry("Those allow mod creators to toggle custom shape keys and attributes for models on and off, respectively.", 1) - .RegisterEntry("Custom shape keys need to have the format 'shpx_*' and custom attributes need 'atrx_*'.", 1) + => log.NextVersion("Version 1.4.0.0"u8) + .RegisterHighlight("Added two types of new Meta Changes, SHP and ATR (Thanks Karou!)."u8) + .RegisterEntry("Those allow mod creators to toggle custom shape keys and attributes for models on and off, respectively."u8, 1) + .RegisterEntry("Custom shape keys need to have the format 'shpx_*' and custom attributes need 'atrx_*'."u8, 1) .RegisterHighlight( - "Shapes of the following formats will automatically be toggled on if both relevant slots contain the same shape key:", 1) - .RegisterEntry("'shpx_wa_*', for the waist seam between the body and leg slot,", 2) - .RegisterEntry("'shpx_wr_*', for the wrist seams between the body and hands slot,", 2) - .RegisterEntry("'shpx_an_*', for the ankle seams between the leg and feet slot.", 2) + "Shapes of the following formats will automatically be toggled on if both relevant slots contain the same shape key:"u8, 1) + .RegisterEntry("'shpx_wa_*', for the waist seam between the body and leg slot,"u8, 2) + .RegisterEntry("'shpx_wr_*', for the wrist seams between the body and hands slot,"u8, 2) + .RegisterEntry("'shpx_an_*', for the ankle seams between the leg and feet slot."u8, 2) .RegisterEntry( - "Custom shape key and attributes can be turned off in the advanced settings section for the moment, but this is not recommended.", + "Custom shape key and attributes can be turned off in the advanced settings section for the moment, but this is not recommended."u8, 1) - .RegisterHighlight("The mod selector width is now draggable within certain restrictions that depend on the total window width.") - .RegisterEntry("The current behavior may not be final, let me know if you have any comments.", 1) - .RegisterEntry("Improved the naming of NPCs for identifiers by using Haselnussbombers new naming functionality (Thanks Hasel!).") - .RegisterEntry("Added global EQP entries to always hide Au Ra horns, Viera ears, or Miqo'te ears, respectively.") - .RegisterEntry("This will leave holes in the heads of the respective race if not modded in some way.", 1) - .RegisterEntry("Added a filter for mods that have temporary settings in the mod selector panel (Thanks Caraxi).") - .RegisterEntry("Made the checkbox for toggling Temporary Settings Mode in the mod tab more visible.") - .RegisterEntry("Improved the option select combo in advanced editing.") - .RegisterEntry("Fixed some issues with item identification for EST changes.") - .RegisterEntry("Fixed the sizing of the mod panel being off by 1 pixel sometimes.") - .RegisterEntry("Fixed an issue with redrawing while in GPose when other plugins broke some assumptions about the game state.") - .RegisterEntry("Fixed a clipping issue within the Meta Manipulations tab in advanced editing.") - .RegisterEntry("Fixed an issue with empty and temporary settings.") + .RegisterHighlight("The mod selector width is now draggable within certain restrictions that depend on the total window width."u8) + .RegisterEntry("The current behavior may not be final, let me know if you have any comments."u8, 1) + .RegisterEntry("Improved the naming of NPCs for identifiers by using Haselnussbombers new naming functionality (Thanks Hasel!)."u8) + .RegisterEntry("Added global EQP entries to always hide Au Ra horns, Viera ears, or Miqo'te ears, respectively."u8) + .RegisterEntry("This will leave holes in the heads of the respective race if not modded in some way."u8, 1) + .RegisterEntry("Added a filter for mods that have temporary settings in the mod selector panel (Thanks Caraxi)."u8) + .RegisterEntry("Made the checkbox for toggling Temporary Settings Mode in the mod tab more visible."u8) + .RegisterEntry("Improved the option select combo in advanced editing."u8) + .RegisterEntry("Fixed some issues with item identification for EST changes."u8) + .RegisterEntry("Fixed the sizing of the mod panel being off by 1 pixel sometimes."u8) + .RegisterEntry("Fixed an issue with redrawing while in GPose when other plugins broke some assumptions about the game state."u8) + .RegisterEntry("Fixed a clipping issue within the Meta Manipulations tab in advanced editing."u8) + .RegisterEntry("Fixed an issue with empty and temporary settings."u8) .RegisterHighlight( - "In the Item Swap tab, items changed by this mod are now sorted and highlighted before items changed in the current collection before other items for the source, and inversely for the target. (1.3.6.8)") + "In the Item Swap tab, items changed by this mod are now sorted and highlighted before items changed in the current collection before other items for the source, and inversely for the target. (1.3.6.8)"u8) .RegisterHighlight( - "Default-valued meta edits should now be kept on import and only removed when the option to keep them is not set AND no other options in the mod edit the same entry. (1.3.6.8)") - .RegisterEntry("Added a right-click context menu on file redirections to copy the full file path. (1.3.6.8)") + "Default-valued meta edits should now be kept on import and only removed when the option to keep them is not set AND no other options in the mod edit the same entry. (1.3.6.8)"u8) + .RegisterEntry("Added a right-click context menu on file redirections to copy the full file path. (1.3.6.8)"u8) .RegisterEntry( - "Added a right-click context menu on the mod export button to open the backup directory in your file explorer. (1.3.6.8)") - .RegisterEntry("Fixed some issues when redrawing characters from other plugins. (1.3.6.8)") + "Added a right-click context menu on the mod export button to open the backup directory in your file explorer. (1.3.6.8)"u8) + .RegisterEntry("Fixed some issues when redrawing characters from other plugins. (1.3.6.8)"u8) .RegisterEntry( - "Added a modifier key separate from the delete modifier key that is used for less important key-checks, specifically toggling incognito mode. (1.3.6.7)") - .RegisterEntry("Fixed some issues with the Material Editor (Thanks Ny). (1.3.6.6)"); + "Added a modifier key separate from the delete modifier key that is used for less important key-checks, specifically toggling incognito mode. (1.3.6.7)"u8) + .RegisterEntry("Fixed some issues with the Material Editor (Thanks Ny). (1.3.6.6)"u8); private static void Add1_3_6_4(Changelog log) - => log.NextVersion("Version 1.3.6.4") - .RegisterEntry("The material editor should be functional again."); + => log.NextVersion("Version 1.3.6.4"u8) + .RegisterEntry("The material editor should be functional again."u8); private static void Add1_3_6_0(Changelog log) - => log.NextVersion("Version 1.3.6.0") - .RegisterImportant("Updated Penumbra for update 7.20 and Dalamud API 12.") + => log.NextVersion("Version 1.3.6.0"u8) + .RegisterImportant("Updated Penumbra for update 7.20 and Dalamud API 12."u8) .RegisterEntry( - "This is not thoroughly tested, but I decided to push to stable instead of testing because otherwise a lot of people would just go to testing just for early access again despite having no business doing so.", + "This is not thoroughly tested, but I decided to push to stable instead of testing because otherwise a lot of people would just go to testing just for early access again despite having no business doing so."u8, 1) .RegisterEntry( - "I also do not use most of the functionality of Penumbra myself, so I am unable to even encounter most issues myself.", 1) - .RegisterEntry("If you encounter any issues, please report them quickly on the discord.", 1) + "I also do not use most of the functionality of Penumbra myself, so I am unable to even encounter most issues myself."u8, 1) + .RegisterEntry("If you encounter any issues, please report them quickly on the discord."u8, 1) .RegisterHighlight( - "The texture editor now has encoding support for Block Compression 1, 4 and 5 and tooltips explaining when to use which format.") - .RegisterEntry("It also is able to use GPU compression and thus has become much faster for BC7 in particular. (Thanks Ny!)", 1) + "The texture editor now has encoding support for Block Compression 1, 4 and 5 and tooltips explaining when to use which format."u8) + .RegisterEntry("It also is able to use GPU compression and thus has become much faster for BC7 in particular. (Thanks Ny!)"u8, 1) .RegisterEntry( - "Added the option to import .atch files found in the particular mod via right-click context menu on the import drag & drop button.") - .RegisterEntry("Added a chat command to clear temporary settings done manually in Penumbra.") + "Added the option to import .atch files found in the particular mod via right-click context menu on the import drag & drop button."u8) + .RegisterEntry("Added a chat command to clear temporary settings done manually in Penumbra."u8) .RegisterEntry( - "The changed item star to select the preferred changed item is a bit more noticeable by default, and its color can be configured.") - .RegisterEntry("Some minor fixes for computing changed items. (Thanks Anna!)") - .RegisterEntry("The EQP entry previously named Unknown 4 was renamed to 'Hide Glove Cuffs'.") - .RegisterEntry("Fixed the changed item identification for EST changes.") - .RegisterEntry("Fixed clipping issues in the changed items panel when no grouping was active."); + "The changed item star to select the preferred changed item is a bit more noticeable by default, and its color can be configured."u8) + .RegisterEntry("Some minor fixes for computing changed items. (Thanks Anna!)"u8) + .RegisterEntry("The EQP entry previously named Unknown 4 was renamed to 'Hide Glove Cuffs'."u8) + .RegisterEntry("Fixed the changed item identification for EST changes."u8) + .RegisterEntry("Fixed clipping issues in the changed items panel when no grouping was active."u8); private static void Add1_3_5_0(Changelog log) - => log.NextVersion("Version 1.3.5.0") + => log.NextVersion("Version 1.3.5.0"u8) .RegisterImportant( - "Redirections of unsupported file types like .atch will now produce warnings when they are enabled. Please update mods still containing them or request updates from their creators.") - .RegisterEntry("You can now import .atch in the Meta section of advanced editing to add their non-default changes to the mod.") - .RegisterHighlight("Added an option in settings and in the collection bar in the mod tab to always use temporary settings.") + "Redirections of unsupported file types like .atch will now produce warnings when they are enabled. Please update mods still containing them or request updates from their creators."u8) + .RegisterEntry("You can now import .atch in the Meta section of advanced editing to add their non-default changes to the mod."u8) + .RegisterHighlight("Added an option in settings and in the collection bar in the mod tab to always use temporary settings."u8) .RegisterEntry( - "While this option is enabled, all changes you make in the current collection will be applied as temporary changes, and you have to use Turn Permanent to make them permanent.", + "While this option is enabled, all changes you make in the current collection will be applied as temporary changes, and you have to use Turn Permanent to make them permanent."u8, 1) .RegisterEntry( - "This should be useful for trying out new mods without needing to reset their settings later, or for creating mod associations in Glamourer from them.", + "This should be useful for trying out new mods without needing to reset their settings later, or for creating mod associations in Glamourer from them."u8, 1) .RegisterEntry( - "Added a context menu entry on the mod selector blank-space context menu to clear all temporary settings made manually.") + "Added a context menu entry on the mod selector blank-space context menu to clear all temporary settings made manually."u8) .RegisterHighlight( - "Resource Trees now consider some additional files like decals, and improved the quick-import behaviour for some files that should not generally be modded.") - .RegisterHighlight("The Changed Item display for single mods has been heavily improved.") - .RegisterEntry("Any changed item will now show how many individual edits are affecting it in the mod in its tooltip.", 1) - .RegisterEntry("Equipment pieces are now grouped by their model id, reducing clutter.", 1) + "Resource Trees now consider some additional files like decals, and improved the quick-import behaviour for some files that should not generally be modded."u8) + .RegisterHighlight("The Changed Item display for single mods has been heavily improved."u8) + .RegisterEntry("Any changed item will now show how many individual edits are affecting it in the mod in its tooltip."u8, 1) + .RegisterEntry("Equipment pieces are now grouped by their model id, reducing clutter."u8, 1) .RegisterEntry( - "The primary equipment piece displayed is the one with the most changes affecting it, but can be configured to a specific item by the mod creator and locally.", + "The primary equipment piece displayed is the one with the most changes affecting it, but can be configured to a specific item by the mod creator and locally."u8, 1) .RegisterEntry( - "Preferred changed items stored in the mod will be shared when exporting the mod, and used as the default for local preferences, which will not be shared.", + "Preferred changed items stored in the mod will be shared when exporting the mod, and used as the default for local preferences, which will not be shared."u8, 2) .RegisterEntry( - "You can configure whether groups are automatically collapsed or expanded, or remove grouping entirely in the settings.", 1) - .RegisterHighlight("Fixed support for model import/export with more than one UV.") - .RegisterEntry("Added some IPC relating to changed items.") - .RegisterEntry("Skeleton and Physics changes should now be identified in Changed Items.") - .RegisterEntry("Item Swaps will now also correctly swap EQP entries of multi-slot pieces.") - .RegisterEntry("Meta edit transmission through IPC should be a lot more efficient than before.") - .RegisterEntry("Fixed an issue with incognito names in some cutscenes.") - .RegisterEntry("Newly extracted mod folders will now try to rename themselves three times before being considered a failure."); + "You can configure whether groups are automatically collapsed or expanded, or remove grouping entirely in the settings."u8, 1) + .RegisterHighlight("Fixed support for model import/export with more than one UV."u8) + .RegisterEntry("Added some IPC relating to changed items."u8) + .RegisterEntry("Skeleton and Physics changes should now be identified in Changed Items."u8) + .RegisterEntry("Item Swaps will now also correctly swap EQP entries of multi-slot pieces."u8) + .RegisterEntry("Meta edit transmission through IPC should be a lot more efficient than before."u8) + .RegisterEntry("Fixed an issue with incognito names in some cutscenes."u8) + .RegisterEntry("Newly extracted mod folders will now try to rename themselves three times before being considered a failure."u8); private static void Add1_3_4_0(Changelog log) - => log.NextVersion("Version 1.3.4.0") + => log.NextVersion("Version 1.3.4.0"u8) .RegisterHighlight( - "Added HDR functionality to diffuse buffers. This allows more accurate representation of non-standard color values for e.g. skin or hair colors when used with advanced customizations in Glamourer.") + "Added HDR functionality to diffuse buffers. This allows more accurate representation of non-standard color values for e.g. skin or hair colors when used with advanced customizations in Glamourer."u8) .RegisterEntry( - "This option requires Wait For Plugins On Load to be enabled in Dalamud and to be enabled on start to work. It is on by default but can be turned off.", + "This option requires Wait For Plugins On Load to be enabled in Dalamud and to be enabled on start to work. It is on by default but can be turned off."u8, 1) - .RegisterHighlight("Added a new option group type: Combining Groups.") + .RegisterHighlight("Added a new option group type: Combining Groups."u8) .RegisterEntry( - "A combining group behaves similarly to a multi group for the user, but instead of enabling the different options separately, it results in exactly one option per choice of settings.", + "A combining group behaves similarly to a multi group for the user, but instead of enabling the different options separately, it results in exactly one option per choice of settings."u8, 1) .RegisterEntry( - "Example: The user sees 2 checkboxes [+25%, +50%], but the 4 different selection states result in +0%, +25%, +50% or +75% if both are toggled on. Every choice of settings can be configured separately by the mod creator.", + "Example: The user sees 2 checkboxes [+25%, +50%], but the 4 different selection states result in +0%, +25%, +50% or +75% if both are toggled on. Every choice of settings can be configured separately by the mod creator."u8, 1) .RegisterEntry( - "Added new functionality to better track copies of the player character in cutscenes if they get forced to specific clothing, like in the Margrat cutscene. Might improve tracking in wedding ceremonies, too, let me know.") - .RegisterEntry("Added a display of the number of selected files and folders to the multi mod selection.") + "Added new functionality to better track copies of the player character in cutscenes if they get forced to specific clothing, like in the Margrat cutscene. Might improve tracking in wedding ceremonies, too, let me know."u8) + .RegisterEntry("Added a display of the number of selected files and folders to the multi mod selection."u8) .RegisterEntry( - "Added cleaning functionality to remove outdated or unused files or backups from the config and mod folders via manual action.") - .RegisterEntry("Updated the Bone and Material limits in the Model Importer.") - .RegisterEntry("Improved handling of IMC and Material files loaded asynchronously.") - .RegisterEntry("Added IPC functionality to query temporary settings.") - .RegisterEntry("Improved some mod setting IPC functions.") - .RegisterEntry("Fixed some path detection issues in the OnScreen tab.") - .RegisterEntry("Fixed some issues with temporary mod settings.") - .RegisterEntry("Fixed issues with IPC calls before the game has finished loading.") - .RegisterEntry("Fixed using the wrong dye channel in the material editor previews.") - .RegisterEntry("Added some log warnings if outdated materials are loaded by the game.") - .RegisterEntry("Added Schemas for some of the json files generated and read by Penumbra to the solution."); + "Added cleaning functionality to remove outdated or unused files or backups from the config and mod folders via manual action."u8) + .RegisterEntry("Updated the Bone and Material limits in the Model Importer."u8) + .RegisterEntry("Improved handling of IMC and Material files loaded asynchronously."u8) + .RegisterEntry("Added IPC functionality to query temporary settings."u8) + .RegisterEntry("Improved some mod setting IPC functions."u8) + .RegisterEntry("Fixed some path detection issues in the OnScreen tab."u8) + .RegisterEntry("Fixed some issues with temporary mod settings."u8) + .RegisterEntry("Fixed issues with IPC calls before the game has finished loading."u8) + .RegisterEntry("Fixed using the wrong dye channel in the material editor previews."u8) + .RegisterEntry("Added some log warnings if outdated materials are loaded by the game."u8) + .RegisterEntry("Added Schemas for some of the json files generated and read by Penumbra to the solution."u8); private static void Add1_3_3_0(Changelog log) - => log.NextVersion("Version 1.3.3.0") - .RegisterHighlight("Added Temporary Settings to collections.") + => log.NextVersion("Version 1.3.3.0"u8) + .RegisterHighlight("Added Temporary Settings to collections."u8) .RegisterEntry( - "Settings can be manually turned temporary (and turned back) while editing mod settings via right-click context on the mod or buttons in the settings panel.", + "Settings can be manually turned temporary (and turned back) while editing mod settings via right-click context on the mod or buttons in the settings panel."u8, 1) .RegisterEntry( - "This can be used to test mods or changes without saving those changes permanently or having to reinstate the old settings afterwards.", + "This can be used to test mods or changes without saving those changes permanently or having to reinstate the old settings afterwards."u8, 1) .RegisterEntry( - "More importantly, this can be set via IPC by other plugins, allowing Glamourer to only set and reset temporary settings when applying Mod Associations.", + "More importantly, this can be set via IPC by other plugins, allowing Glamourer to only set and reset temporary settings when applying Mod Associations."u8, 1) .RegisterEntry( - "As an extreme example, it would be possible to only enable the consistent mods for your character in the collection, and let Glamourer handle all outfit mods itself via temporary settings only.", + "As an extreme example, it would be possible to only enable the consistent mods for your character in the collection, and let Glamourer handle all outfit mods itself via temporary settings only."u8, 1) .RegisterEntry( - "This required some pretty big changes that were in testing for a while now, but nobody talked about it much so it may still have some bugs or usability issues. Let me know!", + "This required some pretty big changes that were in testing for a while now, but nobody talked about it much so it may still have some bugs or usability issues. Let me know!"u8, 1) .RegisterHighlight( - "Added an option to automatically select the collection assigned to the current character on login events. This is off by default.") + "Added an option to automatically select the collection assigned to the current character on login events. This is off by default."u8) .RegisterEntry( - "Added partial copying of color tables in material editing via right-click context menu entries on the import buttons.") + "Added partial copying of color tables in material editing via right-click context menu entries on the import buttons."u8) .RegisterHighlight( - "Added handling for TMB files cached by the game that should resolve issues of leaky TMBs from animation and VFX mods.") + "Added handling for TMB files cached by the game that should resolve issues of leaky TMBs from animation and VFX mods."u8) .RegisterEntry( - "The enabled checkbox, Priority and Inheriting buttons now stick at the top of the Mod Settings panel even when scrolling down for specific settings.") - .RegisterEntry("When creating new mods with Item Swap, the attributed author of the resulting mod was improved.") - .RegisterEntry("Fixed an issue with rings in the On-Screen tab and in the data sent over to other plugins via IPC.") + "The enabled checkbox, Priority and Inheriting buttons now stick at the top of the Mod Settings panel even when scrolling down for specific settings."u8) + .RegisterEntry("When creating new mods with Item Swap, the attributed author of the resulting mod was improved."u8) + .RegisterEntry("Fixed an issue with rings in the On-Screen tab and in the data sent over to other plugins via IPC."u8) .RegisterEntry( - "Fixed some issues when writing material files that resulted in technically valid files that still caused some issues with the game for unknown reasons.") - .RegisterEntry("Fixed some ImGui assertions."); + "Fixed some issues when writing material files that resulted in technically valid files that still caused some issues with the game for unknown reasons."u8) + .RegisterEntry("Fixed some ImGui assertions."u8); private static void Add1_3_2_0(Changelog log) - => log.NextVersion("Version 1.3.2.0") - .RegisterHighlight("Added ATCH meta manipulations that allow the composite editing of attachment points across multiple mods.") - .RegisterEntry("Those ATCH manipulations should be shared via Mare Synchronos.", 1) + => log.NextVersion("Version 1.3.2.0"u8) + .RegisterHighlight("Added ATCH meta manipulations that allow the composite editing of attachment points across multiple mods."u8) + .RegisterEntry("Those ATCH manipulations should be shared via Mare Synchronos."u8, 1) .RegisterEntry( - "This is an early implementation and might be bug-prone. Let me know of any issues. It was in testing for quite a while without reports.", + "This is an early implementation and might be bug-prone. Let me know of any issues. It was in testing for quite a while without reports."u8, 1) .RegisterEntry( - "Added jumping to identified mods in the On-Screen tab via Control + Right-Click and improved their display slightly.") - .RegisterEntry("Added some right-click context menu copy options in the File Redirections editor for paths.") - .RegisterHighlight("Added the option to change a specific mod's settings via chat commands by using '/penumbra mod settings'.") - .RegisterEntry("Fixed issues with the copy-pasting of meta manipulations.") - .RegisterEntry("Fixed some other issues related to meta manipulations.") + "Added jumping to identified mods in the On-Screen tab via Control + Right-Click and improved their display slightly."u8) + .RegisterEntry("Added some right-click context menu copy options in the File Redirections editor for paths."u8) + .RegisterHighlight("Added the option to change a specific mod's settings via chat commands by using '/penumbra mod settings'."u8) + .RegisterEntry("Fixed issues with the copy-pasting of meta manipulations."u8) + .RegisterEntry("Fixed some other issues related to meta manipulations."u8) .RegisterEntry( - "Updated available NPC names and fixed an issue with some supposedly invisible characters in names showing in ImGui."); + "Updated available NPC names and fixed an issue with some supposedly invisible characters in names showing in ImGui."u8); private static void Add1_3_1_0(Changelog log) - => log.NextVersion("Version 1.3.1.0") - .RegisterEntry("Penumbra has been updated for Dalamud API 11 and patch 7.1.") + => log.NextVersion("Version 1.3.1.0"u8) + .RegisterEntry("Penumbra has been updated for Dalamud API 11 and patch 7.1."u8) .RegisterImportant( - "There are some known issues with potential crashes using certain VFX/SFX mods, probably related to sound files.") + "There are some known issues with potential crashes using certain VFX/SFX mods, probably related to sound files."u8) .RegisterEntry( - "If you encounter those issues, please report them in the discord and potentially disable the corresponding mods for the time being.", + "If you encounter those issues, please report them in the discord and potentially disable the corresponding mods for the time being."u8, 1) .RegisterImportant( - "The modding of .atch files has been disabled. Outdated modded versions of these files cause crashes when loaded.") - .RegisterEntry("A better way for modular modding of .atch files via meta changes will release to the testing branch soonish.", 1) - .RegisterHighlight("Temporary collections (as created by Mare) will now always respect ownership.") + "The modding of .atch files has been disabled. Outdated modded versions of these files cause crashes when loaded."u8) + .RegisterEntry("A better way for modular modding of .atch files via meta changes will release to the testing branch soonish."u8, 1) + .RegisterHighlight("Temporary collections (as created by Mare) will now always respect ownership."u8) .RegisterEntry( - "This means that you can toggle this setting off if you do not want it, and Mare will still work for minions and mounts of other players.", + "This means that you can toggle this setting off if you do not want it, and Mare will still work for minions and mounts of other players."u8, 1) .RegisterEntry( - "The new physics and animation engine files (.kdb and .bnmb) should now be correctly redirected and respect EST changes.") - .RegisterEntry("Fixed issues with EQP entries being labeled wrongly and global EQP not changing all required values for earrings.") - .RegisterEntry("Fixed an issue with global EQP changes of a mod being reset upon reloading the mod.") - .RegisterEntry("Fixed another issue with left rings and mare synchronization / the on-screen tab.") - .RegisterEntry("Maybe fixed some issues with characters appearing in the login screen being misidentified.") - .RegisterEntry("Some improvements for debug visualization have been made."); + "The new physics and animation engine files (.kdb and .bnmb) should now be correctly redirected and respect EST changes."u8) + .RegisterEntry( + "Fixed issues with EQP entries being labeled wrongly and global EQP not changing all required values for earrings."u8) + .RegisterEntry("Fixed an issue with global EQP changes of a mod being reset upon reloading the mod."u8) + .RegisterEntry("Fixed another issue with left rings and mare synchronization / the on-screen tab."u8) + .RegisterEntry("Maybe fixed some issues with characters appearing in the login screen being misidentified."u8) + .RegisterEntry("Some improvements for debug visualization have been made."u8); private static void Add1_3_0_0(Changelog log) - => log.NextVersion("Version 1.3.0.0") - .RegisterHighlight("The textures tab in the advanced editing window can now import and export .tga files.") - .RegisterEntry("BC4 and BC6 textures can now also be imported.", 1) - .RegisterHighlight("Added item swapping from and to the Glasses slot.") - .RegisterEntry("Reworked quite a bit of things around face wear / bonus items. Please let me know if anything broke.", 1) - .RegisterEntry("The import date of a mod is now shown in the Edit Mod tab, and can be reset via button.") - .RegisterEntry("A button to open the file containing local mod data for a mod was also added.", 1) + => log.NextVersion("Version 1.3.0.0"u8) + .RegisterHighlight("The textures tab in the advanced editing window can now import and export .tga files."u8) + .RegisterEntry("BC4 and BC6 textures can now also be imported."u8, 1) + .RegisterHighlight("Added item swapping from and to the Glasses slot."u8) + .RegisterEntry("Reworked quite a bit of things around face wear / bonus items. Please let me know if anything broke."u8, 1) + .RegisterEntry("The import date of a mod is now shown in the Edit Mod tab, and can be reset via button."u8) + .RegisterEntry("A button to open the file containing local mod data for a mod was also added."u8, 1) .RegisterHighlight( - "IMC groups can now be configured to only apply the attribute flags for their entry, and take the other values from the default value.") - .RegisterEntry("This allows keeping the material index of every IMC entry of a group, while setting the attributes.", 1) - .RegisterHighlight("Model Import/Export was fixed and re-enabled (thanks ackwell and ramen).") - .RegisterHighlight("Added a hack to allow bonus items (face wear, glasses) to have VFX.") - .RegisterEntry("Also fixed the hack that allowed accessories to have VFX not working anymore.", 1) - .RegisterHighlight("Added rudimentary options to edit PBD files in the advanced editing window.") - .RegisterEntry("Preparing the advanced editing window for a mod now does not freeze the game until it is ready.") + "IMC groups can now be configured to only apply the attribute flags for their entry, and take the other values from the default value."u8) + .RegisterEntry("This allows keeping the material index of every IMC entry of a group, while setting the attributes."u8, 1) + .RegisterHighlight("Model Import/Export was fixed and re-enabled (thanks ackwell and ramen)."u8) + .RegisterHighlight("Added a hack to allow bonus items (face wear, glasses) to have VFX."u8) + .RegisterEntry("Also fixed the hack that allowed accessories to have VFX not working anymore."u8, 1) + .RegisterHighlight("Added rudimentary options to edit PBD files in the advanced editing window."u8) + .RegisterEntry("Preparing the advanced editing window for a mod now does not freeze the game until it is ready."u8) .RegisterEntry( - "Meta Manipulations in the advanced editing window are now ordered and do not eat into performance as much when drawn.") - .RegisterEntry("Added a button to the advanced editing window to remove all default-valued meta manipulations from a mod") + "Meta Manipulations in the advanced editing window are now ordered and do not eat into performance as much when drawn."u8) + .RegisterEntry("Added a button to the advanced editing window to remove all default-valued meta manipulations from a mod"u8) .RegisterEntry( - "Default-valued manipulations will now also be removed on import from archives and .pmps, not just .ttmps, if not configured otherwise.", + "Default-valued manipulations will now also be removed on import from archives and .pmps, not just .ttmps, if not configured otherwise."u8, 1) - .RegisterEntry("Checkbox-based mod filters are now tri-state checkboxes instead of two disjoint checkboxes.") - .RegisterEntry("Paths from the resource logger can now be copied.") - .RegisterEntry("Silenced some redundant error logs when updating mods via Heliosphere.") - .RegisterEntry("Added 'Page' to imported mod data for TexTools interop. The value is not used in Penumbra, just persisted.") - .RegisterEntry("Updated all external dependencies.") - .RegisterEntry("Fixed issue with Demihuman IMC entries.") - .RegisterEntry("Fixed some off-by-one errors on the mod import window.") - .RegisterEntry("Fixed a race-condition concerning the first-time creation of mod-meta files.") - .RegisterEntry("Fixed an issue with long mod titles in the merge mods tab.") - .RegisterEntry("A bunch of other miscellaneous fixes."); + .RegisterEntry("Checkbox-based mod filters are now tri-state checkboxes instead of two disjoint checkboxes."u8) + .RegisterEntry("Paths from the resource logger can now be copied."u8) + .RegisterEntry("Silenced some redundant error logs when updating mods via Heliosphere."u8) + .RegisterEntry("Added 'Page' to imported mod data for TexTools interop. The value is not used in Penumbra, just persisted."u8) + .RegisterEntry("Updated all external dependencies."u8) + .RegisterEntry("Fixed issue with Demihuman IMC entries."u8) + .RegisterEntry("Fixed some off-by-one errors on the mod import window."u8) + .RegisterEntry("Fixed a race-condition concerning the first-time creation of mod-meta files."u8) + .RegisterEntry("Fixed an issue with long mod titles in the merge mods tab."u8) + .RegisterEntry("A bunch of other miscellaneous fixes."u8); private static void Add1_2_1_0(Changelog log) - => log.NextVersion("Version 1.2.1.0") - .RegisterHighlight("Penumbra is now released for Dawntrail!") - .RegisterEntry("Mods themselves may have to be updated. TexTools provides options for this.", 1) - .RegisterEntry("For model files, Penumbra provides a rudimentary update function, but prefer using TexTools if possible.", 1) - .RegisterEntry("Other files, like materials and textures, will have to go through TexTools for the moment.", 1) + => log.NextVersion("Version 1.2.1.0"u8) + .RegisterHighlight("Penumbra is now released for Dawntrail!"u8) + .RegisterEntry("Mods themselves may have to be updated. TexTools provides options for this."u8, 1) + .RegisterEntry("For model files, Penumbra provides a rudimentary update function, but prefer using TexTools if possible."u8, 1) + .RegisterEntry("Other files, like materials and textures, will have to go through TexTools for the moment."u8, 1) .RegisterEntry( - "Some outdated mods can be identified by Penumbra and are prevented from loading entirely (specifically shaders, by Ny).", 1) - .RegisterImportant("I am sorry that it took this long, but there was an immense amount of work to be done from the start.") + "Some outdated mods can be identified by Penumbra and are prevented from loading entirely (specifically shaders, by Ny)."u8, 1) + .RegisterImportant("I am sorry that it took this long, but there was an immense amount of work to be done from the start."u8) .RegisterImportant( - "Since Penumbra has been in Testing for quite a while, multitudes of bugs and issues cropped up that needed to be dealt with.", + "Since Penumbra has been in Testing for quite a while, multitudes of bugs and issues cropped up that needed to be dealt with."u8, 1) - .RegisterEntry("There very well may still be a lot of issues, so please report any you find.", 1) - .RegisterImportant("BUT, please make sure that those issues are not caused by outdated mods before reporting them.", 1) + .RegisterEntry("There very well may still be a lot of issues, so please report any you find."u8, 1) + .RegisterImportant("BUT, please make sure that those issues are not caused by outdated mods before reporting them."u8, 1) .RegisterEntry( - "This changelog may seem rather short for the timespan, but I omitted hundreds of smaller fixes and the details of getting Penumbra to work in Dawntrail.", + "This changelog may seem rather short for the timespan, but I omitted hundreds of smaller fixes and the details of getting Penumbra to work in Dawntrail."u8, 1) - .RegisterHighlight("The Material Editing tab in the Advanced Editing Window has been heavily improved (by Ny).") + .RegisterHighlight("The Material Editing tab in the Advanced Editing Window has been heavily improved (by Ny)."u8) .RegisterEntry( - "Especially for Dawntrail materials using the new shaders, the window provides much more in-depth and user-friendly editing options.", + "Especially for Dawntrail materials using the new shaders, the window provides much more in-depth and user-friendly editing options."u8, 1) - .RegisterHighlight("Many advancements regarding modded shaders, and modding bone deformers have been made.") - .RegisterHighlight("IMC groups now allow their options to toggle attributes off that are on in the default entry.") + .RegisterHighlight("Many advancements regarding modded shaders, and modding bone deformers have been made."u8) + .RegisterHighlight("IMC groups now allow their options to toggle attributes off that are on in the default entry."u8) .RegisterImportant( - "The 'Update Bibo' button was removed. The functionality is redundant since any mods that old need to be updated anyway.") - .RegisterEntry("Clicking the button on modern mods generally caused more harm than benefit.", 1) + "The 'Update Bibo' button was removed. The functionality is redundant since any mods that old need to be updated anyway."u8) + .RegisterEntry("Clicking the button on modern mods generally caused more harm than benefit."u8, 1) .RegisterEntry( - "If you somehow still need to mass-migrate materials in your models, the Material Reassignment tab in Advanced Editing is still available for this.", + "If you somehow still need to mass-migrate materials in your models, the Material Reassignment tab in Advanced Editing is still available for this."u8, 1) - .RegisterEntry("The On-Screen tab was updated and improved and can now display modded actual paths in more useful form.") - .RegisterImportant("Model Import/Export is temporarily disabled until Dawntrail-related changes can be made.") - .RegisterHighlight("You can now change a mods state in any collection from its Collections tab via right-clicking the state.") - .RegisterHighlight("Items changed in a mod now sort before other items in the Item Swap tab, and are highlighted.") - .RegisterEntry("Path handling was improved in regards to case-sensitivity.") - .RegisterEntry("Fixed an issue with negative search matching on folders with no matches") - .RegisterEntry("Mod option groups on the same priority are now applied in reverse index order. (1.2.0.12)") - .RegisterEntry("Fixed the display of missing files in the Advanced Editing Window's header. (1.2.0.8)") + .RegisterEntry("The On-Screen tab was updated and improved and can now display modded actual paths in more useful form."u8) + .RegisterImportant("Model Import/Export is temporarily disabled until Dawntrail-related changes can be made."u8) + .RegisterHighlight("You can now change a mods state in any collection from its Collections tab via right-clicking the state."u8) + .RegisterHighlight("Items changed in a mod now sort before other items in the Item Swap tab, and are highlighted."u8) + .RegisterEntry("Path handling was improved in regards to case-sensitivity."u8) + .RegisterEntry("Fixed an issue with negative search matching on folders with no matches"u8) + .RegisterEntry("Mod option groups on the same priority are now applied in reverse index order. (1.2.0.12)"u8) + .RegisterEntry("Fixed the display of missing files in the Advanced Editing Window's header. (1.2.0.8)"u8) .RegisterEntry( - "Fixed some, but not all soft-locks that occur when your character gets redrawn while fishing. Just do not do that. (1.2.0.7)") - .RegisterEntry("Improved handling of invalid Offhand IMC files for certain jobs. (1.2.0.6)") - .RegisterEntry("Added automatic reduplication for files in the UI category, as they cause crashes when not unique. (1.2.0.5)") - .RegisterEntry("The mod import popup can now be closed by clicking outside of it, if it is finished. (1.2.0.5)") - .RegisterEntry("Fixed an issue with Mod Normalization skipping the default option. (1.2.0.5)") - .RegisterEntry("Improved the Support Info output. (1.1.1.5)") - .RegisterEntry("Reworked the handling of Meta Manipulations entirely. (1.1.1.3)") - .RegisterEntry("Added a configuration option to disable showing mods in the character lobby and at the aesthetician. (1.1.1.1)") - .RegisterEntry("Fixed an issue with the AddMods API and the root directory. (1.1.1.2)") - .RegisterEntry("Fixed an issue with the Mod Merger file lookup and casing. (1.1.1.2)") - .RegisterEntry("Fixed an issue with file saving not happening when merging mods or swapping items in some cases. (1.1.1.2)"); + "Fixed some, but not all soft-locks that occur when your character gets redrawn while fishing. Just do not do that. (1.2.0.7)"u8) + .RegisterEntry("Improved handling of invalid Offhand IMC files for certain jobs. (1.2.0.6)"u8) + .RegisterEntry("Added automatic reduplication for files in the UI category, as they cause crashes when not unique. (1.2.0.5)"u8) + .RegisterEntry("The mod import popup can now be closed by clicking outside of it, if it is finished. (1.2.0.5)"u8) + .RegisterEntry("Fixed an issue with Mod Normalization skipping the default option. (1.2.0.5)"u8) + .RegisterEntry("Improved the Support Info output. (1.1.1.5)"u8) + .RegisterEntry("Reworked the handling of Meta Manipulations entirely. (1.1.1.3)"u8) + .RegisterEntry("Added a configuration option to disable showing mods in the character lobby and at the aesthetician. (1.1.1.1)"u8) + .RegisterEntry("Fixed an issue with the AddMods API and the root directory. (1.1.1.2)"u8) + .RegisterEntry("Fixed an issue with the Mod Merger file lookup and casing. (1.1.1.2)"u8) + .RegisterEntry("Fixed an issue with file saving not happening when merging mods or swapping items in some cases. (1.1.1.2)"u8); private static void Add1_1_1_0(Changelog log) - => log.NextVersion("Version 1.1.1.0") - .RegisterHighlight("Filtering for mods is now tokenized and can filter for multiple things at once, or exclude specific things.") - .RegisterEntry("Hover over the filter to see the new available options in the tooltip.", 1) - .RegisterEntry("Be aware that the tokenization changed the prior behavior slightly.", 1) - .RegisterEntry("This is open to improvements, if you have any ideas, let me know!", 1) - .RegisterHighlight("Added initial identification of characters in the login-screen by name.") + => log.NextVersion("Version 1.1.1.0"u8) + .RegisterHighlight("Filtering for mods is now tokenized and can filter for multiple things at once, or exclude specific things."u8) + .RegisterEntry("Hover over the filter to see the new available options in the tooltip."u8, 1) + .RegisterEntry("Be aware that the tokenization changed the prior behavior slightly."u8, 1) + .RegisterEntry("This is open to improvements, if you have any ideas, let me know!"u8, 1) + .RegisterHighlight("Added initial identification of characters in the login-screen by name."u8) .RegisterEntry( - "Those characters can not be redrawn and re-use some things, so this may not always behave as expected, but should work in general. Let me know if you encounter edge cases!", + "Those characters can not be redrawn and re-use some things, so this may not always behave as expected, but should work in general. Let me know if you encounter edge cases!"u8, 1) - .RegisterEntry("Added functionality for IMC groups to apply to all variants for a model instead of a specific one.") - .RegisterEntry("Improved the resource tree view with filters and incognito mode. (by Ny)") - .RegisterEntry("Added a tooltip to the global EQP condition.") - .RegisterEntry("Fixed the new worlds not being identified correctly because Square Enix could not be bothered to turn them public.") - .RegisterEntry("Fixed model import getting stuck when doing weight adjustments. (by ackwell)") - .RegisterEntry("Fixed an issue with dye previews in the material editor not applying.") - .RegisterEntry("Fixed an issue with collections not saving on renames.") - .RegisterEntry("Fixed an issue parsing collections with settings set to negative values, which should now be set to 0.") - .RegisterEntry("Fixed an issue with the accessory VFX addition.") - .RegisterEntry("Fixed an issue with GMP animation type entries.") - .RegisterEntry("Fixed another issue with the mod merger.") - .RegisterEntry("Fixed an issue with IMC groups and IPC.") - .RegisterEntry("Fixed some issues with the capitalization of the root directory.") - .RegisterEntry("Fixed IMC attribute tooltips not appearing for disabled checkboxes.") - .RegisterEntry("Added GetChangedItems IPC for single mods. (1.1.0.2)") - .RegisterEntry("Fixed an issue with creating unnamed collections. (1.1.0.2)") - .RegisterEntry("Fixed an issue with the mod merger. (1.1.0.2)") - .RegisterEntry("Fixed the global EQP entry for rings checking for bracelets instead of rings. (1.1.0.2)") - .RegisterEntry("Fixed an issue with newly created collections not being added to the collection list. (1.1.0.1)"); + .RegisterEntry("Added functionality for IMC groups to apply to all variants for a model instead of a specific one."u8) + .RegisterEntry("Improved the resource tree view with filters and incognito mode. (by Ny)"u8) + .RegisterEntry("Added a tooltip to the global EQP condition."u8) + .RegisterEntry( + "Fixed the new worlds not being identified correctly because Square Enix could not be bothered to turn them public."u8) + .RegisterEntry("Fixed model import getting stuck when doing weight adjustments. (by ackwell)"u8) + .RegisterEntry("Fixed an issue with dye previews in the material editor not applying."u8) + .RegisterEntry("Fixed an issue with collections not saving on renames."u8) + .RegisterEntry("Fixed an issue parsing collections with settings set to negative values, which should now be set to 0."u8) + .RegisterEntry("Fixed an issue with the accessory VFX addition."u8) + .RegisterEntry("Fixed an issue with GMP animation type entries."u8) + .RegisterEntry("Fixed another issue with the mod merger."u8) + .RegisterEntry("Fixed an issue with IMC groups and IPC."u8) + .RegisterEntry("Fixed some issues with the capitalization of the root directory."u8) + .RegisterEntry("Fixed IMC attribute tooltips not appearing for disabled checkboxes."u8) + .RegisterEntry("Added GetChangedItems IPC for single mods. (1.1.0.2)"u8) + .RegisterEntry("Fixed an issue with creating unnamed collections. (1.1.0.2)"u8) + .RegisterEntry("Fixed an issue with the mod merger. (1.1.0.2)"u8) + .RegisterEntry("Fixed the global EQP entry for rings checking for bracelets instead of rings. (1.1.0.2)"u8) + .RegisterEntry("Fixed an issue with newly created collections not being added to the collection list. (1.1.0.1)"u8); private static void Add1_1_0_0(Changelog log) - => log.NextVersion("Version 1.1.0.0") + => log.NextVersion("Version 1.1.0.0"u8) .RegisterImportant( - "This update comes, again, with a lot of very heavy backend changes (collections and groups) and thus may introduce new issues.") - .RegisterEntry("Updated to .net8 and XIV 6.58, using some new framework facilities to improve performance and stability.") + "This update comes, again, with a lot of very heavy backend changes (collections and groups) and thus may introduce new issues."u8) + .RegisterEntry("Updated to .net8 and XIV 6.58, using some new framework facilities to improve performance and stability."u8) .RegisterHighlight( - "Added an experimental crash handler that is supposed to write a Penumbra.log file when the game crashes, containing Penumbra-specific information.") - .RegisterEntry("This is disabled by default. It can be enabled in Advanced Settings.", 1) - .RegisterHighlight("Collections now have associated GUIDs as identifiers instead of their names, so they can now be renamed.") - .RegisterEntry("Migrating those collections may introduce issues, please let me know as soon as possible if you encounter any.", 1) - .RegisterEntry("A permanent (non-rolling) backup should be created before the migration in case of any issues.", 1) + "Added an experimental crash handler that is supposed to write a Penumbra.log file when the game crashes, containing Penumbra-specific information."u8) + .RegisterEntry("This is disabled by default. It can be enabled in Advanced Settings."u8, 1) + .RegisterHighlight("Collections now have associated GUIDs as identifiers instead of their names, so they can now be renamed."u8) + .RegisterEntry("Migrating those collections may introduce issues, please let me know as soon as possible if you encounter any."u8, + 1) + .RegisterEntry("A permanent (non-rolling) backup should be created before the migration in case of any issues."u8, 1) .RegisterHighlight( - "Added predefined tags that can be setup in the Settings tab and can be more easily applied or removed from mods. (by DZD)") + "Added predefined tags that can be setup in the Settings tab and can be more easily applied or removed from mods. (by DZD)"u8) .RegisterHighlight( - "A total rework of how options and groups are handled internally, and introduction of the first new group type, the IMC Group.") + "A total rework of how options and groups are handled internally, and introduction of the first new group type, the IMC Group."u8) .RegisterEntry( - "Mod Creators can add a IMC Group to their mod that controls a single IMC Manipulation, so they can provide options for the separate attributes for it.", + "Mod Creators can add a IMC Group to their mod that controls a single IMC Manipulation, so they can provide options for the separate attributes for it."u8, 1) .RegisterEntry( - "This makes it a lot easier to have combined options: No need for 'A', 'B' and 'AB', you can just define 'A' and 'B' and skip their combinations", + "This makes it a lot easier to have combined options: No need for 'A', 'B' and 'AB', you can just define 'A' and 'B' and skip their combinations"u8, 1) - .RegisterHighlight("A new type of Meta Manipulation was added, 'Global EQP Manipulation'.") + .RegisterHighlight("A new type of Meta Manipulation was added, 'Global EQP Manipulation'."u8) .RegisterEntry( - "Global EQP Manipulations allow accessories to make other equipment pieces not hide them, e.g. whenever a character is wearing a specific Bracelet, neither body nor hand items will ever hide bracelets.", + "Global EQP Manipulations allow accessories to make other equipment pieces not hide them, e.g. whenever a character is wearing a specific Bracelet, neither body nor hand items will ever hide bracelets."u8, 1) .RegisterEntry( - "This can be used if something like a jacket or a stole is put onto an accessory to prevent it from being hidden in general.", + "This can be used if something like a jacket or a stole is put onto an accessory to prevent it from being hidden in general."u8, 1) .RegisterEntry( - "The first empty option in a single-select option group imported from a TTMP will now keep its location instead of being moved to the first option.") - .RegisterEntry("Further empty options are still removed.", 1) + "The first empty option in a single-select option group imported from a TTMP will now keep its location instead of being moved to the first option."u8) + .RegisterEntry("Further empty options are still removed."u8, 1) .RegisterHighlight( - "Added a field to rename mods directly from the mod selector context menu, instead of moving them in the filesystem.") - .RegisterEntry("You can choose which rename field (none, either one or both) to display in the settings.", 1) - .RegisterEntry("Added the characterglass.shpk shader file to special shader treatment to fix issues when replacing it. (By Ny)") - .RegisterEntry("Made it more obvious if a user has not set their root directory yet.") + "Added a field to rename mods directly from the mod selector context menu, instead of moving them in the filesystem."u8) + .RegisterEntry("You can choose which rename field (none, either one or both) to display in the settings."u8, 1) + .RegisterEntry("Added the characterglass.shpk shader file to special shader treatment to fix issues when replacing it. (By Ny)"u8) + .RegisterEntry("Made it more obvious if a user has not set their root directory yet."u8) .RegisterEntry( - "You can now paste your current clipboard text into the mod selector filter with a simple right-click as long as it is not focused.") + "You can now paste your current clipboard text into the mod selector filter with a simple right-click as long as it is not focused."u8) .RegisterHighlight( - "Added the option to display VFX for accessories if added via IMC edits, which the game does not do inherently (by Ocealot).") - .RegisterEntry("Added support for reading and writing the new material and model file formats from the benchmark.") + "Added the option to display VFX for accessories if added via IMC edits, which the game does not do inherently (by Ocealot)."u8) + .RegisterEntry("Added support for reading and writing the new material and model file formats from the benchmark."u8) .RegisterEntry( - "Added the option to hide Machinist Offhands from the Changed Items tabs (because any change to it changes ALL of them), which is on by default.") - .RegisterEntry("Removed the auto-generated descriptions for newly created groups in Penumbra.") + "Added the option to hide Machinist Offhands from the Changed Items tabs (because any change to it changes ALL of them), which is on by default."u8) + .RegisterEntry("Removed the auto-generated descriptions for newly created groups in Penumbra."u8) .RegisterEntry( - "Made some improvements to the Advanced Editing window, for example a much better and more performant Hex Viewer for unstructured data was added.") - .RegisterEntry("Various improvements to model import/export by ackwell (throughout all patches).") + "Made some improvements to the Advanced Editing window, for example a much better and more performant Hex Viewer for unstructured data was added."u8) + .RegisterEntry("Various improvements to model import/export by ackwell (throughout all patches)."u8) .RegisterEntry( - "Hovering over meta manipulations in other options in the advanced editing window now shows a list of those options.") - .RegisterEntry("Reworked the API and IPC structure heavily.") - .RegisterImportant("This means some plugins interacting with Penumbra may not work correctly until they update.", 1) - .RegisterEntry("Worked around the UI IPC possibly displacing all settings when the drawn additions became too big.") - .RegisterEntry("Fixed an issue where reloading a mod did not ensure settings for that mod being correct afterwards.") - .RegisterEntry("Fixed some issues with the file sizes of compressed files.") - .RegisterEntry("Fixed an issue with merging and deduplicating mods.") - .RegisterEntry("Fixed a crash when scanning for mods without access rights to the folder.") + "Hovering over meta manipulations in other options in the advanced editing window now shows a list of those options."u8) + .RegisterEntry("Reworked the API and IPC structure heavily."u8) + .RegisterImportant("This means some plugins interacting with Penumbra may not work correctly until they update."u8, 1) + .RegisterEntry("Worked around the UI IPC possibly displacing all settings when the drawn additions became too big."u8) + .RegisterEntry("Fixed an issue where reloading a mod did not ensure settings for that mod being correct afterwards."u8) + .RegisterEntry("Fixed some issues with the file sizes of compressed files."u8) + .RegisterEntry("Fixed an issue with merging and deduplicating mods."u8) + .RegisterEntry("Fixed a crash when scanning for mods without access rights to the folder."u8) .RegisterEntry( - "Made plugin conform to Dalamud requirements by adding a punchline and another button to open the menu from the installer.") - .RegisterEntry("Added an option to automatically redraw the player character when saving files. (1.0.0.8)") - .RegisterEntry("Fixed issue with manipulating mods not triggering some events. (1.0.0.7)") - .RegisterEntry("Fixed issue with temporary mods not triggering some events. (1.0.0.6)") - .RegisterEntry("Fixed issue when renaming mods while the advanced edit window is open. (1.0.0.6)") - .RegisterEntry("Fixed issue with empty option groups. (1.0.0.5)") - .RegisterEntry("Fixed issues with cutscene character identification. (1.0.0.4)") - .RegisterEntry("Added locale environment information to support info. (1.0.0.4)") - .RegisterEntry("Fixed an issue with copied mod settings in IPC missing unused settings. (1.0.0.3)"); + "Made plugin conform to Dalamud requirements by adding a punchline and another button to open the menu from the installer."u8) + .RegisterEntry("Added an option to automatically redraw the player character when saving files. (1.0.0.8)"u8) + .RegisterEntry("Fixed issue with manipulating mods not triggering some events. (1.0.0.7)"u8) + .RegisterEntry("Fixed issue with temporary mods not triggering some events. (1.0.0.6)"u8) + .RegisterEntry("Fixed issue when renaming mods while the advanced edit window is open. (1.0.0.6)"u8) + .RegisterEntry("Fixed issue with empty option groups. (1.0.0.5)"u8) + .RegisterEntry("Fixed issues with cutscene character identification. (1.0.0.4)"u8) + .RegisterEntry("Added locale environment information to support info. (1.0.0.4)"u8) + .RegisterEntry("Fixed an issue with copied mod settings in IPC missing unused settings. (1.0.0.3)"u8); private static void Add1_0_0_0(Changelog log) - => log.NextVersion("Version 1.0.0.0") - .RegisterHighlight("Mods in the mod selector can now be filtered by changed item categories.") - .RegisterHighlight("Model Editing options in the Advanced Editing Window have been greatly extended (by ackwell):") - .RegisterEntry("Attributes and referenced materials can now be set per mesh.", 1) - .RegisterEntry("Model files (.mdl) can now be exported to the well-established glTF format, which can be imported e.g. by Blender.", - 1) - .RegisterEntry("glTF files can also be imported back to a .mdl file.", 1) - .RegisterHighlight( - "Model Export and Import are a work in progress and may encounter issues, not support all cases or produce wrong results, please let us know!", - 1) - .RegisterEntry("The last selected mod and the open/close state of the Advanced Editing Window are now stored across launches.") - .RegisterEntry("Footsteps of certain mounts will now be associated to collections correctly.") - .RegisterEntry("Save-in-Place in the texture tab now requires the configurable modifier.") - .RegisterEntry("Updated OtterTex to a newer version of DirectXTex.") - .RegisterEntry("Fixed an issue with horizontal scrolling if a mod title was very long.") - .RegisterEntry("Fixed an issue with the mod panels header not updating its data when the selected mod updates.") - .RegisterEntry("Fixed some issues with EQDP files for invalid characters.") - .RegisterEntry("Fixed an issue with the FileDialog being drawn twice in certain situations.") + => log.NextVersion("Version 1.0.0.0"u8) + .RegisterHighlight("Mods in the mod selector can now be filtered by changed item categories."u8) + .RegisterHighlight("Model Editing options in the Advanced Editing Window have been greatly extended (by ackwell):"u8) + .RegisterEntry("Attributes and referenced materials can now be set per mesh."u8, 1) .RegisterEntry( - "A lot of backend changes that should not have an effect on users, but may cause issues if something got messed up."); + "Model files (.mdl) can now be exported to the well-established glTF format, which can be imported e.g. by Blender."u8, + 1) + .RegisterEntry("glTF files can also be imported back to a .mdl file."u8, 1) + .RegisterHighlight( + "Model Export and Import are a work in progress and may encounter issues, not support all cases or produce wrong results, please let us know!"u8, + 1) + .RegisterEntry("The last selected mod and the open/close state of the Advanced Editing Window are now stored across launches."u8) + .RegisterEntry("Footsteps of certain mounts will now be associated to collections correctly."u8) + .RegisterEntry("Save-in-Place in the texture tab now requires the configurable modifier."u8) + .RegisterEntry("Updated OtterTex to a newer version of DirectXTex."u8) + .RegisterEntry("Fixed an issue with horizontal scrolling if a mod title was very long."u8) + .RegisterEntry("Fixed an issue with the mod panels header not updating its data when the selected mod updates."u8) + .RegisterEntry("Fixed some issues with EQDP files for invalid characters."u8) + .RegisterEntry("Fixed an issue with the FileDialog being drawn twice in certain situations."u8) + .RegisterEntry( + "A lot of backend changes that should not have an effect on users, but may cause issues if something got messed up."u8); private static void Add8_3_0(Changelog log) - => log.NextVersion("Version 0.8.3.0") - .RegisterHighlight("Improved the UI for the On-Screen tabs with highlighting of used paths, filtering and more selections. (by Ny)") + => log.NextVersion("Version 0.8.3.0"u8) + .RegisterHighlight( + "Improved the UI for the On-Screen tabs with highlighting of used paths, filtering and more selections. (by Ny)"u8) .RegisterEntry( - "Added an option to replace non-ASCII symbols with underscores for folder paths on mod import since this causes problems on some WINE systems. This option is off by default.") + "Added an option to replace non-ASCII symbols with underscores for folder paths on mod import since this causes problems on some WINE systems. This option is off by default."u8) .RegisterEntry( - "Added support for the Changed Item Icons to load modded icons, but this depends on a not-yet-released Dalamud update.") + "Added support for the Changed Item Icons to load modded icons, but this depends on a not-yet-released Dalamud update."u8) .RegisterEntry( - "Penumbra should no longer redraw characters while they are fishing, but wait for them to reel in, because that could cause soft-locks. This may cause other issues, but I have not found any.") + "Penumbra should no longer redraw characters while they are fishing, but wait for them to reel in, because that could cause soft-locks. This may cause other issues, but I have not found any."u8) .RegisterEntry( - "Hopefully fixed a bug on mod import where files were being read while they were still saving, causing Penumbra to create wrong options.") - .RegisterEntry("Fixed a few display issues.") - .RegisterEntry("Added some IPC functionality for Xande. (by Asriel)"); + "Hopefully fixed a bug on mod import where files were being read while they were still saving, causing Penumbra to create wrong options."u8) + .RegisterEntry("Fixed a few display issues."u8) + .RegisterEntry("Added some IPC functionality for Xande. (by Asriel)"u8); private static void Add8_2_0(Changelog log) - => log.NextVersion("Version 0.8.2.0") + => log.NextVersion("Version 0.8.2.0"u8) .RegisterHighlight( - "You can now redraw indoor furniture. This may not be entirely stable and might break some customizable decoration like wallpapered walls.") - .RegisterEntry("The redraw bar has been slightly improved and disables currently unavailable redraw commands now.") - .RegisterEntry("Redrawing players now also actively redraws any accessories they are using.") - .RegisterEntry("Power-users can now redraw game objects by index via chat command.") + "You can now redraw indoor furniture. This may not be entirely stable and might break some customizable decoration like wallpapered walls."u8) + .RegisterEntry("The redraw bar has been slightly improved and disables currently unavailable redraw commands now."u8) + .RegisterEntry("Redrawing players now also actively redraws any accessories they are using."u8) + .RegisterEntry("Power-users can now redraw game objects by index via chat command."u8) .RegisterHighlight( - "You can now filter for the special case 'None' for filters where that makes sense (like Tags or Changed Items).") - .RegisterHighlight("When selecting multiple mods, you can now add or remove tags from them at once.") + "You can now filter for the special case 'None' for filters where that makes sense (like Tags or Changed Items)."u8) + .RegisterHighlight("When selecting multiple mods, you can now add or remove tags from them at once."u8) .RegisterEntry( - "The dye template combo in advanced material editing now displays the currently selected dye as it would appear with the respective template.") - .RegisterEntry("The On-Screen tab and associated functionality has been heavily improved by Ny.") - .RegisterEntry("Fixed an issue with the changed item identification for left rings.") - .RegisterEntry("Updated BNPC data.") + "The dye template combo in advanced material editing now displays the currently selected dye as it would appear with the respective template."u8) + .RegisterEntry("The On-Screen tab and associated functionality has been heavily improved by Ny."u8) + .RegisterEntry("Fixed an issue with the changed item identification for left rings."u8) + .RegisterEntry("Updated BNPC data."u8) .RegisterEntry( - "Some configuration like the currently selected tab states are now stored in a separate file that is not backed up and saved less often.") - .RegisterEntry("Added option to open the Penumbra main window at game start independently of Debug Mode.") - .RegisterEntry("Fixed some tooltips in the advanced editing window. (0.8.1.8)") - .RegisterEntry("Fixed clicking to linked changed items not working. (0.8.1.8)") - .RegisterEntry("Support correct handling of offhand-parts for two-handed weapons for changed items. (0.8.1.7)") - .RegisterEntry("Fixed renaming the mod directory not updating paths in the advanced window. (0.8.1.6)") - .RegisterEntry("Fixed portraits not respecting your card settings. (0.8.1.6)") - .RegisterEntry("Added ReverseResolvePlayerPathsAsync for IPC. (0.8.1.6)") - .RegisterEntry("Expanded the tooltip for Wait for Plugins on Startup. (0.8.1.5)") - .RegisterEntry("Disabled window sounds for some popup windows. (0.8.1.5)") - .RegisterEntry("Added support for middle-clicking mods to enable/disable them. (0.8.1.5)"); + "Some configuration like the currently selected tab states are now stored in a separate file that is not backed up and saved less often."u8) + .RegisterEntry("Added option to open the Penumbra main window at game start independently of Debug Mode."u8) + .RegisterEntry("Fixed some tooltips in the advanced editing window. (0.8.1.8)"u8) + .RegisterEntry("Fixed clicking to linked changed items not working. (0.8.1.8)"u8) + .RegisterEntry("Support correct handling of offhand-parts for two-handed weapons for changed items. (0.8.1.7)"u8) + .RegisterEntry("Fixed renaming the mod directory not updating paths in the advanced window. (0.8.1.6)"u8) + .RegisterEntry("Fixed portraits not respecting your card settings. (0.8.1.6)"u8) + .RegisterEntry("Added ReverseResolvePlayerPathsAsync for IPC. (0.8.1.6)"u8) + .RegisterEntry("Expanded the tooltip for Wait for Plugins on Startup. (0.8.1.5)"u8) + .RegisterEntry("Disabled window sounds for some popup windows. (0.8.1.5)"u8) + .RegisterEntry("Added support for middle-clicking mods to enable/disable them. (0.8.1.5)"u8); private static void Add8_1_2(Changelog log) - => log.NextVersion("Version 0.8.1.2") - .RegisterEntry("Fixed an issue keeping mods selected after their deletion.") - .RegisterEntry("Maybe fixed an issue causing individual assignments to get lost on game start."); + => log.NextVersion("Version 0.8.1.2"u8) + .RegisterEntry("Fixed an issue keeping mods selected after their deletion."u8) + .RegisterEntry("Maybe fixed an issue causing individual assignments to get lost on game start."u8); private static void Add8_1_1(Changelog log) - => log.NextVersion("Version 0.8.1.1") + => log.NextVersion("Version 0.8.1.1"u8) .RegisterImportant( - "Updated for 6.5 - Square Enix shuffled around a lot of things this update, so some things still might not work but have not been noticed yet. Please report any issues.") - .RegisterEntry("Added support for chat commands to affect multiple individuals matching the supplied string at once.") + "Updated for 6.5 - Square Enix shuffled around a lot of things this update, so some things still might not work but have not been noticed yet. Please report any issues."u8) + .RegisterEntry("Added support for chat commands to affect multiple individuals matching the supplied string at once."u8) .RegisterEntry( - "Improved messaging: many warnings or errors appearing will stay a little longer and can now be looked at in a Messages tab (visible only if there have been any).") - .RegisterEntry("Fixed an issue with leading or trailing spaces when renaming mods."); + "Improved messaging: many warnings or errors appearing will stay a little longer and can now be looked at in a Messages tab (visible only if there have been any)."u8) + .RegisterEntry("Fixed an issue with leading or trailing spaces when renaming mods."u8); private static void Add8_0_0(Changelog log) - => log.NextVersion("Version 0.8.0.0") + => log.NextVersion("Version 0.8.0.0"u8) .RegisterEntry( - "Penumbra now uses Windows' transparent file system compression by default (on Windows systems). You can disable this functionality in the settings.") - .RegisterImportant("You can retroactively compress your existing mods in the settings via the press of a button, too.", 1) + "Penumbra now uses Windows' transparent file system compression by default (on Windows systems). You can disable this functionality in the settings."u8) + .RegisterImportant("You can retroactively compress your existing mods in the settings via the press of a button, too."u8, 1) .RegisterEntry( - "In our tests, this not only was able to reduce storage space by 30-60%, it even decreased loading times since less I/O had to take place.", + "In our tests, this not only was able to reduce storage space by 30-60%, it even decreased loading times since less I/O had to take place."u8, 1) - .RegisterEntry("Added emotes to changed item identification.") + .RegisterEntry("Added emotes to changed item identification."u8) .RegisterEntry( - "Added quick select buttons to switch to the current interface collection or the collection applying to the current player character in the mods tab, reworked their text and tooltips slightly.") - .RegisterHighlight("Drag & Drop of multiple mods and folders at once is now supported by holding Control while clicking them.") - .RegisterEntry("You can now disable conflicting mods from the Conflicts panel via Control + Right-click.") - .RegisterEntry("Added checks for your deletion-modifiers for restoring mods from backups or deleting backups.") + "Added quick select buttons to switch to the current interface collection or the collection applying to the current player character in the mods tab, reworked their text and tooltips slightly."u8) + .RegisterHighlight("Drag & Drop of multiple mods and folders at once is now supported by holding Control while clicking them."u8) + .RegisterEntry("You can now disable conflicting mods from the Conflicts panel via Control + Right-click."u8) + .RegisterEntry("Added checks for your deletion-modifiers for restoring mods from backups or deleting backups."u8) .RegisterEntry( - "Penumbra now should automatically try to restore your custom sort order (mod folders) and your active collections from backups if they fail to load. No guarantees though.") - .RegisterEntry("The resource watcher now displays a column providing load state information of resources.") + "Penumbra now should automatically try to restore your custom sort order (mod folders) and your active collections from backups if they fail to load. No guarantees though."u8) + .RegisterEntry("The resource watcher now displays a column providing load state information of resources."u8) .RegisterEntry( - "Custom RSP scaling outside of the collection assigned to Base should now be respected for emotes that adjust your stance on height differences.") + "Custom RSP scaling outside of the collection assigned to Base should now be respected for emotes that adjust your stance on height differences."u8) .RegisterEntry( - "Mods that replace the skin shaders will not cause visual glitches like loss of head shadows or Free Company crest tattoos anymore (by Ny).") - .RegisterEntry("The Material editor has been improved (by Ny):") + "Mods that replace the skin shaders will not cause visual glitches like loss of head shadows or Free Company crest tattoos anymore (by Ny)."u8) + .RegisterEntry("The Material editor has been improved (by Ny):"u8) .RegisterHighlight( - "Live-Preview for materials yourself or entities owned by you are currently using, so you can see color set edits in real time.", + "Live-Preview for materials yourself or entities owned by you are currently using, so you can see color set edits in real time."u8, 1) .RegisterEntry( - "Colors on the color table of a material can be highlighted on yourself or entities owned by you by hovering a button.", 1) - .RegisterEntry("The color table has improved color accuracy.", 1) - .RegisterEntry("Materials with non-dyable color tables can be made dyable, and vice-versa.", 1) - .RegisterEntry("The 'Advanced Shader Resources' section has been split apart into dedicated sections.", 1) + "Colors on the color table of a material can be highlighted on yourself or entities owned by you by hovering a button."u8, 1) + .RegisterEntry("The color table has improved color accuracy."u8, 1) + .RegisterEntry("Materials with non-dyable color tables can be made dyable, and vice-versa."u8, 1) + .RegisterEntry("The 'Advanced Shader Resources' section has been split apart into dedicated sections."u8, 1) .RegisterEntry( - "Addition and removal of shader keys, textures, constants and a color table has been automated following shader requirements and can not be done manually anymore.", + "Addition and removal of shader keys, textures, constants and a color table has been automated following shader requirements and can not be done manually anymore."u8, 1) .RegisterEntry( - "Plain English names and tooltips can now be displayed instead of hexadecimal identifiers or code names by providing dev-kit files installed via certain mods.", + "Plain English names and tooltips can now be displayed instead of hexadecimal identifiers or code names by providing dev-kit files installed via certain mods."u8, 1) - .RegisterEntry("The Texture editor has been improved (by Ny):") - .RegisterHighlight("The overlay texture can now be combined in several ways and automatically resized to match the input texture.", + .RegisterEntry("The Texture editor has been improved (by Ny):"u8) + .RegisterHighlight( + "The overlay texture can now be combined in several ways and automatically resized to match the input texture."u8, 1) - .RegisterEntry("New color manipulation options have been added.", 1) - .RegisterEntry("Modifications to the selected texture can now be saved in-place.", 1) - .RegisterEntry("The On-Screen tab has been improved (by Ny):") - .RegisterEntry("The character list will load more quickly.", 1) - .RegisterEntry("It is now able to deal with characters under transformation effects.", 1) + .RegisterEntry("New color manipulation options have been added."u8, 1) + .RegisterEntry("Modifications to the selected texture can now be saved in-place."u8, 1) + .RegisterEntry("The On-Screen tab has been improved (by Ny):"u8) + .RegisterEntry("The character list will load more quickly."u8, 1) + .RegisterEntry("It is now able to deal with characters under transformation effects."u8, 1) .RegisterEntry( - "The headers are now color-coded to distinguish between you and other players, and between NPCs that are handled locally or on the server. Colors are customizable.", + "The headers are now color-coded to distinguish between you and other players, and between NPCs that are handled locally or on the server. Colors are customizable."u8, 1) - .RegisterEntry("More file types will be recognized and shown.", 1) - .RegisterEntry("The actual paths for game files will be displayed and copied correctly.", 1) - .RegisterEntry("The Shader editor has been improved (by Ny):") + .RegisterEntry("More file types will be recognized and shown."u8, 1) + .RegisterEntry("The actual paths for game files will be displayed and copied correctly."u8, 1) + .RegisterEntry("The Shader editor has been improved (by Ny):"u8) .RegisterEntry( - "New sections 'Shader Resources' and 'Shader Selection' have been added, expanding on some data that was in 'Further Content' before.", + "New sections 'Shader Resources' and 'Shader Selection' have been added, expanding on some data that was in 'Further Content' before."u8, 1) - .RegisterEntry("A fail-safe mode for shader decompilation on platforms that do not fully support it has been added.", 1) - .RegisterEntry("Fixed invalid game paths generated for variants of customizations.") - .RegisterEntry("Lots of minor improvements across the codebase.") - .RegisterEntry("Some unnamed mounts were made available for actor identification. (0.7.3.2)"); + .RegisterEntry("A fail-safe mode for shader decompilation on platforms that do not fully support it has been added."u8, 1) + .RegisterEntry("Fixed invalid game paths generated for variants of customizations."u8) + .RegisterEntry("Lots of minor improvements across the codebase."u8) + .RegisterEntry("Some unnamed mounts were made available for actor identification. (0.7.3.2)"u8); private static void Add7_3_0(Changelog log) - => log.NextVersion("Version 0.7.3.0") + => log.NextVersion("Version 0.7.3.0"u8) .RegisterEntry( - "Added the ability to drag and drop mod files from external sources (like a file explorer or browser) into Penumbras mod selector to import them.") - .RegisterEntry("You can also drag and drop texture files into the textures tab of the Advanced Editing Window.", 1) + "Added the ability to drag and drop mod files from external sources (like a file explorer or browser) into Penumbras mod selector to import them."u8) + .RegisterEntry("You can also drag and drop texture files into the textures tab of the Advanced Editing Window."u8, 1) .RegisterEntry( - "Added a priority display to the mod selector using the currently selected collections priorities. This can be hidden in settings.") - .RegisterEntry("Added IPC for texture conversion, improved texture handling backend and threading.") + "Added a priority display to the mod selector using the currently selected collections priorities. This can be hidden in settings."u8) + .RegisterEntry("Added IPC for texture conversion, improved texture handling backend and threading."u8) .RegisterEntry( - "Added Dalamud Substitution so that other plugins can more easily use replaced icons from Penumbras Interface collection when using Dalamuds new Texture Provider.") - .RegisterEntry("Added a filter to texture selection combos in the textures tab of the Advanced Editing Window.") + "Added Dalamud Substitution so that other plugins can more easily use replaced icons from Penumbras Interface collection when using Dalamuds new Texture Provider."u8) + .RegisterEntry("Added a filter to texture selection combos in the textures tab of the Advanced Editing Window."u8) .RegisterEntry( - "Changed behaviour when failing to load group JSON files for mods - the pre-existing but failing files are now backed up before being deleted or overwritten.") - .RegisterEntry("Further backend changes, mostly relating to the Glamourer rework.") - .RegisterEntry("Fixed an issue with modded decals not loading correctly when used with the Glamourer rework.") - .RegisterEntry("Fixed missing scaling with UI Scale for some combos.") - .RegisterEntry("Updated the used version of SharpCompress to deal with Zip64 correctly.") - .RegisterEntry("Added a toggle to not display the Changed Item categories in settings (0.7.2.2).") - .RegisterEntry("Many backend changes relating to the Glamourer rework (0.7.2.2).") - .RegisterEntry("Fixed an issue when multiple options in the same option group had the same label (0.7.2.2).") - .RegisterEntry("Fixed an issue with a GPose condition breaking animation and vfx modding in GPose (0.7.2.1).") - .RegisterEntry("Fixed some handling of decals (0.7.2.1)."); + "Changed behaviour when failing to load group JSON files for mods - the pre-existing but failing files are now backed up before being deleted or overwritten."u8) + .RegisterEntry("Further backend changes, mostly relating to the Glamourer rework."u8) + .RegisterEntry("Fixed an issue with modded decals not loading correctly when used with the Glamourer rework."u8) + .RegisterEntry("Fixed missing scaling with UI Scale for some combos."u8) + .RegisterEntry("Updated the used version of SharpCompress to deal with Zip64 correctly."u8) + .RegisterEntry("Added a toggle to not display the Changed Item categories in settings (0.7.2.2)."u8) + .RegisterEntry("Many backend changes relating to the Glamourer rework (0.7.2.2)."u8) + .RegisterEntry("Fixed an issue when multiple options in the same option group had the same label (0.7.2.2)."u8) + .RegisterEntry("Fixed an issue with a GPose condition breaking animation and vfx modding in GPose (0.7.2.1)."u8) + .RegisterEntry("Fixed some handling of decals (0.7.2.1)."u8); private static void Add7_2_0(Changelog log) - => log.NextVersion("Version 0.7.2.0") + => log.NextVersion("Version 0.7.2.0"u8) .RegisterEntry( - "Added Changed Item Categories and icons that can filter for specific types of Changed Items, in the Changed Items Tab as well as in the Changed Items panel for specific mods..") + "Added Changed Item Categories and icons that can filter for specific types of Changed Items, in the Changed Items Tab as well as in the Changed Items panel for specific mods.."u8) .RegisterEntry( - "Icons at the top can be clicked to filter, as well as right-clicked to open a context menu with the option to inverse-filter for them", + "Icons at the top can be clicked to filter, as well as right-clicked to open a context menu with the option to inverse-filter for them"u8, 1) - .RegisterEntry("There is also an ALL button that can be toggled.", 1) + .RegisterEntry("There is also an ALL button that can be toggled."u8, 1) .RegisterEntry( - "Modded files in the Font category now resolve from the Interface assignment instead of the base assignment, despite not technically being in the UI category.") + "Modded files in the Font category now resolve from the Interface assignment instead of the base assignment, despite not technically being in the UI category."u8) .RegisterEntry( - "Timeline files will no longer be associated with specific characters in cutscenes, since there is no way to correctly do this, and it could cause crashes if IVCS-requiring animations were used on characters without IVCS.") - .RegisterEntry("File deletion in the Advanced Editing Window now also checks for your configured deletion key combo.") + "Timeline files will no longer be associated with specific characters in cutscenes, since there is no way to correctly do this, and it could cause crashes if IVCS-requiring animations were used on characters without IVCS."u8) + .RegisterEntry("File deletion in the Advanced Editing Window now also checks for your configured deletion key combo."u8) .RegisterEntry( - "The Texture tab in the Advanced Editing Window now has some quick convert buttons to just convert the selected texture to a different format in-place.") + "The Texture tab in the Advanced Editing Window now has some quick convert buttons to just convert the selected texture to a different format in-place."u8) .RegisterEntry( - "These buttons only appear if only one texture is selected on the left side, it is not otherwise manipulated, and the texture is a .tex file.", + "These buttons only appear if only one texture is selected on the left side, it is not otherwise manipulated, and the texture is a .tex file."u8, 1) - .RegisterEntry("The text part of the mod filter in the mod selector now also resets when right-clicking the drop-down arrow.") - .RegisterEntry("The Dissolve Folder option in the mod selector context menu has been moved to the bottom.") - .RegisterEntry("Somewhat improved IMC handling to prevent some issues.") + .RegisterEntry("The text part of the mod filter in the mod selector now also resets when right-clicking the drop-down arrow."u8) + .RegisterEntry("The Dissolve Folder option in the mod selector context menu has been moved to the bottom."u8) + .RegisterEntry("Somewhat improved IMC handling to prevent some issues."u8) .RegisterEntry( - "Improved the handling of mod renames on mods with default-search names to correctly rename their search-name in (hopefully) all cases too.") - .RegisterEntry("A lot of backend improvements and changes related to the pending Glamourer rework.") - .RegisterEntry("Fixed an issue where the displayed active collection count in the support info was wrong.") + "Improved the handling of mod renames on mods with default-search names to correctly rename their search-name in (hopefully) all cases too."u8) + .RegisterEntry("A lot of backend improvements and changes related to the pending Glamourer rework."u8) + .RegisterEntry("Fixed an issue where the displayed active collection count in the support info was wrong."u8) .RegisterEntry( - "Fixed an issue with created directories dealing badly with non-standard whitespace characters like half-width or non-breaking spaces.") - .RegisterEntry("Fixed an issue with unknown animation and vfx edits not being recognized correctly.") - .RegisterEntry("Fixed an issue where changing option descriptions to be empty was not working correctly.") - .RegisterEntry("Fixed an issue with texture names in the resource tree of the On-Screen views.") - .RegisterEntry("Fixed a bug where the game would crash when drawing folders in the mod selector that contained a '%' symbol.") - .RegisterEntry("Fixed an issue with parallel algorithms obtaining the wrong number of available cores.") - .RegisterEntry("Updated the available selection of Battle NPC names.") - .RegisterEntry("A typo in the 0.7.1.2 Changlog has been fixed.") - .RegisterEntry("Added the Sea of Stars as accepted repository. (0.7.1.4)") - .RegisterEntry("Fixed an issue with collections sometimes not loading correctly, and IMC files not applying correctly. (0.7.1.3)"); + "Fixed an issue with created directories dealing badly with non-standard whitespace characters like half-width or non-breaking spaces."u8) + .RegisterEntry("Fixed an issue with unknown animation and vfx edits not being recognized correctly."u8) + .RegisterEntry("Fixed an issue where changing option descriptions to be empty was not working correctly."u8) + .RegisterEntry("Fixed an issue with texture names in the resource tree of the On-Screen views."u8) + .RegisterEntry("Fixed a bug where the game would crash when drawing folders in the mod selector that contained a '%' symbol."u8) + .RegisterEntry("Fixed an issue with parallel algorithms obtaining the wrong number of available cores."u8) + .RegisterEntry("Updated the available selection of Battle NPC names."u8) + .RegisterEntry("A typo in the 0.7.1.2 Changlog has been fixed."u8) + .RegisterEntry("Added the Sea of Stars as accepted repository. (0.7.1.4)"u8) + .RegisterEntry( + "Fixed an issue with collections sometimes not loading correctly, and IMC files not applying correctly. (0.7.1.3)"u8); private static void Add7_1_2(Changelog log) - => log.NextVersion("Version 0.7.1.2") + => log.NextVersion("Version 0.7.1.2"u8) .RegisterEntry( - "Changed threaded handling of collection caches. Maybe this fixes the startup problems some people are experiencing.") + "Changed threaded handling of collection caches. Maybe this fixes the startup problems some people are experiencing."u8) .RegisterEntry( - "This is just testing and may not be the solution, or may even make things worse. Sorry if I have to put out multiple small patches again to get this right.", + "This is just testing and may not be the solution, or may even make things worse. Sorry if I have to put out multiple small patches again to get this right."u8, 1) - .RegisterEntry("Fixed Penumbra failing to load if the main configuration file is corrupted.") - .RegisterEntry("Some miscellaneous small bug fixes.") - .RegisterEntry("Slight changes in behaviour for deduplicator/normalizer, mostly backend.") - .RegisterEntry("A typo in the 0.7.1.0 Changelog has been fixed.") - .RegisterEntry("Fixed left rings not being valid for IMC entries after validation. (7.1.1)") + .RegisterEntry("Fixed Penumbra failing to load if the main configuration file is corrupted."u8) + .RegisterEntry("Some miscellaneous small bug fixes."u8) + .RegisterEntry("Slight changes in behaviour for deduplicator/normalizer, mostly backend."u8) + .RegisterEntry("A typo in the 0.7.1.0 Changelog has been fixed."u8) + .RegisterEntry("Fixed left rings not being valid for IMC entries after validation. (7.1.1)"u8) .RegisterEntry( - "Relaxed the scaling restrictions for RSP scaling values to go from 0.01 to 512.0 instead of the prior upper limit of 8.0, in interface as well as validation, to better support the fetish community. (7.1.1)"); + "Relaxed the scaling restrictions for RSP scaling values to go from 0.01 to 512.0 instead of the prior upper limit of 8.0, in interface as well as validation, to better support the fetish community. (7.1.1)"u8); private static void Add7_1_0(Changelog log) - => log.NextVersion("Version 0.7.1.0") - .RegisterEntry("Updated for patch 6.4 - there may be some oversights on edge cases, but I could not find any issues myself.") + => log.NextVersion("Version 0.7.1.0"u8) + .RegisterEntry("Updated for patch 6.4 - there may be some oversights on edge cases, but I could not find any issues myself."u8) .RegisterImportant( - "This update changed some Dragoon skills that were moving the player character before to not do that anymore. If you have any mods that applied to those skills, please make sure that they do not contain any redirections for .tmb files. If skills that should no longer move your character still do that for some reason, this is detectable by the server.", + "This update changed some Dragoon skills that were moving the player character before to not do that anymore. If you have any mods that applied to those skills, please make sure that they do not contain any redirections for .tmb files. If skills that should no longer move your character still do that for some reason, this is detectable by the server."u8, 1) .RegisterEntry( - "Added a Mod Merging tab in the Advanced Editing Window. This can help you merge multiple mods to one, or split off specific options from an existing mod into a new mod.") + "Added a Mod Merging tab in the Advanced Editing Window. This can help you merge multiple mods to one, or split off specific options from an existing mod into a new mod."u8) .RegisterEntry( - "Added advanced options to configure the minimum allowed window size for the main window (to reduce it). This is not quite supported and may look bad, so only use it if you really need smaller windows.") - .RegisterEntry("The last tab selected in the main window is now saved and re-used when relaunching Penumbra.") - .RegisterEntry("Added a hook to correctly associate some sounds that are played while weapons are drawn.") - .RegisterEntry("Added a hook to correctly associate sounds that are played while dismounting.") - .RegisterEntry("A hook to associate weapon-associated VFX was expanded to work in more cases.") - .RegisterEntry("TMB resources now use a collection prefix to prevent retained state in some cases.") - .RegisterEntry("Improved startup times a bit.") - .RegisterEntry("Right-Click context menus for collections are now also ordered by name.") - .RegisterEntry("Advanced Editing tabs have been reordered and renamed slightly.") - .RegisterEntry("Added some validation of metadata changes to prevent stalling on load of bad IMC edits.") - .RegisterEntry("Fixed an issue where collections could lose their configured inheritances during startup in some cases.") - .RegisterEntry("Fixed some bugs when mods were removed from collection caches.") - .RegisterEntry("Fixed some bugs with IMC files not correctly reverting to default values in some cases.") - .RegisterEntry("Fixed an issue with the mod import popup not appearing (0.7.0.10)") - .RegisterEntry("Fixed an issue with the file selectors not always opening at the expected locations. (0.7.0.7)") - .RegisterEntry("Fixed some cache handling issues. (0.7.0.5 - 0.7.0.10)") - .RegisterEntry("Fixed an issue with multiple collection context menus appearing for some identifiers (0.7.0.5)") + "Added advanced options to configure the minimum allowed window size for the main window (to reduce it). This is not quite supported and may look bad, so only use it if you really need smaller windows."u8) + .RegisterEntry("The last tab selected in the main window is now saved and re-used when relaunching Penumbra."u8) + .RegisterEntry("Added a hook to correctly associate some sounds that are played while weapons are drawn."u8) + .RegisterEntry("Added a hook to correctly associate sounds that are played while dismounting."u8) + .RegisterEntry("A hook to associate weapon-associated VFX was expanded to work in more cases."u8) + .RegisterEntry("TMB resources now use a collection prefix to prevent retained state in some cases."u8) + .RegisterEntry("Improved startup times a bit."u8) + .RegisterEntry("Right-Click context menus for collections are now also ordered by name."u8) + .RegisterEntry("Advanced Editing tabs have been reordered and renamed slightly."u8) + .RegisterEntry("Added some validation of metadata changes to prevent stalling on load of bad IMC edits."u8) + .RegisterEntry("Fixed an issue where collections could lose their configured inheritances during startup in some cases."u8) + .RegisterEntry("Fixed some bugs when mods were removed from collection caches."u8) + .RegisterEntry("Fixed some bugs with IMC files not correctly reverting to default values in some cases."u8) + .RegisterEntry("Fixed an issue with the mod import popup not appearing (0.7.0.10)"u8) + .RegisterEntry("Fixed an issue with the file selectors not always opening at the expected locations. (0.7.0.7)"u8) + .RegisterEntry("Fixed some cache handling issues. (0.7.0.5 - 0.7.0.10)"u8) + .RegisterEntry("Fixed an issue with multiple collection context menus appearing for some identifiers (0.7.0.5)"u8) .RegisterEntry( - "Fixed an issue where the Update Bibo button did only work if the Advanced Editing window was opened before. (0.7.0.5)"); + "Fixed an issue where the Update Bibo button did only work if the Advanced Editing window was opened before. (0.7.0.5)"u8); private static void Add7_0_4(Changelog log) - => log.NextVersion("Version 0.7.0.4") - .RegisterEntry("Added options to the bulktag slash command to check all/local/mod tags specifically.") - .RegisterEntry("Possibly improved handling of the delayed loading of individual assignments.") - .RegisterEntry("Fixed a bug that caused metadata edits to apply even though mods were disabled.") - .RegisterEntry("Fixed a bug that prevented material reassignments from working.") - .RegisterEntry("Reverted trimming of whitespace for relative paths to only trim the end, not the start. (0.7.0.3)") - .RegisterEntry("Fixed a bug that caused an integer overflow on textures of high dimensions. (0.7.0.3)") - .RegisterEntry("Fixed a bug that caused Penumbra to enter invalid state when deleting mods. (0.7.0.2)") - .RegisterEntry("Added Notification on invalid collection names. (0.7.0.2)"); + => log.NextVersion("Version 0.7.0.4"u8) + .RegisterEntry("Added options to the bulktag slash command to check all/local/mod tags specifically."u8) + .RegisterEntry("Possibly improved handling of the delayed loading of individual assignments."u8) + .RegisterEntry("Fixed a bug that caused metadata edits to apply even though mods were disabled."u8) + .RegisterEntry("Fixed a bug that prevented material reassignments from working."u8) + .RegisterEntry("Reverted trimming of whitespace for relative paths to only trim the end, not the start. (0.7.0.3)"u8) + .RegisterEntry("Fixed a bug that caused an integer overflow on textures of high dimensions. (0.7.0.3)"u8) + .RegisterEntry("Fixed a bug that caused Penumbra to enter invalid state when deleting mods. (0.7.0.2)"u8) + .RegisterEntry("Added Notification on invalid collection names. (0.7.0.2)"u8); private static void Add7_0_1(Changelog log) - => log.NextVersion("Version 0.7.0.1") - .RegisterEntry("Individual assignments can again be re-ordered by drag-and-dropping them.") - .RegisterEntry("Relax the restriction of a maximum of 32 characters for collection names to 64 characters.") - .RegisterEntry("Fixed a bug that showed the Your Character collection as redundant even if it was not.") - .RegisterEntry("Fixed a bug that caused some required collection caches to not be built on startup and thus mods not to apply.") - .RegisterEntry("Fixed a bug that showed the current collection as unused even if it was used."); + => log.NextVersion("Version 0.7.0.1"u8) + .RegisterEntry("Individual assignments can again be re-ordered by drag-and-dropping them."u8) + .RegisterEntry("Relax the restriction of a maximum of 32 characters for collection names to 64 characters."u8) + .RegisterEntry("Fixed a bug that showed the Your Character collection as redundant even if it was not."u8) + .RegisterEntry("Fixed a bug that caused some required collection caches to not be built on startup and thus mods not to apply."u8) + .RegisterEntry("Fixed a bug that showed the current collection as unused even if it was used."u8); private static void Add7_0_0(Changelog log) - => log.NextVersion("Version 0.7.0.0") + => log.NextVersion("Version 0.7.0.0"u8) .RegisterImportant( - "The entire backend was reworked (this is still in progress). While this does not come with a lot of functionality changes, basically every file and functionality was touched.") + "The entire backend was reworked (this is still in progress). While this does not come with a lot of functionality changes, basically every file and functionality was touched."u8) .RegisterEntry( - "This may have (re-)introduced some bugs that have not yet been noticed despite a long testing period - there are not many users of the testing branch.", + "This may have (re-)introduced some bugs that have not yet been noticed despite a long testing period - there are not many users of the testing branch."u8, 1) - .RegisterEntry("If you encounter any - but especially breaking or lossy - bugs, please report them immediately.", 1) - .RegisterEntry("This also fixed or improved numerous bugs and issues that will not be listed here.", 1) - .RegisterEntry("GitHub currently reports 321 changed files with 34541 additions and 28464 deletions.", 1) - .RegisterEntry("Added Notifications on many failures that previously only wrote to log.") - .RegisterEntry("Reworked the Collections Tab to hopefully be much more intuitive. It should be self-explanatory now.") - .RegisterEntry("The tutorial was adapted to the new window, if you are unsure, maybe try restarting it.", 1) + .RegisterEntry("If you encounter any - but especially breaking or lossy - bugs, please report them immediately."u8, 1) + .RegisterEntry("This also fixed or improved numerous bugs and issues that will not be listed here."u8, 1) + .RegisterEntry("GitHub currently reports 321 changed files with 34541 additions and 28464 deletions."u8, 1) + .RegisterEntry("Added Notifications on many failures that previously only wrote to log."u8) + .RegisterEntry("Reworked the Collections Tab to hopefully be much more intuitive. It should be self-explanatory now."u8) + .RegisterEntry("The tutorial was adapted to the new window, if you are unsure, maybe try restarting it."u8, 1) .RegisterEntry( - "You can now toggle an incognito mode in the collection window so it shows shortened names of collections and players.", 1) + "You can now toggle an incognito mode in the collection window so it shows shortened names of collections and players."u8, 1) .RegisterEntry( - "You can get an overview about the current usage of a selected collection and its active and unused mod settings in the Collection Details panel.", + "You can get an overview about the current usage of a selected collection and its active and unused mod settings in the Collection Details panel."u8, 1) - .RegisterEntry("The currently selected collection is now highlighted in green (default, configurable) in multiple places.", 1) + .RegisterEntry("The currently selected collection is now highlighted in green (default, configurable) in multiple places."u8, 1) .RegisterEntry( - "Mods now have a 'Collections' panel in the Mod Panel containing an overview about usage of the mod in all collections.") - .RegisterEntry("The 'Changed Items' and 'Effective Changes' tab now contain a collection selector.") - .RegisterEntry("Added the On-Screen tab to find what files a specific character is actually using (by Ny).") - .RegisterEntry("Added 3 Quick Move folders in the mod selector that can be setup in context menus for easier cleanup.") + "Mods now have a 'Collections' panel in the Mod Panel containing an overview about usage of the mod in all collections."u8) + .RegisterEntry("The 'Changed Items' and 'Effective Changes' tab now contain a collection selector."u8) + .RegisterEntry("Added the On-Screen tab to find what files a specific character is actually using (by Ny)."u8) + .RegisterEntry("Added 3 Quick Move folders in the mod selector that can be setup in context menus for easier cleanup."u8) .RegisterEntry( - "Added handling for certain animation files for mounts and fashion accessories to correctly associate them to players.") - .RegisterEntry("The file selectors in the Advanced Mod Editing Window now use filterable combos.") + "Added handling for certain animation files for mounts and fashion accessories to correctly associate them to players."u8) + .RegisterEntry("The file selectors in the Advanced Mod Editing Window now use filterable combos."u8) .RegisterEntry( - "The Advanced Mod Editing Window now shows the number of meta edits and file swaps in unselected options and highlights the option selector.") - .RegisterEntry("Added API/IPC to start unpacking and installing mods from external tools (by Sebastina).") - .RegisterEntry("Hidden files and folders are now ignored for unused files in Advanced Mod Editing (by myr)") - .RegisterEntry("Paths in mods are now automatically trimmed of whitespace on loading.") - .RegisterEntry("Fixed double 'by' in mod author display (by Caraxi).") - .RegisterEntry("Fixed a crash when trying to obtain names from the game data.") - .RegisterEntry("Fixed some issues with tutorial windows.") - .RegisterEntry("Fixed some bugs in the Resource Logger.") - .RegisterEntry("Fixed Button Sizing for collapsible groups and several related bugs.") - .RegisterEntry("Fixed issue with mods with default settings other than 0.") - .RegisterEntry("Fixed issue with commands not registering on startup. (0.6.6.5)") - .RegisterEntry("Improved Startup Times and Time Tracking. (0.6.6.4)") - .RegisterEntry("Add Item Swapping between different types of Accessories and Hats. (0.6.6.4)") - .RegisterEntry("Fixed bugs with assignment of temporary collections and their deletion. (0.6.6.4)") - .RegisterEntry("Fixed bugs with new file loading mechanism. (0.6.6.2, 0.6.6.3)") - .RegisterEntry("Added API/IPC to open and close the main window and select specific tabs and mods. (0.6.6.2)"); + "The Advanced Mod Editing Window now shows the number of meta edits and file swaps in unselected options and highlights the option selector."u8) + .RegisterEntry("Added API/IPC to start unpacking and installing mods from external tools (by Sebastina)."u8) + .RegisterEntry("Hidden files and folders are now ignored for unused files in Advanced Mod Editing (by myr)"u8) + .RegisterEntry("Paths in mods are now automatically trimmed of whitespace on loading."u8) + .RegisterEntry("Fixed double 'by' in mod author display (by Caraxi)."u8) + .RegisterEntry("Fixed a crash when trying to obtain names from the game data."u8) + .RegisterEntry("Fixed some issues with tutorial windows."u8) + .RegisterEntry("Fixed some bugs in the Resource Logger."u8) + .RegisterEntry("Fixed Button Sizing for collapsible groups and several related bugs."u8) + .RegisterEntry("Fixed issue with mods with default settings other than 0."u8) + .RegisterEntry("Fixed issue with commands not registering on startup. (0.6.6.5)"u8) + .RegisterEntry("Improved Startup Times and Time Tracking. (0.6.6.4)"u8) + .RegisterEntry("Add Item Swapping between different types of Accessories and Hats. (0.6.6.4)"u8) + .RegisterEntry("Fixed bugs with assignment of temporary collections and their deletion. (0.6.6.4)"u8) + .RegisterEntry("Fixed bugs with new file loading mechanism. (0.6.6.2, 0.6.6.3)"u8) + .RegisterEntry("Added API/IPC to open and close the main window and select specific tabs and mods. (0.6.6.2)"u8); private static void Add6_6_1(Changelog log) - => log.NextVersion("Version 0.6.6.1") - .RegisterEntry("Added an option to make successful chat commands not print their success confirmations to chat.") - .RegisterEntry("Fixed an issue with migration of old mods not working anymore (fixes Material UI problems).") - .RegisterEntry("Fixed some issues with using the Assign Current Player and Assign Current Target buttons."); + => log.NextVersion("Version 0.6.6.1"u8) + .RegisterEntry("Added an option to make successful chat commands not print their success confirmations to chat."u8) + .RegisterEntry("Fixed an issue with migration of old mods not working anymore (fixes Material UI problems)."u8) + .RegisterEntry("Fixed some issues with using the Assign Current Player and Assign Current Target buttons."u8); private static void Add6_6_0(Changelog log) - => log.NextVersion("Version 0.6.6.0") + => log.NextVersion("Version 0.6.6.0"u8) .RegisterEntry( - "Added new Collection Assignment Groups for Children NPC and Elderly NPC. Those take precedence before any non-individual assignments for any NPC using a child- or elderly model respectively.") + "Added new Collection Assignment Groups for Children NPC and Elderly NPC. Those take precedence before any non-individual assignments for any NPC using a child- or elderly model respectively."u8) .RegisterEntry( - "Added an option to display Single Selection Groups as a group of radio buttons similar to Multi Selection Groups, when the number of available options is below the specified value. Default value is 2.") - .RegisterEntry("Added a button in option groups to collapse the option list if it has more than 5 available options.") + "Added an option to display Single Selection Groups as a group of radio buttons similar to Multi Selection Groups, when the number of available options is below the specified value. Default value is 2."u8) + .RegisterEntry("Added a button in option groups to collapse the option list if it has more than 5 available options."u8) .RegisterEntry( - "Penumbra now circumvents the games inability to read files at paths longer than 260 UTF16 characters and can also deal with generic unicode symbols in paths.") + "Penumbra now circumvents the games inability to read files at paths longer than 260 UTF16 characters and can also deal with generic unicode symbols in paths."u8) .RegisterEntry( - "This means that Penumbra should no longer cause issues when files become too long or when there is a non-ASCII character in them.", + "This means that Penumbra should no longer cause issues when files become too long or when there is a non-ASCII character in them."u8, 1) .RegisterEntry( - "Shorter paths are still better, so restrictions on the root directory have not been relaxed. Mod names should no longer replace non-ASCII symbols on import though.", + "Shorter paths are still better, so restrictions on the root directory have not been relaxed. Mod names should no longer replace non-ASCII symbols on import though."u8, 1) .RegisterEntry( - "Resource logging has been relegated to its own tab with better filtering. Please do not keep resource logging on arbitrarily or set a low record limit if you do, otherwise this eats a lot of performance and memory after a while.") + "Resource logging has been relegated to its own tab with better filtering. Please do not keep resource logging on arbitrarily or set a low record limit if you do, otherwise this eats a lot of performance and memory after a while."u8) .RegisterEntry( - "Added a lot of facilities to edit the shader part of .mtrl files and .shpk files themselves in the Advanced Editing Tab (Thanks Ny and aers).") - .RegisterEntry("Added splitting of Multi Selection Groups with too many options when importing .pmp files or adding mods via IPC.") - .RegisterEntry("Discovery, Reloading and Unloading of a specified mod is now possible via HTTP API (Thanks Sebastina).") - .RegisterEntry("Cleaned up the HTTP API somewhat, removed currently useless options.") - .RegisterEntry("Fixed an issue when extracting some textures.") - .RegisterEntry("Fixed an issue with mannequins inheriting individual assignments for the current player when using ownership.") + "Added a lot of facilities to edit the shader part of .mtrl files and .shpk files themselves in the Advanced Editing Tab (Thanks Ny and aers)."u8) .RegisterEntry( - "Fixed an issue with the resolving of .phyb and .sklb files for Item Swaps of head or body items with an EST entry but no unique racial model."); + "Added splitting of Multi Selection Groups with too many options when importing .pmp files or adding mods via IPC."u8) + .RegisterEntry("Discovery, Reloading and Unloading of a specified mod is now possible via HTTP API (Thanks Sebastina)."u8) + .RegisterEntry("Cleaned up the HTTP API somewhat, removed currently useless options."u8) + .RegisterEntry("Fixed an issue when extracting some textures."u8) + .RegisterEntry("Fixed an issue with mannequins inheriting individual assignments for the current player when using ownership."u8) + .RegisterEntry( + "Fixed an issue with the resolving of .phyb and .sklb files for Item Swaps of head or body items with an EST entry but no unique racial model."u8); private static void Add6_5_2(Changelog log) - => log.NextVersion("Version 0.6.5.2") - .RegisterEntry("Updated for game version 6.31 Hotfix.") + => log.NextVersion("Version 0.6.5.2"u8) + .RegisterEntry("Updated for game version 6.31 Hotfix."u8) .RegisterEntry( - "Added option-specific descriptions for mods, instead of having just descriptions for groups of options. (Thanks Caraxi!)") - .RegisterEntry("Those are now accurately parsed from TTMPs, too.", 1) - .RegisterEntry("Improved launch times somewhat through parallelization of some tasks.") + "Added option-specific descriptions for mods, instead of having just descriptions for groups of options. (Thanks Caraxi!)"u8) + .RegisterEntry("Those are now accurately parsed from TTMPs, too."u8, 1) + .RegisterEntry("Improved launch times somewhat through parallelization of some tasks."u8) .RegisterEntry( - "Added some performance tracking for start-up durations and for real time data to Release builds. They can be seen and enabled in the Debug tab when Debug Mode is enabled.") - .RegisterEntry("Fixed an issue with IMC changes and Mare Synchronos interoperability.") - .RegisterEntry("Fixed an issue with housing mannequins crashing the game when resource logging was enabled.") - .RegisterEntry("Fixed an issue generating Mip Maps for texture import on Wine."); + "Added some performance tracking for start-up durations and for real time data to Release builds. They can be seen and enabled in the Debug tab when Debug Mode is enabled."u8) + .RegisterEntry("Fixed an issue with IMC changes and Mare Synchronos interoperability."u8) + .RegisterEntry("Fixed an issue with housing mannequins crashing the game when resource logging was enabled."u8) + .RegisterEntry("Fixed an issue generating Mip Maps for texture import on Wine."u8); private static void Add6_5_0(Changelog log) - => log.NextVersion("Version 0.6.5.0") - .RegisterEntry("Fixed an issue with Item Swaps not using applied IMC changes in some cases.") - .RegisterEntry("Improved error message on texture import when failing to create mip maps (slightly).") - .RegisterEntry("Tried to fix duty party banner identification again, also for the recommendation window this time.") - .RegisterEntry("Added batched IPC to improve Mare performance."); + => log.NextVersion("Version 0.6.5.0"u8) + .RegisterEntry("Fixed an issue with Item Swaps not using applied IMC changes in some cases."u8) + .RegisterEntry("Improved error message on texture import when failing to create mip maps (slightly)."u8) + .RegisterEntry("Tried to fix duty party banner identification again, also for the recommendation window this time."u8) + .RegisterEntry("Added batched IPC to improve Mare performance."u8); private static void Add6_4_0(Changelog log) - => log.NextVersion("Version 0.6.4.0") - .RegisterEntry("Fixed an issue with the identification of actors in the duty group portrait.") - .RegisterEntry("Fixed some issues with wrongly cached actors and resources.") - .RegisterEntry("Fixed animation handling after redraws (notably for PLD idle animations with a shield equipped).") - .RegisterEntry("Fixed an issue with collection listing API skipping one collection.") + => log.NextVersion("Version 0.6.4.0"u8) + .RegisterEntry("Fixed an issue with the identification of actors in the duty group portrait."u8) + .RegisterEntry("Fixed some issues with wrongly cached actors and resources."u8) + .RegisterEntry("Fixed animation handling after redraws (notably for PLD idle animations with a shield equipped)."u8) + .RegisterEntry("Fixed an issue with collection listing API skipping one collection."u8) .RegisterEntry( - "Fixed an issue with BGM files being sometimes loaded from other collections than the base collection, causing crashes.") + "Fixed an issue with BGM files being sometimes loaded from other collections than the base collection, causing crashes."u8) .RegisterEntry( - "Also distinguished file resolving for different file categories (improving performance) and disabled resolving for script files entirely.", + "Also distinguished file resolving for different file categories (improving performance) and disabled resolving for script files entirely."u8, 1) - .RegisterEntry("Some miscellaneous backend changes due to the Glamourer rework."); + .RegisterEntry("Some miscellaneous backend changes due to the Glamourer rework."u8); private static void Add6_3_0(Changelog log) - => log.NextVersion("Version 0.6.3.0") - .RegisterEntry("Add an Assign Current Target button for individual assignments") - .RegisterEntry("Try identifying all banner actors correctly for PvE duties, Crystalline Conflict and Mahjong.") - .RegisterEntry("Please let me know if this does not work for anything except identical twins.", 1) - .RegisterEntry("Add handling for the 3 new screen actors (now 8 total, for PvE dutie portraits).") - .RegisterEntry("Update the Battle NPC name database for 6.3.") - .RegisterEntry("Added API/IPC functions to obtain or set group or individual collections.") - .RegisterEntry("Maybe fix a problem with textures sometimes not loading from their corresponding collection.") - .RegisterEntry("Another try to fix a problem with the collection selectors breaking state.") - .RegisterEntry("Fix a problem identifying companions.") - .RegisterEntry("Fix a problem when deleting collections assigned to Groups.") + => log.NextVersion("Version 0.6.3.0"u8) + .RegisterEntry("Add an Assign Current Target button for individual assignments"u8) + .RegisterEntry("Try identifying all banner actors correctly for PvE duties, Crystalline Conflict and Mahjong."u8) + .RegisterEntry("Please let me know if this does not work for anything except identical twins."u8, 1) + .RegisterEntry("Add handling for the 3 new screen actors (now 8 total, for PvE dutie portraits)."u8) + .RegisterEntry("Update the Battle NPC name database for 6.3."u8) + .RegisterEntry("Added API/IPC functions to obtain or set group or individual collections."u8) + .RegisterEntry("Maybe fix a problem with textures sometimes not loading from their corresponding collection."u8) + .RegisterEntry("Another try to fix a problem with the collection selectors breaking state."u8) + .RegisterEntry("Fix a problem identifying companions."u8) + .RegisterEntry("Fix a problem when deleting collections assigned to Groups."u8) .RegisterEntry( - "Fix a problem when using the Assign Currently Played Character button and then logging onto a different character without restarting in between.") - .RegisterEntry("Some miscellaneous backend changes."); + "Fix a problem when using the Assign Currently Played Character button and then logging onto a different character without restarting in between."u8) + .RegisterEntry("Some miscellaneous backend changes."u8); private static void Add6_2_0(Changelog log) - => log.NextVersion("Version 0.6.2.0") - .RegisterEntry("Update Penumbra for .net7, Dalamud API 8 and patch 6.3.") - .RegisterEntry("Add a Bulktag chat command to toggle all mods with specific tags. (by SoyaX)") - .RegisterEntry("Add placeholder options for setting individual collections via chat command.") - .RegisterEntry("Add toggles to swap left and/or right rings separately for ring item swap.") - .RegisterEntry("Add handling for looping sound effects caused by animations in non-base collections.") - .RegisterEntry("Add an option to not use any mods at all in the Inspect/Try-On window.") - .RegisterEntry("Add handling for Mahjong actors.") - .RegisterEntry("Improve hint text for File Swaps in Advanced Editing, also inverted file swap display order.") - .RegisterEntry("Fix a problem where the collection selectors could get desynchronized after adding or deleting collections.") - .RegisterEntry("Fix a problem that could cause setting state to get desynchronized.") - .RegisterEntry("Fix an oversight where some special screen actors did not actually respect the settings made for them.") - .RegisterEntry("Add collection and associated game object to Full Resource Logging.") - .RegisterEntry("Add performance tracking for DEBUG-compiled versions (i.e. testing only).") - .RegisterEntry("Add some information to .mdl display and fix not respecting padding when reading them. (0.6.1.3)") - .RegisterEntry("Fix association of some vfx game objects. (0.6.1.3)") - .RegisterEntry("Stop forcing AVFX files to load synchronously. (0.6.1.3)") - .RegisterEntry("Fix an issue when incorporating deduplicated meta files. (0.6.1.2)"); + => log.NextVersion("Version 0.6.2.0"u8) + .RegisterEntry("Update Penumbra for .net7, Dalamud API 8 and patch 6.3."u8) + .RegisterEntry("Add a Bulktag chat command to toggle all mods with specific tags. (by SoyaX)"u8) + .RegisterEntry("Add placeholder options for setting individual collections via chat command."u8) + .RegisterEntry("Add toggles to swap left and/or right rings separately for ring item swap."u8) + .RegisterEntry("Add handling for looping sound effects caused by animations in non-base collections."u8) + .RegisterEntry("Add an option to not use any mods at all in the Inspect/Try-On window."u8) + .RegisterEntry("Add handling for Mahjong actors."u8) + .RegisterEntry("Improve hint text for File Swaps in Advanced Editing, also inverted file swap display order."u8) + .RegisterEntry("Fix a problem where the collection selectors could get desynchronized after adding or deleting collections."u8) + .RegisterEntry("Fix a problem that could cause setting state to get desynchronized."u8) + .RegisterEntry("Fix an oversight where some special screen actors did not actually respect the settings made for them."u8) + .RegisterEntry("Add collection and associated game object to Full Resource Logging."u8) + .RegisterEntry("Add performance tracking for DEBUG-compiled versions (i.e. testing only)."u8) + .RegisterEntry("Add some information to .mdl display and fix not respecting padding when reading them. (0.6.1.3)"u8) + .RegisterEntry("Fix association of some vfx game objects. (0.6.1.3)"u8) + .RegisterEntry("Stop forcing AVFX files to load synchronously. (0.6.1.3)"u8) + .RegisterEntry("Fix an issue when incorporating deduplicated meta files. (0.6.1.2)"u8); private static void Add6_1_1(Changelog log) - => log.NextVersion("Version 0.6.1.1") + => log.NextVersion("Version 0.6.1.1"u8) .RegisterEntry( - "Added a toggle to use all the effective changes from the entire currently selected collection for swaps, instead of the selected mod.") - .RegisterEntry("Fix using equipment paths for accessory swaps and thus accessory swaps not working at all") - .RegisterEntry("Fix issues with swaps with gender-locked gear where the models for the other gender do not exist.") - .RegisterEntry("Fix swapping universal hairstyles for midlanders breaking them for other races.") - .RegisterEntry("Add some actual error messages on failure to create item swaps.") - .RegisterEntry("Fix warnings about more than one affected item appearing for single items."); + "Added a toggle to use all the effective changes from the entire currently selected collection for swaps, instead of the selected mod."u8) + .RegisterEntry("Fix using equipment paths for accessory swaps and thus accessory swaps not working at all"u8) + .RegisterEntry("Fix issues with swaps with gender-locked gear where the models for the other gender do not exist."u8) + .RegisterEntry("Fix swapping universal hairstyles for midlanders breaking them for other races."u8) + .RegisterEntry("Add some actual error messages on failure to create item swaps."u8) + .RegisterEntry("Fix warnings about more than one affected item appearing for single items."u8); private static void Add6_1_0(Changelog log) - => log.NextVersion("Version 0.6.1.0 (Happy New Year! Edition)") - .RegisterEntry("Add a prototype for Item Swapping.") - .RegisterEntry("A new tab in Advanced Editing.", 1) - .RegisterEntry("Swapping of Hair, Tail, Ears, Equipment and Accessories is supported. Weapons and Faces may be coming.", 1) - .RegisterEntry("The manipulations currently in use by the selected mod with its currents settings (ignoring enabled state)" - + " should be used when creating the swap, but you can also just swap unmodded things.", 1) - .RegisterEntry("You can write a swap to a new mod, or to a new option in the currently selected mod.", 1) - .RegisterEntry("The swaps are not heavily tested yet, and may also be not perfectly efficient. Please leave feedback.", 1) - .RegisterEntry("More detailed help or explanations will be added later.", 1) - .RegisterEntry("Heavily improve Chat Commands. Use /penumbra help for more information.") - .RegisterEntry("Penumbra now considers meta manipulations for Changed Items.") - .RegisterEntry("Penumbra now tries to associate battle voices to specific actors, so that they work in collections.") + => log.NextVersion("Version 0.6.1.0 (Happy New Year! Edition)"u8) + .RegisterEntry("Add a prototype for Item Swapping."u8) + .RegisterEntry("A new tab in Advanced Editing."u8, 1) + .RegisterEntry("Swapping of Hair, Tail, Ears, Equipment and Accessories is supported. Weapons and Faces may be coming."u8, 1) + .RegisterEntry("The manipulations currently in use by the selected mod with its currents settings (ignoring enabled state)"u8 + + " should be used when creating the swap, but you can also just swap unmodded things."u8, 1) + .RegisterEntry("You can write a swap to a new mod, or to a new option in the currently selected mod."u8, 1) + .RegisterEntry("The swaps are not heavily tested yet, and may also be not perfectly efficient. Please leave feedback."u8, 1) + .RegisterEntry("More detailed help or explanations will be added later."u8, 1) + .RegisterEntry("Heavily improve Chat Commands. Use /penumbra help for more information."u8) + .RegisterEntry("Penumbra now considers meta manipulations for Changed Items."u8) + .RegisterEntry("Penumbra now tries to associate battle voices to specific actors, so that they work in collections."u8) .RegisterEntry( - "Heavily improve .atex and .avfx handling, Penumbra can now associate VFX to specific actors far better, including ground effects.") - .RegisterEntry("Improve some file handling for Mare-Interaction.") - .RegisterEntry("Add Equipment Slots to Demihuman IMC Edits.") + "Heavily improve .atex and .avfx handling, Penumbra can now associate VFX to specific actors far better, including ground effects."u8) + .RegisterEntry("Improve some file handling for Mare-Interaction."u8) + .RegisterEntry("Add Equipment Slots to Demihuman IMC Edits."u8) .RegisterEntry( - "Add a toggle to keep metadata edits that apply the default value (and thus do not really change anything) on import from TexTools .meta files.") - .RegisterEntry("Add an option to directly change the 'Wait For Plugins To Load'-Dalamud Option from Penumbra.") - .RegisterEntry("Add API to copy mod settings from one mod to another.") - .RegisterEntry("Fix a problem where creating individual collections did not trigger events.") - .RegisterEntry("Add a Hack to support Anamnesis Redrawing better. (0.6.0.6)") - .RegisterEntry("Fix another problem with the aesthetician. (0.6.0.6)") - .RegisterEntry("Fix a problem with the export directory not being respected. (0.6.0.6)"); + "Add a toggle to keep metadata edits that apply the default value (and thus do not really change anything) on import from TexTools .meta files."u8) + .RegisterEntry("Add an option to directly change the 'Wait For Plugins To Load'-Dalamud Option from Penumbra."u8) + .RegisterEntry("Add API to copy mod settings from one mod to another."u8) + .RegisterEntry("Fix a problem where creating individual collections did not trigger events."u8) + .RegisterEntry("Add a Hack to support Anamnesis Redrawing better. (0.6.0.6)"u8) + .RegisterEntry("Fix another problem with the aesthetician. (0.6.0.6)"u8) + .RegisterEntry("Fix a problem with the export directory not being respected. (0.6.0.6)"u8); private static void Add6_0_5(Changelog log) - => log.NextVersion("Version 0.6.0.5") - .RegisterEntry("Allow hyphen as last character in player and retainer names.") - .RegisterEntry("Fix various bugs with ownership and GPose.") - .RegisterEntry("Fix collection selectors not updating for new or deleted collections in some cases.") - .RegisterEntry("Fix Chocobos not being recognized correctly.") - .RegisterEntry("Fix some problems with UI actors.") - .RegisterEntry("Fix problems with aesthetician again."); + => log.NextVersion("Version 0.6.0.5"u8) + .RegisterEntry("Allow hyphen as last character in player and retainer names."u8) + .RegisterEntry("Fix various bugs with ownership and GPose."u8) + .RegisterEntry("Fix collection selectors not updating for new or deleted collections in some cases."u8) + .RegisterEntry("Fix Chocobos not being recognized correctly."u8) + .RegisterEntry("Fix some problems with UI actors."u8) + .RegisterEntry("Fix problems with aesthetician again."u8); private static void Add6_0_2(Changelog log) - => log.NextVersion("Version 0.6.0.2") - .RegisterEntry("Let Bell Retainer collections apply to retainer-named mannequins.") - .RegisterEntry("Added a few informations to a help marker for new individual assignments.") - .RegisterEntry("Fix bug with Demi Human IMC paths.") - .RegisterEntry("Fix Yourself collection not applying to UI actors.") - .RegisterEntry("Fix Yourself collection not applying during aesthetician."); + => log.NextVersion("Version 0.6.0.2"u8) + .RegisterEntry("Let Bell Retainer collections apply to retainer-named mannequins."u8) + .RegisterEntry("Added a few informations to a help marker for new individual assignments."u8) + .RegisterEntry("Fix bug with Demi Human IMC paths."u8) + .RegisterEntry("Fix Yourself collection not applying to UI actors."u8) + .RegisterEntry("Fix Yourself collection not applying during aesthetician."u8); private static void Add6_0_0(Changelog log) - => log.NextVersion("Version 0.6.0.0") - .RegisterEntry("Revamped Individual Collections:") - .RegisterEntry("You can now specify individual collections for players (by name) of specific worlds or any world.", 1) - .RegisterEntry("You can also specify NPCs (by grouped name and type of NPC), and owned NPCs (by specifying an NPC and a Player).", + => log.NextVersion("Version 0.6.0.0"u8) + .RegisterEntry("Revamped Individual Collections:"u8) + .RegisterEntry("You can now specify individual collections for players (by name) of specific worlds or any world."u8, 1) + .RegisterEntry("You can also specify NPCs (by grouped name and type of NPC), and owned NPCs (by specifying an NPC and a Player)."u8, 1) .RegisterImportant( - "Migration should move all current names that correspond to NPCs to the appropriate NPC group and all names that can be valid Player names to a Player of any world.", + "Migration should move all current names that correspond to NPCs to the appropriate NPC group and all names that can be valid Player names to a Player of any world."u8, 1) .RegisterImportant( - "Please look through your Individual Collections to verify everything migrated correctly and corresponds to the game object you want. You might also want to change the 'Player (Any World)' collections to your specific homeworld.", + "Please look through your Individual Collections to verify everything migrated correctly and corresponds to the game object you want. You might also want to change the 'Player (Any World)' collections to your specific homeworld."u8, 1) - .RegisterEntry("You can also manually sort your Individual Collections by drag and drop now.", 1) - .RegisterEntry("This new system is a pretty big rework, so please report any discrepancies or bugs you find.", 1) - .RegisterEntry("These changes made the specific ownership settings for Retainers and for preferring named over ownership obsolete.", - 1) - .RegisterEntry("General ownership can still be toggled and should apply in order of: Owned NPC > Owner (if enabled) > General NPC.", + .RegisterEntry("You can also manually sort your Individual Collections by drag and drop now."u8, 1) + .RegisterEntry("This new system is a pretty big rework, so please report any discrepancies or bugs you find."u8, 1) + .RegisterEntry( + "These changes made the specific ownership settings for Retainers and for preferring named over ownership obsolete."u8, 1) .RegisterEntry( - "Added NPC Model Parsing, changes in NPC models should now display the names of the changed game objects for most NPCs.") - .RegisterEntry("Changed Items now also display variant or subtype in addition to the model set ID where applicable.") - .RegisterEntry("Collection selectors can now be filtered by name.") - .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("New Special or Individual Assignments now default to your current Base assignment instead of None.") - .RegisterEntry("Improved Support Info somewhat.") - .RegisterEntry("Added Dye Previews for in-game dyes and dyeing templates in Material Editing.") - .RegisterEntry("Colorset Editing now allows for negative values in all cases.") - .RegisterEntry("Added Export buttons to .mdl and .mtrl previews in Advanced Editing.") - .RegisterEntry("File Selection in the .mdl and .mtrl tabs now shows one associated game path by default and all on hover.") + "General ownership can still be toggled and should apply in order of: Owned NPC > Owner (if enabled) > General NPC."u8, + 1) .RegisterEntry( - "Added the option to reduplicate and normalize a mod, restoring all duplicates and moving the files to appropriate folders. (Duplicates Tab in Advanced Editing)") + "Added NPC Model Parsing, changes in NPC models should now display the names of the changed game objects for most NPCs."u8) + .RegisterEntry("Changed Items now also display variant or subtype in addition to the model set ID where applicable."u8) + .RegisterEntry("Collection selectors can now be filtered by name."u8) + .RegisterEntry("Try to use Unicode normalization before replacing invalid path symbols on import for somewhat nicer paths."u8) + .RegisterEntry("Improved interface for group settings (minimally)."u8) + .RegisterEntry("New Special or Individual Assignments now default to your current Base assignment instead of None."u8) + .RegisterEntry("Improved Support Info somewhat."u8) + .RegisterEntry("Added Dye Previews for in-game dyes and dyeing templates in Material Editing."u8) + .RegisterEntry("Colorset Editing now allows for negative values in all cases."u8) + .RegisterEntry("Added Export buttons to .mdl and .mtrl previews in Advanced Editing."u8) + .RegisterEntry("File Selection in the .mdl and .mtrl tabs now shows one associated game path by default and all on hover."u8) .RegisterEntry( - "Added an option to re-export metadata changes to TexTools-typed .meta and .rgsp files. (Meta-Manipulations Tab in Advanced Editing)") - .RegisterEntry("Fixed several bugs with the incorporation of meta changes when not done during TTMP import.") - .RegisterEntry("Fixed a bug with RSP changes on non-base collections not applying correctly in some cases.") - .RegisterEntry("Fixed a bug when dragging options during mod edit.") - .RegisterEntry("Fixed a bug where sometimes the valid folder check caused issues.") - .RegisterEntry("Fixed a bug where collections with inheritances were newly saved on every load.") - .RegisterEntry("Fixed a bug where the /penumbra enable/disable command displayed the wrong message (functionality unchanged).") - .RegisterEntry("Mods without names or invalid mod folders are now warnings instead of errors.") - .RegisterEntry("Added IPC events for mod deletion, addition or moves, and resolving based on game objects.") - .RegisterEntry("Prevent a bug that allowed IPC to add Mods from outside the Penumbra root folder.") - .RegisterEntry("A lot of big backend changes."); + "Added the option to reduplicate and normalize a mod, restoring all duplicates and moving the files to appropriate folders. (Duplicates Tab in Advanced Editing)"u8) + .RegisterEntry( + "Added an option to re-export metadata changes to TexTools-typed .meta and .rgsp files. (Meta-Manipulations Tab in Advanced Editing)"u8) + .RegisterEntry("Fixed several bugs with the incorporation of meta changes when not done during TTMP import."u8) + .RegisterEntry("Fixed a bug with RSP changes on non-base collections not applying correctly in some cases."u8) + .RegisterEntry("Fixed a bug when dragging options during mod edit."u8) + .RegisterEntry("Fixed a bug where sometimes the valid folder check caused issues."u8) + .RegisterEntry("Fixed a bug where collections with inheritances were newly saved on every load."u8) + .RegisterEntry("Fixed a bug where the /penumbra enable/disable command displayed the wrong message (functionality unchanged)."u8) + .RegisterEntry("Mods without names or invalid mod folders are now warnings instead of errors."u8) + .RegisterEntry("Added IPC events for mod deletion, addition or moves, and resolving based on game objects."u8) + .RegisterEntry("Prevent a bug that allowed IPC to add Mods from outside the Penumbra root folder."u8) + .RegisterEntry("A lot of big backend changes."u8); private static void Add5_11_1(Changelog log) - => log.NextVersion("Version 0.5.11.1") + => log.NextVersion("Version 0.5.11.1"u8) .RegisterEntry( - "The 0.5.11.0 Update exposed an issue in Penumbras file-saving scheme that rarely could cause some, most or even all of your mods to lose their group information.") + "The 0.5.11.0 Update exposed an issue in Penumbras file-saving scheme that rarely could cause some, most or even all of your mods to lose their group information."u8) .RegisterEntry( - "If this has happened to you, you will need to reimport affected mods, or manually restore their groups. I am very sorry for that.", + "If this has happened to you, you will need to reimport affected mods, or manually restore their groups. I am very sorry for that."u8, 1) .RegisterEntry( - "I believe the problem is fixed with 0.5.11.1, but I can not be sure since it would occur only rarely. For the same reason, a testing build would not help (as it also did not with 0.5.11.0 itself).", + "I believe the problem is fixed with 0.5.11.1, but I can not be sure since it would occur only rarely. For the same reason, a testing build would not help (as it also did not with 0.5.11.0 itself)."u8, 1) .RegisterImportant( - "If you do encounter this or similar problems in 0.5.11.1, please immediately let me know in Discord so I can revert the update again.", + "If you do encounter this or similar problems in 0.5.11.1, please immediately let me know in Discord so I can revert the update again."u8, 1); private static void Add5_11_0(Changelog log) - => log.NextVersion("Version 0.5.11.0") + => log.NextVersion("Version 0.5.11.0"u8) .RegisterEntry( - "Added local data storage for mods in the plugin config folder. This information is not exported together with your mod, but not dependent on collections.") - .RegisterEntry("Moved the import date from mod metadata to local data.", 1) - .RegisterEntry("Added Favorites. You can declare mods as favorites and filter for them.", 1) - .RegisterEntry("Added Local Tags. You can apply custom Tags to mods and filter for them.", 1) + "Added local data storage for mods in the plugin config folder. This information is not exported together with your mod, but not dependent on collections."u8) + .RegisterEntry("Moved the import date from mod metadata to local data."u8, 1) + .RegisterEntry("Added Favorites. You can declare mods as favorites and filter for them."u8, 1) + .RegisterEntry("Added Local Tags. You can apply custom Tags to mods and filter for them."u8, 1) .RegisterEntry( - "Added Mod Tags. Mod Creators (and the Edit Mod tab) can set tags that are stored in the mod meta data and are thus exported.") - .RegisterEntry("Add backface and transparency toggles to .mtrl editing, as well as a info section.") - .RegisterEntry("Meta Manipulation editing now highlights if the selected ID is 0 or 1.") - .RegisterEntry("Fixed a bug when manually adding EQP or EQDP entries to Mods.") - .RegisterEntry("Updated some tooltips and hints.") - .RegisterEntry("Improved handling of IMC exception problems.") - .RegisterEntry("Fixed a bug with misidentification of equipment decals.") + "Added Mod Tags. Mod Creators (and the Edit Mod tab) can set tags that are stored in the mod meta data and are thus exported."u8) + .RegisterEntry("Add backface and transparency toggles to .mtrl editing, as well as a info section."u8) + .RegisterEntry("Meta Manipulation editing now highlights if the selected ID is 0 or 1."u8) + .RegisterEntry("Fixed a bug when manually adding EQP or EQDP entries to Mods."u8) + .RegisterEntry("Updated some tooltips and hints."u8) + .RegisterEntry("Improved handling of IMC exception problems."u8) + .RegisterEntry("Fixed a bug with misidentification of equipment decals."u8) .RegisterEntry( - "Character collections can now be set via chat command, too. (/penumbra collection character | )") - .RegisterEntry("Backend changes regarding API/IPC, consumers can but do not need to use the Penumbra.Api library as a submodule.") - .RegisterEntry("Added API to delete mods and read and set their pseudo-filesystem paths.", 1) - .RegisterEntry("Added API to check Penumbras enabled state and updates to it.", 1); + "Character collections can now be set via chat command, too. (/penumbra collection character | )"u8) + .RegisterEntry("Backend changes regarding API/IPC, consumers can but do not need to use the Penumbra.Api library as a submodule."u8) + .RegisterEntry("Added API to delete mods and read and set their pseudo-filesystem paths."u8, 1) + .RegisterEntry("Added API to check Penumbras enabled state and updates to it."u8, 1); private static void Add5_10_0(Changelog log) - => log.NextVersion("Version 0.5.10.0") - .RegisterEntry("Renamed backup functionality to export functionality.") - .RegisterEntry("A default export directory can now optionally be specified.") - .RegisterEntry("If left blank, exports will still be stored in your mod directory.", 1) - .RegisterEntry("Existing exports corresponding to existing mods will be moved automatically if the export directory is changed.", + => log.NextVersion("Version 0.5.10.0"u8) + .RegisterEntry("Renamed backup functionality to export functionality."u8) + .RegisterEntry("A default export directory can now optionally be specified."u8) + .RegisterEntry("If left blank, exports will still be stored in your mod directory."u8, 1) + .RegisterEntry("Existing exports corresponding to existing mods will be moved automatically if the export directory is changed."u8, 1) - .RegisterEntry("Added buttons to export and import all color set rows at once during material editing.") - .RegisterEntry("Fixed texture import being case sensitive on the extension.") - .RegisterEntry("Fixed special collection selector increasing in size on non-default UI styling.") - .RegisterEntry("Fixed color set rows not importing the dye values during material editing.") - .RegisterEntry("Other miscellaneous small fixes."); + .RegisterEntry("Added buttons to export and import all color set rows at once during material editing."u8) + .RegisterEntry("Fixed texture import being case sensitive on the extension."u8) + .RegisterEntry("Fixed special collection selector increasing in size on non-default UI styling."u8) + .RegisterEntry("Fixed color set rows not importing the dye values during material editing."u8) + .RegisterEntry("Other miscellaneous small fixes."u8); private static void Add5_9_0(Changelog log) - => log.NextVersion("Version 0.5.9.0") - .RegisterEntry("Special Collections are now split between male and female.") - .RegisterEntry("Fix a bug where the Base and Interface Collection were set to None instead of Default on a fresh install.") - .RegisterEntry("Fix a bug where cutscene actors were not properly reset and could be misidentified across multiple cutscenes.") - .RegisterEntry("TexTools .meta and .rgsp files are now incorporated based on file- and game path extensions."); + => log.NextVersion("Version 0.5.9.0"u8) + .RegisterEntry("Special Collections are now split between male and female."u8) + .RegisterEntry("Fix a bug where the Base and Interface Collection were set to None instead of Default on a fresh install."u8) + .RegisterEntry("Fix a bug where cutscene actors were not properly reset and could be misidentified across multiple cutscenes."u8) + .RegisterEntry("TexTools .meta and .rgsp files are now incorporated based on file- and game path extensions."u8); private static void Add5_8_7(Changelog log) - => log.NextVersion("Version 0.5.8.7") - .RegisterEntry("Fixed some problems with metadata reloading and reverting and IMC files. (5.8.1 to 5.8.7).") + => log.NextVersion("Version 0.5.8.7"u8) + .RegisterEntry("Fixed some problems with metadata reloading and reverting and IMC files. (5.8.1 to 5.8.7)."u8) .RegisterImportant( - "If you encounter any issues, please try completely restarting your game after updating (not just relogging), before reporting them.", + "If you encounter any issues, please try completely restarting your game after updating (not just relogging), before reporting them."u8, 1); private static void Add5_8_0(Changelog log) - => log.NextVersion("Version 0.5.8.0") - .RegisterEntry("Added choices what Change Logs are to be displayed. It is recommended to just keep showing all.") - .RegisterEntry("Added an Interface Collection assignment.") - .RegisterEntry("All your UI mods will have to be in the interface collection.", 1) - .RegisterEntry("Files that are categorized as UI files by the game will only check for redirections in this collection.", 1) + => log.NextVersion("Version 0.5.8.0"u8) + .RegisterEntry("Added choices what Change Logs are to be displayed. It is recommended to just keep showing all."u8) + .RegisterEntry("Added an Interface Collection assignment."u8) + .RegisterEntry("All your UI mods will have to be in the interface collection."u8, 1) + .RegisterEntry("Files that are categorized as UI files by the game will only check for redirections in this collection."u8, 1) .RegisterImportant( - "Migration should have set your currently assigned Base Collection to the Interface Collection, please verify that.", 1) - .RegisterEntry("New API / IPC for the Interface Collection added.", 1) - .RegisterImportant("API / IPC consumers should verify whether they need to change resolving to the new collection.", 1) + "Migration should have set your currently assigned Base Collection to the Interface Collection, please verify that."u8, 1) + .RegisterEntry("New API / IPC for the Interface Collection added."u8, 1) + .RegisterImportant("API / IPC consumers should verify whether they need to change resolving to the new collection."u8, 1) .RegisterImportant( - "If other plugins are not using your interface collection yet, you can just keep Interface and Base the same collection for the time being.") + "If other plugins are not using your interface collection yet, you can just keep Interface and Base the same collection for the time being."u8) .RegisterEntry( - "Mods can now have default settings for each option group, that are shown while the mod is unconfigured and taken as initial values when configured.") - .RegisterEntry("Default values are set when importing .ttmps from their default values, and can be changed in the Edit Mod tab.", + "Mods can now have default settings for each option group, that are shown while the mod is unconfigured and taken as initial values when configured."u8) + .RegisterEntry("Default values are set when importing .ttmps from their default values, and can be changed in the Edit Mod tab."u8, 1) - .RegisterEntry("Files that the game loads super early should now be replaceable correctly via base or interface collection.") + .RegisterEntry("Files that the game loads super early should now be replaceable correctly via base or interface collection."u8) .RegisterEntry( - "The 1.0 neck tattoo file should now be replaceable, even in character collections. You can also replace the transparent texture used instead. (This was ugly.)") - .RegisterEntry("Continued Work on the Texture Import/Export Tab:") - .RegisterEntry("Should work with lot more texture types for .dds and .tex files, most notably BC7 compression.", 1) - .RegisterEntry("Supports saving .tex and .dds files in multiple texture types and generating MipMaps for them.", 1) - .RegisterEntry("Interface reworked a bit, gives more information and the overlay side can be collapsed.", 1) + "The 1.0 neck tattoo file should now be replaceable, even in character collections. You can also replace the transparent texture used instead. (This was ugly.)"u8) + .RegisterEntry("Continued Work on the Texture Import/Export Tab:"u8) + .RegisterEntry("Should work with lot more texture types for .dds and .tex files, most notably BC7 compression."u8, 1) + .RegisterEntry("Supports saving .tex and .dds files in multiple texture types and generating MipMaps for them."u8, 1) + .RegisterEntry("Interface reworked a bit, gives more information and the overlay side can be collapsed."u8, 1) .RegisterImportant( - "May contain bugs or missing safeguards. Generally let me know what's missing, ugly, buggy, not working or could be improved. Not really feasible for me to test it all.", + "May contain bugs or missing safeguards. Generally let me know what's missing, ugly, buggy, not working or could be improved. Not really feasible for me to test it all."u8, 1) .RegisterEntry( - "Added buttons for redrawing self or all as well as a tooltip to describe redraw options and a tutorial step for it.") - .RegisterEntry("Collection Selectors now display None at the top if available.") + "Added buttons for redrawing self or all as well as a tooltip to describe redraw options and a tutorial step for it."u8) + .RegisterEntry("Collection Selectors now display None at the top if available."u8) .RegisterEntry( - "Adding mods via API/IPC will now cause them to incorporate and then delete TexTools .meta and .rgsp files automatically.") - .RegisterEntry("Fixed an issue with Actor 201 using Your Character collections in cutscenes.") - .RegisterEntry("Fixed issues with and improved mod option editing.") + "Adding mods via API/IPC will now cause them to incorporate and then delete TexTools .meta and .rgsp files automatically."u8) + .RegisterEntry("Fixed an issue with Actor 201 using Your Character collections in cutscenes."u8) + .RegisterEntry("Fixed issues with and improved mod option editing."u8) .RegisterEntry( - "Fixed some issues with and improved file redirection editing - you are now informed if you can not add a game path (because it is invalid or already in use).") - .RegisterEntry("Backend optimizations.") - .RegisterEntry("Changed metadata change system again.", 1) - .RegisterEntry("Improved logging efficiency.", 1); + "Fixed some issues with and improved file redirection editing - you are now informed if you can not add a game path (because it is invalid or already in use)."u8) + .RegisterEntry("Backend optimizations."u8) + .RegisterEntry("Changed metadata change system again."u8, 1) + .RegisterEntry("Improved logging efficiency."u8, 1); private static void Add5_7_1(Changelog log) - => log.NextVersion("Version 0.5.7.1") - .RegisterEntry("Fixed the Changelog window not considering UI Scale correctly.") - .RegisterEntry("Reworked Changelog display slightly."); + => log.NextVersion("Version 0.5.7.1"u8) + .RegisterEntry("Fixed the Changelog window not considering UI Scale correctly."u8) + .RegisterEntry("Reworked Changelog display slightly."u8); private static void Add5_7_0(Changelog log) - => log.NextVersion("Version 0.5.7.0") - .RegisterEntry("Added a Changelog!") - .RegisterEntry("Files in the UI category will no longer be deduplicated for the moment.") - .RegisterImportant("If you experience UI-related crashes, please re-import your UI mods.", 1) - .RegisterEntry("This is a temporary fix against those not-yet fully understood crashes and may be reworked later.", 1) + => log.NextVersion("Version 0.5.7.0"u8) + .RegisterEntry("Added a Changelog!"u8) + .RegisterEntry("Files in the UI category will no longer be deduplicated for the moment."u8) + .RegisterImportant("If you experience UI-related crashes, please re-import your UI mods."u8, 1) + .RegisterEntry("This is a temporary fix against those not-yet fully understood crashes and may be reworked later."u8, 1) .RegisterImportant( - "There is still a possibility of UI related mods crashing the game, we are still investigating - they behave very weirdly. If you continue to experience crashing, try disabling your UI mods.", + "There is still a possibility of UI related mods crashing the game, we are still investigating - they behave very weirdly. If you continue to experience crashing, try disabling your UI mods."u8, 1) .RegisterEntry( - "On import, Penumbra will now show files with extensions '.ttmp', '.ttmp2' and '.pmp'. You can still select showing generic archive files.") + "On import, Penumbra will now show files with extensions '.ttmp', '.ttmp2' and '.pmp'. You can still select showing generic archive files."u8) .RegisterEntry( - "Penumbra Mod Pack ('.pmp') files are meant to be renames of any of the archive types that could already be imported that contain the necessary Penumbra meta files.", + "Penumbra Mod Pack ('.pmp') files are meant to be renames of any of the archive types that could already be imported that contain the necessary Penumbra meta files."u8, 1) .RegisterImportant( - "If you distribute any mod as an archive specifically for Penumbra, you should change its extension to '.pmp'. Supported base archive types are ZIP, 7-Zip and RAR.", + "If you distribute any mod as an archive specifically for Penumbra, you should change its extension to '.pmp'. Supported base archive types are ZIP, 7-Zip and RAR."u8, 1) - .RegisterEntry("Penumbra will now save mod backups with the file extension '.pmp'. They still are regular ZIP files.", 1) + .RegisterEntry("Penumbra will now save mod backups with the file extension '.pmp'. They still are regular ZIP files."u8, 1) .RegisterEntry( - "Existing backups in your current mod directory should be automatically renamed. If you manage multiple mod directories, you may need to migrate the other ones manually.", + "Existing backups in your current mod directory should be automatically renamed. If you manage multiple mod directories, you may need to migrate the other ones manually."u8, 1) - .RegisterEntry("Fixed assigned collections not working correctly on adventurer plates.") - .RegisterEntry("Fixed a wrongly displayed folder line in some circumstances.") - .RegisterEntry("Fixed crash after deleting mod options.") - .RegisterEntry("Fixed Inspect Window collections not working correctly.") - .RegisterEntry("Made identically named options selectable in mod configuration. Do not name your options identically.") - .RegisterEntry("Added some additional functionality for Mare Synchronos."); + .RegisterEntry("Fixed assigned collections not working correctly on adventurer plates."u8) + .RegisterEntry("Fixed a wrongly displayed folder line in some circumstances."u8) + .RegisterEntry("Fixed crash after deleting mod options."u8) + .RegisterEntry("Fixed Inspect Window collections not working correctly."u8) + .RegisterEntry("Made identically named options selectable in mod configuration. Do not name your options identically."u8) + .RegisterEntry("Added some additional functionality for Mare Synchronos."u8); #endregion private static void AddDummy(Changelog log) - => log.NextVersion(string.Empty); + => log.NextVersion(""u8); private (int, ChangeLogDisplayType) ConfigData() => (_config.Ephemeral.LastSeenVersion, _config.ChangeLogDisplayType); diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index 6bcc3064..72f6b129 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -1,7 +1,6 @@ -using Dalamud.Interface.Windowing; using Dalamud.Plugin; using Dalamud.Bindings.ImGui; -using Luna.Widgets; +using Luna; using OtterGui; using OtterGui.Raii; using OtterGui.Text; @@ -10,6 +9,7 @@ using Penumbra.Services; using Penumbra.UI.Classes; using Penumbra.UI.Tabs; using Penumbra.Util; +using Window = Dalamud.Interface.Windowing.Window; namespace Penumbra.UI; @@ -17,19 +17,17 @@ public sealed class ConfigWindow : Window, Luna.IUiService { private readonly IDalamudPluginInterface _pluginInterface; private readonly Configuration _config; - private readonly PerformanceTracker _tracker; private readonly ValidityChecker _validityChecker; private Penumbra? _penumbra; private ConfigTabBar _configTabs = null!; private string? _lastException; - public ConfigWindow(PerformanceTracker tracker, IDalamudPluginInterface pi, Configuration config, ValidityChecker checker, + public ConfigWindow(IDalamudPluginInterface pi, Configuration config, ValidityChecker checker, TutorialService tutorial) : base(GetLabel(checker)) { _pluginInterface = pi; _config = config; - _tracker = tracker; _validityChecker = checker; RespectCloseHotkey = true; @@ -68,7 +66,6 @@ public sealed class ConfigWindow : Window, Luna.IUiService public override void Draw() { - using var timer = _tracker.Measure(PerformanceType.UiMainWindow); UiHelpers.SetupCommonSizes(); try { diff --git a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs index c8f67539..6a88922e 100644 --- a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs +++ b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs @@ -221,12 +221,12 @@ public sealed class ModFileSystemSelector : FileSystemSelector DeleteSelectionButton(size, _config.DeleteModModifier, "mod", "mods", _modManager.DeleteMod); + => DeleteSelectionButton(size, Unsafe.BitCast(_config.DeleteModModifier), "mod", "mods", _modManager.DeleteMod); private void AddHelpButton(Vector2 size) { @@ -471,7 +471,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector !c.Mod2.Priority.IsHidden) .OrderByDescending(GetPriority) - .ThenBy(c => c.Mod2.Name.Lower).Index()) + .ThenBy(c => c.Mod2.Name, StringComparer.OrdinalIgnoreCase).Index()) { using var id = ImRaii.PushId(index); DrawConflictRow(conflict, priorityWidth, buttonSize); @@ -71,7 +71,7 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy ImGui.TableNextColumn(); using var c = ImRaii.PushColor(ImGuiCol.Text, ColorId.FolderLine.Value()); ImGui.AlignTextToFramePadding(); - ImGui.TextUnformatted(selector.Selected!.Name.Text); + ImGui.TextUnformatted(selector.Selected!.Name); ImGui.TableNextColumn(); var actualSettings = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!; var priority = actualSettings.Priority.Value; @@ -102,7 +102,7 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy private void DrawConflictSelectable(ModConflicts conflict) { ImGui.AlignTextToFramePadding(); - if (ImGui.Selectable(conflict.Mod2.Name.Text) && conflict.Mod2 is Mod otherMod) + if (ImGui.Selectable(conflict.Mod2.Name) && conflict.Mod2 is Mod otherMod) selector.SelectByValue(otherMod); var hovered = ImGui.IsItemHovered(); var rightClicked = ImGui.IsItemClicked(ImGuiMouseButton.Right); diff --git a/Penumbra/UI/ModsTab/ModPanelHeader.cs b/Penumbra/UI/ModsTab/ModPanelHeader.cs index f979aea8..96288df4 100644 --- a/Penumbra/UI/ModsTab/ModPanelHeader.cs +++ b/Penumbra/UI/ModsTab/ModPanelHeader.cs @@ -80,8 +80,8 @@ public class ModPanelHeader : IDisposable // Author if (_mod.Author != _modAuthor) { - var author = _mod.Author.IsEmpty ? string.Empty : $"by {_mod.Author}"; - _modAuthor = _mod.Author.Text; + var author = _mod.Author.Length is 0 ? string.Empty : $"by {_mod.Author}"; + _modAuthor = _mod.Author; _modAuthorWidth = ImGui.CalcTextSize(author).X; _secondRowWidth = _modAuthorWidth + _modWebsiteButtonWidth + ImGui.GetStyle().ItemSpacing.X; } diff --git a/Penumbra/UI/ModsTab/ModSearchStringSplitter.cs b/Penumbra/UI/ModsTab/ModSearchStringSplitter.cs index 1eff1919..f542c940 100644 --- a/Penumbra/UI/ModsTab/ModSearchStringSplitter.cs +++ b/Penumbra/UI/ModsTab/ModSearchStringSplitter.cs @@ -97,18 +97,18 @@ public sealed class ModSearchStringSplitter : SearchStringSplitter MatchesName(i, folder.Name, fullName, false)) && !Negated.Any(i => MatchesName(i, folder.Name, fullName, true)) - && (General.Count == 0 || General.Any(i => MatchesName(i, folder.Name, fullName, false))); + && (General.Count is 0 || General.Any(i => MatchesName(i, folder.Name, fullName, false))); } protected override bool Matches(Entry entry, ModFileSystem.Leaf leaf) => entry.Type switch { ModSearchType.Default => leaf.FullName().AsSpan().Contains(entry.Needle, StringComparison.OrdinalIgnoreCase) - || leaf.Value.Name.Lower.AsSpan().Contains(entry.Needle, StringComparison.Ordinal), + || leaf.Value.Name.AsSpan().Contains(entry.Needle, StringComparison.OrdinalIgnoreCase), ModSearchType.ChangedItem => leaf.Value.LowerChangedItemsString.AsSpan().Contains(entry.Needle, StringComparison.Ordinal), ModSearchType.Tag => leaf.Value.AllTagsLower.AsSpan().Contains(entry.Needle, StringComparison.Ordinal), - ModSearchType.Name => leaf.Value.Name.Lower.AsSpan().Contains(entry.Needle, StringComparison.Ordinal), - ModSearchType.Author => leaf.Value.Author.Lower.AsSpan().Contains(entry.Needle, StringComparison.Ordinal), + ModSearchType.Name => leaf.Value.Name.AsSpan().Contains(entry.Needle, StringComparison.OrdinalIgnoreCase), + ModSearchType.Author => leaf.Value.Author.AsSpan().Contains(entry.Needle, StringComparison.OrdinalIgnoreCase), ModSearchType.Category => leaf.Value.ChangedItems.Any(p => ((p.Value?.Icon.ToFlag() ?? ChangedItemIconFlag.Unknown) & entry.IconFlagFilter) != 0), _ => true, @@ -117,14 +117,14 @@ public sealed class ModSearchStringSplitter : SearchStringSplitter type switch { - ModSearchType.Author when negated => !haystack.Value.Author.IsEmpty, - ModSearchType.Author => haystack.Value.Author.IsEmpty, + ModSearchType.Author when negated => haystack.Value.Author.Length > 0, + ModSearchType.Author => haystack.Value.Author.Length is 0, ModSearchType.ChangedItem when negated => haystack.Value.LowerChangedItemsString.Length > 0, - ModSearchType.ChangedItem => haystack.Value.LowerChangedItemsString.Length == 0, + ModSearchType.ChangedItem => haystack.Value.LowerChangedItemsString.Length is 0, ModSearchType.Tag when negated => haystack.Value.AllTagsLower.Length > 0, - ModSearchType.Tag => haystack.Value.AllTagsLower.Length == 0, + ModSearchType.Tag => haystack.Value.AllTagsLower.Length is 0, ModSearchType.Category when negated => haystack.Value.ChangedItems.Count > 0, - ModSearchType.Category => haystack.Value.ChangedItems.Count == 0, + ModSearchType.Category => haystack.Value.ChangedItems.Count is 0, _ => true, }; diff --git a/Penumbra/UI/ModsTab/MultiModPanel.cs b/Penumbra/UI/ModsTab/MultiModPanel.cs index 90a0f277..63c9116d 100644 --- a/Penumbra/UI/ModsTab/MultiModPanel.cs +++ b/Penumbra/UI/ModsTab/MultiModPanel.cs @@ -70,7 +70,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, { using var id = ImRaii.PushId(i++); var (icon, text) = path is ModFileSystem.Leaf l - ? (FontAwesomeIcon.FileCircleMinus, l.Value.Name.Text) + ? (FontAwesomeIcon.FileCircleMinus, l.Value.Name) : (FontAwesomeIcon.FolderMinus, string.Empty); ImGui.TableNextColumn(); if (ImUtf8.IconButton(icon, "Remove from selection."u8, sizeType)) @@ -112,7 +112,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, ? _tag.Length == 0 ? "No tag specified." : $"All mods selected already contain the tag \"{_tag}\", either locally or as mod data." - : $"Add the tag \"{_tag}\" to {_addMods.Count} mods as a local tag:\n\n\t{string.Join("\n\t", _addMods.Select(m => m.Name.Text))}"; + : $"Add the tag \"{_tag}\" to {_addMods.Count} mods as a local tag:\n\n\t{string.Join("\n\t", _addMods.Select(m => m.Name))}"; ImUtf8.SameLineInner(); if (ImUtf8.ButtonEx(label, tooltip, width, _addMods.Count == 0)) foreach (var mod in _addMods) @@ -125,7 +125,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, ? _tag.Length == 0 ? "No tag specified." : $"No selected mod contains the tag \"{_tag}\" locally." - : $"Remove the local tag \"{_tag}\" from {_removeMods.Count} mods:\n\n\t{string.Join("\n\t", _removeMods.Select(m => m.Item1.Name.Text))}"; + : $"Remove the local tag \"{_tag}\" from {_removeMods.Count} mods:\n\n\t{string.Join("\n\t", _removeMods.Select(m => m.Item1.Name))}"; ImUtf8.SameLineInner(); if (ImUtf8.ButtonEx(label, tooltip, width, _removeMods.Count == 0)) foreach (var (mod, index) in _removeMods) diff --git a/Penumbra/UI/ResourceWatcher/Record.cs b/Penumbra/UI/ResourceWatcher/Record.cs index ba718bc9..1821d90d 100644 --- a/Penumbra/UI/ResourceWatcher/Record.cs +++ b/Penumbra/UI/ResourceWatcher/Record.cs @@ -1,4 +1,4 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Collections; using Penumbra.Enums; using Penumbra.Interop; diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs index 97df095e..1289612d 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs @@ -1,7 +1,7 @@ using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using Luna; using OtterGui; -using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Table; using OtterGui.Text; diff --git a/Penumbra/UI/Tabs/ChangedItemsTab.cs b/Penumbra/UI/Tabs/ChangedItemsTab.cs index 9813846a..8959c8a3 100644 --- a/Penumbra/UI/Tabs/ChangedItemsTab.cs +++ b/Penumbra/UI/Tabs/ChangedItemsTab.cs @@ -1,6 +1,6 @@ using Dalamud.Bindings.ImGui; +using ImSharp; using OtterGui; -using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; @@ -25,8 +25,8 @@ public class ChangedItemsTab( public ReadOnlySpan Label => "Changed Items"u8; - private LowerString _changedItemFilter = LowerString.Empty; - private LowerString _changedItemModFilter = LowerString.Empty; + private string _changedItemFilter = string.Empty; + private string _changedItemModFilter = string.Empty; private Vector2 _buttonSize; public void DrawContent() @@ -66,17 +66,17 @@ public class ChangedItemsTab( - 450 * UiHelpers.Scale - ImGui.GetStyle().ItemSpacing.X; ImGui.SetNextItemWidth(450 * UiHelpers.Scale); - LowerString.InputWithHint("##changedItemsFilter", "Filter Item...", ref _changedItemFilter, 128); + Im.Input.Text("##changedItemsFilter"u8, ref _changedItemFilter, "Filter Item..."u8); ImGui.SameLine(); ImGui.SetNextItemWidth(varWidth); - LowerString.InputWithHint("##changedItemsModFilter", "Filter Mods...", ref _changedItemModFilter, 128); + Im.Input.Text("##changedItemsModFilter"u8, ref _changedItemModFilter, "Filter Mods..."u8); return varWidth; } /// Apply the current filters. private bool FilterChangedItem(KeyValuePair, IIdentifiedObjectData)> item) => drawer.FilterChangedItem(item.Key, item.Value.Item2, _changedItemFilter) - && (_changedItemModFilter.IsEmpty || item.Value.Item1.Any(m => m.Name.Contains(_changedItemModFilter))); + && (_changedItemModFilter.Length is 0 || item.Value.Item1.Any(m => m.Name.Contains(_changedItemModFilter, StringComparison.OrdinalIgnoreCase))); /// Draw a full column for a changed item. private void DrawChangedItemColumn(KeyValuePair, IIdentifiedObjectData)> item) @@ -101,7 +101,7 @@ public class ChangedItemsTab( return; var first = mods[0]; - if (ImUtf8.Selectable(first.Name.Text, false, ImGuiSelectableFlags.None, _buttonSize with { X = 0 }) + if (ImUtf8.Selectable(first.Name, false, ImGuiSelectableFlags.None, _buttonSize with { X = 0 }) && ImGui.GetIO().KeyCtrl && first is Mod mod) communicator.SelectTab.Invoke(new SelectTab.Arguments(TabType.Mods, mod)); diff --git a/Penumbra/UI/Tabs/Debug/DebugTab.cs b/Penumbra/UI/Tabs/Debug/DebugTab.cs index 65b4bb0b..d5b02db0 100644 --- a/Penumbra/UI/Tabs/Debug/DebugTab.cs +++ b/Penumbra/UI/Tabs/Debug/DebugTab.cs @@ -1,6 +1,5 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; -using Dalamud.Interface.Windowing; using Dalamud.Plugin.Services; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.Game.Character; @@ -10,6 +9,7 @@ using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using Dalamud.Bindings.ImGui; using Dalamud.Interface.Colors; +using ImSharp; using Luna; using Microsoft.Extensions.DependencyInjection; using OtterGui; @@ -31,7 +31,6 @@ using Penumbra.Mods.Manager; using Penumbra.Services; using Penumbra.String; using Penumbra.UI.Classes; -using Penumbra.Util; using static OtterGui.Raii.ImRaii; using CharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase; using ImGuiClip = OtterGui.ImGuiClip; @@ -43,7 +42,6 @@ using Penumbra.GameData.Files.StainMapStructs; using Penumbra.Interop; using Penumbra.String.Classes; using Penumbra.UI.AdvancedWindow.Materials; -using FrameworkManager = OtterGui.Classes.FrameworkManager; namespace Penumbra.UI.Tabs.Debug; @@ -72,7 +70,6 @@ public class Diagnostics(ServiceManager provider) : IUiService public class DebugTab : Window, ITab, IUiService { - private readonly PerformanceTracker _performance; private readonly Configuration _config; private readonly CollectionManager _collectionManager; private readonly ModManager _modManager; @@ -111,7 +108,7 @@ public class DebugTab : Window, ITab, IUiService private readonly ModMigratorDebug _modMigratorDebug; private readonly ShapeInspector _shapeInspector; - public DebugTab(PerformanceTracker performance, Configuration config, CollectionManager collectionManager, ObjectManager objects, + public DebugTab(Configuration config, CollectionManager collectionManager, ObjectManager objects, IClientState clientState, IDataManager dataManager, ValidityChecker validityChecker, ModManager modManager, HttpApi httpApi, ActorManager actors, StainService stains, ResourceManagerService resourceManager, ResourceLoader resourceLoader, CollectionResolver collectionResolver, @@ -122,7 +119,7 @@ public class DebugTab : Window, ITab, IUiService HookOverrideDrawer hookOverrides, RsfService rsfService, GlobalVariablesDrawer globalVariablesDrawer, SchedulerResourceManagementService schedulerService, ObjectIdentification objectIdentification, RenderTargetDrawer renderTargetDrawer, ModMigratorDebug modMigratorDebug, ShapeInspector shapeInspector) - : base("Penumbra Debug Window", ImGuiWindowFlags.NoCollapse) + : base("Penumbra Debug Window", WindowFlags.NoCollapse) { IsOpen = true; SizeConstraints = new WindowSizeConstraints @@ -130,7 +127,6 @@ public class DebugTab : Window, ITab, IUiService MinimumSize = new Vector2(200, 200), MaximumSize = new Vector2(2000, 2000), }; - _performance = performance; _config = config; _collectionManager = collectionManager; _validityChecker = validityChecker; @@ -277,7 +273,7 @@ public class DebugTab : Window, ITab, IUiService foreach (var (mod, paths, manips) in collection._cache!.ModData.Data.OrderBy(t => t.Item1.Name)) { using var id = mod is TemporaryMod t ? PushId(t.Priority.Value) : PushId(((Mod)mod).ModPath.Name); - using var node2 = TreeNode(mod.Name.Text); + using var node2 = TreeNode(mod.Name); if (!node2) continue; @@ -503,8 +499,6 @@ public class DebugTab : Window, ITab, IUiService if (start) ImGui.NewLine(); } - - _performance.Draw("##performance", "Enable Runtime Performance Tracking", TimingExtensions.ToName); } private unsafe void DrawActorsDebug() @@ -774,9 +768,35 @@ public class DebugTab : Window, ITab, IUiService DrawActionTmbs(); DrawStainTemplates(); DrawAtch(); + DrawFileTest(); DrawChangedItemTest(); } + private string _filePath = string.Empty; + private byte[]? _fileData; + + private void DrawFileTest() + { + using var node = TreeNode("Game File Test"); + if (!node) + return; + + if (Im.Input.Text("##Path"u8, ref _filePath, "File Path..."u8)) + _fileData = _dataManager.GetFile(_filePath)?.Data; + + using (Im.Group()) + { + Im.Text("Exists"u8); + Im.Text("File Size"u8); + } + Im.Line.SameInner(); + using (Im.Group()) + { + Im.Text($"{_fileData is not null}"); + Im.Text($"{_fileData?.Length ?? 0}"); + } + } + private string _changedItemPath = string.Empty; private readonly Dictionary _changedItems = []; @@ -1204,7 +1224,7 @@ public class DebugTab : Window, ITab, IUiService private string _cloudTesterPath = string.Empty; private bool? _cloudTesterReturn; private Exception? _cloudTesterError; - + private void DrawCloudApi() { if (!ImUtf8.CollapsingHeader("Cloud API"u8)) @@ -1213,7 +1233,6 @@ public class DebugTab : Window, ITab, IUiService using var id = ImRaii.PushId("CloudApiTester"u8); if (ImUtf8.InputText("Path"u8, ref _cloudTesterPath, flags: ImGuiInputTextFlags.EnterReturnsTrue)) - { try { _cloudTesterReturn = CloudApi.IsCloudSynced(_cloudTesterPath); @@ -1224,7 +1243,6 @@ public class DebugTab : Window, ITab, IUiService _cloudTesterReturn = null; _cloudTesterError = e; } - } if (_cloudTesterReturn.HasValue) ImUtf8.Text($"Is Cloud Synced? {_cloudTesterReturn}"); diff --git a/Penumbra/UI/Tabs/EffectiveTab.cs b/Penumbra/UI/Tabs/EffectiveTab.cs index 2dc8ec90..c2ba7a87 100644 --- a/Penumbra/UI/Tabs/EffectiveTab.cs +++ b/Penumbra/UI/Tabs/EffectiveTab.cs @@ -1,7 +1,6 @@ using Dalamud.Bindings.ImGui; using Dalamud.Interface; using OtterGui; -using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; @@ -51,8 +50,8 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH private float _effectiveArrowLength; // Filters - private LowerString _effectiveGamePathFilter = LowerString.Empty; - private LowerString _effectiveFilePathFilter = LowerString.Empty; + private string _effectiveGamePathFilter = string.Empty; + private string _effectiveFilePathFilter = string.Empty; /// Setup table sizes. private void SetupEffectiveSizes() @@ -72,14 +71,14 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH /// Draw the header line for filters. private void DrawFilters() { - var tmp = _effectiveGamePathFilter.Text; + var tmp = _effectiveGamePathFilter; ImGui.SetNextItemWidth(_effectiveLeftTextLength); if (ImGui.InputTextWithHint("##gamePathFilter", "Filter game path...", ref tmp, 256)) _effectiveGamePathFilter = tmp; ImGui.SameLine(_effectiveArrowLength + _effectiveLeftTextLength + 3 * ImGui.GetStyle().ItemSpacing.X); ImGui.SetNextItemWidth(-1); - tmp = _effectiveFilePathFilter.Text; + tmp = _effectiveFilePathFilter; if (ImGui.InputTextWithHint("##fileFilter", "Filter file path...", ref tmp, 256)) _effectiveFilePathFilter = tmp; } @@ -144,7 +143,7 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH } /// Draw a line for a path and its name. - private static void DrawLine((string, LowerString) pair) + private static void DrawLine((string, string) pair) { var (path, name) = pair; ImGui.TableNextColumn(); @@ -153,7 +152,7 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH ImGui.TableNextColumn(); ImGuiUtil.PrintIcon(FontAwesomeIcon.LongArrowAltLeft); ImGui.TableNextColumn(); - ImGuiUtil.CopyOnClickSelectable(name.Text); + ImGuiUtil.CopyOnClickSelectable(name); } /// Draw a line for a unfiltered/unconverted manipulation and mod-index pair. @@ -166,26 +165,26 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH ImGui.TableNextColumn(); ImGuiUtil.PrintIcon(FontAwesomeIcon.LongArrowAltLeft); ImGui.TableNextColumn(); - ImGuiUtil.CopyOnClickSelectable(mod.Name.Text); + ImGuiUtil.CopyOnClickSelectable(mod.Name); } /// Check filters for file replacements. private bool CheckFilters(KeyValuePair kvp) { var (gamePath, fullPath) = kvp; - if (_effectiveGamePathFilter.Length > 0 && !gamePath.ToString().Contains(_effectiveGamePathFilter.Lower)) + if (_effectiveGamePathFilter.Length > 0 && !gamePath.ToString().Contains(_effectiveGamePathFilter, StringComparison.OrdinalIgnoreCase)) return false; - return _effectiveFilePathFilter.Length == 0 || fullPath.Path.FullName.ToLowerInvariant().Contains(_effectiveFilePathFilter.Lower); + return _effectiveFilePathFilter.Length == 0 || fullPath.Path.FullName.Contains(_effectiveFilePathFilter, StringComparison.OrdinalIgnoreCase); } /// Check filters for meta manipulations. - private bool CheckFilters((string, LowerString) kvp) + private bool CheckFilters((string, string) kvp) { var (name, path) = kvp; - if (_effectiveGamePathFilter.Length > 0 && !name.ToLowerInvariant().Contains(_effectiveGamePathFilter.Lower)) + if (_effectiveGamePathFilter.Length > 0 && !name.Contains(_effectiveGamePathFilter, StringComparison.OrdinalIgnoreCase)) return false; - return _effectiveFilePathFilter.Length == 0 || path.Contains(_effectiveFilePathFilter.Lower); + return _effectiveFilePathFilter.Length == 0 || path.Contains(_effectiveFilePathFilter, StringComparison.OrdinalIgnoreCase); } } diff --git a/Penumbra/UI/Tabs/SettingsTab.cs b/Penumbra/UI/Tabs/SettingsTab.cs index 3f42cece..48f79be6 100644 --- a/Penumbra/UI/Tabs/SettingsTab.cs +++ b/Penumbra/UI/Tabs/SettingsTab.cs @@ -5,10 +5,9 @@ using Dalamud.Interface.Utility; using Dalamud.Plugin; using Dalamud.Plugin.Services; using Dalamud.Utility; +using ImSharp; using Luna; -using Luna.Widgets; using OtterGui; -using OtterGui.Custom; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; @@ -105,22 +104,24 @@ public class SettingsTab : ITab, IUiService _tutorial.OpenTutorial(BasicTutorialSteps.Faq2); } + private readonly TwoPanelLayout _test = new(); + public void DrawContent() { using var child = ImRaii.Child("##SettingsTab", -Vector2.One, false); if (!child) return; - + DrawEnabledBox(); EphemeralCheckbox("Lock Main Window", "Prevent the main window from being resized or moved.", _config.Ephemeral.FixMainWindow, v => _config.Ephemeral.FixMainWindow = v); - + ImGui.NewLine(); DrawRootFolder(); DrawDirectoryButtons(); ImGui.NewLine(); ImGui.NewLine(); - + DrawGeneralSettings(); _migrationDrawer.Draw(); DrawColorSettings(); @@ -582,16 +583,16 @@ public class SettingsTab : ITab, IUiService _selector.SetFilterDirty(); }); - Widget.DoubleModifierSelector("Mod Deletion Modifier", - "A modifier you need to hold while clicking the Delete Mod button for it to take effect.", UiHelpers.InputTextWidth.X, + KeySelector.DoubleModifier("Mod Deletion Modifier"u8, + "A modifier you need to hold while clicking the Delete Mod button for it to take effect."u8, UiHelpers.InputTextWidth.X, _config.DeleteModModifier, v => { _config.DeleteModModifier = v; _config.Save(); }); - Widget.DoubleModifierSelector("Incognito Modifier", - "A modifier you need to hold while clicking the Incognito or Temporary Settings Mode button for it to take effect.", + KeySelector.DoubleModifier("Incognito Modifier"u8, + "A modifier you need to hold while clicking the Incognito or Temporary Settings Mode button for it to take effect."u8, UiHelpers.InputTextWidth.X, _config.IncognitoModifier, v => @@ -646,6 +647,7 @@ public class SettingsTab : ITab, IUiService DrawDefaultModAuthor(); DrawDefaultModImportFolder(); DrawPcpFolder(); + DrawPcpExtension(); DrawDefaultModExportPath(); } @@ -770,6 +772,28 @@ public class SettingsTab : ITab, IUiService "The folder any penumbra character packs are moved to on import.\nLeave blank to import into Root."); } + private void DrawPcpExtension() + { + var tmp = _config.PcpSettings.PcpExtension; + ImGui.SetNextItemWidth(UiHelpers.InputTextWidth.X); + if (ImUtf8.InputText("##pcpExtension"u8, ref tmp)) + _config.PcpSettings.PcpExtension = tmp; + + if (ImGui.IsItemDeactivatedAfterEdit()) + _config.Save(); + + Im.Line.SameInner(); + if (ImEx.Button("Reset##pcpExtension"u8, Vector2.Zero, "Reset the extension to its default value of \".pcp\".", + _config.PcpSettings.PcpExtension is ".pcp")) + { + _config.PcpSettings.PcpExtension = ".pcp"; + _config.Save(); + } + + ImGuiUtil.LabeledHelpMarker("PCP Extension", + "The extension used when exporting PCP files. Should generally be either \".pcp\" or \".pmp\"."); + } + /// Draw all settings pertaining to advanced editing of mods. private void DrawModEditorSettings() @@ -1113,7 +1137,7 @@ public class SettingsTab : ITab, IUiService if (ImGui.Button("Show Changelogs", new Vector2(width, 0))) _penumbra.ForceChangelogOpen(); - ImGui.SetCursorPos(new Vector2(xPos, 5 * ImGui.GetFrameHeightWithSpacing())); + ImGui.SetCursorPos(new Vector2(xPos, 5 * ImGui.GetFrameHeightWithSpacing())); SupportButton.KoFiPatreon(Penumbra.Messager, new Vector2(width, 0)); } diff --git a/Penumbra/Util/PerformanceType.cs b/Penumbra/Util/PerformanceType.cs deleted file mode 100644 index 2d2aef1b..00000000 --- a/Penumbra/Util/PerformanceType.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Dalamud.Plugin.Services; - -namespace Penumbra.Util; - -public sealed class PerformanceTracker(IFramework framework) : OtterGui.Classes.PerformanceTracker(framework), Luna.IService; - -public enum PerformanceType -{ - UiMainWindow, - UiAdvancedWindow, - CharacterResolver, - IdentifyCollection, - GetResourceHandler, - ReadSqPack, - CharacterBaseCreate, - TimelineResources, - LoadCharacterVfx, - LoadAreaVfx, - LoadSound, - ScheduleClipUpdate, - LoadAction, - LoadCharacterBaseAnimation, - LoadPap, - LoadTextures, - LoadShaders, - LoadApricotResources, - UpdateModels, - GetEqp, - SetupVisor, - SetupCharacter, - ChangeCustomize, - DebugTimes, -} - -public static class TimingExtensions -{ - public static string ToName(this PerformanceType type) - => type switch - { - PerformanceType.UiMainWindow => "Main Interface Drawing", - PerformanceType.UiAdvancedWindow => "Advanced Window Drawing", - PerformanceType.GetResourceHandler => "GetResource Hook", - PerformanceType.ReadSqPack => "ReadSqPack Hook", - PerformanceType.CharacterResolver => "Resolving Characters", - PerformanceType.IdentifyCollection => "Identifying Collections", - PerformanceType.CharacterBaseCreate => "CharacterBaseCreate Hook", - PerformanceType.TimelineResources => "LoadTimelineResources Hook", - PerformanceType.LoadCharacterVfx => "LoadCharacterVfx Hook", - PerformanceType.LoadAreaVfx => "LoadAreaVfx Hook", - PerformanceType.LoadTextures => "LoadTextures Hook", - PerformanceType.LoadShaders => "LoadShaders Hook", - PerformanceType.LoadApricotResources => "LoadApricotFiles Hook", - PerformanceType.UpdateModels => "UpdateModels Hook", - PerformanceType.GetEqp => "GetEqp Hook", - PerformanceType.SetupVisor => "SetupVisor Hook", - PerformanceType.SetupCharacter => "SetupCharacter Hook", - PerformanceType.ChangeCustomize => "ChangeCustomize Hook", - PerformanceType.LoadSound => "LoadSound Hook", - PerformanceType.ScheduleClipUpdate => "ScheduleClipUpdate Hook", - PerformanceType.LoadCharacterBaseAnimation => "LoadCharacterAnimation Hook", - PerformanceType.LoadPap => "LoadPap Hook", - PerformanceType.LoadAction => "LoadAction Hook", - PerformanceType.DebugTimes => "Debug Tracking", - _ => $"Unknown {(int)type}", - }; -}