Use new context menu service.

This commit is contained in:
Ottermandias 2024-03-20 17:28:46 +01:00
parent 9750736d57
commit 2d75c24371
3 changed files with 88 additions and 113 deletions

View file

@ -88,7 +88,6 @@
<ProjectReference Include="..\Penumbra.String\Penumbra.string.csproj" /> <ProjectReference Include="..\Penumbra.String\Penumbra.string.csproj" />
<ProjectReference Include="..\Penumbra.GameData\Penumbra.GameData.csproj" /> <ProjectReference Include="..\Penumbra.GameData\Penumbra.GameData.csproj" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Dalamud.ContextMenu" Version="1.3.1" />
<PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" /> <PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" />
</ItemGroup> </ItemGroup>

View file

@ -1,8 +1,6 @@
using Dalamud.ContextMenu; using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
@ -16,142 +14,119 @@ public class ContextMenuService : IDisposable
public const int ItemSearchContextItemId = 0x1738; public const int ItemSearchContextItemId = 0x1738;
public const int ChatLogContextItemId = 0x948; public const int ChatLogContextItemId = 0x948;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly DalamudContextMenu _contextMenu; private readonly IContextMenu _contextMenu;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ObjectManager _objects; private readonly ObjectManager _objects;
private readonly IGameGui _gameGui; private readonly IGameGui _gameGui;
private EquipItem _lastItem;
private StainId _lastStain;
private readonly MenuItem _inventoryItem;
public ContextMenuService(ItemManager items, StateManager state, ObjectManager objects, IGameGui gameGui, Configuration config, public ContextMenuService(ItemManager items, StateManager state, ObjectManager objects, IGameGui gameGui, Configuration config,
DalamudPluginInterface pi) IContextMenu context)
{ {
_contextMenu = new DalamudContextMenu(pi); _contextMenu = context;
_items = items; _items = items;
_state = state; _state = state;
_objects = objects; _objects = objects;
_gameGui = gameGui; _gameGui = gameGui;
if (config.EnableGameContextMenu) if (config.EnableGameContextMenu)
Enable(); Enable();
_inventoryItem = new MenuItem
{
IsEnabled = true,
IsReturn = false,
PrefixChar = 'G',
Name = "Try On",
OnClicked = OnClick,
IsSubmenu = false,
PrefixColor = 541,
};
} }
public void Enable() public void Enable()
{ {
_contextMenu.OnOpenGameObjectContextMenu += AddGameObjectItem; _contextMenu.OnMenuOpened += OnMenuOpened;
_contextMenu.OnOpenInventoryContextMenu += AddInventoryItem; }
private unsafe void OnMenuOpened(MenuOpenedArgs args)
{
if (args.MenuType is ContextMenuType.Inventory)
{
var arg = (MenuTargetInventory)args.Target;
if (arg.TargetItem.HasValue && HandleItem(arg.TargetItem.Value.ItemId))
{
_lastStain = arg.TargetItem.Value.Stain;
args.AddMenuItem(_inventoryItem);
}
}
else
{
switch (args.AddonName)
{
case "ItemSearch" when args.AgentPtr != nint.Zero:
{
if (HandleItem((ItemId)AgentContext.Instance()->UpdateCheckerParam))
args.AddMenuItem(_inventoryItem);
break;
}
case "ChatLog":
{
var agent = _gameGui.FindAgentInterface("ChatLog");
if (agent == nint.Zero || !ValidateChatLogContext(agent))
return;
if (HandleItem(*(ItemId*)(agent + ChatLogContextItemId)))
{
_lastStain = 0;
args.AddMenuItem(_inventoryItem);
}
break;
}
}
}
}
private bool HandleItem(ItemId id)
{
var itemId = Math.Clamp(id.Id, 0, 500000u);
return _items.ItemData.TryGetValue(itemId, EquipSlot.MainHand, out _lastItem);
} }
public void Disable() public void Disable()
{ {
_contextMenu.OnOpenGameObjectContextMenu -= AddGameObjectItem; _contextMenu.OnMenuOpened -= OnMenuOpened;
_contextMenu.OnOpenInventoryContextMenu -= AddInventoryItem;
} }
public void Dispose() public void Dispose()
{ {
Disable(); Disable();
_contextMenu.Dispose();
} }
private static readonly SeString TryOnString = new SeStringBuilder().AddUiForeground(SeIconChar.BoxedLetterG.ToIconString(), 541) private void OnClick(MenuItemClickedArgs _)
.AddText(" Try On").AddUiForegroundOff().BuiltString;
private void AddInventoryItem(InventoryContextMenuOpenArgs args)
{ {
var item = CheckInventoryItem(args.ItemId); var (id, playerData) = _objects.PlayerData;
if (item != null) if (!playerData.Valid)
args.AddCustomItem(item); return;
}
private InventoryContextMenuItem? CheckInventoryItem(uint itemId) if (!_state.GetOrCreate(id, playerData.Objects[0], out var state))
{ return;
if (itemId > 500000)
itemId -= 500000;
if (!_items.ItemData.TryGetValue(itemId, EquipSlot.MainHand, out var item)) var slot = _lastItem.Type.ToSlot();
return null; _state.ChangeEquip(state, slot, _lastItem, _lastStain, ApplySettings.Manual);
if (!_lastItem.Type.ValidOffhand().IsOffhandType())
return;
return new InventoryContextMenuItem(TryOnString, GetInventoryAction(item)); if (_lastItem.PrimaryId.Id is > 1600 and < 1651
} && _items.ItemData.TryGetValue(_lastItem.ItemId, EquipSlot.Hands, out var gauntlets))
_state.ChangeEquip(state, EquipSlot.Hands, gauntlets, _lastStain, ApplySettings.Manual);
if (_items.ItemData.TryGetValue(_lastItem.ItemId, EquipSlot.OffHand, out var offhand))
private GameObjectContextMenuItem? CheckGameObjectItem(uint itemId) _state.ChangeEquip(state, EquipSlot.OffHand, offhand, _lastStain, ApplySettings.Manual);
{
if (itemId > 500000)
itemId -= 500000;
if (!_items.ItemData.TryGetValue(itemId, EquipSlot.MainHand, out var item))
return null;
return new GameObjectContextMenuItem(TryOnString, GetGameObjectAction(item));
}
private unsafe GameObjectContextMenuItem? CheckGameObjectItem(IntPtr agent, int offset, Func<nint, bool> validate)
=> agent != IntPtr.Zero && validate(agent) ? CheckGameObjectItem(*(uint*)(agent + offset)) : null;
private unsafe GameObjectContextMenuItem? CheckGameObjectItem(IntPtr agent, int offset)
=> agent != IntPtr.Zero ? CheckGameObjectItem(*(uint*)(agent + offset)) : null;
private GameObjectContextMenuItem? CheckGameObjectItem(string name, int offset, Func<nint, bool> validate)
=> CheckGameObjectItem(_gameGui.FindAgentInterface(name), offset, validate);
private void AddGameObjectItem(GameObjectContextMenuOpenArgs args)
{
var item = args.ParentAddonName switch
{
"ItemSearch" => CheckGameObjectItem(args.Agent, ItemSearchContextItemId),
"ChatLog" => CheckGameObjectItem("ChatLog", ChatLogContextItemId, ValidateChatLogContext),
_ => null,
};
if (item != null)
args.AddCustomItem(item);
}
private DalamudContextMenu.InventoryContextMenuItemSelectedDelegate GetInventoryAction(EquipItem item)
{
return _ =>
{
var (id, playerData) = _objects.PlayerData;
if (!playerData.Valid)
return;
if (!_state.GetOrCreate(id, playerData.Objects[0], out var state))
return;
var slot = item.Type.ToSlot();
_state.ChangeEquip(state, slot, item, 0, ApplySettings.Manual);
if (item.Type.ValidOffhand().IsOffhandType())
{
if (item.PrimaryId.Id is > 1600 and < 1651
&& _items.ItemData.TryGetValue(item.ItemId, EquipSlot.Hands, out var gauntlets))
_state.ChangeEquip(state, EquipSlot.Hands, gauntlets, 0, ApplySettings.Manual);
if (_items.ItemData.TryGetValue(item.ItemId, EquipSlot.OffHand, out var offhand))
_state.ChangeEquip(state, EquipSlot.OffHand, offhand, 0, ApplySettings.Manual);
}
};
}
private DalamudContextMenu.GameObjectContextMenuItemSelectedDelegate GetGameObjectAction(EquipItem item)
{
return _ =>
{
var (id, playerData) = _objects.PlayerData;
if (!playerData.Valid)
return;
if (!_state.GetOrCreate(id, playerData.Objects[0], out var state))
return;
var slot = item.Type.ToSlot();
_state.ChangeEquip(state, slot, item, 0, ApplySettings.Manual);
if (item.Type.ValidOffhand().IsOffhandType())
{
if (item.PrimaryId.Id is > 1600 and < 1651
&& _items.ItemData.TryGetValue(item.ItemId, EquipSlot.Hands, out var gauntlets))
_state.ChangeEquip(state, EquipSlot.Hands, gauntlets, 0, ApplySettings.Manual);
if (_items.ItemData.TryGetValue(item.ItemId, EquipSlot.OffHand, out var offhand))
_state.ChangeEquip(state, EquipSlot.OffHand, offhand, 0, ApplySettings.Manual);
}
};
} }
private static unsafe bool ValidateChatLogContext(nint agent) private static unsafe bool ValidateChatLogContext(nint agent)

View file

@ -27,5 +27,6 @@ public class DalamudServices
services.AddDalamudService<IPluginLog>(pi); services.AddDalamudService<IPluginLog>(pi);
services.AddDalamudService<IGameInteropProvider>(pi); services.AddDalamudService<IGameInteropProvider>(pi);
services.AddDalamudService<INotificationManager>(pi); services.AddDalamudService<INotificationManager>(pi);
services.AddDalamudService<IContextMenu>(pi);
} }
} }