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 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 readonly ResourceType Type = type;
public MissingFileException(ResourceType type, object path)
: base($"Could not load {type} File Data for \"{path}\".")
=> Type = type;
} }
private static bool LoadFile(MetaFileManager manager, FullPath path, out byte[] data) 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}"); Penumbra.Log.Debug($"Could not load file {path}:\n{e}");
} }
data = Array.Empty<byte>(); data = [];
return false; return false;
} }

View file

@ -22,6 +22,7 @@ using Penumbra.Mods.Settings;
using Penumbra.Mods.SubMods; using Penumbra.Mods.SubMods;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using Penumbra.UI.ModsTab;
namespace Penumbra.UI.AdvancedWindow; namespace Penumbra.UI.AdvancedWindow;
@ -34,7 +35,8 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
private readonly MetaFileManager _metaFileManager; private readonly MetaFileManager _metaFileManager;
public ItemSwapTab(CommunicatorService communicator, ItemData itemService, CollectionManager collectionManager, 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; _communicator = communicator;
_collectionManager = collectionManager; _collectionManager = collectionManager;
@ -46,15 +48,15 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
_selectors = new Dictionary<SwapType, (ItemSelector Source, ItemSelector Target, string TextFrom, string TextTo)> _selectors = new Dictionary<SwapType, (ItemSelector Source, ItemSelector Target, string TextFrom, string TextTo)>
{ {
// @formatter:off // @formatter:off
[SwapType.Hat] = (new ItemSelector(itemService, FullEquipType.Head), new ItemSelector(itemService, FullEquipType.Head), "Take this Hat", "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, FullEquipType.Body), new ItemSelector(itemService, FullEquipType.Body), "Take this Top", "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, FullEquipType.Hands), new ItemSelector(itemService, FullEquipType.Hands), "Take these Gloves", "and put them on these" ), [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, FullEquipType.Legs), new ItemSelector(itemService, FullEquipType.Legs), "Take these Pants", "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, FullEquipType.Feet), new ItemSelector(itemService, FullEquipType.Feet), "Take these Shoes", "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, FullEquipType.Ears), new ItemSelector(itemService, FullEquipType.Ears), "Take these Earrings", "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, FullEquipType.Neck), new ItemSelector(itemService, FullEquipType.Neck), "Take this Necklace", "and put it on this one" ), [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, FullEquipType.Wrists), new ItemSelector(itemService, FullEquipType.Wrists), "Take these Bracelets", "and put them on these" ), [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, FullEquipType.Finger), new ItemSelector(itemService, FullEquipType.Finger), "Take this Ring", "and put it on this one" ), [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 // @formatter:on
}; };
@ -129,11 +131,24 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
Weapon, Weapon,
} }
private class ItemSelector(ItemData data, FullEquipType type) private class ItemSelector(ItemData data, ModFileSystemSelector? selector, FullEquipType type)
: FilterComboCache<EquipItem>(() => data.ByType[type], MouseWheelType.None, Penumbra.Log) : 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) protected override bool DrawSelectable(int globalIdx, bool selected)
=> obj.Name; {
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; 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.Bracelet:
case SwapType.Ring: case SwapType.Ring:
var values = _selectors[_lastTab]; var values = _selectors[_lastTab];
if (values.Source.CurrentSelection.Type != FullEquipType.Unknown if (values.Source.CurrentSelection.Item.Type != FullEquipType.Unknown
&& values.Target.CurrentSelection.Type != FullEquipType.Unknown) && values.Target.CurrentSelection.Item.Type != FullEquipType.Unknown)
_affectedItems = _swapData.LoadEquipment(values.Target.CurrentSelection, values.Source.CurrentSelection, _affectedItems = _swapData.LoadEquipment(values.Target.CurrentSelection.Item, values.Source.CurrentSelection.Item,
_useCurrentCollection ? _collectionManager.Active.Current : null, _useRightRing, _useLeftRing); _useCurrentCollection ? _collectionManager.Active.Current : null, _useRightRing, _useLeftRing);
break; break;
case SwapType.BetweenSlots: case SwapType.BetweenSlots:
var (_, _, selectorFrom) = GetAccessorySelector(_slotFrom, true); var (_, _, selectorFrom) = GetAccessorySelector(_slotFrom, true);
var (_, _, selectorTo) = GetAccessorySelector(_slotTo, false); var (_, _, selectorTo) = GetAccessorySelector(_slotTo, false);
if (selectorFrom.CurrentSelection.Valid && selectorTo.CurrentSelection.Valid) if (selectorFrom.CurrentSelection.Item.Valid && selectorTo.CurrentSelection.Item.Valid)
_affectedItems = _swapData.LoadTypeSwap(_slotTo, selectorTo.CurrentSelection, _slotFrom, selectorFrom.CurrentSelection, _affectedItems = _swapData.LoadTypeSwap(_slotTo, selectorTo.CurrentSelection.Item, _slotFrom, selectorFrom.CurrentSelection.Item,
_useCurrentCollection ? _collectionManager.Active.Current : null); _useCurrentCollection ? _collectionManager.Active.Current : null);
break; break;
case SwapType.Hair when _targetId > 0 && _sourceId > 0: case SwapType.Hair when _targetId > 0 && _sourceId > 0:
@ -455,7 +470,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
} }
ImGui.TableNextColumn(); 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()); ImGui.GetTextLineHeightWithSpacing());
(article1, _, selector) = GetAccessorySelector(_slotTo, false); (article1, _, selector) = GetAccessorySelector(_slotTo, false);
@ -480,7 +495,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGui.TableNextColumn(); 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()); ImGui.GetTextLineHeightWithSpacing());
if (_affectedItems is not { Length: > 1 }) if (_affectedItems is not { Length: > 1 })
return; return;
@ -489,7 +504,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero, ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero,
Colors.PressEnterWarningBg); Colors.PressEnterWarningBg);
if (ImGui.IsItemHovered()) 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))); .Select(i => i.Name)));
} }
@ -521,7 +536,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(text1); ImGui.TextUnformatted(text1);
ImGui.TableNextColumn(); 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()); ImGui.GetTextLineHeightWithSpacing());
if (type == SwapType.Ring) if (type == SwapType.Ring)
@ -534,7 +549,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(text2); ImGui.TextUnformatted(text2);
ImGui.TableNextColumn(); 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()); ImGui.GetTextLineHeightWithSpacing());
if (type == SwapType.Ring) 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, ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero,
Colors.PressEnterWarningBg); Colors.PressEnterWarningBg);
if (ImGui.IsItemHovered()) 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))); .Select(i => i.Name)));
} }