Context menu fixes
- Allow opening of titled context menus we didn't create - Allow customization of the red button context menus
This commit is contained in:
@@ -314,7 +314,14 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
|
||||
// Read the context menu items from the game, then allow subscribers to modify them
|
||||
ContextMenuReaderWriter contextMenuReaderWriter = new ContextMenuReaderWriter(m_CurrentContextMenuAgent, atkValueCount, atkValues);
|
||||
m_CurrentContextMenuOpenedArgs = NotifyContextMenuOpened(addon, m_CurrentContextMenuAgent, contextMenuOpenedDelegate, contextMenuReaderWriter.Read());
|
||||
|
||||
string? title = null;
|
||||
if (contextMenuReaderWriter.Title != null)
|
||||
{
|
||||
title = contextMenuReaderWriter.Title.TextValue;
|
||||
}
|
||||
|
||||
m_CurrentContextMenuOpenedArgs = NotifyContextMenuOpened(addon, m_CurrentContextMenuAgent, title, contextMenuOpenedDelegate, contextMenuReaderWriter.Read());
|
||||
if (m_CurrentContextMenuOpenedArgs == null)
|
||||
{
|
||||
return;
|
||||
@@ -413,17 +420,10 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
|
||||
private unsafe void SubContextMenuOpenedImplementation(IntPtr addon, ref int atkValueCount, ref AtkValue* atkValues)
|
||||
{
|
||||
// For now, don't allow to modifying sub context menus unless we created them.
|
||||
// TODO: May want to allow this.
|
||||
if (m_CurrentSelectedItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ContextMenuOpenedImplementation(addon, ref atkValueCount, ref atkValues);
|
||||
}
|
||||
|
||||
private unsafe ContextMenuOpenedArgs? NotifyContextMenuOpened(IntPtr addon, IntPtr agent, ContextMenuOpenedDelegate contextMenuOpenedDelegate, IEnumerable<ContextMenuItem> initialContextMenuItems)
|
||||
private unsafe ContextMenuOpenedArgs? NotifyContextMenuOpened(IntPtr addon, IntPtr agent, string? title, ContextMenuOpenedDelegate contextMenuOpenedDelegate, IEnumerable<ContextMenuItem> initialContextMenuItems)
|
||||
{
|
||||
var parentAddonName = GetParentAddonName(addon);
|
||||
|
||||
@@ -451,6 +451,7 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
|
||||
var contextMenuOpenedArgs = new ContextMenuOpenedArgs(addon, agent, parentAddonName, initialContextMenuItems)
|
||||
{
|
||||
Title = title,
|
||||
ItemContext = itemContext,
|
||||
GameObjectContext = gameObjectContext
|
||||
};
|
||||
|
||||
@@ -24,6 +24,11 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
/// </summary>
|
||||
public string? ParentAddonName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The title of the context menu.
|
||||
/// </summary>
|
||||
public string? Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The items in the context menu.
|
||||
/// </summary>
|
||||
|
||||
@@ -239,16 +239,22 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
}
|
||||
|
||||
// Get the action
|
||||
byte* actions = null;
|
||||
byte action = 0;
|
||||
if (IsInventoryContext)
|
||||
{
|
||||
actions = &((AgentInventoryContext*)m_Agent)->Actions;
|
||||
var actions = &((AgentInventoryContext*)m_Agent)->Actions;
|
||||
action = *(actions + contextMenuItemAtkValueBaseIndex);
|
||||
}
|
||||
else if (StructLayout != null && StructLayout.Value == SubContextMenuStructLayout.Alternate)
|
||||
{
|
||||
var actions = &((AgentContext*)m_Agent)->ItemData->RedButtonActions;
|
||||
action = (byte)*(actions + contextMenuItemIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
actions = &((AgentContext*)m_Agent)->ItemData->Actions;
|
||||
}
|
||||
byte action = *(actions + contextMenuItemAtkValueBaseIndex);
|
||||
var actions = &((AgentContext*)m_Agent)->ItemData->Actions;
|
||||
action = *(actions + contextMenuItemAtkValueBaseIndex);
|
||||
}
|
||||
|
||||
// Get the has previous indicator flag
|
||||
var hasPreviousIndicatorFlagsAtkValue = &m_AtkValues[HasPreviousIndicatorFlagsIndex];
|
||||
@@ -281,7 +287,7 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
return gameContextMenuItems.ToArray();
|
||||
}
|
||||
|
||||
public unsafe void Write(ContextMenuOpenedArgs contextMenuOpenedArgs, ContextMenuItem selectedContextMenuItem, AtkValueChangeTypeDelegate_Unmanaged atkValueChangeType, AtkValueSetStringDelegate_Unmanaged atkValueSetString)
|
||||
public unsafe void Write(ContextMenuOpenedArgs contextMenuOpenedArgs, ContextMenuItem? selectedContextMenuItem, AtkValueChangeTypeDelegate_Unmanaged atkValueChangeType, AtkValueSetStringDelegate_Unmanaged atkValueSetString)
|
||||
{
|
||||
var newAtkValuesCount = FirstContextMenuItemIndex + (contextMenuOpenedArgs.ContextMenuItems.Count() * TotalDesiredAtkValuesPerContextMenuItem);
|
||||
|
||||
@@ -358,7 +364,7 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
byte action = 0;
|
||||
if (contextMenuItem is GameContextMenuItem gameContextMenuItem)
|
||||
{
|
||||
action = gameContextMenuItem.ItemSelectedAction;
|
||||
action = gameContextMenuItem.SelectedAction;
|
||||
}
|
||||
else if (contextMenuItem is CustomContextMenuItem customContextMenuItem)
|
||||
{
|
||||
@@ -375,7 +381,8 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
{
|
||||
if (IsInventoryContext)
|
||||
{
|
||||
action = 0x30;
|
||||
// TODO: Fix inventory sub context menus
|
||||
action = /*0x30*/ 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -383,16 +390,21 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
}
|
||||
}
|
||||
|
||||
byte* actions = null;
|
||||
if (IsInventoryContext)
|
||||
{
|
||||
actions = &((AgentInventoryContext*)m_Agent)->Actions;
|
||||
var actions = &((AgentInventoryContext*)m_Agent)->Actions;
|
||||
*(actions + FirstContextMenuItemIndex + contextMenuItemIndex) = action;
|
||||
}
|
||||
else if (StructLayout != null && StructLayout.Value == SubContextMenuStructLayout.Alternate)
|
||||
{
|
||||
var actions = &((AgentContext*)m_Agent)->ItemData->RedButtonActions;
|
||||
*(actions + contextMenuItemIndex) = action;
|
||||
}
|
||||
else
|
||||
{
|
||||
actions = &((AgentContext*)m_Agent)->ItemData->Actions;
|
||||
var actions = &((AgentContext*)m_Agent)->ItemData->Actions;
|
||||
*(actions + FirstContextMenuItemIndex + contextMenuItemIndex) = action;
|
||||
}
|
||||
*(actions + FirstContextMenuItemIndex + contextMenuItemIndex) = action;
|
||||
|
||||
if (contextMenuItem.Indicator == ContextMenuItemIndicator.Previous)
|
||||
{
|
||||
@@ -436,7 +448,7 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
object? value = null;
|
||||
if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Int)
|
||||
{
|
||||
value = atkValue->Int;
|
||||
value = $"{atkValue->Int:X}";
|
||||
}
|
||||
else if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Bool)
|
||||
{
|
||||
|
||||
@@ -9,5 +9,6 @@ namespace FFXIVClientStructs.FFXIV.Client.UI.Agent
|
||||
[FieldOffset(0x0)] public ushort AtkValuesCount;
|
||||
[FieldOffset(0x8)] public AtkValue AtkValues;
|
||||
[FieldOffset(0x428)] public byte Actions;
|
||||
[FieldOffset(0x598)] public ulong RedButtonActions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,17 +10,17 @@ namespace PlayerTags.GameInterface.ContextMenus
|
||||
/// <summary>
|
||||
/// The game action that will be handled when the item is selected.
|
||||
/// </summary>
|
||||
public byte ItemSelectedAction { get; }
|
||||
public byte SelectedAction { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GameContextMenuItem"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the item.</param>
|
||||
/// <param name="itemSelectedAction">The game action that will be handled when the item is selected.</param>
|
||||
public GameContextMenuItem(SeString name, byte itemSelectedAction)
|
||||
/// <param name="selectedAction">The game action that will be handled when the item is selected.</param>
|
||||
public GameContextMenuItem(SeString name, byte selectedAction)
|
||||
: base(name)
|
||||
{
|
||||
ItemSelectedAction = itemSelectedAction;
|
||||
SelectedAction = selectedAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user