Files
coa-weakauras/WeakAuras/Libs/LibGetFrame-1.0/LibGetFrame-1.0.lua
T
Bunny67 7cbc40c959 beta
2020-11-15 23:43:10 +03:00

265 lines
7.6 KiB
Lua

local MAJOR_VERSION = "LibGetFrame-1.0"
local MINOR_VERSION = 24
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, UnitIsUnit, SecureButton_GetUnit = GetPlayerInfoByGUID, UnitExists, IsAddOnLoaded, 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] = "^PlexusLayout", -- plexus
[11] = "^ElvUF_RaidGroup", -- elv
[12] = "^oUF_bdGrid", -- bdgrid
[13] = "^oUF_.-Raid", -- generic oUF
[14] = "^LimeGroup", -- lime
[15] = "^SUFHeaderraid", -- suf
-- party frames
[16] = "^AleaUI_GroupHeader", -- Alea
[17] = "^SUFHeaderparty", --suf
[18] = "^ElvUF_PartyGroup", -- elv
[19] = "^oUF_.-Party", -- generic oUF
[20] = "^PitBull4_Groups_Party", -- pitbull4
[21] = "^CompactRaid", -- blizz
[22] = "^PartyMemberFrame", -- blizz
-- player frame
[23] = "^SUFUnitplayer",
[24] = "^PitBull4_Frames_Player",
[25] = "^ElvUF_Player",
[26] = "^oUF_.-Player",
[27] = "^PlayerFrame",
}
local defaultPlayerFrames = {
"SUFUnitplayer",
"PitBull4_Frames_Player",
"ElvUF_Player",
"oUF_.-Player",
"oUF_PlayerPlate",
"PlayerFrame",
}
local defaultTargetFrames = {
"SUFUnittarget",
"PitBull4_Frames_Target",
"ElvUF_Target",
"oUF_.-Target",
"TargetFrame",
}
local defaultTargettargetFrames = {
"SUFUnittargetarget",
"PitBull4_Frames_Target's target",
"ElvUF_TargetTarget",
"oUF_.-TargetTarget",
"oUF_ToT",
"TargetTargetFrame",
}
local defaultPartyTargetFrames = {
"SUFChildpartytarget%d",
}
local GetFramesCache = {}
local FrameToUnitFresh = {}
local FrameToUnit = {}
local UpdatedFrames = {}
local function ScanFrames(depth, frame, ...)
if not frame then return end
if depth < maxDepth 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
if unit ~= FrameToUnit[frame] then
FrameToUnit[frame] = unit
UpdatedFrames[frame] = unit
end
FrameToUnitFresh[frame] = unit
end
end
end
ScanFrames(depth, ...)
end
local wait = false
local function doScanForUnitFrames()
wait = false
wipe(UpdatedFrames)
wipe(GetFramesCache)
wipe(FrameToUnitFresh)
ScanFrames(0, UIParent)
callbacks:Fire("GETFRAME_REFRESH")
for frame, unit in pairs(UpdatedFrames) do
callbacks:Fire("FRAME_UNIT_UPDATE", frame, unit)
end
for frame, unit in pairs(FrameToUnit) do
if FrameToUnitFresh[frame] ~= unit then
callbacks:Fire("FRAME_UNIT_REMOVED", frame, unit)
FrameToUnit[frame] = nil
end
end
end
local waitFrame = CreateFrame("Frame")
local function waitFrame_OnUpdate(self, elapsed)
self.delay = (self.delay or 1) - elapsed
if self.delay < elapsed then
doScanForUnitFrames()
self:SetScript("OnUpdate", nil)
self.delay = nil
end
end
local function ScanForUnitFrames(noDelay)
if noDelay then
doScanForUnitFrames()
elseif not wait then
wait = true
waitFrame:SetScript("OnUpdate", waitFrame_OnUpdate)
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,
ignorePartyTargetFrame = true,
playerFrames = defaultPlayerFrames,
targetFrames = defaultTargetFrames,
targettargetFrames = defaultTargettargetFrames,
partyTargetFrames = defaultPartyTargetFrames,
ignoreFrames = {
"PitBull4_Frames_Target's target's target",
"ElvUF_PartyGroup%dUnitButton%dTarget",
"ElvUF_FocusTarget",
"RavenButton"
},
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
if opt.ignorePartyTargetFrame then
for _,v in pairs(opt.partyTargetFrames) 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