Mercurial > wow > buffalo2
view BuffButton.lua @ 37:e84d645c8ab8
- revised the tracker update function to build its complete data list up front and use the values as points of comparison for determining possible out of place blocks, which will be iterated over afterward to remove what wasn't re-used
- also entailed revising the exact role of global event handlers and function hooks, limiting their directions of communication so one doesn't end up calling the other multiple or inifinity times
- schema handling polish
author | Nenue |
---|---|
date | Mon, 18 Apr 2016 07:56:23 -0400 |
parents | 5301c68f28d8 |
children |
line wrap: on
line source
--- Actual BlizzUI modifications are applied here -- @file-author@ -- @project-revision@ @project-hash@ -- @file-revision@ @file-hash@ -- Created: 3/12/2016 12:47 AM local MODULE = 'BuffFrame' local _, A = ... local B, _G = A.frame, _G local type, unpack, select, pairs, ipairs = _G.type, _G.unpack, _G.select, _G.pairs, _G.ipairs local min, ceil, mod, tonumber, tostring = _G.min, _G.ceil, _G.mod, _G.tonumber, _G.tostring local floor, wipe, max = _G.math.floor, _G.table.wipe, _G.math.max local CreateFrame, IsInGroup, GetCVarBool = _G.CreateFrame, _G.IsInGroup, _G.GetCVarBool local BuffFrame, ConsolidatedBuffs = _G.BuffFrame, _G.ConsolidatedBuffs local print, gprint, aprint, fprint = B.print('Buff'), B.print('SetGuides'), B.print('SetAnchors'), B.fprint local displays, anchors, guides, decors, positioned, drawn, zoom = B.displays, {}, {}, {}, {}, {}, {} local UnitAura, UnitName, RegisterStateDriver = _G.UnitAura, _G.UnitName, _G.RegisterStateDriver local M = B:RegisterModule(MODULE) M.GetBuffZoom = function(buffName) local zoom = tonumber(B.displays[buffName].conf['Zoom']) / 100 / 2 local zoomL, zoomU, zoomR, zoomD = zoom, zoom, 1-zoom, 1-zoom print(buffName, zoom) return function(self, ...) if select('#',...) == 4 then zoomL, zoomR, zoomU, zoomD = ... end self:SetTexCoord(zoomL, zoomR, zoomU, zoomD) return zoomL, zoomR, zoomU, zoomD end end M.UpdateButtonAlpha = function(self) if not self.parent.timeLeft or not self:IsVisible() then self:SetScript('OnUpdate', nil) return end if self.parent.timeLeft < _G.BUFF_WARNING_TIME then self:SetAlpha(BuffFrame.BuffAlphaValue) else self:SetAlpha(1) end end --- Called infrequently to align stencil frames local refreshCount = 0 M.UpdateGuideFrames = function(buffName) refreshCount = refreshCount + 1 local print = fprint() local anchor = anchors[buffName] local c, g, d = displays[buffName].conf, guides[buffName], decors[buffName] local perRow = c['PerRow'] local buffSpacing, buffSize, buffBorder, buffDurationSize, buffCountSize, relativeX, relativeY = c['Spacing'], c['Size'], c['Border'], c['DurationSize'], c['CountSize'], c['RelativeX'], c['RelativeY'] local consolidated = (anchors[buffName].contains and IsInGroup()) local consolidatedPosition = (consolidated and anchors[buffName].containPosition or 0) print('|cFF00FF00Setting Guides ('..refreshCount..'):|r', buffName, 'user max:',c['Max'], 'hard max:', displays[buffName].maxIcons) local buffMax = min(c['Max'], displays[buffName].maxIcons) local anchorFrom, anchorTo = c.Point[1], c.Point[2] anchor.Zoom = M.GetBuffZoom(buffName) if consolidated then buffMax = buffMax + 1 end local legend = {} legend.r, legend.g, legend.b, legend.a = unpack(displays[buffName].legendColor) local horizFrom = (relativeX < 0) and 'RIGHT' or 'LEFT' local horizTo = (relativeX < 0) and 'LEFT' or 'RIGHT' local vertFrom = (relativeY < 0) and 'TOP' or 'BOTTOM' local vertTo = (relativeY < 0) and 'BOTTOM' or 'TOP' local previous, up local bottom_extent = 0 for i = 1, buffMax do print('update idx', i) if not g[i] then g[i] = CreateFrame('Frame', buffName..'Guide'..i, anchor, displays[buffName].template or 'VeneerGuideTemplate') RegisterStateDriver(g[i], "visibility", "[petbattle] [vehicleui] hide; show") end local guide = g[i] local row = ceil(i / perRow) local col = mod(i, perRow) if col == 0 then col = perRow end guide.previous = previous guide.up = up local x, y, parent = 0, 0, anchor if i == 1 then parent = anchor up = guide elseif col == 1 then parent = g[i-perRow] y = (buffSpacing + bottom_extent) * relativeY up = guide anchorFrom = vertFrom .. horizFrom anchorTo = vertFrom .. horizFrom bottom_extent = 0 else parent = g[i-1] x = buffSpacing * relativeX anchorFrom = vertFrom .. horizFrom anchorTo = vertFrom .. horizTo end previous = guide guide.parent = parent --------------------------------- -- Positioning layer if i ~= consolidatedPosition or not consolidated then guide:SetSize(buffSize, buffSize + buffDurationSize) -- RaidBuffTray will fix the sizing end bottom_extent = max(bottom_extent, guide:GetHeight()) guide.info = {} -- UnitAura cache if i == consolidatedPosition then guide.legend:SetTexture(1,1,0,0.5) else guide.legend:SetTexture(legend.r, legend.g, legend.b, legend.a) end guide.idText:SetText(i) -- needs to reflect the current position guide:ClearAllPoints() guide:SetPoint(anchorFrom, parent, anchorTo, x, y) print(anchorFrom, parent, anchorTo, x, y) guide.icon:SetSize(buffSize - buffBorder * 2, buffSize - buffBorder * 2) guide.icon:ClearAllPoints() guide.icon:SetPoint('TOPLEFT', guide, 'TOPLEFT', buffBorder, -buffBorder ) local anchorTo, anchorFrom, x, y = unpack(c.DurationPoint) guide.duration:ClearAllPoints() guide.duration:SetPoint(anchorTo, guide, anchorFrom, x, y) --guide.duration:SetSize(buffSize, buffDurationSize) print(' duration ->', anchorFrom, anchorTo, x, y) local anchorTo, anchorFrom, x, y = unpack(c.CountPoint) guide.count:ClearAllPoints() guide.count:SetPoint(anchorTo, guide.icon, anchorFrom, x, y) --guide.count:SetSize(buffSize, c.CountSize) print(' count ->', anchorFrom, anchorTo, x, y) ----------------------------------- -- Background decorations layer if not d[i] then d[i] = CreateFrame('Frame', buffName..i..'Decor', _G.UIParent, 'VeneerDecorTemplate') -- todo: sort out a way to fix this without creating taint issues RegisterStateDriver(d[i], "visibility", "[petbattle] [vehicleui] hide") end d[i]:SetPoint('BOTTOMLEFT', guide.icon, 'BOTTOMLEFT', -buffBorder, -buffBorder) d[i]:SetPoint('TOPRIGHT', guide.icon, 'TOPRIGHT', buffBorder, buffBorder) guide:Show() B.SetConfigLayers(guide) end if #guides[buffName] > buffMax then local lim = #guides[buffName] for i = buffMax+1, lim do local g = guides[buffName][i] if g:IsVisible() then print('cleaning up #', i, buffName) g:Hide() B.RemoveConfigLayers(g) end end end anchor.last = previous anchor.up = up print(anchor:GetName(), anchor:GetSize()) end M.UpdateButtonPositions = function(buffName, auraType) local print = fprint() local c = auraType.conf local numBuffs = 0 local actualIcons = auraType.actualIcons() local maxIcons = auraType.maxIcons local anchor = anchors[buffName] local buffMax = c['Max'] local consolidated = (anchor.contains and IsInGroup()) local consolidatedPosition = (consolidated and anchor.containPosition or 0) for k,v in pairs(decors[buffName]) do print(v) end if consolidated then decors[buffName][1]:Hide() numBuffs = numBuffs + 1 buffMax = buffMax + 1 end print(' ', 'frame count:', auraType.actualIcons(), 'hardmax:', maxIcons) if auraType.actualIcons() > 0 then for i = 1, actualIcons do local buff = _G[buffName .. i] local buffIcon = _G[buffName .. i .. 'Icon'] local buffBorder = c['Border'] local buffDuration = _G[buffName .. i .. 'Duration'] local buffCount = _G[buffName .. i .. 'Count'] local buffDurationSize = c['DurationSize'] local debuffBorder = _G[buffName .. i .. 'Border'] if buff and not buff.consolidated then numBuffs = numBuffs + 1 local guide = guides[buffName][numBuffs] local deco = decors[buffName][numBuffs] if numBuffs > buffMax then -- if a limit is reached, start hiding if guide then guide.info = nil end if deco then deco:Hide() end buff:Hide() else local buffData = guide.info buffData.name, buffData.rank, buffData.icon, buffData.count, buffData.dispelType, buffData.duration, buffData.expires, buffData.caster, buffData.isStealable, buffData.shouldConsolidate, buffData.spellID, buffData.canApplyAura, buffData.isBossDebuff, buffData.value1, buffData.value2, buffData.value3 = UnitAura(buff.unit, buff:GetID(), nil, buff.filters) if guide.caster and buffData.caster then if (buffData.caster ~= 'player' or c.ShowSelfCast) then guide.caster:SetText(UnitName(buffData.caster)) else guide.caster:SetText(nil) end end print(numBuffs, i, buff:GetName(), buff:GetID(), decors[buffName][numBuffs]:GetName()) buff:SetAllPoints(guide) buffIcon:ClearAllPoints() buffIcon:SetPoint('TOPLEFT', guide.icon, 'TOPLEFT', 0, 0) buffIcon:SetPoint('BOTTOMRIGHT', guide.icon, 'BOTTOMRIGHT', 0, 0) deco.parent = buff -- make sure so they aren't re-shown in pet battle if not C_PetBattles.IsInBattle() then deco:Show() deco:SetAlpha(1) end if debuffBorder then deco.background:SetTexture(debuffBorder:GetVertexColor()) debuffBorder:Hide() else if guide.info.caster == 'player' then print(guide.info.caster) deco.background:SetTexture(unpack(c.PlayerColor)) elseif buffData.isBossDebuff then print(guide.info.isBossDebuff) deco.background:SetTexture(unpack(c.BossColor)) else print(guide.info.caster) deco.background:SetTexture(unpack(c.Color)) end end buffDuration:ClearAllPoints() local from, to = unpack(c.DurationPoint) buffDuration:SetPoint(from, guide.duration, to) buffDuration:SetText('WHAT') if buff.timeLeft and c.WarningFade then deco:SetScript('OnUpdate', M.UpdateButtonAlpha) else deco:SetScript('OnUpdate', nil) deco:SetAlpha(1.0) end buffCount:ClearAllPoints() local from, to = unpack(c.CountPoint) buffCount:SetPoint(from, guide.count, to) if not drawn[buffName][numBuffs] then anchors[buffName].Zoom(buffIcon) if buffDuration then local font = buffDuration:GetFont() buffDuration:SetFont(font, c.DurationSize, 'OUTLINE') end if buffCount then local font = buffCount:GetFont() buffCount:SetFont(font, c.CountSize, 'OUTLINE') end drawn[buffName][numBuffs] = true end end end end end -- clear any outliers for i = numBuffs+1, buffMax do if guides[buffName][i].caster then guides[buffName][i].caster:SetText(nil) end --if not decors[buffName][i].parent or decors[buffName][i].parent = nil decors[buffName][i]:SetAlpha(1.0) decors[buffName][i]:SetScript('OnUpdate', nil) decors[buffName][i]:Hide() end -- parametric occlusion data for compacted anchor points if numBuffs == 0 then anchor.cutout_X = 0 anchor.cutout_Y = 0 anchor.outer_X = 0 anchor.outer_Y = 0 elseif numBuffs <= buffMax then local sX, sY = guides[buffName][numBuffs]:GetWidth(), guides[buffName][numBuffs]:GetHeight() local p = c.PerRow local lX = mod(numBuffs, p) local lY = floor(numBuffs / p) local oX = min(numBuffs, c.PerRow) local oY = ceil(numBuffs / p) anchor.cutout_X = lX * sX + lX * c.Spacing -- max clearance to fit alongside the row anchor.cutout_Y = lY * sY + lY * c.Spacing anchor.outer_Y = oY * sY + oY * c.Spacing -- distance of farthest row anchor.outer_X = oX * sX + oX * c.Spacing print('|cFF0088FF', 'inner corner', lX, lY, 'outer corners', oX, oY) print('cutout delta =', anchor.cutout_X, anchor.cutout_Y, 'out of', floor(anchor:GetWidth()), floor(anchor:GetHeight())) print('extent delta =', anchor.outer_X, anchor.outer_Y) else anchor.cutout_X = 0 anchor.cutout_Y = 0 anchor.outer_X = 0 anchor.outer_Y = 0 end if anchor.attached then M.UpdateAnchorChild(anchor, anchor.attached, anchor.attachmentConf) end end M.PostBuffAnchors = function() local print = fprint() if M.ShowConsolidatedBuffs then M.UpdateRaidBuffs() end for buttonName, auraType in pairs(displays) do print('sending', buttonName, auraType) -- if waiting for anchors if not anchors[buttonName] then return end --if positioned[buttonName] == 0 then print('possibly reloaded UI, check positions') M.UpdateGuideFrames(buttonName) --end M.UpdateButtonPositions(buttonName, auraType) end end M.UpdateBuffs = function(buttonName, forced) local print = B.fprint(buttonName) local c = displays[buttonName].conf if drawn[buttonName] then wipe(drawn[buttonName]) else drawn[buttonName] = {} end M.UpdateAnchorFrames(buttonName) M.UpdateGuideFrames(buttonName) M.UpdateButtonPositions(buttonName, displays[buttonName]) end --- should only be called from user input print('init def') function M:OnInitialize () drawn = B.Abstract(B.displays, 'drawn') -- Lesser extent of guide frames that have been positioned positioned = B.Abstract(B.displays, 'positioned', positioned) -- Backdrop style frame decors = B.Abstract(B.displays, 'decorator', decors) -- Static positioning frames guides = B.Abstract(B.displays, 'guides', guides) -- Anchor points for guides anchors = B.Abstract(B.displays, 'anchor') -- Stored functions for doing icon texture adjustments zoom = B.Abstract(B.displays, 'zoom', zoom) B:RegisterUnitEvent("UNIT_AURA", "player", "vehicle") B:RegisterEvent("GROUP_ROSTER_UPDATE") B:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") hooksecurefunc("BuffFrame_UpdateAllBuffAnchors", M.PostBuffAnchors) hooksecurefunc("RaidBuffTray_Update", M.UpdateRaidBuffs) end print('update def') function M:OnUpdate () M.ShowConsolidated = (IsInGroup() and GetCVarBool("consolidateBuffs")) M.ShowMissingBuffs = (IsInGroup() and B.Conf.RaidShowMissing) for name, auraType in pairs(displays) do print(name, auraType) M.UpdateBuffs(auraType.buffName, true) end M.UpdateAnchorAnchors() M.UpdateRaidBuffs() M.UpdateBuffsTodo() end