feat(ui): inventory/shortcut/paperdoll item-name tooltips — UIElement_UIItem::UpdateTooltip port

Retail UIElement_UIItem::UpdateTooltip @0x004E1CB0 caches the item's
NAME_APPROPRIATE display name (stack-count-prefixed "%d %s" when
StackSize > 1) as m_TTText every UIItem_Update refresh; the generic
UIElementManager::CheckTooltip dwell timer is what actually shows it
on hover — no special-cased trigger of its own.

UiItemSlot cells are built programmatically (never through
LayoutImporter.Build), so #409's original round left this deferred:
the class carried neither the popup locator (P0x47/P0x48) nor a name
source. A live-DAT sweep of the shared UIItem cell-template catalog
(ItemListCellTemplate.CatalogLayoutId, 0x21000037) found all 47
UIItem-type (class 0x10000032) prototypes — inventory's cell, every
toolbar slot, every paperdoll/armor slot skin — resolve the IDENTICAL
popup locator (P0x47=0x10000395/P0x48=0x21000041) through catalog
inheritance, with no literal text authored on any of them. UiItemSlot
now hardcodes that pair and exposes GetTooltipText() via a new
TooltipTextResolve delegate, wired at every physical-item
construction site: InventoryController (main-pack cell + grid cells),
ExternalContainerController, PaperdollController (closes the
separate gmPaperDollUI::UpdateItemSlotTooltip @0x004A52EF gap too —
same cell class, same fix), VendorUiController (shop/buying/selling
lists), SecureTradeUiController, ToolbarController.

Text is the new ClientObject.GetTooltipDisplayName(): GetAppropriateName()
prefixed with the stack count via "{count} {name}" when StackSize > 1,
matching UpdateTooltip's exact NAME_APPROPRIATE + "%d %s" sprintf.
UiCatalogSlot (spell/component catalog cells, a different UiItemSlot
subclass) is unaffected — it already overrides GetTooltipText() with
its own Label.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-16 23:02:10 +02:00
parent 5f9ca18155
commit e29c61a3a4
8 changed files with 87 additions and 3 deletions

View file

@ -1102,6 +1102,10 @@ public sealed class VendorUiController : IRetainedPanelController, IItemListDrag
// comment for why this must be gated at the source,
// not left to every destination handler to reject.
AllowDragSource = false,
// Shop items are materialized into ClientObjectTable
// (VendorShopItemMaterializer), so the same resolver
// every other physical cell uses works here too.
TooltipTextResolve = g => _objects.Get(g)?.GetTooltipDisplayName(),
};
cell.SetItem(item.ItemGuid, icon);
cell.Selected = item.ItemGuid == selectedGuid;
@ -2205,6 +2209,7 @@ public sealed class VendorUiController : IRetainedPanelController, IItemListDrag
SpriteResolve = list.SpriteResolve,
SlotIndex = list.GetNumUIItems(),
AllowDragSource = false,
TooltipTextResolve = g => _objects.Get(g)?.GetTooltipDisplayName(),
};
cell.SetItem(shopItem.ItemGuid, icon);
cell.Selected = shopItem.ItemGuid == selectedGuid;
@ -2243,6 +2248,7 @@ public sealed class VendorUiController : IRetainedPanelController, IItemListDrag
SpriteResolve = list.SpriteResolve,
SlotIndex = list.GetNumUIItems(),
AllowDragSource = false,
TooltipTextResolve = g => _objects.Get(g)?.GetTooltipDisplayName(),
};
cell.SetItem(item.ObjectId, icon);
cell.Selected = item.ObjectId == selectedGuid;