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