diff Fog.lua @ 1:766d8a40a1d6

first commit?
author Nenue
date Tue, 15 Dec 2015 08:07:21 -0500
parents
children 62f9b057c91b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fog.lua	Tue Dec 15 08:07:21 2015 -0500
@@ -0,0 +1,326 @@
+-- User: Krakyn
+-- Created: 12/4/2015 11:13 PM
+--[[
+--  Core tools, mostly frame handling business. It's an interface script after all.
+--  Types:
+--  StatusFrame
+--    Primary container for status data, carries primary value information by default
+--  FIELDS
+--    value              = exact primary value represented by frame
+--    min                = exact minimum for primary value
+--    max                = exact maximum for primary value
+--    percent            = value / max
+--    alpha              = base frame alpha level, set when a fade animation has completed
+--    fadeTo             = when set, the frame will begin fading to this level
+--    fadeDuration       = set with fadeTo when the transition needs to be time-adjusted for unpredictable alpha states
+--    fadeTime           = set with fadeTo when the transition has an explicit desired timing
+--    throttle_rate      = animation frame delay
+--
+--  METHODS
+--    Update()           = Runs the frame's Update script, and calls UpdateText()
+--    UpdateText()       = Iterates over frame children and calls Update() if it is a StatusText frame
+--
+--  StatusText
+--    Sub-container for individual text elements, carries string output values, controlled by from Update(). By default
+--    these are derived from the parent's primary value data, but is mostly overridden in module code.
+--  FIELDS
+--    text               = WoW FontString object housing text data
+--    format             = a format string for expressing complex data (timer bars, etc.)
+--  METHODS
+--    SetText()          = shortcut for text:SetText(...)
+--    SetJustifyH()      = shortcut for text:SetJustifyH(...)
+-- Implements:
+-- frame = CreateBar(name, config root)
+--   Creates and displays a generic bar frame with progress textures and default updater, based on the variables from
+--   the smart config table. Seeded with methods Update() and UpdateText().
+--   Update() will refresh the entire frame and tail call UpdateText()
+--   UpdateText() will iterate over the contents of frame:GetChildren() and call Update()
+--   NEVER CREATE A CHILD FRAME WITHOUT Update() DEFINED
+--   NEVER INVOKE METHODS FROM A GetParent() RETURN
+--
+-- Bar_SetUpdateHandler(frame, function)
+--   Takes the desired OnUpdate script and wraps it inside frame throttling logic, then does SetScript
+--
+-- frame = AddLabel(frame, config root, name)
+--   Constructs a text display and adds it to the frame's list of internal text objects. Contains method Update(), which
+--   refreshed text.
+--
+-- HANDLERS
+-- Bar_Update([value, min/duration, max/end])
+--   Default handler for any non-timed bar (where isTimer = false in config vars. Invoked by frame:Update()
+]]
+local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
+local LSM = LibStub("LibSharedMedia-3.0")
+local TL = 'Fog'
+local print = function(...)
+  _G.print(TL, ...)
+end
+--setprinthandler(function (...) T:debug('Fog', nil, ...) end)
+local time = _G.ct
+local FADE_OUT_TIME = 1   -- duration per 1-0 alpha transition
+local FADE_IN_TIME = 0.4  -- duration per 0-1 alpha transition
+
+local inset_factor = {
+  ['TOPLEFT']     = {-1, 1},
+  ['TOP']         = {0,  1},
+  ['TOPRIGHT']    = {1,  1},
+  ['RIGHT']       = {1,  0},
+  ['BOTTOMRIGHT'] = {1, -1},
+  ['BOTTOM']      = {0, -1},
+  ['BOTTOMLEFT']  = {-1,-1},
+  ['LEFT']        = {-1, 0}
+}
+
+T.anchor_inverse = { ['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['UP'] = 'DOWN', ['DOWN'] = 'UP' }  -- directional inverse
+T.direction_coord = { ['LEFT'] = {1, 0}, ['RIGHT'] = {-1,0}, ['UP'] = {0, -1}, ['DOWN'] = {0, 1 } } -- directional derivatives
+T.anchor_direction = { ['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['UP'] = 'BOTTOM', ['DOWN'] = 'TOP'}  -- directional anchors
+
+function T:CreateBar(name, config)
+  local parent = type(config.parent) == 'string' and _G[config.parent] or parent
+  if not parent then
+    parent = CreateFrame('Frame', config.parent, UIParent)
+    print('creating dry frame |cFFDDDDDD' .. config.parent .. '|r for |cFFFFFF00' .. name .. '|r')
+  end
+
+  local f
+  if _G[name] and _G[name].GetFrameType and _G[name].GetFrameType() == 'Frame' then
+    f = _G[name]
+    print('found existing table |cFFFFFF00' .. name .. '|r')
+  else
+    print('creating statusbar '.. name, config.anchor, parent:GetName(), config.anchorTo, config.posX, config.posY)
+  end
+
+
+  f = CreateFrame('Frame', name, UIParent)
+  f.db = config
+
+  -- state vars
+  f.combat = InCombatLockdown()
+  f.min = 0
+  f.max = 1
+  f.value = 0
+  f.percent = 0
+  f.alpha = f.combat and config.alpha or config.alpha_ooc
+  f:SetAlpha(f.combat and config.alpha or config.alpha_ooc)
+  f:SetPoint(config.anchor, config.parent, config.anchorTo, config.posX, config.posY)
+  f:SetSize(config.width, config.height)
+  f:SetFrameStrata(config.strata)
+  self:CreateStatusTextures(f, config)
+
+  f.throttle_rate = 0.0166666666 -- ~60fps
+  f.throttle_point = time
+
+  -- default handler
+  f.Update = T.Bar_Update
+  f.UpdateText = T.Bar_UpdateText
+  T:Bar_SetUpdateHandler(f, T.Bar_Update)
+
+  return f
+end
+
+function T:CreateStatusTextures(region, c)
+  c = c and c or region.db
+  print('STATUSTEX_make', region:GetName(), c.background_texture, c.background_color, c.foreground_texture, c.foreground_color)
+  region.background = region:CreateTexture('background', 'BACKGROUND')
+  region.background:SetAllPoints(region)
+  if c.background_texture then
+    region.background:SetTexture(LSM:Fetch('statusbar', c.background_texture))
+    region.background:SetVertexColor(unpack(c.background_color))
+  else
+    region.background:SetTexture(unpack(c.background_color))
+  end
+  region.background:SetBlendMode(c.background_blend)
+
+  region.foreground = region:CreateTexture('foreground', 'ARTWORK')
+  region.foreground:SetPoint('TOPLEFT', region, 'TOPLEFT', 0-c.foreground_inset, c.foreground_inset)
+  region.foreground:SetPoint('BOTTOMRIGHT', region, 'BOTTOMRIGHT', c.foreground_inset, 0-c.foreground_inset)
+  if c.foreground_texture then
+    region.foreground:SetTexture(LSM:Fetch('statusbar', c.foreground_texture))
+    region.foreground:SetVertexColor(unpack(c.foreground_color))
+  else
+    region.foreground:SetTexture(unpack(c.foreground_color))
+  end
+  region.foreground:SetBlendMode(c.foreground_blend)
+end
+
+function T:CreateStatusIcon(region, c)
+  local file = type(c) == 'string' and c or region.icon
+  if type(c) ~= 'table' then
+    c = region.db
+  end
+  print('STATUSICON', region:GetName(), file, c.icon_show)
+
+end
+
+-- Sets the OnUpdate handler within a timing scheme
+function T:Bar_SetUpdateHandler(bar, func)
+  bar:SetScript('OnUpdate', function(bar)
+    if GetTime() < bar.throttle_point then
+      return
+    end
+
+    bar.throttle_point = bar.throttle_point +  bar.throttle_rate
+    if type(func) == 'string' then
+      if type(bar[func]) ~= 'function' then
+        error('TurokBar:SetUpdateScript(); string "' ..func.. '" is not a valid method name')
+        return
+      end
+    elseif type(func) ~= 'function' then
+      error('TurokBar:SetUpdateScript(function or string); got '.. type(func) .. 'instead')
+      return
+    end
+
+    func(bar)
+  end)
+end
+
+-- Default update loop
+function T:Bar_Update (value, min, max)
+
+  if value ~= nil then -- could be 0
+    self.value = value
+  end
+  if (min ~= nil and max ~= nil) then
+    if self.isTimer then
+      self.duration = min
+      self.endTime = max
+    else
+      self.min = min
+      self.max = max
+      self.duration = max
+    end
+  end
+
+  if self.combat ~= InCombatLockdown() then
+    self.combat = InCombatLockdown()
+    if self.combat then
+      self.fadeTo = self.db.alpha
+      self.fadeDuration = FADE_IN_TIME
+    else
+      self.fadeTo = self.db.alpha_ooc
+      self.fadeDuration = FADE_OUT_TIME
+      end
+  end
+
+  -- we need the time for something
+  if self.isTimer or self.fadeTo ~= nil then
+    local time = GetTime()
+
+    -- start doing fade animation things
+    if self.fadeTo ~= nil then
+
+      if not self.fadeFrom then
+        self.fadeFrom = self:GetAlpha()
+      end
+
+      -- fadeDuration missing, fill it in
+      if not self.fadeDuration then
+        self.fadeDuration = self.fadeFrom > self.fadeTo and FADE_OUT_TIME or FADE_IN_TIME
+      end
+
+      -- fadeTime missing,
+      if not self.fadeTime then
+        local fadeRatio = 1
+        if self.fadeFrom ~= self.alpha then
+          fadeRatio = (self.fadeTo - self.fadeFrom) / (self.fadeTo - self.alpha) -- target delta
+        end
+        --print(fadeRatio, self.fadeDuration)
+        self.fadeTime = time + fadeRatio * self.fadeDuration -- fixed rate of change
+      end
+
+      -- are we done?
+      if time >= self.fadeTime then
+        self:SetAlpha(self.fadeTo)
+        self.alpha = self.fadeTo
+        self.fadeTo = nil
+        self.fadeFrom = nil
+        self.fadeDuration = nil
+        self.fadeTime = nil
+      else --nope
+        local remaining = (self.fadeTime - time) / self.fadeDuration
+        local fadeTotal = (self.fadeTo - self.fadeFrom)
+        --print(self.fadeTo - (fadeTotal * remaining), fadeTotal * remaining)
+        self:SetAlpha(self.fadeTo - (fadeTotal * remaining))
+      end
+    end
+
+    -- termination check
+    if self.isTimer then
+      if time >= self.endTime and self.fadeTo == nil then
+        self:Hide()
+        return
+      else
+        self.percent = (self.endTime - time) / self.duration
+      end
+    end
+
+  else
+    self.percent = (self.value - self.min) / (self.max - self.min)
+  end
+
+  self:UpdateText()
+  self.foreground:SetPoint('BOTTOMRIGHT', self, 'BOTTOMLEFT', self.db.width * self.percent + self.db.foreground_inset, 0-self.db.foreground_inset)
+end
+
+function T:Bar_UpdateText()
+  local c = {self:GetChildren()}
+  for _, rl in ipairs(c) do
+    if rl.text then
+      rl.format = self.db.label_string
+      rl:Update()
+    end
+  end
+end
+
+-- addon:AddLabel
+-- Constructs a text display and adds it to that region
+--
+function T:AddLabel (region, config, labelname)
+  assert(region:IsObjectType('Frame'), "T:CreateLabel(table, table [, string])")
+  labelname = (labelname or string.format('%x', GetTime() % 1000000))
+  print('assigning frame for text object |cFFFF9922'..labelname..'|r to '..region:GetName())
+
+  local lf = CreateFrame('Frame', region:GetName()..'_'..labelname, region)
+  local ft = lf:CreateFontString(labelname, 'OVERLAY')
+  local lx, ly, lp = 0,0, config.label_point
+  if config.label_inset ~= 0 and lp ~= 'CENTER' then
+    lx = config.label_inset * inset_factor[lp][1]
+    ly = config.label_inset * inset_factor[lp][2]
+  end
+
+  lf:SetPoint(lp, region, lp, lx, ly)
+  lf:SetSize(region:GetWidth(), region:GetHeight())
+  lf:SetFrameStrata(config.label_strata)
+
+  ft:SetFont(LSM:Fetch('font', config.label_font), config.label_size, config.label_outline)
+  ft:SetAllPoints(lf)
+  ft:SetJustifyH(config.label_justifyH or (config.label_point:find('LEFT') and 'LEFT' or (config.label_point:find('RIGHT') and 'RIGHT' or 'CENTER')))
+  ft:SetJustifyV(config.label_justifyV or (config.label_point:find('TOP') and 'TOP' or (config.label_point:find('BOTTOM') and 'BOTTOM' or 'MIDDLE')))
+  ft:SetTextColor(1, 1, 1)
+  ft:SetText('SET ME!')
+
+  lf.Update = region.isTimer and T.Label_UpdateFormat or T.Label_Update
+  lf.SetJustifyH = function(self, justify) ft:SetJustifyH(justify) end
+  lf.SetText = function(self, text) ft:SetText(text) end
+
+  lf.text = ft
+  region[labelname] = lf
+  return lf
+end
+
+-- one of two possible assignments for label:Update()
+function T:Label_UpdateFormat()
+  local region = self:GetParent()
+  if self.format then
+    self.value = string.gsub(self.format, '%%p', string.format('%.1f', region.value))
+    self.value = string.gsub(self.value, '%%d', region.duration)
+    if region.name then
+      self.value = string.gsub(self.value, '%%n', region.name)
+    end
+  end
+  self.text:SetText(self.value)
+end
+function T:Label_Update()
+  self.text:SetText(self:GetParent().value)
+end
+