Mercurial > wow > buffalo2
view ObjectiveTracker/Frame.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 | a487841050be |
children | 1f8f9cc3d956 |
line wrap: on
line source
--- ${PACKAGE_NAME} -- @file-author@ -- @project-revision@ @project-hash@ -- @file-revision@ @file-hash@ -- Created: 3/30/2016 12:49 AM local B = select(2,...).frame local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') local _G, ipairs, max, min, unpack, floor, pairs, tostring, type, band = _G, ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band local IsResting, UnitXP, UnitXPMax, GetXPExhaustion, tinsert, tremove = IsResting, UnitXP, UnitXPMax, GetXPExhaustion, table.insert, table.remove local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent local GetAutoQuestPopUp, GetQuestLogCompletionText = GetAutoQuestPopUp, GetQuestLogCompletionText local PERCENTAGE_STRING, GetQuestProgressBarPercent = PERCENTAGE_STRING, GetQuestProgressBarPercent local Default, AutoQuest, Quest, Bonus, Cheevs = T.DefaultHandler, T.AutoQuest, T.Quest, T.Bonus, T.Cheevs local InCombatLockdown, format, lshift, CreateFrame = InCombatLockdown, format, bit.lshift, CreateFrame local IsModifiedClick, ChatEdit_GetActiveWindow = IsModifiedClick, ChatEdit_GetActiveWindow local print = B.print('Layout') local oprint = B.print('Objectives') local bprint = B.print('Block') local tprint = B.print('Tracker') local lprint = B.print('Layout') local unitLevel = 1 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_REASON local debug = false --- FRAMES local Wrapper = _G.VeneerObjectiveWrapper local Scroller = Wrapper.scrollArea local Scroll = _G.VeneerObjectiveScroll local orderedHandlers = T.orderedHandlers local orderedNames = T.orderedNames --- FRAME TEMP VARIABLES local wrapperWidth, wrapperHeight = 0, 0 local scrollWidth, scrollHeight --- SCHEMA VARIABLES local schemaName, lastSchema = { tracker = '', block = '', line = '' }, {} local trackerSchema, blockSchema, lineSchema local itemButtonSize, itemButtonSpacing = 36, 1 local wrapperMaxWidth, wrapperMaxHeight = 270, 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 wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0 } local rewardSize = 24 local headerHeight, headerColor, headerSpacing = 16, {1,.75,0,1}, 2 local headerbg = {'VERTICAL', 1, 1, 0.5, 0.5, 1, 1, 0.5, 0} local headerFont, headerSize, headerOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 14, 'OUTLINE' local titlebg = {'HORIZONTAL', 1, 0, .7, 0, 1, 0, .7, .2} local titleFont, titleSize, titleOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE' local titleColor = {0,.7,1,1} local textbg = {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 } local textFont, textSize, textOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE' local textColor = {1,1,1,1} local selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225} local titleSpacing, textSpacing, blockSpacing = 3, 3, 1 local titleIndent, textIndent,selectionIndent = 2, 5, 50 --- END SCHEMA local blockPosition --- schema swapper T.UpdateSchema = function(layer, newSchema) if not (T.Conf.Schema[layer] and T.Conf.Schema[layer][newSchema]) then return elseif schemaName[layer] == newSchema then return end lastSchema[layer] = schemaName[layer] schemaName[layer] = newSchema local c = T.Conf.Schema[layer][newSchema] if layer == 'tracker' then headerHeight, headerSpacing = c.headerHeight, c.headerSpacing headerColor = c.headerColor headerbg = c.headerbg headerFont, headerSize, headerOutline = unpack(c.headerFont) trackerSchema = newSchema elseif layer == 'block' then titlebg = c.titlebg titleFont, titleSize, titleOutline = unpack(c.titleFont) selectionbg = c.selectionbg titleSpacing, textSpacing, blockSpacing = c.titleSpacing, c.textSpacing, c.blockSpacing titleIndent, textIndent,selectionIndent = c.titleIndex, c.textIndex, c.selectionIndent titleColor = c.titleColor print(unpack(c.titleColor)) rewardSize = 24 textFont, textSize, textOutline = unpack(c.textFont) textbg = c.textbg textIndent = c.textIndent rewardSize = c.rewardSize blockSchema = newSchema elseif layer == 'line' then textColor = c.textColor lineSchema = newSchema end tprint('|cFFFF0088UpdateSchema:|r', layer, lastSchema[layer], '->', newSchema) end -- todo: figure out why objectives go invisible local anchorPoint, anchorFrame local abs, GetTime = math.abs, GetTime Default.AddTracker = function(handler, frame, index) if index == 1 then print('|cFF00FF00### beginning wrapper layout -----------------') anchorPoint, anchorFrame = 'TOP', Scroll wrapperHeight = 0 end frame.destinationOffset = -wrapperHeight print(frame.destinationOffset, frame.previousOffset) if handler.initialized and (abs(frame.previousOffset - frame.destinationOffset) > 0.9) and frame:IsVisible() then if frame.wasEmpty then frame.previousOffset = -Wrapper:GetHeight() end local postFrame, postPoint = anchorFrame, anchorPoint local delta = frame.destinationOffset - frame.previousOffset local _, _, _, _, offset = frame:GetPoint(1) print(' |cFF00FFBBpushing', frame:GetName(), delta, 'pixels, from', frame.previousOffset, '(', offset, ')') frame.SlideIn.translation:SetTarget(frame) frame.SlideIn.translation:SetOffset(0, delta) frame.SlideIn:Play() --for i, b in ipairs(handler.usedBlocks) do --b.SlideIn.translation:SetOffset(0, delta) -- b.SlideIn:Play() --end local start = GetTime() frame.SlideIn:SetScript('OnFinished', function() print(' |cFF00BBFF'..frame:GetName(), 'moved', delta, 'over duration of ', GetTime()-start) frame:SetParent(Scroll) frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset) frame.previousOffset = frame.destinationOffset frame.SlideIn:SetScript('OnFinished', nil) if Wrapper.destinationHeight then Wrapper:SetHeight(Wrapper.destinationHeight) Scroller:SetHeight(Wrapper.destinationHeight) Scroll:SetHeight(Wrapper.destinationHeight) Wrapper.previousHeight = Wrapper.destinationHeight Wrapper.destinationHeight = nil end end) else print(' |cFF00BBFFpinning '..handler.name..' to', anchorFrame:GetName(), anchorPoint, '|rcurrent frame height:', frame.height) print(' |cFFFF0088total height:', wrapperHeight) frame:ClearAllPoints() frame:SetParent(Scroll) frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset) frame.previousOffset = frame.destinationOffset handler.initialized = true end frame.title:SetFont(headerFont, headerSize, headerOutline) frame.titlebg:SetHeight(headerHeight) frame.title:SetTextColor(unpack(headerColor)) if frame.height ~= frame.previousHeight then frame:SetHeight(frame.height) end frame:Show() if frame.wasEmpty then frame.headerFade:Play() frame.wasEmpty = nil end wrapperHeight = wrapperHeight + frame.height anchorFrame = handler.frame anchorPoint = 'BOTTOM' end Default.AddBlock = function(self, block, blockIndex) local blockIndex = blockIndex or (self.currentBlock + 1) local print = bprint local tracker = self.frame local info = block.info block.index = blockIndex print('blockschema', blockSchema, block.schema) if blockSchema ~= block.schema then T.UpdateSchema('block', block.schema) print('new schema detected, applicating...') end block:SetWidth(T.Conf.Wrapper.Width) block.title:SetSpacing(titleSpacing) block.title:SetPoint('TOP', block, 'TOP', 0, -titleSpacing) block.title:SetPoint('LEFT', block, 'LEFT', titleIndent, 0) block.title:SetTextColor(unpack(titleColor)) block.titlebg:SetTexture(1,1,1,1) block.titlebg:SetGradientAlpha(unpack(titlebg)) block.titlebg:SetPoint('TOP', block, 'TOP', 0, 0) block.titlebg:SetPoint('BOTTOM', block.title, 'BOTTOM', 0, -titleSpacing) block.status:SetSpacing(textSpacing) block.status:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, -textSpacing) block.status:SetPoint('LEFT', block.titlebg, 'LEFT', textIndent, 0) block.statusbg:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, 0) block.statusbg:SetPoint('BOTTOM', block, 'BOTTOM', 0, 0) block.statusbg:SetTexture(1,1,1,1) block.statusbg:SetGradientAlpha(unpack(textbg)) block.SelectionOverlay:SetGradientAlpha(unpack(selectionbg)) block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0) block.SelectionOverlay:SetPoint('BOTTOMRIGHT') local anchor, target, point, x, y = 'TOPRIGHT', block, 'TOPRIGHT', -2, -2 for i, tile in ipairs(block.rewardTile) do --print(rewardSize) tile:SetSize(rewardSize, rewardSize) tile:ClearAllPoints() tile:SetPoint(anchor, target, point, x, y) block.rewardLabel[i]:SetPoint('TOP', tile, 'TOP', 0, 0) anchor, target, point, x, y = 'TOPRIGHT', tile, 'TOPLEFT', -2, 0 end local titleHeight = floor(block.title:GetHeight()+.5) local titlebgHeight = titleHeight + titleSpacing*2 block.titlebg:SetHeight(titlebgHeight) local statusHeight = floor(block.status:GetHeight()+.5) local statusbgHeight = statusHeight + textSpacing*2 local attachmentHeight =floor(block.attachmentHeight + .5) print(' |cFF0088FFanchor to', self.currentAnchor:GetName()) print(' |cFF00FF00attachment:|r', attachmentHeight, '|cFF00FF00title:|r', titlebgHeight, '('.. titleHeight..')') if attachmentHeight > 0 then attachmentHeight = attachmentHeight + textSpacing end block.height = titlebgHeight + attachmentHeight block:SetHeight(block.height) if block.debug then local func = (B.Conf.GuidesMode == true) and 'Show' or 'Hide' for _, region in ipairs(block.debug) do region[func]() end end --- Handler vars if blockIndex == 1 then tracker.previousHeight = tracker.height tracker.height = headerHeight blockPosition = -headerHeight tprint(' |cFF88FF00AddBlock:|r new layout: headerHeight =', headerHeight, 'previousHeight =', tracker.previousHeight) else blockPosition = blockPosition tprint(' |cFF8888FFAddBlock:|r advancing: height =', tracker.height) end self.currentBlock = blockIndex self.currentAnchor = block block:SetPoint('TOPLEFT', self.frame, 'TOPLEFT', 0, blockPosition) block:SetPoint('RIGHT', tracker,'RIGHT', 0, 0) self.numBlocks = self.numBlocks + 1 print(' |cFFFFFF00'..tracker.height..'|r', '|cFF00FF00'..block:GetName()..'|r', block.height, tracker.height) tracker.height = tracker.height + block.height blockPosition = blockPosition - block.height end --- Used as an iterator of sorts for cascaded tag icon placements (the daily/faction/account icons) Default.AddTag = function (handler, block, tagInfo, tagPoint, tagAnchor, tagRelative) local print = bprint for order, tagName in ipairs(block.info.tagInfo) do local tag = block[tagName] if block.tagCoords[tagName] and tag then tag:SetTexCoord(unpack(block.tagCoords[tagName])) tag:Show() tag:SetPoint(tagPoint, tagAnchor, tagRelative, 0, 0) tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', tag, 'TOPLEFT' else block[tagName]:Hide() end end return tagPoint, tagAnchor, tagRelative end --- Adds the given line to the current content and advances the anchor pointer to that new line for the following call. Default.AddLine = function(handler, block, text, attachment, template) local print = lprint local lineIndex = block.currentLine + 1 local line = handler:GetLine(block, lineIndex) line.index = lineIndex if template then if line.schema ~= template then print(' |cFF00FF00change schema', template) T.UpdateSchema('line', template) line.status:SetSpacing(textSpacing) line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0) line.status:SetPoint('RIGHT', line, 'RIGHT',0, 0) line.status:SetTextColor(unpack(textColor)) line.schema = template else print(' |cFFFFFF00keep schema', line.schema) end end line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, -textSpacing) line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0) line:SetPoint('LEFT', block, 'LEFT') line:SetPoint('RIGHT', block, 'RIGHT') line:Show() tprint(' |cFF0088FFAddLine|r (|cFF00FFFF'..tostring(line.schema)..'|r):', line:GetName()) -- fill in the text, then derive pixel-rounded height line.status:SetText(text) line.height = floor(line.status:GetStringHeight()+.5) -- For progressbar and timer lines, status text may be used as the title heading if attachment then print(' |cFFFF0088doing things with a widget', attachment:GetSize()) line.height = attachment:GetHeight() if text then line.height = max(line.height, line.status:GetStringHeight()) end if attachment.status:GetText() then line.height = max(line.height, attachment.status:GetStringHeight()) end attachment:Show() end line:SetHeight(line.height) block.attachmentHeight = block.attachmentHeight + line.height + textSpacing local debug_points = '' for i = 1, line:GetNumPoints() do local point, parent, anchor = line:GetPoint(i) debug_points = debug_points .. tostring(parent:GetName()) .. ', ' .. anchor .. ' ' end print(' |cFF0088FFsetting line #'..lineIndex..' for|r', block.info.title, "\n |cFF0088FFsize:|r", line.height, "|cFF0088FFpoint:|r", debug_points, "|cFF0088FFwidget:|r", (line.widget and 'Y' or 'N')) block.currentLine = lineIndex block.endPoint = line -- edge used for the next block return lineIndex end --- Creates or retrieves a complete line data object Default.GetLine = function(handler, block, lineIndex) local print = lprint local blockIndex = block.index local lines = block.lines if not lineIndex then lineIndex = block.currentLine + 1 print(' |cFFFFFF00generating a frame') end block.numLines = max(block.numLines, lineIndex) if not lines[lineIndex] then print(' |cFF00FF88created line #'..lineIndex..' from for '..handler.name..' block #'..blockIndex) lines[lineIndex] = CreateFrame('Frame', 'Vn'..handler.name .. blockIndex..'ObjectiveLine'..lineIndex, block, 'VeneerTrackerObjective') local line = lines[lineIndex] line.index = lineIndex line.height = 0 line.schema = '' B.SetConfigLayers(line) if debug then for _, region in ipairs(lines[lineIndex].debug) do region:Show() end end end return lines[lineIndex] end --- Creates or retrieves a complete block frame object --- todo: make it use data index to avoid re-coloring every block Default.GetBlock = function(handler, index) local print = bprint print('|cFF0088FFgetting a block for index', index ..',', #handler.usedBlocks,'used', #handler.freeBlocks, 'free') local block = handler.InfoBlock[index] local used = handler.usedBlocks if not block then if #handler.freeBlocks >= 1 then block = tremove(handler.freeBlocks) tinsert(handler.usedBlocks, block) block.posIndex = #handler.usedBlocks print(' |cFF00FF00 assigning from free heap', block:GetName()) else local blockIndex = (#handler.usedBlocks + #handler.freeBlocks) + 1 block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, handler.frame, 'VeneerTrackerBlock') --block:SetParent() block.schema = '' block.lines = {} block.numLines = 0 block.currentLine = 0 block.attachmentHeight = 0 block.offset = 0 B.SetConfigLayers(block) --- methods for event handlers block.Select = handler.Select block.Open = handler.Open block.Remove = handler.Remove block.Link = handler.Link block.clickZone:SetScript('OnMouseUp', function(self, ...) handler.OnMouseUp(block, ...) end) block.clickZone:SetScript('OnMouseDown', function(self, ...) handler.OnMouseDown(block, ...) end) block:ClearAllPoints() block.index = blockIndex print(' |cFF00FFBBcreating new|r', block:GetName()) end handler.InfoBlock[index] = block tinsert(handler.usedBlocks, block) block.posIndex = #handler.usedBlocks else print(' |cFFFFFF00use existing block|r', block:GetName()) local found = false for i, entry in ipairs(used) do if entry == block then found = true break end end if not found then tinsert(used, block) block.posIndex = #used end end return block end ---------- --- Top level methods T.UpdateBlockAction = function (block, itemButton) local print = bprint print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()') if itemButton.questID ~= block.info.questID then print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID) -- something happened between this and last frame, go back and set new probes return T.UpdateActionButtons() end local previousItem = itemButton.previousItem local upper_bound = Scroller:GetTop() + Scroller.snap_upper local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize local point, anchor, relative if block:GetBottom() < lower_bound then print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5)) if previousItem then print('adjusting', previousItem:GetName()) previousItem:ClearAllPoints() previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing) end itemButton:ClearAllPoints() itemButton.x = Wrapper:GetLeft() -4 itemButton.y = Wrapper:GetBottom() point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT' Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing elseif block:GetTop() > upper_bound then print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5)) itemButton:ClearAllPoints() if previousItem then print('latch onto another piece') point, anchor, relative ='TOP', previousItem, 'BOTTOM' itemButton.x = 0 itemButton.y = -itemButtonSpacing else print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop()) point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' itemButton.x = Scroller:GetLeft() -4 itemButton.y = Scroller:GetTop() end itemButton:Show() Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing) else print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5)) itemButton:ClearAllPoints() itemButton.x = block:GetLeft() - itemButtonSpacing itemButton.y = block:GetTop() point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' end itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y) itemButton:Show() end T.UpdateItemButtonCooldown = function(button) end function T:FinishWrapper () if wrapperHeight > Wrapper.previousHeight then Wrapper:SetHeight(wrapperHeight) Scroller:SetHeight(wrapperHeight*3) Scroll:SetHeight(wrapperHeight) Wrapper.previousHeight = wrapperHeight Wrapper.destinationHeight = wrapperHeight end Scroller:SetVerticalScroll(B.Conf.ObjectiveScroll or 0) print('|cFF00FF00### end of wrapper layout', Wrapper:GetSize()) print(' |cFF00FF00Scroller:', Scroller:GetSize()) print(' |cFF00FF00Scroll:', Scroll:GetSize()) for i = 1, Wrapper:GetNumPoints() do print('|cFF00FF00 ', Wrapper:GetPoint(i)) end for i = 1, Scroller:GetNumPoints() do print('|cFF00FF00 ', Scroller:GetPoint(i)) end for i = 1, Scroll:GetNumPoints() do print('|cFF00FF00 ', Scroll:GetPoint(i)) end Wrapper:Show() Scroller:Show() Scroll:Show() end