diff ObjectiveFrame.lua @ 2:a2396b03ce63

- identify action buttons by the associated QuestID instead of QuestLogIndex - deferred button placement in general to a self-destructing OnUpdate -- and defer self-destruct to a end of combat event if InCombatLockdown - tracker wrapper has an experience/reputation bar; the two elements "feel" related and it's a very simple info display
author Nenue
date Thu, 31 Mar 2016 01:38:47 -0400
parents b0447b382f36
children 3397aae1f44d
line wrap: on
line diff
--- a/ObjectiveFrame.lua	Wed Mar 30 16:30:49 2016 -0400
+++ b/ObjectiveFrame.lua	Thu Mar 31 01:38:47 2016 -0400
@@ -4,7 +4,9 @@
 -- @file-revision@ @file-hash@
 -- Created: 3/30/2016 12:49 AM
 local B = select(2,...).frame
-local ipairs, max, unpack = ipairs, max, unpack
+local ipairs, max, min, unpack, floor, pairs, tostring, type = ipairs, max, min, unpack, floor, pairs, tostring, type
+local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion
+local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent
 local CreateFrame = CreateFrame
 local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
 local print = B.print('Objectives')
@@ -13,9 +15,9 @@
 --------------------------------------------------------------------
 
 --- Upvalues
-local Wrapper = _G.VeneerObjectiveWrapper
+local Wrapper = VeneerObjectiveWrapper
 local Scroller = Wrapper.scrollArea
-local Scroll = _G.VeneerObjectiveScroll
+local Scroll = VeneerObjectiveScroll
 local orderedHandlers = mod.orderedHandlers
 local orderedNames = mod.orderedNames
 
@@ -31,82 +33,31 @@
 local titleSpacing, textSpacing = 4, 3
 local textIndent = 5
 local wrapperMaxWidth, wrapperMaxHeight = 280, 490 -- these are the hard bounds, actual *Height variables are changed
+local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE'
 local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24
-local headerOutline, headerColor = 'OUTLINE', {1,1,1,1}
+local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2
 local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0}
 
