Support model id input in weapon combo, support middle-mouse pipette.

This commit is contained in:
Ottermandias 2025-05-06 00:30:27 +02:00
parent fcb0660def
commit b1abbb8e77
5 changed files with 134 additions and 10 deletions

View file

@ -27,6 +27,9 @@ public struct EquipDrawData(EquipSlot slot, in DesignData designData)
public readonly void SetStains(StainIds stains) public readonly void SetStains(StainIds stains)
=> _editor.ChangeStains(_object, Slot, stains, ApplySettings.Manual); => _editor.ChangeStains(_object, Slot, stains, ApplySettings.Manual);
public readonly void SetStain(int which, StainId stain)
=> _editor.ChangeStains(_object, Slot, CurrentStains.With(which, stain), ApplySettings.Manual);
public readonly void SetApplyItem(bool value) public readonly void SetApplyItem(bool value)
{ {
var manager = (DesignManager)_editor; var manager = (DesignManager)_editor;

View file

@ -3,16 +3,15 @@ using Dalamud.Interface.Utility;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Gui.Materials; using Glamourer.Gui.Materials;
using Glamourer.Interop.Material;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using ImGuiNET; using ImGuiNET;
using OtterGui;
using OtterGui.Extensions; using OtterGui.Extensions;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using OtterGui.Text.EndObjects; using OtterGui.Text.EndObjects;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.GameData.Data;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
@ -33,6 +32,7 @@ public class EquipmentDrawer
private readonly Configuration _config; private readonly Configuration _config;
private readonly GPoseService _gPose; private readonly GPoseService _gPose;
private readonly AdvancedDyePopup _advancedDyes; private readonly AdvancedDyePopup _advancedDyes;
private readonly ItemCopyService _itemCopy;
private float _requiredComboWidthUnscaled; private float _requiredComboWidthUnscaled;
private float _requiredComboWidth; private float _requiredComboWidth;
@ -40,13 +40,14 @@ public class EquipmentDrawer
private Stain? _draggedStain; private Stain? _draggedStain;
public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures, public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures,
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes) Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes, ItemCopyService itemCopy)
{ {
_items = items; _items = items;
_textures = textures; _textures = textures;
_config = config; _config = config;
_gPose = gPose; _gPose = gPose;
_advancedDyes = advancedDyes; _advancedDyes = advancedDyes;
_itemCopy = itemCopy;
_stainData = items.Stains; _stainData = items.Stains;
_stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites); _stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites);
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray(); _itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray();
@ -184,6 +185,7 @@ public class EquipmentDrawer
return change; return change;
} }
#region Small #region Small
private void DrawEquipSmall(in EquipDrawData equipDrawData) private void DrawEquipSmall(in EquipDrawData equipDrawData)
@ -402,6 +404,7 @@ public class EquipmentDrawer
? _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss) ? _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss)
: _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width); : _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width);
_itemCopy.HandleCopyPaste(data, index);
if (!change) if (!change)
DrawStainDragDrop(data, index, stain, found); DrawStainDragDrop(data, index, stain, found);
@ -456,6 +459,7 @@ public class EquipmentDrawer
data.SetItem(combo.CurrentSelection); data.SetItem(combo.CurrentSelection);
else if (combo.CustomVariant.Id > 0) else if (combo.CustomVariant.Id > 0)
data.SetItem(_items.Identify(data.Slot, combo.CustomSetId, combo.CustomVariant)); data.SetItem(_items.Identify(data.Slot, combo.CustomSetId, combo.CustomVariant));
_itemCopy.HandleCopyPaste(data);
if (ResetOrClear(data.Locked, clear, data.AllowRevert, true, data.CurrentItem, data.GameItem, ItemManager.NothingItem(data.Slot), if (ResetOrClear(data.Locked, clear, data.AllowRevert, true, data.CurrentItem, data.GameItem, ItemManager.NothingItem(data.Slot),
out var item)) out var item))
@ -473,6 +477,14 @@ public class EquipmentDrawer
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.Id.BonusItem, var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.Id.BonusItem,
small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth); _requiredComboWidth);
if (ImGui.IsItemHovered() && ImGui.GetIO().KeyCtrl)
{
if (ImGui.IsKeyPressed(ImGuiKey.C))
_itemCopy.Copy(combo.CurrentSelection);
else if (ImGui.IsKeyPressed(ImGuiKey.V))
_itemCopy.Paste(data.Slot.ToEquipType(), data.SetItem);
}
if (change) if (change)
data.SetItem(combo.CurrentSelection); data.SetItem(combo.CurrentSelection);
else if (combo.CustomVariant.Id > 0) else if (combo.CustomVariant.Id > 0)
@ -531,7 +543,11 @@ public class EquipmentDrawer
if (combo.Draw(mainhand.CurrentItem.Name, mainhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, if (combo.Draw(mainhand.CurrentItem.Name, mainhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth)) _requiredComboWidth))
changedItem = combo.CurrentSelection; changedItem = combo.CurrentSelection;
else if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem, else if (combo.CustomVariant.Id > 0 && (drawAll || ItemData.ConvertWeaponId(combo.CustomSetId) == mainhand.CurrentItem.Type))
changedItem = _items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant);
_itemCopy.HandleCopyPaste(mainhand);
if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
default, out var c)) default, out var c))
changedItem = c; changedItem = c;
@ -549,7 +565,8 @@ public class EquipmentDrawer
} }
if (unknown) if (unknown)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8); ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled,
"The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8);
} }
private void DrawOffhand(in EquipDrawData mainhand, in EquipDrawData offhand, out string label, bool small, bool clear, bool open) private void DrawOffhand(in EquipDrawData mainhand, in EquipDrawData offhand, out string label, bool small, bool clear, bool open)
@ -569,6 +586,9 @@ public class EquipmentDrawer
if (combo.Draw(offhand.CurrentItem.Name, offhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, if (combo.Draw(offhand.CurrentItem.Name, offhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth)) _requiredComboWidth))
offhand.SetItem(combo.CurrentSelection); offhand.SetItem(combo.CurrentSelection);
else if (combo.CustomVariant.Id > 0 && ItemData.ConvertWeaponId(combo.CustomSetId) == offhand.CurrentItem.Type)
offhand.SetItem(_items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant));
_itemCopy.HandleCopyPaste(offhand);
var defaultOffhand = _items.GetDefaultOffhand(mainhand.CurrentItem); var defaultOffhand = _items.GetDefaultOffhand(mainhand.CurrentItem);
if (ResetOrClear(locked, clear, offhand.AllowRevert, true, offhand.CurrentItem, offhand.GameItem, defaultOffhand, out var item)) if (ResetOrClear(locked, clear, offhand.AllowRevert, true, offhand.CurrentItem, offhand.GameItem, defaultOffhand, out var item))
@ -623,6 +643,7 @@ public class EquipmentDrawer
{ {
ImUtf8.Text(label); ImUtf8.Text(label);
} }
if (hasAdvancedDyes) if (hasAdvancedDyes)
ImUtf8.HoverTooltip("This design has advanced dyes setup for this slot."u8); ImUtf8.HoverTooltip("This design has advanced dyes setup for this slot."u8);
} }

