diff --git a/EllesmereUIUnitFrames/EUI_UnitFrames_Options.lua b/EllesmereUIUnitFrames/EUI_UnitFrames_Options.lua index 5875d127..43b5d24a 100644 --- a/EllesmereUIUnitFrames/EUI_UnitFrames_Options.lua +++ b/EllesmereUIUnitFrames/EUI_UnitFrames_Options.lua @@ -2153,15 +2153,22 @@ initFrame:SetScript("OnEvent", function(self) elseif unitKey == "focustarget" then s = db.profile.focustarget else s = db.profile.player end - -- Player/target preview: mirror the live shared aura border style. + -- Player/target/boss preview: mirror the live aura border style. + -- Apply after the preview's final scale is known (below), otherwise + -- pixel-sized borders can be built against the previous scale. + local ApplyPreviewAuraBorders if unitKey == "player" or unitKey == "target" or unitKey == "boss" then local function ApplyPreviewAuraBorder(icon) if icon._iconTex then icon._iconTex:ClearAllPoints() - local inset = (s.auraBorderSize or 1) > 0 and 1 or 0 - PP.Point(icon._iconTex, "TOPLEFT", icon, "TOPLEFT", inset, -inset) - PP.Point(icon._iconTex, "BOTTOMRIGHT", icon, "BOTTOMRIGHT", -inset, inset) - end + -- Live aura icons fill the button and the configurable + -- border draws independently above/behind that texture. + -- The old 1px inset exposed the preview's hard-coded + -- black backdrop underneath textured boss borders. + PP.Point(icon._iconTex, "TOPLEFT", icon, "TOPLEFT", 0, 0) + PP.Point(icon._iconTex, "BOTTOMRIGHT", icon, "BOTTOMRIGHT", 0, 0) + end + if icon.SetBackdropColor then icon:SetBackdropColor(0, 0, 0, 0) end local border = icon._euiAuraBorder if not border then border = CreateFrame("Frame", nil, icon) @@ -2170,7 +2177,7 @@ initFrame:SetScript("OnEvent", function(self) icon._euiAuraBorder = border end if s.auraBorderBehindUnitFrame then - border:SetFrameLevel(0) + border:SetFrameLevel(math.max(0, pf:GetFrameLevel() - 1)) else border:SetFrameLevel(s.auraBorderBehind and math.max(0, icon:GetFrameLevel() - 1) or (icon:GetFrameLevel() + 1)) @@ -2182,11 +2189,13 @@ initFrame:SetScript("OnEvent", function(self) s.auraBorderTextureShiftX, s.auraBorderTextureShiftY, "unitframes", s.auraBorderSize or 1) end - for i = 1, #buffIcons do ApplyPreviewAuraBorder(buffIcons[i]) end - for i = 1, #debuffIcons do ApplyPreviewAuraBorder(debuffIcons[i]) end + ApplyPreviewAuraBorders = function() + for i = 1, #buffIcons do ApplyPreviewAuraBorder(buffIcons[i]) end + for i = 1, #debuffIcons do ApplyPreviewAuraBorder(debuffIcons[i]) end + end end - -- Donor settings for mini frames (border/texture/font inherit from focus player) + -- Donor settings for mini frames (texture/font inherit from focus player; local isMini = (unitKey == "pet" or unitKey == "boss" or unitKey == "targettarget" or unitKey == "focustarget") local ds = s if isMini then @@ -2855,15 +2864,16 @@ initFrame:SetScript("OnEvent", function(self) end -- Border size and color (encompasses health+power+BTB+above pips) - local bs = ds.borderSize or 1 - local bc = ds.borderColor or { r = 0, g = 0, b = 0 } - local bTexKey = ds.borderTexture or "solid" + local previewBorder = (unitKey == "boss" or unitKey == "targettarget") and s or ds + local bs = previewBorder.borderSize or 1 + local bc = previewBorder.borderColor or { r = 0, g = 0, b = 0 } + local bTexKey = previewBorder.borderTexture or "solid" local borderH = bh2 + (s.bottomTextBar and btbIsAtt and (s.bottomTextBarHeight or 16) or 0) border:ClearAllPoints() border:SetPoint("TOPLEFT", barArea, "TOPLEFT", 0, 0) border:SetPoint("TOPRIGHT", barArea, "TOPRIGHT", 0, 0) border:SetHeight(borderH) - EllesmereUI.ApplyBorderStyle(border, bs, bc.r, bc.g, bc.b, ds.borderAlpha or 1, bTexKey, ds.borderTextureOffset, ds.borderTextureOffsetY, ds.borderTextureShiftX, ds.borderTextureShiftY, "unitframes", bs) + EllesmereUI.ApplyBorderStyle(border, bs, bc.r, bc.g, bc.b, previewBorder.borderAlpha or 1, bTexKey, previewBorder.borderTextureOffset, previewBorder.borderTextureOffsetY, previewBorder.borderTextureShiftX, previewBorder.borderTextureShiftY, "unitframes", bs) -- Class Power Pips update (player only) if cpPipContainer and cpPips then @@ -3479,11 +3489,17 @@ initFrame:SetScript("OnEvent", function(self) local combinedScale = baseScale * fitScale pf:SetScale(combinedScale) + -- Border thickness/default offsets depend on effective scale. Do this + -- only after pf has its final scale so boss aura previews match live. + if ApplyPreviewAuraBorders then ApplyPreviewAuraBorders() end + -- Recalculate border sizes after scale change so they stay pixel-perfect if border then - local bs2 = ds.borderSize or 1 - local bTex2 = ds.borderTexture or "solid" - EllesmereUI.ApplyBorderStyle(border, bs2, (ds.borderColor or {r=0,g=0,b=0}).r, (ds.borderColor or {r=0,g=0,b=0}).g, (ds.borderColor or {r=0,g=0,b=0}).b, ds.borderAlpha or 1, bTex2, ds.borderTextureOffset, ds.borderTextureOffsetY, ds.borderTextureShiftX, ds.borderTextureShiftY, "unitframes", bs2) + local finalBorder = (unitKey == "boss" or unitKey == "targettarget") and s or ds + local bs2 = finalBorder.borderSize or 1 + local bTex2 = finalBorder.borderTexture or "solid" + local bc2 = finalBorder.borderColor or {r=0,g=0,b=0} + EllesmereUI.ApplyBorderStyle(border, bs2, bc2.r, bc2.g, bc2.b, finalBorder.borderAlpha or 1, bTex2, finalBorder.borderTextureOffset, finalBorder.borderTextureOffsetY, finalBorder.borderTextureShiftX, finalBorder.borderTextureShiftY, "unitframes", bs2) end if castbar then if PP.GetBorders(castbar) then PP.SetBorderSize(castbar, 1) end @@ -12277,12 +12293,117 @@ initFrame:SetScript("OnEvent", function(self) end end - -- DISPLAY bottom row: per-frame Border Size override for ToT / Focus - -- Target / Pet (the mini frames). Just the size slider, no color swatch -- - -- overrides ONLY the border size; color and texture still inherit from the - -- main frames. borderSizeOverride nil = inherit the donor border size until - -- the user sets it. Boss frames are NOT mini frames, so they are excluded. - if unitKey ~= "boss" then + -- Boss and Target-of-Target use their own full border configuration. + -- Their profile tables already carry the base border keys; optional + -- offsets and Show Behind remain nil until explicitly changed. + if unitKey == "boss" or unitKey == "targettarget" then + local bossTexValues, bossTexOrder = EllesmereUI.GetBorderTextureDropdown() + local bossBorderSizes = { none = "None", thin = "Thin", normal = "Normal", heavy = "Heavy", strong = "Strong" } + local bossBorderSizeOrder = { "none", "thin", "normal", "heavy", "strong" } + local bossBorderSizeToNumber = { none = 0, thin = 1, normal = 2, heavy = 3, strong = 4 } + local bossBorderNumberToSize = { [0] = "none", [1] = "thin", [2] = "normal", [3] = "heavy", [4] = "strong" } + local bossBorderRow + bossBorderRow, h = W:DualRow(parent, y, + { type = "dropdown", text = "Border Style", values = bossTexValues, order = bossTexOrder, + getValue = function() return settingsTable.borderTexture or "solid" end, + setValue = function(v) + settingsTable.borderTexture = v + settingsTable.borderTextureOffset = nil + settingsTable.borderTextureOffsetY = nil + settingsTable.borderTextureShiftX = nil + settingsTable.borderTextureShiftY = nil + local color, behind = EllesmereUI.GetBorderStyleSelectDefaults(v) + settingsTable.borderColor = color + settingsTable.borderAlpha = 1 + settingsTable.borderBehind = behind + local defSz = EllesmereUI.GetBorderDefaultSize("unitframes", v) + if defSz then settingsTable.borderSize = defSz end + ReloadAndUpdate() + end }, + { type = "dropdown", text = "Border Size", values = bossBorderSizes, order = bossBorderSizeOrder, + getValue = function() return bossBorderNumberToSize[settingsTable.borderSize or 1] or "thin" end, + setValue = function(v) + settingsTable.borderSize = bossBorderSizeToNumber[v] or 1 + ReloadAndUpdate() + end }); y = y - h + + do + local rgn = bossBorderRow._leftRegion + local _, bossBorderCogShow = EllesmereUI.BuildCogPopup({ + title = "Border Offset", + rows = { + { type = "slider", label = "Offset X", min = -10, max = 10, step = 1, + get = function() + local v = settingsTable.borderTextureOffset + if v ~= nil then return v end + return EllesmereUI.GetBorderDefaults("unitframes", settingsTable.borderTexture or "solid", settingsTable.borderSize or 1) + end, + set = function(v) settingsTable.borderTextureOffset = v; ReloadAndUpdate() end }, + { type = "slider", label = "Offset Y", min = -10, max = 10, step = 1, + get = function() + local v = settingsTable.borderTextureOffsetY + if v ~= nil then return v end + local _, oy = EllesmereUI.GetBorderDefaults("unitframes", settingsTable.borderTexture or "solid", settingsTable.borderSize or 1) + return oy + end, + set = function(v) settingsTable.borderTextureOffsetY = v; ReloadAndUpdate() end }, + { type = "slider", label = "Shift X", min = -10, max = 10, step = 1, + get = function() + local v = settingsTable.borderTextureShiftX + if v ~= nil then return v end + local _, _, sx = EllesmereUI.GetBorderDefaults("unitframes", settingsTable.borderTexture or "solid", settingsTable.borderSize or 1) + return sx + end, + set = function(v) settingsTable.borderTextureShiftX = v == 0 and nil or v; ReloadAndUpdate() end }, + { type = "slider", label = "Shift Y", min = -10, max = 10, step = 1, + get = function() + local v = settingsTable.borderTextureShiftY + if v ~= nil then return v end + local _, _, _, sy = EllesmereUI.GetBorderDefaults("unitframes", settingsTable.borderTexture or "solid", settingsTable.borderSize or 1) + return sy + end, + set = function(v) settingsTable.borderTextureShiftY = v == 0 and nil or v; ReloadAndUpdate() end }, + { type = "toggle", label = "Show Behind", + get = function() return settingsTable.borderBehind == true end, + set = function(v) settingsTable.borderBehind = v and true or nil; ReloadAndUpdate() end }, + }, + }) + local bossBorderCog = MCogBtn(rgn, bossBorderCogShow, EllesmereUI.DIRECTIONS_ICON) + local function UpdateBossBorderCog() + bossBorderCog:SetShown((settingsTable.borderTexture or "solid") ~= "solid") + end + EllesmereUI.RegisterWidgetRefresh(UpdateBossBorderCog) + UpdateBossBorderCog() + end + + do + local rgn = bossBorderRow._rightRegion + local swatch, refreshSwatch = EllesmereUI.BuildColorSwatch( + rgn, bossBorderRow:GetFrameLevel() + 3, + function() + local c = settingsTable.borderColor or { r = 0, g = 0, b = 0 } + return c.r, c.g, c.b, settingsTable.borderAlpha or 1 + end, + function(r, g, b, a) + settingsTable.borderColor = { r = r, g = g, b = b } + settingsTable.borderAlpha = a + ReloadAndUpdate() + end, true, 20) + PP.Point(swatch, "RIGHT", rgn._control, "LEFT", -8, 0) + EllesmereUI.RegisterWidgetRefresh(refreshSwatch) + end + end + + -- Target of Target now owns its full border above, but keeps the existing + -- opt-out for the donor's hover-highlight color. Focus Target and Pet + -- retain their donor-size override. + if unitKey == "targettarget" then + _, h = W:DualRow(parent, y, + { type="toggle", text="Show Highlight Border", + tooltip="Use the main frames' hover highlight color on this frame. When the cursor leaves, the Target of Target border returns to its own configured color.", + getValue=function() return settingsTable.showHighlightBorder ~= false end, + setValue=function(v) settingsTable.showHighlightBorder = v end }); y = y - h + elseif unitKey ~= "boss" then _, h = W:DualRow(parent, y, { type="slider", text="Border Size", min=0, max=4, step=1, tooltip="Overrides the border size from the main frames for this frame only. Border color and texture still follow the main frames.", diff --git a/EllesmereUIUnitFrames/EllesmereUIUnitFrames.lua b/EllesmereUIUnitFrames/EllesmereUIUnitFrames.lua index 6253a5ba..ec31e703 100644 --- a/EllesmereUIUnitFrames/EllesmereUIUnitFrames.lua +++ b/EllesmereUIUnitFrames/EllesmereUIUnitFrames.lua @@ -1312,6 +1312,10 @@ ns.healthBarTextureNames = healthBarTextureNames -- to the settings sub-table key in db.profile. local function UnitToSettingsKey(unit) if not unit then return nil end + -- The shared boss configuration is also addressed by the generic "boss" + -- key in a few layout/preview paths. Keep it on the boss profile instead + -- of falling through to the player profile. + if unit == "boss" then return "boss" end if unit:match("^boss%d$") then return "boss" end if unit == "pet" then return "pet" end if db.profile[unit] then return unit end @@ -2335,6 +2339,7 @@ local function GetSettingsForUnit(unit) pet = db.profile.pet, focus = db.profile.focus, focustarget = db.profile.focustarget, + boss = db.profile.boss, } for i = 1, 5 do unitSettingsMap["boss" .. i] = db.profile.boss @@ -2500,8 +2505,9 @@ local function LayoutCastbarIcon(castbar, inWidth, iconH, onRight, offX, offY) end end --- Returns the donor settings table for mini frames (focus > target > player) --- Used to inherit border, texture, and font settings +-- Returns the donor settings table for mini frames (focus > target > player). +-- Boss frames use this only for their shared texture/font fallbacks; their +-- frame and aura borders always come from db.profile.boss. local function GetMiniDonorSettings() local ef = db.profile.enabledFrames if ef.focus ~= false and db.profile.focus then return db.profile.focus end @@ -6023,16 +6029,31 @@ ns.ApplyBossBorderState = function(self) local s = db.profile.boss if not s then return end local r, g, b, a + local raised = false if self._hovered and s.bossHoverBorderEnabled then local c = s.bossHoverBorderColor or { r = 1, g = 1, b = 1 } r, g, b, a = c.r, c.g, c.b, s.bossHoverBorderAlpha or 1 + raised = true elseif self._isTarget and s.bossTargetBorderEnabled then local c = s.bossTargetBorderColor or { r = 1, g = 1, b = 1 } r, g, b, a = c.r, c.g, c.b, s.bossTargetBorderAlpha or 1 + raised = true else local c = s.borderColor or { r = 0, g = 0, b = 0 } r, g, b, a = c.r, c.g, c.b, s.borderAlpha or 1 end + -- A normal boss border may intentionally render behind the frame. Hover + -- and target states must temporarily raise that same styled border so the + -- highlight stays visible, then restore its configured level afterwards. + local frameLevel = self:GetFrameLevel() + local level = (s.borderBehind and not raised) + and math.max(0, frameLevel - 1) or (frameLevel + 10) + local border = self.unifiedBorder + local container = PP.GetBorders(border) + if border:GetFrameLevel() ~= level then border:SetFrameLevel(level) end + if container and container:GetFrameLevel() ~= level + 1 then + container:SetFrameLevel(level + 1) + end EllesmereUI.SetBorderStyleColor(self.unifiedBorder, r, g, b, a) end @@ -6065,7 +6086,10 @@ local function FrameBorderLeave(self) return end local isMini = (unit == "pet" or unit == "targettarget" or unit == "focustarget") - local settings = isMini and GetMiniDonorSettings() or GetSettingsForUnit(unit) + -- Target of Target owns its base border. Its optional hover highlight still + -- follows the donor, but leaving hover must restore the ToT border color. + local settings = (unit == "targettarget") and GetSettingsForUnit(unit) + or (isMini and GetMiniDonorSettings() or GetSettingsForUnit(unit)) local bc = settings.borderColor or { r = 0, g = 0, b = 0 } local ba = settings.borderAlpha or 1 EllesmereUI.SetBorderStyleColor(self.unifiedBorder, bc.r, bc.g, bc.b, ba) @@ -6463,6 +6487,14 @@ local function CreateTargetAuras(frame, unit) button._euiABGen = gen -- stamped after the apply, never before end + local function RestyleLegacyAuraElement(element) + if not element then return end + local n = element.num or 0 + for i = 1, n do + ApplyLegacyAuraBorder(element[i]) + end + end + local function SetupAuraIcon(container, button) if not button then return end @@ -6754,6 +6786,14 @@ local function CreateTargetAuras(frame, unit) end frame.Debuffs = debuffs end + + -- Border-only settings changes do not necessarily trigger an aura update. + -- Restyle the already-pooled buttons directly on the next config reload; + -- this reads only our numeric button slots and never inspects aura data. + frame._restyleAuraBorders = function() + RestyleLegacyAuraElement(frame.Buffs) + RestyleLegacyAuraElement(frame.Debuffs) + end end local function StyleFullFrame(frame, unit) @@ -11123,8 +11163,10 @@ local function ReloadFrames() ReparentBarsToClip(frame, settings.powerPosition, settings) end - -- Determine if this is a mini frame that inherits border/texture/font - local isMiniFrame = (unit == "pet" or unit == "targettarget" or unit == "focustarget" or unit:match("^boss%d$")) + -- Mini frames inherit donor texture/font settings. Boss frames share + -- those donor fallbacks for bars/text, but keep their own border. + local isBossFrame = unit:match("^boss%d$") ~= nil + local isMiniFrame = (unit == "pet" or unit == "targettarget" or unit == "focustarget" or isBossFrame) local donorSettings = isMiniFrame and GetMiniDonorSettings() or settings -- Apply health bar texture overlay (mini frames inherit the donor @@ -11147,14 +11189,6 @@ local function ReloadFrames() end ns.ApplyCastBarTexture(frame.Castbar, cbTexKey) end - -- Boss Hover/Target border: the border was just restyled to its normal - -- color above, so re-apply the hover/target recolor (both default off, - -- so this is a no-op unless the user enabled a boss border). - if unit:match("^boss%d$") then - local isT = UnitIsUnit(unit, "target") - frame._isTarget = (not issecretvalue(isT) and isT) and true or false - ns.ApplyBossBorderState(frame) - end frame.Health:SetReverseFill(settings.healthReverseFill and true or false) ApplyDarkTheme(frame.Health) UpdateAbsorbBarReverseFill(frame, settings.healthReverseFill and true or false) @@ -11260,15 +11294,35 @@ local function ReloadFrames() if frame.unifiedBorder then frame.unifiedBorder:ClearAllPoints() - -- Mini frames (ToT/Focus Target/Pet) may override ONLY the border - -- size per frame (settings.borderSizeOverride); color and texture - -- still inherit from the donor. nil = inherit the donor size. - local bs = settings.borderSizeOverride or donorSettings.borderSize or 1 - local bc = donorSettings.borderColor or { r = 0, g = 0, b = 0 } - local btex = donorSettings.borderTexture or "solid" + -- Preserve the old mini-frame size override when upgrading ToT + -- to a fully independent border. This consumes the legacy key + -- once, so subsequent edits operate only on borderSize. + if unit == "targettarget" and settings.borderSizeOverride ~= nil then + settings.borderSize = settings.borderSizeOverride + settings.borderSizeOverride = nil + end + -- Boss and Target-of-Target own their complete border. Focus + -- Target and Pet retain the established donor inheritance. + local ownsBorder = isBossFrame or unit == "targettarget" + local borderSettings = ownsBorder and settings or donorSettings + local bs = ownsBorder and (borderSettings.borderSize or 1) + or (settings.borderSizeOverride or borderSettings.borderSize or 1) + local bc = borderSettings.borderColor or { r = 0, g = 0, b = 0 } + local btex = borderSettings.borderTexture or "solid" PP.Point(frame.unifiedBorder, "TOPLEFT", frame, "TOPLEFT", 0, 0) PP.Point(frame.unifiedBorder, "BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0) - EllesmereUI.ApplyBorderStyle(frame.unifiedBorder, bs, bc.r, bc.g, bc.b, donorSettings.borderAlpha or 1, btex, donorSettings.borderTextureOffset, donorSettings.borderTextureOffsetY, donorSettings.borderTextureShiftX, donorSettings.borderTextureShiftY, "unitframes", bs) + frame.unifiedBorder:SetFrameLevel(borderSettings.borderBehind + and math.max(0, frame:GetFrameLevel() - 1) + or (frame:GetFrameLevel() + 10)) + EllesmereUI.ApplyBorderStyle(frame.unifiedBorder, bs, bc.r, bc.g, bc.b, borderSettings.borderAlpha or 1, btex, borderSettings.borderTextureOffset, borderSettings.borderTextureOffsetY, borderSettings.borderTextureShiftX, borderSettings.borderTextureShiftY, "unitframes", bs) + -- Apply this after rebuilding the configured border style. Doing + -- it earlier lets ApplyBorderStyle overwrite an active hover or + -- target color during an options refresh. + if isBossFrame then + local isT = UnitIsUnit(unit, "target") + frame._isTarget = (not issecretvalue(isT) and isT) and true or false + ns.ApplyBossBorderState(frame) + end end -- Helper: set font on a FontString, using donor font for mini frames @@ -11334,6 +11388,7 @@ local function ReloadFrames() if cb._syncOffsetsAndLayout then cb:_syncOffsetsAndLayout(settings) end end end + if frame._restyleAuraBorders then frame._restyleAuraBorders() end end -- else (enabled frame processing) end end @@ -13330,6 +13385,33 @@ function SetupOptionsPanel() local FAKE_DEBUFF_STACKS = { [2] = 3 } -- one fake stack (icon 2 only) local FAKE_DEBUFF_FRACS = { 0.35, 0.62, 0.88 } -- static fake swipe fraction remaining local FAKE_DEBUFF_SECS = { 8, 15, 23 } -- static fake duration-text seconds + + -- The boss preview uses addon-owned fake aura frames, so style their borders + -- through the same boss aura settings as live legacy/container buttons. + -- Keeping this on an owned host avoids touching Blizzard aura buttons and is + -- safe regardless of aura secrecy/combat state. + local function ApplyBossPreviewAuraBorder(iconFrame, ownerFrame, settings) + local border = CreateFrame("Frame", nil, iconFrame) + border:SetAllPoints(iconFrame) + border:EnableMouse(false) + if settings.auraBorderBehindUnitFrame then + border:SetFrameLevel(math.max(0, ownerFrame:GetFrameLevel() - 1)) + else + border:SetFrameLevel(settings.auraBorderBehind + and math.max(0, iconFrame:GetFrameLevel() - 1) + or (iconFrame:GetFrameLevel() + 1)) + end + local size = settings.auraBorderSize or 1 + EllesmereUI.ApplyBorderStyle(border, size, + settings.auraBorderR or 0, settings.auraBorderG or 0, + settings.auraBorderB or 0, settings.auraBorderA or 1, + settings.auraBorderTexture or "solid", + settings.auraBorderTextureOffset, settings.auraBorderTextureOffsetY, + settings.auraBorderTextureShiftX, settings.auraBorderTextureShiftY, + "unitframes", size) + return border + end + local function AttachFakeDebuffs(frame) -- Tear down any prior holder so size/anchor refresh on every call. if frame._previewDebuffs then @@ -13492,12 +13574,8 @@ function SetupOptionsPanel() stack:SetTextColor(stackTextColor.r, stackTextColor.g, stackTextColor.b) stack:SetText(FAKE_DEBUFF_STACKS[idx]) end - -- Border just above the icon; its PP container renders at border+1 - -- (iconFrame+2), below the swipe and text host so both stay on top. - local border = CreateFrame("Frame", nil, iconFrame) - border:SetAllPoints(icon) - border:SetFrameLevel(iconFrame:GetFrameLevel() + 1) - if PP and PP.CreateBorder then PP.CreateBorder(border, 0, 0, 0, 1) end + -- Uses the boss aura border style; cooldown/text remain above it. + ApplyBossPreviewAuraBorder(iconFrame, frame, settings) end frame._previewDebuffs = holder end @@ -13600,10 +13678,7 @@ function SetupOptionsPanel() if tex then icon:SetTexture(tex) end local z = settings.buffIconZoom or 0.07 icon:SetTexCoord(z, 1 - z, z, 1 - z) - local border = CreateFrame("Frame", nil, iconFrame) - border:SetAllPoints(icon) - border:SetFrameLevel(iconFrame:GetFrameLevel() + 1) - if PP and PP.CreateBorder then PP.CreateBorder(border, 0, 0, 0, 1) end + ApplyBossPreviewAuraBorder(iconFrame, frame, settings) end frame._previewBuffs = holder end