-local Scroller_OnShow = function()
-  Wrapper.watchMoneyReasons = 0;
-  mod.UpdateWrapper()
-end
-
-local Scroller_OnHide = function()
-  local self = Wrapper
-  Wrapper:UnregisterAllEvents()
-  Wrapper:SetScript('OnEvent', nil)
-  Wrapper.Background:Hide()
-  Wrapper.BackgroundR:Hide()
-end
-
-local Scroller_OnMouseWheel = function(self, delta)
-  local r = Scroll:GetHeight() - Scroller:GetHeight()
-  local s = self:GetVerticalScroll() - delta * floor(r/5+.5)
-  if r == 0 then return end
-  if s >= r then
-    s = r
-  elseif s < 1 then
-    s = 0
-  end
-  self:SetVerticalScroll(s)
-  print(s, r, self:GetVerticalScroll())
-
-  mod.UpdateActionButtons()
-end
-
-local WrapperCloseButton_OnClick = function(self)
-  if Scroller:IsVisible() then
-    Scroller:Hide()
-  else
-    Scroller:Show()
-  end
-end
-
-
-mod.InitializeTrackers = function()
-  for i, name in ipairs(orderedNames) do
-    if not mod.orderedHandlers[i] then
-      if mod.Tracker(name, i) then
-        local handler = mod[name]
-
-        local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate')
-        tracker.header:SetText(handler.name)
-        tracker.header:SetHeight(headerHeight)
-        tracker.header:SetFont(headerFont, headerSize, headerOutline)
-        tracker.header:SetTextColor(unpack(headerColor))
-
-        handler.Tracker = tracker
-        mod.orderedTrackers[i] = tracker
-        mod.namedTrackers[name] = tracker
-        mod.indexedTrackers[handler] = tracker
-        print('created new tracker frames for new handler')
-      end
-    end
-  end
-
-  Scroller:SetScrollChild(Scroll)
-  Scroller:SetScript('OnMouseWheel', Scroller_OnMouseWheel)
-  Scroller:SetScript('OnShow', Scroller_OnShow)
-  Scroller:SetScript('OnHide', Scroller_OnHide)
-  Wrapper.close:SetScript('OnClick', WrapperCloseButton_OnClick)
-  Wrapper:SetPoint(unpack(wrapperPosition))
-  Scroller_OnShow(Scroller)
-end
-
+--- These are mostly aesthetic choices so it lives here
 mod.defaults = {
   ObjectiveTrackerAnchor = {'BOTTOM', 'RIGHT'},
   ObjectiveTrackerParent = 'DebuffButton',
   ObjectiveTrackerSize = {250, 600},
   ObjectiveWrapperParent = '',
+  WrapperStyle = {
+    Header = {
+      Background = {Left = [[Objective-Header]], Right = [[Objective-Header]], Tile = [[Objective-Header]]},
+      BackgroundCrop = {Left = {0, 0.4, 0,1}, Right={0.6,1,0,1}, Tile = {0.4,.6,0,1,}},
+      BackgroundScale = {Left = 100, Right = 100},
+      Font = {wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline}
+    }
+  },
+  ObjectiveHeaderStyle = {
+    Normal = {
+      Gradient = {MinColor = {0,0,0,0.5}, MaxColor = {0,0,0,1}},
+      Font = {headerFont, headerSize, headerOutline}, Spacing = headerSpacing,
+    }
+  },
   ObjectiveTrackerStyle = {
     Normal = {
       Title = {
@@ -158,12 +109,155 @@
   }
 }
 
+local Scroller_OnShow = function()
+  Wrapper.watchMoneyReasons = 0;
+  mod.UpdateWrapper()
+  mod.SetEvents()
+  for i, region in ipairs(Wrapper.header) do
+    region:Show()
+  end
+end
+
+local Scroller_OnHide = function()
+  local self = Wrapper
+  Wrapper:UnregisterAllEvents()
+  Wrapper:SetScript('OnEvent', nil)
+  for i, region in ipairs(Wrapper.header) do
+    region:Hide()
+  end
+end
+
+local Scroller_OnMouseWheel = function(self, delta)
+  local r = Scroll:GetHeight() - Scroller:GetHeight()
+  local s = self:GetVerticalScroll() - delta * floor(r/5+.5)
+  if r == 0 then return end
+  if s >= r then
+    s = r
+  elseif s < 1 then
+    s = 0
+  end
+  self:SetVerticalScroll(s)
+  print(s, r, self:GetVerticalScroll())
+
+  mod.UpdateActionButtons()
+end
+
+local WrapperCloseButton_OnClick = function(self)
+  if Scroller:IsVisible() then
+    Scroller:Hide()
+  else
+    Scroller:Show()
+  end
+end
+
+mod.InitializeTrackers = function()
+
+  local c = mod.defaults.ObjectiveHeaderStyle.Normal
+  local g1, g2, g3, g4 = unpack(c.Gradient.MinColor)
+  local h1, h2, h3, h4 = unpack(c.Gradient.MaxColor)
+
+  for i, name in ipairs(orderedNames) do
+    if not mod.orderedHandlers[i] then
+      if mod.Tracker(name, i) then
+        local handler = mod[name]
+
+        local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate')
+        tracker.header:SetText(handler.name)
+        tracker.header:SetHeight(headerHeight)
+        tracker.header:SetFont(unpack(c.Font))
+        tracker.header:SetTextColor(unpack(headerColor))
+
+        tracker.headerbg:SetGradientAlpha('HORIZONTAL', g1, g2 ,g3, g4, h1, h2, h3, h4)
+        tracker.headerbg:SetHeight(headerHeight)
+
+        handler.Tracker = tracker
+        mod.orderedTrackers[i] = tracker
+        mod.namedTrackers[name] = tracker
+        mod.indexedTrackers[handler] = tracker
+        print('created new tracker frames for new handler')
+      end
+    end
+  end
+
+  Scroller:SetScrollChild(Scroll)
+  Scroller:SetScript('OnMouseWheel', Scroller_OnMouseWheel)
+  Scroller:SetScript('OnShow', Scroller_OnShow)
+  Scroller:SetScript('OnHide', Scroller_OnHide)
+  Wrapper.close:SetScript('OnClick', WrapperCloseButton_OnClick)
+  Wrapper:SetPoint(unpack(wrapperPosition))
+  Scroller_OnShow(Scroller)
+
+  mod.UpdateWrapperStyle()
+end
+
+mod.InitializeXPTracker = function()
+  local XPBar = Wrapper.XPBar
+  if UnitLevel('player') == 100 then
+    XPBar:Hide()
+    return
+  end
+
+  --- xp bar
+  XPBar:Show()
+  XPBar.rested:SetTexture(2,.6,1,1)
+  XPBar.fg:SetTexture(.3,.1,.95,1)
+  XPBar.bg:SetTexture(0,0,0,.25)
+  XPBar:RegisterEvent('PLAYER_XP_UPDATE')
+  XPBar:RegisterEvent('PLAYER_LEVEL_UP')
+  XPBar:RegisterEvent('PLAYER_UPDATE_RESTING')
+  XPBar:SetScript('OnEvent', mod.UpdateXP)
+  mod.UpdateXP(Wrapper.xpBar)
+end
+
+mod.UpdateXP = function()
+  local XPBar = Wrapper.XPBar
+  local xp = UnitXP('player')
+  local xpmax = UnitXPMax('player')
+  local rest = GetXPExhaustion()
+
+  XPBar.bg:SetAllPoints(XPBar)
+  XPBar.fg:SetWidth((xp/xpmax) * XPBar:GetWidth())
+
+  if IsResting() then
+    XPBar.bg:SetTexture(.2,.8,.2,.5)
+  else
+    XPBar.bg:SetTexture(0,0,0,.25)
+  end
+
+  if rest then
+    XPBar.rested:ClearAllPoints()
+    if xp == 0 then
+      XPBar.rested:SetPoint('LEFT', XPBar, 'LEFT', 0, 0)
+    else
+      XPBar.rested:SetPoint('LEFT', XPBar.fg, 'RIGHT', 0, 0)
+    end
+
+    if (xp + rest) > xpmax then
+      XPBar.rested:SetPoint('RIGHT', XPBar, 'RIGHT', 0, 0)
+    else
+      XPBar.rested:SetWidth((xp/xpmax) * XPBar:GetWidth())
+    end
+    XPBar.rested:Show()
+  else
+    XPBar.rested:Hide()
+  end
+
+  XPBar.xpText:SetText(xp .. '/'.. xpmax .. (rest and (' ('..tostring(rest)..')') or ''))
+end
+
+mod.UpdateReputation = function(self)
+end
 
 --- Argument containers
 local a1, a2, a3, a4, b1, b2, b3, b4, f1, f2, f3, w1, w2
 mod.SetBlockStyle = function(block, name)
   -- var names intended to reflect argument order
+  --@debug@
   local c = mod.defaults.ObjectiveTrackerStyle[name]
+  --@end-debug@
+  --[===[@non-debug
+  local c = mod.Conf
+  --@end-non-debug]===]
   a1, a2, a3, a4 = unpack(c.Title.Gradient.MinColor)
   b1, b2, b3, b4 = unpack(c.Title.Gradient.MaxColor)
   block.titlebg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
@@ -212,7 +306,19 @@
   block.width = blockWidth
   block.height = blockHeight
 
-  print('|cFF88DDFFApplyStyle(', block:GetName(), ')|r', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
+  print('    |cFF00FFFF'..block:GetName()..'|r:|cFF0088FFSetStyle|r(', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
+end
+
+local segments = {'Left', 'Right', 'Tile'}
+mod.UpdateWrapperStyle = function()
+  local c = mod.defaults.WrapperStyle
+  for _, segment in ipairs(segments) do
+    Wrapper['Background'..segment]:SetAtlas(c.Header.Background[segment])
+    Wrapper['Background'..segment]:SetTexCoord(unpack(c.Header.BackgroundCrop[segment]))
+    if c.Header.BackgroundScale[segment] then
+    Wrapper['Background'..segment]:SetWidth(c.Header.BackgroundScale[segment])
+    end
+  end
 end
 
 --- Updates the selected block frame to display the given info batch
@@ -221,7 +327,7 @@
 -- @param info the reference returned by the GetXInfo functions
 -- REMEMBER: t.info and questData[questID] are the same table
 mod.UpdateTrackerBlock = function (handler, blockIndex, info)
-  print('|cFF00FFFFUpdateTrackerBlock('..blockIndex..'|r')
+  print('  |cFF00FFFFUpdateTrackerBlock('..blockIndex..'|r')
   if not blockIndex or not info then
     return
   end
@@ -237,8 +343,8 @@
     end
     t:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
   end
-  print(t:GetName(), t:GetSize())
-  print(t:GetPoint(1))
+  --print(t:GetName(), t:GetSize())
+  --print(t:GetPoint(1))
 
   t.info = info
 
@@ -260,7 +366,7 @@
     t.objectives:SetText(info.completionText)
   elseif info.numObjectives >= 1 then
     t.objectives:Show()
-    print('objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
+    print('  - objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
     local text = ''
     for o, obj in ipairs(t.info.objectives) do
       local line = obj.text
@@ -277,12 +383,9 @@
 
 
     -- todo: set up a SecureActionButton template
-    if info.specialItem then
-      print('|cFF00FFFFretrieve item button')
+    if info.specialItem and not info.itemButton then
+      print('  - |cFF00FFFFupdate item button')
       mod.SetItemButton(t, info)
-    elseif t.itemButton then
-      print('|cFF00FF88drop item button')
-      mod.FreeItemButton(t, info)
     end
 
 
@@ -304,7 +407,7 @@
 
   local fullheight = t:GetHeight()
   t:Show()
-  print('|cFF00FFFF)|r -> ', t, t:GetHeight(), fullheight)
+  print('  |cFF00FFFF)|r -> ', t, t:GetHeight(), fullheight)
   return t
 end
 
@@ -326,7 +429,6 @@
       if info then
         local currentBlock = mod.UpdateTrackerBlock(handler, blockIndex, info)
         previousBlock = currentBlock
-        print('adding ', currentBlock.height)
         trackerHeight = trackerHeight + currentBlock.height
         numBlocks = max(numBlocks, watchIndex)
         actualBlocks = actualBlocks + 1
@@ -412,11 +514,13 @@
   headerHeight = floor(headerHeight+.5)
 
   if wrapperBlocks >= 1 then
-    Wrapper.Background:Show()
-    Wrapper.BackgroundR:Show()
+    for i, region in ipairs(Wrapper.header) do
+      region:Show()
+    end
   else
-    Wrapper.Background:Hide()
-    Wrapper.BackgroundR:Hide()
+    for i, region in ipairs(Wrapper.header) do
+      region:Hide()
+    end
     return
   end
   --wrapperHeight = scrollHeight
@@ -452,7 +556,8 @@
 --- Queue any active item buttons for update for that frame
 mod.UpdateActionButtons = function()
   local previousItem
-  for questIndex, itemButton in pairs(usedButtons) do
+  for questID, itemButton in pairs(usedButtons) do
+    local questIndex = mod.Quest.Info[questID].questLogIndex
     print('|cFF00FFFF', questIndex, itemButton:GetName())
     local block = mod.Quest.LogBlock[questIndex]
     print(block:GetTop())
@@ -469,13 +574,20 @@
           end)
         return
       else
-        mod.FreeItemButton(block, itemButton)
+        mod.FreeItemButtons(block)
       end
     end
   end
 end
 
 mod.UpdateBlockAction = function (block, itemButton, previousItem)
+  if block.itemButton ~= itemButton then
+    block.itemButton = itemButton
+  end
+  if itemButton.block ~= block then
+    itemButton.block = block
+  end
+
   if block:GetBottom() < Scroller:GetBottom() then
     print('|cFFFFFF00bottom not fully visible')
     if previousItem then