Make items changed in a mod sort before other items for item swap, also color them.

This commit is contained in:
Ottermandias 2024-07-26 18:42:48 +02:00
parent 72f2834dfd
commit 246f4f65f5
3 changed files with 44 additions and 33 deletions

@ -1 +1 @@
Subproject commit dc17161b1d9c47ffd6bcc17e91f4832cf7762993
Subproject commit 87a532620d622a00e60059b5dd42a04f0319b5b5

View file

@ -15,13 +15,9 @@ public static class ItemSwap
public class InvalidItemTypeException : Exception
{ }
public class MissingFileException : Exception
public class MissingFileException(ResourceType type, object path) : Exception($"Could not load {type} File Data for \"{path}\".")
{
public readonly ResourceType Type;
public MissingFileException(ResourceType type, object path)
: base($"Could not load {type} File Data for \"{path}\".")
=> Type = type;
public readonly ResourceType Type = type;
}
private static bool LoadFile(MetaFileManager manager, FullPath path, out byte[] data)
@ -47,7 +43,7 @@ public static class ItemSwap
Penumbra.Log.Debug($"Could not load file {path}:\n{e}");
}
data = Array.Empty<byte>();
data = [];
return false;
}

View file

@ -22,6 +22,7 @@ using Penumbra.Mods.Settings;
using Penumbra.Mods.SubMods;
using Penumbra.Services;
using Penumbra.UI.Classes;
using Penumbra.UI.ModsTab;
namespace Penumbra.UI.AdvancedWindow;
@ -34,7 +35,8 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
private readonly MetaFileManager _metaFileManager;
public ItemSwapTab(CommunicatorService communicator, ItemData itemService, CollectionManager collectionManager,
ModManager modManager, ObjectIdentification identifier, MetaFileManager metaFileManager, Configuration config)
ModManager modManager, ModFileSystemSelector selector, ObjectIdentification identifier, MetaFileManager metaFileManager,
Configuration config)
{
_communicator = communicator;
_collectionManager = collectionManager;
@ -46,15 +48,15 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
_selectors = new Dictionary<SwapType, (ItemSelector Source, ItemSelector Target, string TextFrom, string TextTo)>
{
// @formatter:off
[SwapType.Hat] = (new ItemSelector(itemService, FullEquipType.Head), new ItemSelector(itemService, FullEquipType.Head), "Take this Hat", "and put it on this one" ),
[SwapType.Top] = (new ItemSelector(itemService, FullEquipType.Body), new ItemSelector(itemService, FullEquipType.Body), "Take this Top", "and put it on this one" ),
[SwapType.Gloves] = (new ItemSelector(itemService, FullEquipType.Hands), new ItemSelector(itemService, FullEquipType.Hands), "Take these Gloves", "and put them on these" ),
[SwapType.Pants] = (new ItemSelector(itemService, FullEquipType.Legs), new ItemSelector(itemService, FullEquipType.Legs), "Take these Pants", "and put them on these" ),
[SwapType.Shoes] = (new ItemSelector(itemService, FullEquipType.Feet), new ItemSelector(itemService, FullEquipType.Feet), "Take these Shoes", "and put them on these" ),
[SwapType.Earrings] = (new ItemSelector(itemService, FullEquipType.Ears), new ItemSelector(itemService, FullEquipType.Ears), "Take these Earrings", "and put them on these" ),
[SwapType.Necklace] = (new ItemSelector(itemService, FullEquipType.Neck), new ItemSelector(itemService, FullEquipType.Neck), "Take this Necklace", "and put it on this one" ),
[SwapType.Bracelet] = (new ItemSelector(itemService, FullEquipType.Wrists), new ItemSelector(itemService, FullEquipType.Wrists), "Take these Bracelets", "and put them on these" ),
[SwapType.Ring] = (new ItemSelector(itemService, FullEquipType.Finger), new ItemSelector(itemService, FullEquipType.Finger), "Take this Ring", "and put it on this one" ),
[SwapType.Hat] = (new ItemSelector(itemService, selector, FullEquipType.Head), new ItemSelector(itemService, null, FullEquipType.Head), "Take this Hat", "and put it on this one" ),
[SwapType.Top] = (new ItemSelector(itemService, selector, FullEquipType.Body), new ItemSelector(itemService, null, FullEquipType.Body), "Take this Top", "and put it on this one" ),
[SwapType.Gloves] = (new ItemSelector(itemService, selector, FullEquipType.Hands), new ItemSelector(itemService, null, FullEquipType.Hands), "Take these Gloves", "and put them on these" ),
[SwapType.Pants] = (new ItemSelector(itemService, selector, FullEquipType.Legs), new ItemSelector(itemService, null, FullEquipType.Legs), "Take these Pants", "and put them on these" ),
[SwapType.Shoes] = (new ItemSelector(itemService, selector, FullEquipType.Feet), new ItemSelector(itemService, null, FullEquipType.Feet), "Take these Shoes", "and put them on these" ),
[SwapType.Earrings] = (new ItemSelector(itemService, selector, FullEquipType.Ears), new ItemSelector(itemService, null, FullEquipType.Ears), "Take these Earrings", "and put them on these" ),
[SwapType.Necklace] = (new ItemSelector(itemService, selector, FullEquipType.Neck), new ItemSelector(itemService, null, FullEquipType.Neck), "Take this Necklace", "and put it on this one" ),
[SwapType.Bracelet] = (new ItemSelector(itemService, selector, FullEquipType.Wrists), new ItemSelector(itemService, null, FullEquipType.Wrists), "Take these Bracelets", "and put them on these" ),
[SwapType.Ring] = (new ItemSelector(itemService, selector, FullEquipType.Finger), new ItemSelector(itemService, null, FullEquipType.Finger), "Take this Ring", "and put it on this one" ),
// @formatter:on
};
@ -129,11 +131,24 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
Weapon,
}
private class ItemSelector(ItemData data, FullEquipType type)
: FilterComboCache<EquipItem>(() => data.ByType[type], MouseWheelType.None, Penumbra.Log)
private class ItemSelector(ItemData data, ModFileSystemSelector? selector, FullEquipType type)
: FilterComboCache<(EquipItem Item, bool InMod)>(() =>
{
var list = data.ByType[type];
if (selector?.Selected is { } mod && mod.ChangedItems.Values.Any(o => o is EquipItem i && i.Type == type))
return list.Select(i => (i, mod.ChangedItems.ContainsKey(i.Name))).OrderByDescending(p => p.Item2).ToList();
return list.Select(i => (i, false)).ToList();
}, MouseWheelType.None, Penumbra.Log)
{
protected override string ToString(EquipItem obj)
=> obj.Name;
protected override bool DrawSelectable(int globalIdx, bool selected)
{
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ResTreeLocalPlayer.Value(), Items[globalIdx].InMod);
return base.DrawSelectable(globalIdx, selected);
}
protected override string ToString((EquipItem Item, bool InMod) obj)
=> obj.Item.Name;
}
private readonly Dictionary<SwapType, (ItemSelector Source, ItemSelector Target, string TextFrom, string TextTo)> _selectors;
@ -186,17 +201,17 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
case SwapType.Bracelet:
case SwapType.Ring:
var values = _selectors[_lastTab];
if (values.Source.CurrentSelection.Type != FullEquipType.Unknown
&& values.Target.CurrentSelection.Type != FullEquipType.Unknown)
_affectedItems = _swapData.LoadEquipment(values.Target.CurrentSelection, values.Source.CurrentSelection,
if (values.Source.CurrentSelection.Item.Type != FullEquipType.Unknown
&& values.Target.CurrentSelection.Item.Type != FullEquipType.Unknown)
_affectedItems = _swapData.LoadEquipment(values.Target.CurrentSelection.Item, values.Source.CurrentSelection.Item,
_useCurrentCollection ? _collectionManager.Active.Current : null, _useRightRing, _useLeftRing);
break;
case SwapType.BetweenSlots:
var (_, _, selectorFrom) = GetAccessorySelector(_slotFrom, true);
var (_, _, selectorTo) = GetAccessorySelector(_slotTo, false);
if (selectorFrom.CurrentSelection.Valid && selectorTo.CurrentSelection.Valid)
_affectedItems = _swapData.LoadTypeSwap(_slotTo, selectorTo.CurrentSelection, _slotFrom, selectorFrom.CurrentSelection,
if (selectorFrom.CurrentSelection.Item.Valid && selectorTo.CurrentSelection.Item.Valid)
_affectedItems = _swapData.LoadTypeSwap(_slotTo, selectorTo.CurrentSelection.Item, _slotFrom, selectorFrom.CurrentSelection.Item,
_useCurrentCollection ? _collectionManager.Active.Current : null);
break;
case SwapType.Hair when _targetId > 0 && _sourceId > 0:
@ -455,7 +470,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
}
ImGui.TableNextColumn();
_dirty |= selector.Draw("##itemSource", selector.CurrentSelection.Name ?? string.Empty, string.Empty, InputWidth * 2 * UiHelpers.Scale,
_dirty |= selector.Draw("##itemSource", selector.CurrentSelection.Item.Name ?? string.Empty, string.Empty, InputWidth * 2 * UiHelpers.Scale,
ImGui.GetTextLineHeightWithSpacing());
(article1, _, selector) = GetAccessorySelector(_slotTo, false);
@ -480,7 +495,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGui.TableNextColumn();
_dirty |= selector.Draw("##itemTarget", selector.CurrentSelection.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
_dirty |= selector.Draw("##itemTarget", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
ImGui.GetTextLineHeightWithSpacing());
if (_affectedItems is not { Length: > 1 })
return;
@ -489,7 +504,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero,
Colors.PressEnterWarningBg);
if (ImGui.IsItemHovered())
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, selector.CurrentSelection.Name))
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, selector.CurrentSelection.Item.Name))
.Select(i => i.Name)));
}
@ -521,7 +536,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(text1);
ImGui.TableNextColumn();
_dirty |= sourceSelector.Draw("##itemSource", sourceSelector.CurrentSelection.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
_dirty |= sourceSelector.Draw("##itemSource", sourceSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
ImGui.GetTextLineHeightWithSpacing());
if (type == SwapType.Ring)
@ -534,7 +549,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(text2);
ImGui.TableNextColumn();
_dirty |= targetSelector.Draw("##itemTarget", targetSelector.CurrentSelection.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
_dirty |= targetSelector.Draw("##itemTarget", targetSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
ImGui.GetTextLineHeightWithSpacing());
if (type == SwapType.Ring)
{
@ -549,7 +564,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero,
Colors.PressEnterWarningBg);
if (ImGui.IsItemHovered())
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, targetSelector.CurrentSelection.Name))
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, targetSelector.CurrentSelection.Item.Name))
.Select(i => i.Name)));
}