Allow configuration of the changed item display.

This commit is contained in:
Ottermandias 2025-03-01 16:55:50 +01:00
parent 26985e01a2
commit 13adbd5466
4 changed files with 144 additions and 26 deletions

View file

@ -0,0 +1,57 @@
using ImGuiNET;
using OtterGui.Text;
namespace Penumbra;
public enum ChangedItemMode
{
GroupedCollapsed,
GroupedExpanded,
Alphabetical,
}
public static class ChangedItemModeExtensions
{
public static ReadOnlySpan<byte> 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<byte> 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<byte> label, ChangedItemMode value, float width, Action<ChangedItemMode> 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<ChangedItemMode>())
{
var selected = ImUtf8.Selectable(newValue.ToName(), newValue == value);
if (selected)
{
ret = true;
setter(newValue);
}
ImUtf8.HoverTooltip(newValue.ToTooltip());
}
return ret;
}
}

View file

@ -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;
@ -72,6 +68,7 @@ public class Configuration : IPluginConfiguration, ISavable, IService
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<T>(ref T field, T value, Action<T, T>? @event, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.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<T>(ref T field, T value, Action<T>? @event, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.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;
}
}

View file

@ -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<Container> 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<IdentifiedItem>>();
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<IdentifiedItem>>();
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)

View file

@ -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.",