300 lines
7.6 KiB
Lua
300 lines
7.6 KiB
Lua
BNP = BNP or {}
|
|
|
|
local _, playerClass = UnitClass("player")
|
|
local COMBO_CLASS = (playerClass == "ROGUE" or playerClass == "DRUID")
|
|
|
|
local MAX_POINTS = 5
|
|
local POINT_GAP = 1
|
|
|
|
local function Enabled()
|
|
return COMBO_CLASS and BNP.AreComboPointsEnabled and BNP:AreComboPointsEnabled()
|
|
end
|
|
|
|
local function GetTargetGUID()
|
|
local exists, guid = UnitExists("target")
|
|
if exists and guid then return guid end
|
|
return nil
|
|
end
|
|
|
|
local function GetComboCount()
|
|
if not GetComboPoints then return 0 end
|
|
local count = tonumber(GetComboPoints()) or 0
|
|
if count < 0 then count = 0 end
|
|
if count > MAX_POINTS then count = MAX_POINTS end
|
|
return count
|
|
end
|
|
|
|
local function GetSourcePoint()
|
|
if getglobal then
|
|
return getglobal("TargetFrameComboPoint1")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function GetSourceSize()
|
|
local source = GetSourcePoint()
|
|
local w, h = 12, 16
|
|
|
|
if source then
|
|
if source.GetWidth then w = tonumber(source:GetWidth()) or w end
|
|
if source.GetHeight then h = tonumber(source:GetHeight()) or h end
|
|
end
|
|
|
|
if w <= 0 then w = 12 end
|
|
if h <= 0 then h = 16 end
|
|
return w, h
|
|
end
|
|
|
|
local function ApplyTargetFrameScale(holder)
|
|
if not holder then return end
|
|
|
|
local source = GetSourcePoint()
|
|
local parent = holder:GetParent()
|
|
|
|
local sourceScale = 1.0
|
|
local parentScale = 1.0
|
|
|
|
-- Match the actual on-screen scale of Blizzard's TargetFrame combo points.
|
|
if source and source.GetEffectiveScale then
|
|
sourceScale = tonumber(source:GetEffectiveScale()) or 1.0
|
|
elseif UIParent and UIParent.GetEffectiveScale then
|
|
sourceScale = tonumber(UIParent:GetEffectiveScale()) or 1.0
|
|
elseif UIParent and UIParent.GetScale then
|
|
sourceScale = tonumber(UIParent:GetScale()) or 1.0
|
|
end
|
|
|
|
if parent and parent.GetEffectiveScale then
|
|
parentScale = tonumber(parent:GetEffectiveScale()) or 1.0
|
|
end
|
|
|
|
if sourceScale <= 0 then sourceScale = 1.0 end
|
|
if parentScale <= 0 then parentScale = 1.0 end
|
|
|
|
holder:SetScale(sourceScale / parentScale)
|
|
end
|
|
|
|
local function CopySourceTextureAppearance(dst, src)
|
|
if not dst or not src then return end
|
|
|
|
if src.GetTexture and dst.SetTexture then
|
|
dst:SetTexture(src:GetTexture())
|
|
end
|
|
|
|
if src.GetTexCoord and dst.SetTexCoord then
|
|
local l, r, t, b = src:GetTexCoord()
|
|
if l then dst:SetTexCoord(l, r, t, b) end
|
|
end
|
|
|
|
if src.GetVertexColor and dst.SetVertexColor then
|
|
local r, g, b, a = src:GetVertexColor()
|
|
if r then dst:SetVertexColor(r, g, b, a or 1) end
|
|
end
|
|
|
|
if src.GetBlendMode and dst.SetBlendMode then
|
|
local mode = src:GetBlendMode()
|
|
if mode then dst:SetBlendMode(mode) end
|
|
end
|
|
end
|
|
|
|
local function CreateExactPoint(parent)
|
|
local source = GetSourcePoint()
|
|
local pointW, pointH = GetSourceSize()
|
|
|
|
local point = CreateFrame("Frame", nil, parent)
|
|
point:SetWidth(pointW)
|
|
point:SetHeight(pointH)
|
|
|
|
local copied = false
|
|
|
|
-- Clone the actual texture regions from Blizzard's TargetFrame combo point.
|
|
-- This guarantees the same client artwork/skin instead of guessing atlas cuts.
|
|
if source and source.GetRegions then
|
|
local regions = { source:GetRegions() }
|
|
local i
|
|
|
|
for i = 1, table.getn(regions) do
|
|
local src = regions[i]
|
|
if src and src.GetObjectType and src:GetObjectType() == "Texture" then
|
|
local tex = point:CreateTexture(nil, "ARTWORK")
|
|
CopySourceTextureAppearance(tex, src)
|
|
|
|
local w = src.GetWidth and tonumber(src:GetWidth()) or pointW
|
|
local h = src.GetHeight and tonumber(src:GetHeight()) or pointH
|
|
if not w or w <= 0 then w = pointW end
|
|
if not h or h <= 0 then h = pointH end
|
|
|
|
tex:SetWidth(w)
|
|
tex:SetHeight(h)
|
|
|
|
-- Preserve the standard TargetFrame relative offsets where possible.
|
|
local anchored = false
|
|
if src.GetPoint then
|
|
local pnt, rel, relp, x, y = src:GetPoint(1)
|
|
if pnt then
|
|
-- Source textures are normally anchored to their own combo frame.
|
|
-- Re-anchor them to our clone with the same point/offset.
|
|
tex:SetPoint(pnt, point, relp or pnt, x or 0, y or 0)
|
|
anchored = true
|
|
end
|
|
end
|
|
|
|
if not anchored then
|
|
tex:SetPoint("CENTER", point, "CENTER", 0, 0)
|
|
end
|
|
|
|
copied = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Fallback only if the client does not expose TargetFrameComboPoint1 regions.
|
|
if not copied then
|
|
local base = point:CreateTexture(nil, "BACKGROUND")
|
|
base:SetTexture("Interface\\ComboFrame\\ComboPoint")
|
|
base:SetWidth(12)
|
|
base:SetHeight(16)
|
|
base:SetPoint("TOPLEFT", point, "TOPLEFT", 0, 0)
|
|
base:SetTexCoord(0, 0.375, 0, 1)
|
|
|
|
local highlight = point:CreateTexture(nil, "ARTWORK")
|
|
highlight:SetTexture("Interface\\ComboFrame\\ComboPoint")
|
|
highlight:SetWidth(8)
|
|
highlight:SetHeight(16)
|
|
highlight:SetPoint("TOPLEFT", point, "TOPLEFT", 2, 0)
|
|
highlight:SetTexCoord(0.375, 0.5625, 0, 1)
|
|
end
|
|
|
|
point:Hide()
|
|
return point
|
|
end
|
|
|
|
local function EnsurePoints(plate)
|
|
if plate.BNPComboPoints then
|
|
ApplyTargetFrameScale(plate.BNPComboPoints)
|
|
return plate.BNPComboPoints
|
|
end
|
|
|
|
if not plate or not plate.name then return nil end
|
|
|
|
local pointW, pointH = GetSourceSize()
|
|
local parent = plate.BNPScaleWrapper or plate
|
|
|
|
local holder = CreateFrame("Frame", nil, parent)
|
|
holder:SetWidth(MAX_POINTS * pointW + (MAX_POINTS - 1) * POINT_GAP)
|
|
holder:SetHeight(pointH)
|
|
|
|
-- Keep the position the user already approved.
|
|
holder:SetPoint("BOTTOM", plate.name, "TOP", 0, 2)
|
|
holder:SetFrameLevel((plate:GetFrameLevel() or 1) + 12)
|
|
holder.points = {}
|
|
holder:Hide()
|
|
|
|
local i
|
|
for i = 1, MAX_POINTS do
|
|
local point = CreateExactPoint(holder)
|
|
|
|
if i == 1 then
|
|
point:SetPoint("LEFT", holder, "LEFT", 0, 0)
|
|
else
|
|
point:SetPoint("LEFT", holder.points[i - 1], "RIGHT", POINT_GAP, 0)
|
|
end
|
|
|
|
holder.points[i] = point
|
|
end
|
|
|
|
ApplyTargetFrameScale(holder)
|
|
plate.BNPComboPoints = holder
|
|
return holder
|
|
end
|
|
|
|
local function HidePoints(plate)
|
|
local holder = plate and plate.BNPComboPoints
|
|
if not holder then return end
|
|
|
|
local i
|
|
for i = 1, MAX_POINTS do
|
|
holder.points[i]:Hide()
|
|
end
|
|
holder:Hide()
|
|
end
|
|
|
|
local function UpdatePlate(plate)
|
|
if not plate or not plate:IsShown() then return end
|
|
|
|
if not Enabled() then
|
|
HidePoints(plate)
|
|
return
|
|
end
|
|
|
|
local targetGUID = GetTargetGUID()
|
|
local plateGUID = plate.GetName and plate:GetName(1) or nil
|
|
|
|
if not targetGUID or not plateGUID or targetGUID ~= plateGUID then
|
|
HidePoints(plate)
|
|
return
|
|
end
|
|
|
|
local count = GetComboCount()
|
|
if count <= 0 then
|
|
HidePoints(plate)
|
|
return
|
|
end
|
|
|
|
local holder = EnsurePoints(plate)
|
|
if not holder then return end
|
|
ApplyTargetFrameScale(holder)
|
|
|
|
local i
|
|
for i = 1, MAX_POINTS do
|
|
if i <= count then
|
|
holder.points[i]:Show()
|
|
else
|
|
holder.points[i]:Hide()
|
|
end
|
|
end
|
|
|
|
holder:Show()
|
|
end
|
|
|
|
function BNP:RefreshComboPoints()
|
|
local plate
|
|
for plate in pairs(BNP.plates or {}) do
|
|
if plate:IsShown() then
|
|
UpdatePlate(plate)
|
|
else
|
|
HidePoints(plate)
|
|
end
|
|
end
|
|
|
|
if BNP.RefreshAllAuraLayouts then
|
|
BNP:RefreshAllAuraLayouts()
|
|
end
|
|
end
|
|
|
|
table.insert(BNP.libnameplate.OnInit, function(plate)
|
|
if COMBO_CLASS then
|
|
EnsurePoints(plate)
|
|
HidePoints(plate)
|
|
end
|
|
end)
|
|
|
|
table.insert(BNP.libnameplate.OnShow, function(plate)
|
|
if COMBO_CLASS then
|
|
HidePoints(plate)
|
|
UpdatePlate(plate)
|
|
end
|
|
end)
|
|
|
|
table.insert(BNP.libnameplate.OnUpdate, function(plate)
|
|
if COMBO_CLASS then UpdatePlate(plate) end
|
|
end)
|
|
|
|
if COMBO_CLASS then
|
|
local events = CreateFrame("Frame")
|
|
events:RegisterEvent("PLAYER_TARGET_CHANGED")
|
|
events:RegisterEvent("PLAYER_COMBO_POINTS")
|
|
events:SetScript("OnEvent", function()
|
|
BNP:RefreshComboPoints()
|
|
end)
|
|
end
|