From 13adbd54667e4eff64812d7e281c7d26dfb9689c Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sat, 1 Mar 2025 16:55:50 +0100 Subject: [PATCH] Allow configuration of the changed item display. --- Penumbra/ChangedItemMode.cs | 57 ++++++++++++++ Penumbra/Configuration.cs | 78 ++++++++++++++----- .../UI/ModsTab/ModPanelChangedItemsTab.cs | 26 +++++-- Penumbra/UI/Tabs/SettingsTab.cs | 9 +++ 4 files changed, 144 insertions(+), 26 deletions(-) create mode 100644 Penumbra/ChangedItemMode.cs diff --git a/Penumbra/ChangedItemMode.cs b/Penumbra/ChangedItemMode.cs new file mode 100644 index 00000000..dccffded --- /dev/null +++ b/Penumbra/ChangedItemMode.cs @@ -0,0 +1,57 @@ +using ImGuiNET; +using OtterGui.Text; + +namespace Penumbra; + +public enum ChangedItemMode +{ + GroupedCollapsed, + GroupedExpanded, + Alphabetical, +} + +public static class ChangedItemModeExtensions +{ + public static ReadOnlySpan ToName(this ChangedItemMode mode) + => mode switch + { + ChangedItemMode.GroupedCollapsed => "Grouped (Collapsed)"u8, + ChangedItemMode.GroupedExpanded => "Grouped (Expanded)"u8, + ChangedItemMode.Alphabetical => "Alphabetical"u8, + _ => "Error"u8, + }; + + public static ReadOnlySpan ToTooltip(this ChangedItemMode mode) + => mode switch + { + ChangedItemMode.GroupedCollapsed => + "Display items as groups by their model and slot. Collapse those groups to a single item by default. Prefers items with more changes affecting them or configured items as the main item."u8, + ChangedItemMode.GroupedExpanded => + "Display items as groups by their model and slot. Expand those groups showing all items by default. Prefers items with more changes affecting them or configured items as the main item."u8, + ChangedItemMode.Alphabetical => "Display all changed items in a single list sorted alphabetically."u8, + _ => ""u8, + }; + + public static bool DrawCombo(ReadOnlySpan label, ChangedItemMode value, float width, Action setter) + { + ImGui.SetNextItemWidth(width); + using var combo = ImUtf8.Combo(label, value.ToName()); + if (!combo) + return false; + + var ret = false; + foreach (var newValue in Enum.GetValues()) + { + var selected = ImUtf8.Selectable(newValue.ToName(), newValue == value); + if (selected) + { + ret = true; + setter(newValue); + } + + ImUtf8.HoverTooltip(newValue.ToTooltip()); + } + + return ret; + } +} diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index ce86dd4a..939eb122 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -39,11 +39,7 @@ public class Configuration : IPluginConfiguration, ISavable, IService public bool EnableMods { get => _enableMods; - set - { - _enableMods = value; - ModsEnabled?.Invoke(value); - } + set => SetField(ref _enableMods, value, ModsEnabled); } public string ModDirectory { get; set; } = string.Empty; @@ -58,21 +54,22 @@ public class Configuration : IPluginConfiguration, ISavable, IService public bool AutoSelectCollection { get; set; } = false; - public bool ShowModsInLobby { get; set; } = true; - public bool UseCharacterCollectionInMainWindow { get; set; } = true; - public bool UseCharacterCollectionsInCards { get; set; } = true; - public bool UseCharacterCollectionInInspect { get; set; } = true; - public bool UseCharacterCollectionInTryOn { get; set; } = true; - public bool UseOwnerNameForCharacterCollection { get; set; } = true; - public bool UseNoModsInInspect { get; set; } = false; - public bool HideChangedItemFilters { get; set; } = false; - public bool ReplaceNonAsciiOnImport { get; set; } = false; - public bool HidePrioritiesInSelector { get; set; } = false; - public bool HideRedrawBar { get; set; } = false; - public bool HideMachinistOffhandFromChangedItems { get; set; } = true; - public bool DefaultTemporaryMode { get; set; } = false; - public RenameField ShowRename { get; set; } = RenameField.BothDataPrio; - public int OptionGroupCollapsibleMin { get; set; } = 5; + public bool ShowModsInLobby { get; set; } = true; + public bool UseCharacterCollectionInMainWindow { get; set; } = true; + public bool UseCharacterCollectionsInCards { get; set; } = true; + public bool UseCharacterCollectionInInspect { get; set; } = true; + public bool UseCharacterCollectionInTryOn { get; set; } = true; + public bool UseOwnerNameForCharacterCollection { get; set; } = true; + public bool UseNoModsInInspect { get; set; } = false; + public bool HideChangedItemFilters { get; set; } = false; + public bool ReplaceNonAsciiOnImport { get; set; } = false; + public bool HidePrioritiesInSelector { get; set; } = false; + public bool HideRedrawBar { get; set; } = false; + public bool HideMachinistOffhandFromChangedItems { get; set; } = true; + public bool DefaultTemporaryMode { get; set; } = false; + public RenameField ShowRename { get; set; } = RenameField.BothDataPrio; + public ChangedItemMode ChangedItemDisplay { get; set; } = ChangedItemMode.GroupedCollapsed; + public int OptionGroupCollapsibleMin { get; set; } = 5; public Vector2 MinimumSize = new(Constants.MinimumSizeX, Constants.MinimumSizeY); @@ -217,4 +214,45 @@ public class Configuration : IPluginConfiguration, ISavable, IService var serializer = new JsonSerializer { Formatting = Formatting.Indented }; serializer.Serialize(jWriter, this); } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static bool SetField(ref T field, T value, Action? @event, [CallerMemberName] string? propertyName = null) + { + if (EqualityComparer.Default.Equals(value)) + return false; + + var oldValue = field; + field = value; + try + { + @event?.Invoke(oldValue, field); + } + catch (Exception ex) + { + Penumbra.Log.Error($"Error in subscribers updating configuration field {propertyName} from {oldValue} to {field}:\n{ex}"); + throw; + } + + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static bool SetField(ref T field, T value, Action? @event, [CallerMemberName] string? propertyName = null) + { + if (EqualityComparer.Default.Equals(value)) + return false; + + field = value; + try + { + @event?.Invoke(field); + } + catch (Exception ex) + { + Penumbra.Log.Error($"Error in subscribers updating configuration field {propertyName} to {field}:\n{ex}"); + throw; + } + + return true; + } } diff --git a/Penumbra/UI/ModsTab/ModPanelChangedItemsTab.cs b/Penumbra/UI/ModsTab/ModPanelChangedItemsTab.cs index ac4fd167..f97e4d51 100644 --- a/Penumbra/UI/ModsTab/ModPanelChangedItemsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelChangedItemsTab.cs @@ -18,7 +18,7 @@ public class ModPanelChangedItemsTab( ModFileSystemSelector selector, ChangedItemDrawer drawer, ImGuiCacheService cacheService, - EphemeralConfig config) + Configuration config) : ITab, IUiService { private readonly ImGuiCacheService.CacheId _cacheId = cacheService.GetNewId(); @@ -28,6 +28,7 @@ public class ModPanelChangedItemsTab( private Mod? _lastSelected; private ushort _lastUpdate; private ChangedItemIconFlag _filter = ChangedItemFlagExtensions.DefaultFlags; + private ChangedItemMode _lastMode; private bool _reset; public readonly List Data = []; public bool AnyExpandable { get; private set; } @@ -90,9 +91,9 @@ public class ModPanelChangedItemsTab( public void Reset() => _reset = true; - public void Update(Mod? mod, ChangedItemDrawer drawer, ChangedItemIconFlag filter) + public void Update(Mod? mod, ChangedItemDrawer drawer, ChangedItemIconFlag filter, ChangedItemMode mode) { - if (mod == _lastSelected && _lastSelected!.LastChangedItemsUpdate == _lastUpdate && _filter == filter && !_reset) + if (mod == _lastSelected && _lastSelected!.LastChangedItemsUpdate == _lastUpdate && _filter == filter && !_reset && _lastMode == mode) return; _reset = false; @@ -100,12 +101,25 @@ public class ModPanelChangedItemsTab( AnyExpandable = false; _lastSelected = mod; _filter = filter; + _lastMode = mode; if (_lastSelected == null) return; _lastUpdate = _lastSelected.LastChangedItemsUpdate; - var tmp = new Dictionary<(PrimaryId, FullEquipType), List>(); + if (mode is ChangedItemMode.Alphabetical) + { + foreach (var (s, i) in _lastSelected.ChangedItems) + { + if (drawer.FilterChangedItem(s, i, LowerString.Empty)) + Data.Add(Container.Single(s, i)); + } + + return; + } + + var tmp = new Dictionary<(PrimaryId, FullEquipType), List>(); + var defaultExpansion = _lastMode is ChangedItemMode.GroupedExpanded; foreach (var (s, i) in _lastSelected.ChangedItems) { if (i is not IdentifiedItem item) @@ -165,7 +179,7 @@ public class ModPanelChangedItemsTab( else { var id = ImUtf8.GetId($"{mainItem.Item.PrimaryId}{(int)mainItem.Item.Type}"); - var expanded = ImGui.GetStateStorage().GetBool(id, false); + var expanded = ImGui.GetStateStorage().GetBool(id, defaultExpansion); Data.Add(Container.Parent(mainItem.Item.Name, mainItem, id, list.Count - 1, expanded)); AnyExpandable = true; if (!expanded) @@ -196,7 +210,7 @@ public class ModPanelChangedItemsTab( drawer.DrawTypeFilter(); _stateStorage = ImGui.GetStateStorage(); - cache.Update(selector.Selected, drawer, config.ChangedItemFilter); + cache.Update(selector.Selected, drawer, config.Ephemeral.ChangedItemFilter, config.ChangedItemDisplay); ImGui.Separator(); _buttonSize = new Vector2(ImGui.GetStyle().ItemSpacing.Y + ImGui.GetFrameHeight()); using var style = ImRaii.PushStyle(ImGuiStyleVar.CellPadding, Vector2.Zero) diff --git a/Penumbra/UI/Tabs/SettingsTab.cs b/Penumbra/UI/Tabs/SettingsTab.cs index 4ff0cd42..ba226aa8 100644 --- a/Penumbra/UI/Tabs/SettingsTab.cs +++ b/Penumbra/UI/Tabs/SettingsTab.cs @@ -445,6 +445,15 @@ public class SettingsTab : ITab, IUiService _config.Ephemeral.Save(); } }); + + ChangedItemModeExtensions.DrawCombo("##ChangedItemMode"u8, _config.ChangedItemDisplay, UiHelpers.InputTextWidth.X, v => + { + _config.ChangedItemDisplay = v; + _config.Save(); + }); + ImUtf8.LabeledHelpMarker("Mod Changed Item Display"u8, + "Configure how to display the changed items of a single mod in the mods info panel."u8); + Checkbox("Omit Machinist Offhands in Changed Items", "Omits all Aetherotransformers (machinist offhands) in the changed items tabs because any change on them changes all of them at the moment.\n\n" + "Changing this triggers a rediscovery of your mods so all changed items can be updated.",