Mercurial > wow > buffalo2
diff Veneer.lua @ 59:07ef62fe201f
Re-write of BuffFrame module:
- uses secure hooks on blizzard BuffFrame.lua functions to determine needed action
- make use of built-in table behavior to reduce unnecessary frame updates
author | Nenue |
---|---|
date | Thu, 28 Jul 2016 18:27:56 -0400 |
parents | f253baf6022d |
children | 3f083d389c18 |
line wrap: on
line diff
--- a/Veneer.lua Fri Jul 08 18:01:49 2016 -0400 +++ b/Veneer.lua Thu Jul 28 18:27:56 2016 -0400 @@ -1,546 +1,32 @@ --------------------------------------------- -- Veneer --- Core --- author: Krakyn --- @project-revision@ @project-hash@ --- @file-revision@ @file-hash@ --- Created: 4/27/2016 1:02 AM --------------------------------------------- ---- Implemented methods --- OnInitialize --- OnUpdate --- OnEnable -- runs as soon as GetSpecialization() returns valid data +-- Customization tool for the small bits and pieces -local ADDON, A = ... -local wipe, min, max, random, tinsert, tremove = table.wipe, math.min, math.max, math.random, table.insert, table.remove -local pairs, ipairs, select, unpack, _G = pairs, ipairs, select, unpack, _G -local type, tostring, format = type, tostring, string.format +-- BuffFrame +-- Provides mechanisms for positioning and alter buff button parameters. +-- Mostly re-configures the blizzard UI frames due to limitations of SecureTemplate. ---- Establish presence -Veneer = Veneer or CreateFrame('Frame', 'Veneer', UIParent) -local V = Veneer -A.frame = V +local vn, print = LibStub("LibKraken").register(VeneerController) ---- Work variables -local modules = {} -- module collector -local queuedModules = {} -- indicates modules that were encountered out of dependency order -local checkForConfig = {} -- indicates frames created from XML that use their own namespace for position control -local moduleStack = {} -- dictates the order in which module methods are fired -local initOnced -- internal check for doing bottom-up SV retrieval ---- Utilities -V.wipeall = function (...) - for i = 1, select('#', ...) do - wipe(select(i, ...)) - end -end +local defaults = { + enableAll = true, + enableModule = { + BuffFrame = true, + }, + BuffFrame = { + width = 48, + height = 48, ---- Various region categories -V.displays = {} -V.configLayers = {} -V.configLayersRef = {} + } +} - ---- Returns a debug hook for adding generic module information to each message --- @usage func = V.print(sig) --- @param sig channel name or number -local debugstack = _G.debugstack -local Devian = _G.Devian -local printfuncs = {} -V.print = function(pref, ...) - if Devian and Devian.InWorkspace() then - printfuncs[pref] = printfuncs[pref] or function(...) print(pref, ...) end - - return printfuncs[pref] - else - return function () end - end -end - ---@debug@ -local rgb = {} -local getcolor = function() - local n, p = 0, 4 - for i = 1, 3 do - rgb[i] = min(random(n,p) * 64, 255) - if rgb[i] == 255 then - p = 4 - elseif rgb[i] > 0 then - n = 2 - end - end - return unpack(rgb) -end - -local color = {} -local fprints = {} ---- Attempts to generate a debug printer based on the local scope. Results vary by where the originator was invoked. -V.fprint = function() - if not (Devian and Devian.InWorkspace()) then - return function() end +vn.init = function() + if (not VeneerData) or (not VeneerData.version) then + VeneerData = defaults end - local sig = debugstack(2,1) - if fprints[sig] then - return fprints[sig] - end - local func = sig:match("%`(%a+)%'") - if not func then - func = sig:match("<(.-)>") - end - func = func:gsub('(%l+)(%u)', function(a, b) return a:sub(0,2) .. b end, 1) - func = func:gsub('^.+%\\', '') - if not func then - func = 'noname' - end - local r, g, b = getcolor() - color[sig] = color[sig] or format('|cFF%02X%02X%02X%s|r', r, g, b, func) - --print(color[func] .. ' ( ' .. table.concat(args, ', ')..' )' ) - func = V.print(func) - fprints[sig] = func - return func -end - ---@end-debug@ ---[=[@non-debug@ -V.print = function() end ---@end-non-debug@]=] - --- for the Mikk script --- GLOBALS: NUM_LE_RAID_BUFF_TYPES --- GLOBALS: BUFF_FLASH_TIME_ON, BUFF_FLASH_TIME_OFF, BUFF_MIN_ALPHA, BUFF_WARNING_TIME, BUFF_DURATION_WARNING_TIME --- GLOBALS: BUFFS_PER_ROW, BUFF_MAX_DISPLAY, BUFF_ACTUAL_DISPLAY, DEBUFF_MAX_DISPLAY, DEBUFF_ACTUAL_DISPLAY, BUFF_ROW_SPACING --- GLOBALS: CONSOLIDATED_BUFFS_PER_ROW, CONSOLIDATED_BUFF_ROW_HEIGHT, NUM_TEMP_ENCHANT_FRAMES --- GLOBALS: BUFF_BUTTON_HEIGHT, BUFF_FRAME_BASE_EXTENT, BUFF_HORIZ_SPACING - -local print = V.print('Bfl') - ---- Template for making perpendicular traversals of the displays structure; also makes sure the table is there -local setmetatable = setmetatable -V.Abstract = function(dest, key, table) - if table then - for _, v in pairs(dest) do - v[key] = {} - end - end - V[key] = setmetatable({}, { - __index = function(t, k) - return dest[k][key] - end, - __newindex = function(_, k, v) - print('abstract write ('..key..'):', k) - dest[k][key] = v - end, - __tostring = function() return 'Abstract:'..key..'' end - }) - - - return V[key] -end - - ---- internal -local ModulesCall = function(func, flag) - local n = 0 - for i = 1, #moduleStack do - print('calling level '..i) - local stackset = moduleStack[i] - for name, module in pairs(stackset) do - n = n + 1 - if module[func] then - -- nil = pass - if not flag or (module.Conf and module.Conf[flag]) then - if (flag) then - print(' check', flag, '=', module.Conf[flag]) - end - - print(' ',n..' '..name..'.'..func..'()') - module[func](module, module.Conf) - end - end - end - end -end - - -local Enable = function() -end - ---- The things that happen repeatedly -local Init = function () -end - - -local layers, refs, displays = V.configLayers, V.configLayersRef, V.displays ---- Things that happen immediately upon entering world -local InitOnce = function() - print('entering world first time') - local defaults = {} - print('|cFFFFFF00Veneer|r') - if not VeneerData then - VeneerData = {} - for k,v in pairs(defaults) do - VeneerData[k] = v - end - print('Veneer defaults being used.') - end - V.Conf = setmetatable(VeneerData, {__index = function(_, k) return defaults[k] end}) - - -- To ensure that modules are run in controlled order, walk the dependency list; if the dep shows up - -- in the loaded manifest, remove the value. If the dep list isn't empty, move that module to the next - -- layer. - local loaded = {} - local stackLevels = #moduleStack - local i = 1 - moduleStack[1] = modules - repeat - print('setting init level '.. i) - local queue = moduleStack[i] - for name, module in pairs(queue) do - - if queuedModules[name] and #queuedModules[name] > 0 then - local p = #queuedModules[name] - for j = 1, p do - local dep = queuedModules[name][j] - - if loaded[dep] then - print( ' ' .. dep .. ' OK') - queuedModules[name][j] = nil - for k = j, p do - print(' shift ' .. (k+1) .. ' ('..tostring(queuedModules[name][k+1])..') to ' .. k ..'') - queuedModules[name][k] = queuedModules[name][k+1] - end - end - end - - if #queuedModules[name] == 0 then - queuedModules[name] = nil - print(' |cFF00FFFF'.. name ..'|r deps OK') - loaded[name] = true - else - - print(' |cFFFF8800' .. name ..'|r pending') - local next = i+1 - if not moduleStack[next] then - moduleStack[next] = {} - end - stackLevels = next - moduleStack[next][name] = module - queue[name] = nil - end - - else - print(' |cFF00FF00'.. name ..'|r no deps') - loaded[name] = true - end - end - i = i + 1 - until i > stackLevels - - for level, batch in ipairs(moduleStack) do - print('config level', level) - for name, module in pairs(batch) do - if not VeneerData[name] then - VeneerData[name] = {} - end - - if module.defaults then - print('setting defaults for module', name) - --[===[@non-debug@ - if not VeneerData[name] then - --@end-non-debug@]===] - VeneerData[name] = {} - --[===[@non-debug@ - end - --@end-non-debug@]===] - for k,v in pairs(module.defaults) do - VeneerData[name][k] = v - end - module.Conf = VeneerData[name] - end - - if VeneerData[name].enabled == nil then - VeneerData[name].enabled = true - end - - end - end - - --- Pull in any XML templates - if #checkForConfig >= 1 then - local queuedFrame = tremove(checkForConfig) - while queuedFrame do - V.SetConfigLayers(queuedFrame) - V.UpdateXMLFrame(queuedFrame) - queuedFrame = tremove(checkForConfig) - end - end -end - ---- Fires an update to all modules -local lastUpdate -function V.UpdateAll(...) - lastUpdate = GetTime() - ModulesCall('OnUpdate') -end - -V:RegisterEvent('PLAYER_ENTERING_WORLD') -V:SetScript('OnEvent', function(self, event) - if event == 'PLAYER_ENTERING_WORLD' then - if not initOnced then - InitOnce() - ModulesCall('OnInitialize') - initOnced = true - C_Timer.After(1, function() - if GetSpecialization() then - print(GetSpecialization(), 'enabling') - - ModulesCall('OnEnable', 'enabled') - V:SetScript('OnUpdate', nil) - end - end) - end - end - - V.UpdateAll() - - if event == 'PLAYER_ENTERING_WORLD' then - V.UpdateConfigLayers() - end - -end) - ---- Modulizer method --- -function V:RegisterModule (name, module, ...) - if modules[name] then - print('pulling modules[|cFFFF8800'.. tostring(name) ..'|r]') - return modules[name] - end - - print('new module |cFF00BBFF'.. tostring(name) ..'|r') - if module then - if modules[name] then - error("Module table for '"..tostring(name).."' already exists.") - end - else - module = CreateFrame('Frame', 'Veneer' .. tostring(name) .. 'Handler', V, 'VeneerHandlerTemplate') - end - modules[name] = module - V[name] = module - if select('#', ...) >= 1 then - local numDeps = select('#', ...) - print(' '..numDeps..' deps detected') - for i = 1, numDeps do - local dep = select(i, ...) - -- means that init/enable funcs are ordered to run after deps do their things - queuedModules[name] = queuedModules[name] or {} - tinsert(queuedModules[name], dep) - print(' needs '..dep) - end - end - return module -end - - -V.SetConfigLayers = function(frame) - local print = V.fprint() - if not frame.config then - --print(frame:GetName(), 'has no config layers') - return - end - --print('Registering config layers from', frame:GetName()) - - for i, subframe in ipairs(frame.config) do - -- make sure there are no duplicates - if not refs[subframe] then - local key = #layers+1 - layers[key] = subframe - refs[subframe] = key - end - --print(' ', i, subframe:GetName()) - end -end - -V.RemoveConfigLayers = function(frame) - - local print = V.fprint() - print('|cFFFF0000RemoveConfigLayers', frame:GetName()) - for i, subframe in pairs(layers) do - if subframe:GetParent() == frame then - print('|cFFFF8800 ', subframe:GetParent():GetName(), '|cFFFFFF00', subframe:GetName()) - layers[i]:Hide() - layers[i] = nil - refs[subframe] = nil - end - end -end - -V.ToggleGuideLayers = function() - local print = V.fprint() - local func = V.Conf.GuidesMode and 'Show' or 'Hide' - local numAnchors = 0 - - for id, region in pairs(layers) do - --print(id, region:GetName(), func) - region[func](region) - end - - --print('['..func..'] updated', #layers, 'regions,', numAnchors, 'frames') -end -V.UpdateConfigLayers = function() - print('|cFFFF0000', debugstack()) - V.ToggleGuideLayers() -end - -local XMLFrame_Enable = function(self, value) - local name = self:GetName() - local print = V.print('XML') - - if not V.Conf[name] then - V.Conf[name] = { - enabled = true - } - end - - print() - local enabled - if value == nil then - if V.Conf[name].enabled == nil then - print('toggle based on visibility') - enabled = (not self:IsVisible()) and true or false - else - print('toggle a config value =', V.Conf[name].enabled) - enabled = V.Conf[name].enabled - end - - enabled = (enabled ~= true) and true or false - else - print('use argument value', value) - enabled = value - end - - print('arg =', value, 'conf =', V.Conf[name].enabled, 'result=', enabled) - - V.Conf[name].enabled = enabled - - local stateFunc = enabled and 'Show' or 'Hide' - local eventFunc = enabled and 'OnToggle' or 'OnToggle' - --- taggled layers - if self.toggled then - for i, region in pairs(self.toggled) do - region[stateFunc](region) - end - end - --- toggle action - if self.OnToggle then - self:OnToggle(V.Conf[name].enabled) - end - --- do enable - if V.Conf[name].enabled then - if self.OnEnable then - self:OnEnable() - end - else - if self.OnDisable then - self:OnDisable() - end - end -end ---- Generic handlers for keeping track of XML-defined frames -local print = V.print('XML') -local prototypes = {} -prototypes.OnDragStart = function(self) - self.xA = self:GetLeft() - self.yA = self:GetBottom() - self.anchorTo, self.relativeTo, self.relativePoint, self.x, self.y = self:GetPoint(1) - print('acquire anchor', self:GetPoint(1)) - print(self:GetName(), 'start moving ('..self.x..', '..self.y..')') - self:StartMoving() -end - -prototypes.OnDragStop = function(self) - local name = self:GetName() - print(name, 'stop moving ('..self:GetLeft()..', '..self:GetBottom()..')') - local xB = self:GetLeft() - self.xA - local yB = self:GetBottom() - self.yA - print('storing anchor point', self.anchorTo, self.relativePoint, self.x + xB, self.y + yB) - self:StopMovingOrSizing() - V.Conf[name].position = {self.anchorTo, self.relativePoint, self.x + xB, self.y + yB} - V.UpdateXMLFrame(self) -end - - -V.RegisterModuleFrame = function(self, moduleName) - local name = self:GetName() - tinsert(checkForConfig, self) - self.Enable = XMLFrame_Enable - self.moduleName = moduleName - print('|cFF00FF00XML stuff related to '.. tostring(moduleName) .. ':', self:GetName()) - ------------------------------------------------------------------------------------------ - if not V[name] then - return - end - - local scriptTypes = {'OnUpdate', 'OnEvent', 'OnDragStart', 'OnDragStop'} - for script in next(scriptTypes) do - if V[name][script] then - self:SetScript(script, V[name][script]) - end - end - -end -local XMLFrame_OnDragStart = function() end -local XMLFrame_OnDragStop = function() end - -V.UpdateXMLFrame = function(self) - local print = V.print('XML') - - local name = self:GetName() - - - - if self.drag then - self:RegisterForDrag('LeftButton') - self:SetScript('OnDragStart', prototypes.OnDragStart) - if self.OnDragStop then - self:SetScript('OnDragStop', function(self, ...) - print('|cFFFF0088end of dragging'). - self:OnDragStop(self, ...) - prototypes.OnDragStop(self, ...) - end) - else - self:SetScript('OnDragStop', prototypes.OnDragStop) - end - else - self:EnableMouse(false) - end - - -- establish internal storage - if not V.Conf[name] then - V.Conf[name] = { - enabled = self.enabled, - } - end - local c = V.Conf[name] - - -- establish position data; if undefined, round the API values - if not c.position then - local anchor, _, point, x, y = self:GetPoint(1) - x = floor(x+.5) - y = floor(y+.5) - print('obtained frame position', name, anchor, point, x, y) - c.position = {anchor, point, x, y} - else - print('restoring frame position', name, unpack(c.position)) - self:ClearAllPoints() - local anchorTo, relativePoint, x, y = unpack(c.position) - self:SetPoint(anchorTo, UIParent, relativePoint, x, y) - end - self:Enable(c.enabled) - - -end + vn.db = VeneerData +end \ No newline at end of file