222 lines
6.4 KiB
Lua
222 lines
6.4 KiB
Lua
local MAJOR_VERSION = "LibGetFrame-1.0"
|
|
local MINOR_VERSION = 9
|
|
if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
|
|
local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
|
|
if not lib then return end
|
|
|
|
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
|
|
local callbacks = lib.callbacks
|
|
|
|
local GetPlayerInfoByGUID, UnitExists, IsAddOnLoaded, C_Timer, UnitIsUnit, SecureButton_GetUnit = GetPlayerInfoByGUID, UnitExists, IsAddOnLoaded, C_Timer, UnitIsUnit, SecureButton_GetUnit
|
|
local tinsert, CopyTable, wipe = tinsert, CopyTable, wipe
|
|
|
|
local maxDepth = 50
|
|
|
|
local defaultFramePriorities = {
|
|
-- raid frames
|
|
[1] = "^Vd1", -- vuhdo
|
|
[2] = "^Vd2", -- vuhdo
|
|
[3] = "^Vd3", -- vuhdo
|
|
[4] = "^Vd4", -- vuhdo
|
|
[5] = "^Vd5", -- vuhdo
|
|
[6] = "^Vd", -- vuhdo
|
|
[7] = "^HealBot", -- healbot
|
|
[8] = "^GridLayout", -- grid
|
|
[9] = "^Grid2Layout", -- grid2
|
|
[10] = "^ElvUF_RaidGroup", -- elv
|
|
[11] = "^oUF_bdGrid", -- bdgrid
|
|
[12] = "^oUF.*raid", -- generic oUF
|
|
[13] = "^LimeGroup", -- lime
|
|
[14] = "^SUFHeaderraid", -- suf
|
|
[15] = "^CompactRaid", -- blizz
|
|
-- party frames
|
|
[16] = "^AleaUI_GroupHeader", -- Alea
|
|
[17] = "^SUFHeaderparty", --suf
|
|
[18] = "^ElvUF_PartyGroup", -- elv
|
|
[19] = "^oUF.*party", -- generic oUF
|
|
[20] = "^PitBull4_Groups_Party", -- pitbull4
|
|
[21] = "^CompactParty", -- blizz
|
|
-- player frame
|
|
[22] = "^SUFUnitplayer",
|
|
[23] = "^PitBull4_Frames_Player",
|
|
[24] = "^ElvUF_Player",
|
|
[25] = "^oUF.*player",
|
|
[26] = "^PlayerFrame",
|
|
}
|
|
|
|
local defaultPlayerFrames = {
|
|
"SUFUnitplayer",
|
|
"PitBull4_Frames_Player",
|
|
"ElvUF_Player",
|
|
"oUF_TukuiPlayer",
|
|
"PlayerFrame",
|
|
}
|
|
local defaultTargetFrames = {
|
|
"SUFUnittarget",
|
|
"PitBull4_Frames_Target",
|
|
"ElvUF_Target",
|
|
"TargetFrame",
|
|
"oUF_TukuiTarget",
|
|
}
|
|
local defaultTargettargetFrames = {
|
|
"SUFUnittargetarget",
|
|
"PitBull4_Frames_Target's target",
|
|
"ElvUF_TargetTarget",
|
|
"TargetTargetFrame",
|
|
"oUF_TukuiTargetTarget",
|
|
}
|
|
|
|
local GetFramesCache = {}
|
|
|
|
local function ScanFrames(depth, frame, ...)
|
|
if not frame then return end
|
|
if depth < maxDepth
|
|
and frame.IsForbidden
|
|
and not frame:IsForbidden()
|
|
then
|
|
local frameType = frame:GetObjectType()
|
|
if frameType == "Frame" or frameType == "Button" then
|
|
ScanFrames(depth + 1, frame:GetChildren())
|
|
end
|
|
if frameType == "Button" then
|
|
local unit = SecureButton_GetUnit(frame)
|
|
local name = frame:GetName()
|
|
if unit and frame:IsVisible() and name then
|
|
GetFramesCache[frame] = name
|
|
end
|
|
end
|
|
end
|
|
ScanFrames(depth, ...)
|
|
end
|
|
|
|
local wait = false
|
|
local function ScanForUnitFrames(noDelay)
|
|
if noDelay then
|
|
wipe(GetFramesCache)
|
|
ScanFrames(0, UIParent)
|
|
callbacks:Fire("GETFRAME_REFRESH")
|
|
elseif not wait then
|
|
wait = true
|
|
C_Timer:After(1, function()
|
|
wipe(GetFramesCache)
|
|
ScanFrames(0, UIParent)
|
|
wait = false
|
|
callbacks:Fire("GETFRAME_REFRESH")
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function isFrameFiltered(name, ignoredFrames)
|
|
for _, filter in pairs(ignoredFrames) do
|
|
if name:find(filter) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function GetUnitFrames(target, ignoredFrames)
|
|
if not UnitExists(target) then
|
|
if type(target) == "string" and target:find("Player") then
|
|
target = select(6, GetPlayerInfoByGUID(target))
|
|
else
|
|
target = target:gsub(" .*", "")
|
|
if not UnitExists(target) then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
local frames
|
|
for frame, frameName in pairs(GetFramesCache) do
|
|
local unit = SecureButton_GetUnit(frame)
|
|
if unit and UnitIsUnit(unit, target)
|
|
and not isFrameFiltered(frameName, ignoredFrames)
|
|
then
|
|
frames = frames or {}
|
|
frames[frame] = frameName
|
|
end
|
|
end
|
|
return frames
|
|
end
|
|
|
|
local function ElvuiWorkaround(frame)
|
|
if IsAddOnLoaded("ElvUI") and frame and frame:GetName():find("^ElvUF_") and frame.Health then
|
|
return frame.Health
|
|
else
|
|
return frame
|
|
end
|
|
end
|
|
|
|
local defaultOptions = {
|
|
framePriorities = defaultFramePriorities,
|
|
ignorePlayerFrame = true,
|
|
ignoreTargetFrame = true,
|
|
ignoreTargettargetFrame = true,
|
|
playerFrames = defaultPlayerFrames,
|
|
targetFrames = defaultTargetFrames,
|
|
targettargetFrames = defaultTargettargetFrames,
|
|
ignoreFrames = {
|
|
"PitBull4_Frames_Target's target's target"
|
|
},
|
|
returnAll = false,
|
|
}
|
|
|
|
local GetFramesCacheListener
|
|
local function Init(noDelay)
|
|
GetFramesCacheListener = CreateFrame("Frame")
|
|
GetFramesCacheListener:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
GetFramesCacheListener:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
GetFramesCacheListener:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
GetFramesCacheListener:RegisterEvent("PARTY_MEMBERS_CHANGED")
|
|
GetFramesCacheListener:RegisterEvent("RAID_ROSTER_UPDATE")
|
|
GetFramesCacheListener:SetScript("OnEvent", function() ScanForUnitFrames(false) end)
|
|
ScanForUnitFrames(noDelay)
|
|
end
|
|
|
|
function lib.GetUnitFrame(target, opt)
|
|
if type(GetFramesCacheListener) ~= "table" then Init(true) end
|
|
opt = opt or {}
|
|
setmetatable(opt, { __index = defaultOptions })
|
|
|
|
if not target then return end
|
|
|
|
local ignoredFrames = CopyTable(opt.ignoreFrames)
|
|
if opt.ignorePlayerFrame then
|
|
for _,v in pairs(opt.playerFrames) do
|
|
tinsert(ignoredFrames, v)
|
|
end
|
|
end
|
|
if opt.ignoreTargetFrame then
|
|
for _,v in pairs(opt.targetFrames) do
|
|
tinsert(ignoredFrames, v)
|
|
end
|
|
end
|
|
if opt.ignoreTargettargetFrame then
|
|
for _,v in pairs(opt.targettargetFrames) do
|
|
tinsert(ignoredFrames, v)
|
|
end
|
|
end
|
|
|
|
local frames = GetUnitFrames(target, ignoredFrames)
|
|
if not frames then return end
|
|
|
|
if not opt.returnAll then
|
|
for i = 1, #opt.framePriorities do
|
|
for frame, frameName in pairs(frames) do
|
|
if frameName:find(opt.framePriorities[i]) then
|
|
return ElvuiWorkaround(frame)
|
|
end
|
|
end
|
|
end
|
|
local next = next
|
|
return ElvuiWorkaround(next(frames))
|
|
else
|
|
for frame in pairs(frames) do
|
|
frames[frame] = ElvuiWorkaround(frame)
|
|
end
|
|
return frames
|
|
end
|
|
end
|
|
lib.GetFrame = lib.GetUnitFrame -- compatibility
|