Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions EllesmereUIOptions/EUI_RaidFrames_ManagerPages.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ local function BuildBaseDetailDM(frame, fontPath)
title = "Tooltips",
rows = {
{ type = "dropdown", label = "Use Modifier",
tooltip = "Shared with buff tooltips. None shows tooltips without requiring a key.",
values = { none = "None", shift = "Shift", control = "Control", alt = "Alt" },
order = { "none", "shift", "control", "alt" },
get = function() return p.debuffTooltipModifier or "none" end,
Expand Down
13 changes: 10 additions & 3 deletions EllesmereUIOptions/EUI_RaidFrames_Options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4115,19 +4115,26 @@ initFrame:SetScript("OnEvent", function(self)
tipRows = {
{ type="dropdown", label="Buff Tooltips",
tooltip="Tooltip behavior when hovering a buff/HoT icon on a raid or party frame.",
values={ hidden="Hidden", shown="Shown", cursor="Shown At Cursor", combat="Hidden In Combat" },
order={ "hidden", "shown", "cursor", "combat" },
values={ hidden="Hidden", shown="Shown", cursor="Shown At Cursor", combat="Hidden In Combat", modifier="Shown on Modifier" },
order={ "hidden", "shown", "cursor", "modifier", "combat" },
get=function()
local v = SVal("buffHideTooltips", true)
if v == false then return "shown" end
if v == "cursor" or v == "combat" then return v end
if v == "cursor" or v == "combat" or v == "modifier" then return v end
return "hidden"
end,
set=function(k)
local v = k
if k == "shown" then v = false elseif k == "hidden" then v = true end
SSet("buffHideTooltips", v); if ns.ReloadFrames then ns.ReloadFrames() end
end },
{ type="dropdown", label="Use Modifier",
tooltip="Shared with debuff tooltips. None shows tooltips without requiring a key.",
values={ none="None", shift="Shift", control="Control", alt="Alt" },
order={ "none", "shift", "control", "alt" },
get=function() return db.profile.debuffTooltipModifier or "none" end,
set=function(v) SSet("debuffTooltipModifier", v) end,
disabled=function() return SVal("buffHideTooltips", true) ~= "modifier" end },
}
local _, cogShow = EllesmereUI.BuildCogPopup({
title = "Tooltip Settings",
Expand Down
154 changes: 132 additions & 22 deletions EllesmereUIRaidFrames/EUI_RaidFrames_AuraContainers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ end
-- aura buttons render their own tooltip when mouse motion is on, showing the real
-- aura even while secret; effect slots (healthcolor/border) stay motion-off always
-- (they overlay the health bar). 4-state mode: true/nil=hidden, false=shown,
-- "combat"=hidden in combat, "cursor"=shown at cursor.
-- "combat"=hidden in combat, "cursor"=shown at cursor, "modifier"=secure hover gate.
local function BmTipMode()
local p = ns.db and ns.db.profile
local v = p and p.buffHideTooltips
Expand All @@ -1293,7 +1293,7 @@ end

local function BmTipsOff()
local v = BmTipMode()
return not (v == false or v == "combat" or v == "cursor")
return not (v == false or v == "combat" or v == "cursor" or v == "modifier")
end

local function BuildBmIconStyle(ind, iscale, size)
Expand Down Expand Up @@ -1846,9 +1846,7 @@ end
-- members = array of { ind, count }; members[1] is the ROOT driving position/growth/
-- wrap. Attached members (Anchor To) each contribute one flow group with their own
-- element size and Max Icons cap.
local function AnchorBmChainContainer(container, health, members, iscale)
if not container then return end
local ind = members[1].ind
local function BmChainPin(ind, iscale)
local pos = ind.position or "TOPLEFT"
local grow = ind.growDirection or "RIGHT"
local size = (ind.size or 18) * iscale
Expand All @@ -1862,16 +1860,15 @@ local function AnchorBmChainContainer(container, health, members, iscale)

local per = tonumber(ind.iconsPerRow) or 0

container:ClearAllPoints()
local gH, gV
if grow == "CENTER" then
local point = (posT and "TOP") or (posB and "BOTTOM") or "CENTER"
container:SetPoint(point, health, pos, ox, oy)
-- Wrapped rows stack away from the anchored edge (simple-grid
-- convention); the flow origin corner follows the stack direction.
gH = "RIGHT"
gV = (per > 0 and posB) and "UP" or "DOWN"
AK.SetContainerAnchor(container, (gV == "UP") and "BOTTOMLEFT" or "TOPLEFT")
return point, pos, ox, oy, gH, gV,
(gV == "UP") and "BOTTOMLEFT" or "TOPLEFT"
else
gH = (grow == "LEFT") and "LEFT" or "RIGHT"
gV = (grow == "UP") and "UP" or "DOWN"
Expand Down Expand Up @@ -1899,9 +1896,20 @@ local function AnchorBmChainContainer(container, health, members, iscale)
else
if posT then dy = -size elseif not posB then dy = -size / 2 end
end
container:SetPoint(corner, health, pos, ox + dx, oy + dy)
AK.SetContainerAnchor(container, corner)
return corner, pos, ox + dx, oy + dy, gH, gV, corner
end
end

local function AnchorBmChainContainer(container, health, members, iscale)
if not container then return end
local ind = members[1].ind
local grow = ind.growDirection or "RIGHT"
local size = (ind.size or 18) * iscale
local per = tonumber(ind.iconsPerRow) or 0
local point, corner, x, y, gH, gV, anchor = BmChainPin(ind, iscale)
container:ClearAllPoints()
container:SetPoint(point, health, corner, x, y)
AK.SetContainerAnchor(container, anchor)
AK.SetContainerGrowth(container, FlowDir(gH), FlowDir(gV))
local spacing = (ind.spacing or 0) * iscale
local vertical = (grow == "UP" or grow == "DOWN")
Expand Down Expand Up @@ -2164,17 +2172,10 @@ end
-- Mirrors the legacy AnchorSimpleGrid: the grid's start corner pinned at the same
-- corner of the health bar, rows wrap after Icons Per Row and stack away from the
-- anchored edge; CENTER growth centers rows on the anchor point.
local function AnchorBmSimpleContainer(container, health, bs, iscale, d)
if not container then return end
-- Uniform Icon Anchoring: bs is the bmSimple sub-table, so the toggle is
-- read from the button's class proxy.
if d and ns.RF_AnchorHost then health = ns.RF_AnchorHost(health, ProxyFor(d)) end
local function BmSimplePin(bs, iscale)
local pos = bs.position or "topright"
local corner = CORNERS[pos] or "TOPRIGHT"
local grow = bs.growDirection or "LEFT"
local size = (bs.size or 18) * iscale
local spacing = (bs.spacing or 1) * iscale
local perRow = bs.iconsPerRow or 4
local ox = (bs.offsetX or 0) * iscale
local oy = (bs.offsetY or 0) * iscale

Expand All @@ -2184,22 +2185,33 @@ local function AnchorBmSimpleContainer(container, health, bs, iscale, d)
local vEdge = bottomish and "BOTTOM" or "TOP"
local gV = bottomish and "UP" or "DOWN"

container:ClearAllPoints()
local anchorPoint, gH
if not horizontal then
gH = rightish and "LEFT" or "RIGHT" -- moot in a single column
gV = grow
anchorPoint = (grow == "UP" and "BOTTOM" or "TOP") .. (rightish and "RIGHT" or "LEFT")
container:SetPoint(anchorPoint, health, corner, ox, oy)
elseif grow == "CENTER" then
gH = "RIGHT"
anchorPoint = vEdge .. "LEFT"
container:SetPoint(vEdge, health, corner, ox, oy)
else
gH = grow
anchorPoint = vEdge .. ((grow == "LEFT") and "RIGHT" or "LEFT")
container:SetPoint(anchorPoint, health, corner, ox, oy)
end
return grow == "CENTER" and vEdge or anchorPoint, corner, ox, oy, gH, gV, anchorPoint
end

local function AnchorBmSimpleContainer(container, health, bs, iscale, d)
if not container then return end
-- Uniform Icon Anchoring: bs is the bmSimple sub-table, so the toggle is
-- read from the button's class proxy.
if d and ns.RF_AnchorHost then health = ns.RF_AnchorHost(health, ProxyFor(d)) end
local size = (bs.size or 18) * iscale
local spacing = (bs.spacing or 1) * iscale
local perRow = bs.iconsPerRow or 4
local horizontal = bs.growDirection ~= "UP" and bs.growDirection ~= "DOWN"
local point, corner, x, y, gH, gV, anchorPoint = BmSimplePin(bs, iscale)
container:ClearAllPoints()
container:SetPoint(point, health, corner, x, y)
AK.SetContainerAnchor(container, anchorPoint)
AK.SetContainerGrowth(container, FlowDir(gH), FlowDir(gV))

Expand All @@ -2217,6 +2229,99 @@ local function AnchorBmSimpleContainer(container, health, bs, iscale, d)
})
end

-- The secure modifier overlay covers the maximum configured footprint, just
-- like Debuff Manager. No native aura identity, visibility or bounds are read.
local function EnsureBmTipModifiers(button, d)
if not ns.DM_TipModSync then return end
ns.DM_TipModSync(d)
if BmTipMode() ~= "modifier" or ns.DM_TipMod() == "none" then
ns.DM_ParkBuffTipEaters(d)
return
end
if InCombatLockdown() then d.rfcBmPending = true; return end
local health = d.rfcHealth
if not health then return end
local s = ProxyFor(d)
local pinHost = ns.RF_AnchorHost and ns.RF_AnchorHost(health, s) or health
local hugBar = pinHost._euiHealth or pinHost
local iscale = BmScaleFor(d)
local seen = {}
local function Grid(key, container, n, size, spacing, per, vertical, padding, lineWidth,
point, corner, x, y)
if not container or n < 1 then return end
-- GetPoint can return secret values even on owned aura containers.
-- Share the settings-derived pin with the container's layout instead.
local along = per and per > 0 and math.min(n, per) or n
local lines = per and per > 0 and math.ceil(n / per) or 1
local w = math.max(size, along * size + (along - 1) * spacing, lineWidth or 0)
local h = math.max(size, lines * size + (lines - 1) * spacing)
if vertical then w, h = h, w end
padding = padding or 0
w, h = w + padding * 2, h + padding * 2
-- Expand around the same pin when members have custom gaps.
if point:find("LEFT", 1, true) then x = x - padding
elseif point:find("RIGHT", 1, true) then x = x + padding end
if point:find("TOP", 1, true) then y = y + padding
elseif point:find("BOTTOM", 1, true) then y = y - padding end
seen[key] = true
ns.DM_EnsureBuffTipEater(button, d, key, container, pinHost, point, corner, x, y, w, h)
end
local bs = BmSimpleSettings()
if bs and bs.showBuffs and ns.BM_BaseActive and ns.BM_BaseActive() then
local vertical = bs.growDirection == "UP" or bs.growDirection == "DOWN"
local per = bs.iconsPerRow or 4
if per < 2 then per = 0 end
Grid("simple", d.rfcBmSimple, bs.maxBuffs or 8, (bs.size or 18) * iscale,
(bs.spacing or 1) * iscale, vertical and 1 or per, false, nil, nil,
BmSimplePin(bs, iscale))
end
for _, m in ipairs(d.rfcBmMeta or {}) do
if m.isChain and not m.anchored then
local members = m.members or { { ind = m.ind, count = m.count or (m.ind.spells and #m.ind.spells) or 0 } }
local n, size, padding = 0, 0, 0
local budgets = {}
for i, member in ipairs(members) do
local ind = member.ind
local count = member.count or 0
local cap = ind.maxIcons or 0
local index = member.memberIndex or i
if cap > 0 then
local remaining = budgets[index] or cap
count = math.min(count, remaining)
budgets[index] = remaining - count
end
n = n + count
size = math.max(size, (ind.size or 18) * iscale)
if i > 1 and (member.segIndex or 1) <= 1 and index > 1 then
local grow = members[1].ind.growDirection
local offset = (grow == "UP" or grow == "DOWN") and ind.offsetY or ind.offsetX
padding = padding + math.abs(offset or 0) * iscale
end
end
local ind = members[1].ind
local spacing = (ind.spacing or 0) * iscale
local per = tonumber(ind.iconsPerRow) or 0
local width
-- Mixed-size groups may fit fewer cells than the root's row width.
if per > 0 then
width = per * (ind.size or 18) * iscale + (per - 1) * spacing
per = math.max(1, math.floor((width + spacing) / math.max(1, size + spacing)))
end
Grid("chain:" .. m.chainKey, d.rfcBmChain and d.rfcBmChain[m.chainKey],
n, size, spacing, per, ind.growDirection == "UP" or ind.growDirection == "DOWN", padding, width,
BmChainPin(ind, iscale))
elseif not m.isChain and d.rfcBm and (m.kind == "icon" or m.kind == "square" or m.kind == "bar") then
local key = "slot:" .. m.key
seen[key] = true
ns.DM_EnsureBuffTipEater(button, d, key, d.rfcBm, pinHost, "CENTER", "CENTER", 0, 0, 1, 1,
function(e) BmAnchorOneSlot(e, m, pinHost, hugBar, iscale) end,
BmGeoFP({ m }, iscale, s))
end
end
ns.DM_ParkBuffTipEaters(d, seen)
end
ns.RFC_EnsureBmTipModifiers = EnsureBmTipModifiers

local function CreateBmSimpleContainer(button, health, d, unit, specKey)
local bs = BmSimpleSettings() or {}
local iscale = BmScaleFor(d)
Expand All @@ -2240,6 +2345,7 @@ local function CreateBmSimpleContainer(button, health, d, unit, specKey)
st.style = BmSimpleStyleFP(bs, font, iscale)
st.cand = BmSimpleCandFP(bs)
st.geo = BmSimpleGeoFP(bs, iscale, ProxyFor(d))
EnsureBmTipModifiers(button, d)
return
end

Expand Down Expand Up @@ -2272,6 +2378,7 @@ local function CreateBmSimpleContainer(button, health, d, unit, specKey)
st.style = BmSimpleStyleFP(bs, font, iscale)
st.cand = BmSimpleCandFP(bs)
st.geo = BmSimpleGeoFP(bs, iscale, ProxyFor(d))
EnsureBmTipModifiers(button, d)
return
end
local c = AK.CreateContainer(button, unit, {
Expand Down Expand Up @@ -2299,6 +2406,7 @@ local function CreateBmSimpleContainer(button, health, d, unit, specKey)
st.style = BmSimpleStyleFP(bs, font, iscale)
st.cand = BmSimpleCandFP(bs)
st.geo = BmSimpleGeoFP(bs, iscale, ProxyFor(d))
EnsureBmTipModifiers(button, d)
end

local function ReloadBmSimple(button, d, cls)
Expand Down Expand Up @@ -2658,6 +2766,7 @@ local function CreateBmContainer(button, health, d, unit)
end
end
bmOwnFP[StyleKeyFor(d)] = BmOwnKey(meta)
EnsureBmTipModifiers(button, d)
end

-- Chains-only rebind for pool shells that finished building after the
Expand Down Expand Up @@ -3503,6 +3612,7 @@ function ns.RFC_ReloadAll()
clsCache[styleKey] = cls
end
ReloadBm(button, d, s, cls)
EnsureBmTipModifiers(button, d)
end
end
end
Expand Down
22 changes: 14 additions & 8 deletions EllesmereUIRaidFrames/EUI_RaidFrames_ClickCast.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,8 @@ end
-- hides itself so the hover falls through to the aura button beneath.
-- The "eui_tipmod" state driver on this header flips only the HOVERED eater
-- on a modifier edge (one macro-conditional check per press, nothing else)
-- and re-shows the peeked eater on release. wrappedFrames is set here first,
-- and re-shows the peeked eaters on release. Overlapping eaters each hide
-- on entry while the key is held. wrappedFrames is set here first,
-- so DoRegisterFrame (click attributes when enabled) never wraps them twice.
-------------------------------------------------------------------------------
local tipEaters = setmetatable({}, { __mode = "k" })
Expand All @@ -1521,11 +1522,12 @@ local TIP_ENTER_BODY = [[
eui_hoveractive = true
end
local k = control:GetAttribute("eui_tipmod_key")
if k and not eui_tippeeked
if k
and ((k == "shift" and IsShiftKeyDown())
or (k == "control" and IsControlKeyDown())
or (k == "alt" and IsAltKeyDown())) then
eui_tippeeked = self
eui_tippeeked = eui_tippeeked or newtable()
eui_tippeeked[self] = true
self:Hide()
end
]]
Expand Down Expand Up @@ -1567,7 +1569,7 @@ function ns.CC_ReleaseTipEater(frame)
header:SetFrameRef("eui_tipclear", frame)
header:Execute([[
local f = self:GetFrameRef("eui_tipclear")
if eui_tippeeked == f then eui_tippeeked = nil end
if eui_tippeeked then eui_tippeeked[f] = nil end
if eui_hoverframe == f then eui_hoverframe = nil end
]])
end
Expand All @@ -1580,19 +1582,23 @@ function ns.CC_SetTipModKey(key)
header:SetAttribute("eui_tipmod_key", key)
if not key then
header:Execute([[
if eui_tippeeked then eui_tippeeked:Show(); eui_tippeeked = nil end
if eui_tippeeked then
for f in pairs(eui_tippeeked) do f:Show() end
eui_tippeeked = nil
end
]])
return
end
header:SetAttribute("_onstate-eui_tipmod", [[
if newstate == "held" then
local f = eui_hoverframe
if f and not eui_tippeeked and f:GetAttribute("eui_tipeater") then
eui_tippeeked = f
if f and f:GetAttribute("eui_tipeater") then
eui_tippeeked = eui_tippeeked or newtable()
eui_tippeeked[f] = true
f:Hide()
end
elseif eui_tippeeked then
eui_tippeeked:Show()
for f in pairs(eui_tippeeked) do f:Show() end
eui_tippeeked = nil
end
]])
Expand Down
Loading