View file

@ -0,0 +1,78 @@
using Dalamud.Game.ClientState.Keys;
using Dalamud.Plugin.Services;
using Glamourer.Services;
using ImGuiNET;
using OtterGui.OtterGuiInternal.Enums;
using OtterGui.Services;
using OtterGuiInternal;
using Penumbra.GameData.Data;
using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Equipment;
public class ItemCopyService(ItemManager items, IKeyState keyState, DictStain stainData) : IUiService
{
public EquipItem? Item { get; private set; }
public Stain? Stain { get; private set; }
public void Copy(in EquipItem item)
=> Item = item;
public void Copy(in Stain stain)
=> Stain = stain;
public void Paste(int which, Action<int, StainId> setter)
{
if (Stain is { } stain)
setter(which, stain.RowIndex);
}
public void Paste(FullEquipType type, Action<EquipItem> setter)
{
if (Item is not { } item)
return;
if (type != item.Type)
{
if (type.IsBonus())
item = items.Identify(type.ToBonus(), item.PrimaryId, item.Variant);
else if (type.IsEquipment() || type.IsAccessory())
item = items.Identify(type.ToSlot(), item.PrimaryId, item.Variant);
else
item = items.Identify(type.ToSlot(), item.PrimaryId, item.SecondaryId, item.Variant);
}
if (item.Valid && item.Type == type)
setter(item);
}
public void HandleCopyPaste(in EquipDrawData data)
{
if (ImGui.GetIO().KeyCtrl)
{
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
Paste(data.CurrentItem.Type, data.SetItem);
}
else if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled) && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
{
Copy(data.CurrentItem);
}
}
public void HandleCopyPaste(in EquipDrawData data, int which)
{
if (ImGui.GetIO().KeyCtrl)
{
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
Paste(which, data.SetStain);
}
else if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)
&& ImGui.IsMouseClicked(ImGuiMouseButton.Middle)
&& stainData.TryGetValue(data.CurrentStains[which].Id, out var stain))
{
Copy(stain);
}
}
}

View file

@ -1,7 +1,6 @@
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using ImGuiNET; using ImGuiNET;
using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions; using OtterGui.Extensions;
using OtterGui.Log; using OtterGui.Log;
@ -20,6 +19,10 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
private ItemId _currentItem; private ItemId _currentItem;
private float _innerWidth; private float _innerWidth;
public PrimaryId CustomSetId { get; private set; }
public SecondaryId CustomWeaponId { get; private set; }
public Variant CustomVariant { get; private set; }
public WeaponCombo(ItemManager items, FullEquipType type, Logger log, FavoriteManager favorites) public WeaponCombo(ItemManager items, FullEquipType type, Logger log, FavoriteManager favorites)
: base(() => GetWeapons(favorites, items, type), MouseWheelType.Control, log) : base(() => GetWeapons(favorites, items, type), MouseWheelType.Control, log)
{ {
@ -49,6 +52,7 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
{ {
_innerWidth = innerWidth; _innerWidth = innerWidth;
_currentItem = previewIdx; _currentItem = previewIdx;
CustomVariant = 0;
return Draw($"##{Label}", previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing()); return Draw($"##{Label}", previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
} }
@ -75,6 +79,24 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
return ret; return ret;
} }
protected override void OnClosePopup()
{
// If holding control while the popup closes, try to parse the input as a full tuple of set id, weapon id and variant, and set a custom item for that.
if (!ImGui.GetIO().KeyCtrl)
return;
var split = Filter.Text.Split('-', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (split.Length != 3
|| !ushort.TryParse(split[0], out var setId)
|| !ushort.TryParse(split[1], out var weaponId)
|| !byte.TryParse(split[2], out var variant))
return;
CustomSetId = setId;
CustomWeaponId = weaponId;
CustomVariant = variant;
}
protected override bool IsVisible(int globalIndex, LowerString filter) protected override bool IsVisible(int globalIndex, LowerString filter)
=> base.IsVisible(globalIndex, filter) || Items[globalIndex].ModelString.StartsWith(filter.Lower); => base.IsVisible(globalIndex, filter) || Items[globalIndex].ModelString.StartsWith(filter.Lower);

@ -1 +1 @@
Subproject commit 002260d9815e571f1496c50374f5b712818e9880 Subproject commit 1019b56de3b7ab2a6a1aefd699f9a507323e92fc