Mercurial > wow > buffalo2
view ObjectiveTracker/ObjectiveFrame.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 | 4b3da1b221de |
children |
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 = IsResting, UnitXP, UnitXPMax, GetXPExhaustion 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 print = B.print('Tracker') local unitLevel = 1 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_REASON local debug = false -------------------------------------------------------------------- --- Global frame layout -------------------------------------------------------------------- --- Upvalues local Wrapper = _G.VeneerObjectiveWrapper local Scroller = Wrapper.scrollArea local Scroll = _G.VeneerObjectiveScroll local orderedHandlers = T.orderedHandlers local orderedNames = T.orderedNames --- Temp values set during updates local wrapperWidth, wrapperHeight local scrollWidth, scrollHeight local previousBlock local currentBlock --- todo: source these from config local itemButtonSize, itemButtonSpacing = 36, 1 local headerHeight, headerColor, headerSpacing = 16, {1,1,1,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, .25, 1, 0, .7, .125} local titlebg_daily = {'HORIZONTAL', 0, .7, 1, .25, 0, 1, .7, .125 } local titlebg_account = {'HORIZONTAL', 0, .45, 1, .25, 0, .45, 1, .125} local titleFont, titleSize, titleOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE' local textbg = {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 } local textbg_daily = {'HORIZONTAL', 0, .7, 1, .1, 0, 1, .7, .075 } local textbg_account = {'HORIZONTAL', 0, .45, 1, 0.4, 0, .41, 1, .085 } local textFont, textSize, textOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE' 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 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 = 32 local oprint = B.print('Objectives') local bprint = B.print('Block') local tprint = B.print('Tracker') local lprint = B.print('Line') local currentPosition, anchorFrame, anchorPoint T.AddBlock = function(handler, block) local print = bprint end --- Used as an iterator of sorts for cascaded tag icon placements (the daily/faction/account icons) T.AddTag = function (block, tagName, tagPoint, tagAnchor, tagRelative) local print = bprint local tag = block[tagName] if block.info[tagName] and tag then tag:SetTexCoord(unpack(block.info[tagName])) tag:Show() tag:SetPoint(tagPoint, tagAnchor, tagRelative, 0, 0) tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', tag, 'TOPLEFT' else block[tagName]:Hide() 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. T.AddLine = function(block, line) local print = lprint line:ClearAllPoints() line:SetPoint('LEFT', block, 'LEFT', 0, 0) line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, -textSpacing) line:SetPoint('RIGHT', block, 'RIGHT', 0, 0) line:SetHeight(line.height) line:Show() block.endIndex = line.index block.numLines = block.numLines + 1 block.attachmentHeight = block.attachmentHeight + (line.height + textSpacing) print(' |cFF0088FFsetting line #'..block.numLines..' for|r', block.info.title, "\n |cFF0088FFsize:|r", line.height, "|cFF0088FFpoint:|r", line:GetPoint(1), "|cFF0088FFwidget:|r", (line.widget and 'Y' or 'N')) block.endPoint = line end --- Creates or retrieves a complete line data object T.GetLine = function(handler, block, lineIndex) local print = lprint local blockIndex = block.index if not block.lines then block.lines = {} end local lines = block.lines 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.status:SetSpacing(textSpacing) line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0) B.SetConfigLayers(line) if lines[lineIndex+1] then lines[lineIndex+1]:ClearAllPoints() end 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 T.GetBlock = function(handler, blockIndex) local print = bprint local block = handler.usedBlocks[blockIndex] if not handler.usedBlocks[blockIndex] then if #handler.freeBlocks >= 1 then block = handler.freeBlocks[#handler.freeBlocks] handler.freeBlocks[#handler.freeBlocks] = nil else block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, Scroll, 'VeneerTrackerBlock') local c = T.Conf.Wrapper block.index = blockIndex block.SetStyle = T.SetBlockStyle block:SetWidth(c.Width) block.title:SetSpacing(c.TitleSpacing) block.title:SetPoint('TOP', block, 'TOP', 0, -titleSpacing) block.titlebg:SetTexture(1,1,1,1) block.titlebg:SetGradientAlpha(unpack(T.colors.default.titlebg)) block.titlebg:SetPoint('TOP', block, 'TOP', 0, 0) block.titlebg:SetPoint('BOTTOM', block.title, 'BOTTOM', 0, -titleSpacing) block.status:SetSpacing(c.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(T.colors.default.textbg)) block.SelectionOverlay:SetGradientAlpha(unpack(T.colors.default.selectionbg)) block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0) block.SelectionOverlay:SetPoint('BOTTOMRIGHT') block.icon:SetSize(rewardSize, rewardSize) block.icon:SetPoint('TOPRIGHT', block, 'TOPRIGHT', -2, -2) --- 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.attachmentHeight = 0 block:ClearAllPoints() B.SetConfigLayers(block) if debug then for _, region in ipairs(block.debug) do region:Show() end end end handler.usedBlocks[blockIndex] = block end return handler.usedBlocks[blockIndex] end --- Module-specific data wrangling that has to happen during UpdateBlock() -- Most of this is sculpting objectives data into a parsible list. -- Some of it is additional block manipulation that doesn't quite fit with the other modules.. Bonus.UpdateObjectives = function(handler, block) Default.UpdateObjectives(handler, block) end --- They are not exactly quests, but the aliases used to signal that a quest was pushed into your log by the environment. -- Once accepted they never appear again unless the quest is dropped (daily reset/abandon quest) local CLICK_TO_COMPLETE = 'Click to Complete' local CLICK_TO_ACCEPT = 'Click to Accept' AutoQuest.UpdateObjectives = function(handler, block) local print = lprint if block.info.type == 'OFFER' then block.status:SetText(CLICK_TO_ACCEPT) end end --- Does the main iterations for populating block content. -- Hooked by corresponding handler functions where additional details need to be sorted. Default.UpdateObjectives = function(handler, block) local print = lprint local info = block.info print(' |cFF00FF00default objectives routine', block:GetName()) -- reset the starting positions block.attachmentHeight = 0 block.endPoint = block.titlebg local completionScore, completionMax = 0, 0 local displayObjectiveHeader = false --- The first line is going to be used no matter what, so it is hard-pulled. -- It also ensures that we're in the right position for cleaning up the leftover lines. local lineIndex = 1 local line = T.GetLine(handler, block, lineIndex) block.numLines = 0 block.attachmentHeight = 0 if info.description and #info.description >= 1 then print(' |cFF00FFFF header line:|r', info.description) line.status:SetText(info.description) line.height = floor(line.status:GetStringHeight()+.5) + textSpacing if line.widget then line.widget:Hide() end T.AddLine(block, line) lineIndex = lineIndex + 1 line = T.GetLine(handler, block, lineIndex) end if (info.isComplete == true or info.isComplete == nil) and info.completionText then print(' overriding line #1 for completion text:', info.completionText) line.status:SetText(info.completionText) line.height = floor(line.status:GetStringHeight()+.5) + textSpacing if line.widget then line.widget:Hide() end T.AddLine(block, line) else if info.objectives then for i, data in ipairs(info.objectives) do print(' |cFF88FF00#', i, data.type, data.text) displayObjectiveHeader = true line.height = 0 handler:UpdateLine(block, line, data) -- For progressbar and timer lines, status text may be used as the title heading if line.widget then local widgetPosition = 0 --- WIDGET POSITION ------------------------------------------------- line.widget:SetPoint('TOP', line, 'TOP', 0, -widgetPosition) line.widget:Show() line.height = line.widget:GetHeight() + textSpacing --------------------------------------------------------------------- if line.displayText and #line.displayText >= 1 then widgetPosition = line.status:GetHeight() + textSpacing line.status:SetText(line.displayText) line.height = floor(line.status:GetStringHeight()+.5) + textSpacing + line.widget.height print(' - progressbar has text, adjust') end elseif line.displayText then line.status:SetText(line.displayText) line.height = floor(line.status:GetStringHeight()+.5) end T.AddLine(block, line) --print(' sz', line:GetWidth(), line:GetHeight(), 'pt', line:GetPoint(1)) --print(' |cFF44BBFF#', i, 'anchoring line, size:', line.height, 'current endpoint:', line.statusbg) lineIndex = lineIndex + 1 line = T.GetLine(handler, block, lineIndex) end end end while (block.lines[lineIndex+1]) do print(' - hide |cFFFF0088'..lineIndex..'|r') block.lines[lineIndex]:Hide() lineIndex = lineIndex +1 end if lineIndex > 0 then block.attachmentHeight = block.attachmentHeight + textSpacing * 2 print(' |cFF00FF00attachment:', block.attachmentHeight) end --[[ local lines = handler.lines[block.index] if lines and #lines > block.numLines then print(' |cFFFF008' .. (#lines - block.numLines) .. ' extra lines to hide.') for i = block.numLines + 1, #lines do print(' hide', i, lines[i]:GetName()) lines[i]:Hide() end end ]] if debug then for i, region in ipairs(block.debug) do for j = 1, region:GetNumPoints() do local _, target = region:GetPoint(j) if target:IsVisible() then region:Hide() else region:Show() end end end end block.completionScore = completionScore / completionMax end --- Module-specific display variables -- * height - height of whatever display widget is involved in conveying the task -- * money - boolean that determines listening for money events or not -- * progress - number ranging 0 to 2 indicating none/partial/full completion respectively Bonus.UpdateLine = function(handler, block, line, data) local info = block.info local print = lprint line.displayColor = 'FFFFFF' line.displayText = data.text line.progress = 0 print(' ', data.objectiveIndex,'|cFFFF0088-|r', data.objectiveType, data.text) if data.objectiveType == 'progressbar' then line.widgetType = 'ProgressBar' print(' |cFFFF44DDpercent='..tostring(GetQuestProgressBarPercent(info.questID))) data.value = GetQuestProgressBarPercent(info.questID) or 0 data.maxValue = 100 if data.value >= data.maxValue then line.progress = 1 elseif data.value > 0 then line.progress = 2 end line.format = PERCENTAGE_STRING local widget = T.SetWidget(line, data, 'ProgressBar', info.questID..'-'..data.objectiveIndex) print(' |cFFFF0022** text:|r', data.text, '|cFFFF0022value:|r', data.value, '|cFFFF0022max:|r', data.maxValue) widget:SetPoint('TOP', line, 'TOP', 0, 0) line.widget = widget line.height = widget.height else line.displayText = data.text line.widget = nil end return line end Cheevs.UpdateLine = function(handler, block, line, data) local print = B.print('CheevsLine') line.progress = 0 print(' ', data.objectiveIndex,'|cFF0088FF-|r', data.objectiveType, data.text) if data.flags then if band(data.flags, 0x00000001) > 0 then line.format = "%d/%d" line.widget = T.SetWidget(line, data, 'ProgressBar', data.criteriaID) line.height = line.widget.height elseif band(data.flags, 0x00000002) then line.widget = nil else line.widget = nil line.displayColor = 'FFFFFF' line.displayText = line.text end else line.displayText = data.text end print('line.type =', data.type) print(' ** qtyStr:', data.quantityString, 'qty:', data.quantity, 'assetID:', data.assetID) end Default.UpdateLine = function(block, line) if line.finished then line.progress = 2 elseif line.quantity > 0 then line.progress = 1 else line.progress = 0 end return line end T.Quest.numButtons = 0 local usedButtons = T.Quest.itemButtons local freeButtons = T.Quest.freeButtons --[=[ T.UpdateWrapper = function(reason) print('|cFF00FFFFUpdateWrapper:|r', reason) unitLevel = UnitLevel('player') wrapperWidth = T.Conf.Wrapper.WrapperWidth scrollWidth = T.Conf.Wrapper.WrapperWidth local wrapperBlocks = 0 -- Update scroll child vertical size scrollHeight = 0 for i, handler in ipairs(orderedHandlers) do T.UpdateTracker(handler) local frame = handler.frame if handler.actualBlocks >= 1 then frame:SetParent(Scroll) frame:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight) frame:SetSize(wrapperWidth, frame.height) print('|cFF00FFFF'..frame:GetName()..'|r h:|cFF00FF00', frame.height, '|r y:|cFF00FF00', -scrollHeight) scrollHeight = scrollHeight + frame.height frame:Show() else frame:Hide() end wrapperBlocks = wrapperBlocks + handler.actualBlocks end print('final scrollHeight:', scrollHeight) -- Update frame dimensions if scrollHeight > wrapperMaxHeight then print(' is larger than', wrapperMaxHeight) wrapperHeight = wrapperMaxHeight else wrapperHeight = scrollHeight B.Conf.ObjectiveScroll = 0 end scrollWidth = floor(scrollWidth+.5) scrollHeight = floor(scrollHeight+.5) wrapperWidth = floor(wrapperWidth+.5) wrapperHeight = floor(wrapperHeight+.5) headerHeight = floor(headerHeight+.5) if wrapperBlocks >= 1 then for i, region in ipairs(Wrapper.headerComplex) do region:Show() end else for i, region in ipairs(Wrapper.headerComplex) do region:Hide() end return end --[[wrapperHeight = scrollHeight print('|cFFFFFF00params:|r scroller:', scrollWidth .. ',' .. scrollHeight, 'scroll:', scrollWidth .. ',' .. scrollHeight, 'wrapper:', wrapperWidth .. ',' .. wrapperHeight, 'header:', headerHeight)]] --Scroller:SetSize(wrapperWidth, wrapperHeight) Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, 0) Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT') Scroll:SetSize(scrollWidth, scrollHeight) Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0) Scroll:SetPoint('RIGHT', Scroller, 'RIGHT') --Scroller:UpdateScrollChildRect() Wrapper:SetSize(wrapperWidth, wrapperHeight) --[[ update action buttons print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(), '|cFF00FF00'..Scroller:GetName()..'|r:', Scroller:GetWidth(), Scroller:GetHeight(), '|cFF00FF00'..Wrapper:GetName()..'|r:', Wrapper:GetWidth(), Wrapper:GetHeight(), '|cFF0088FFvScrollRange|r:', floor(Scroller:GetVerticalScrollRange()+.5) ) --]] T.UpdateActionButtons() end --]=] Default.Update = function (self, reason, ...) local print = tprint local tracker = self.frame local blockIndex = 0 local trackerHeight = headerHeight tracker.title:SetFont(headerFont, headerSize, headerOutline) tracker.titlebg:SetHeight(headerHeight) tracker.title:SetTextColor(unpack(headerColor)) --tracker.titlebg:SetGradientAlpha(unpack(headerbg)) self.currentAnchor = tracker.titlebg local numWatched = self:GetNumWatched() local numBlocks = self.numBlocks local actualBlocks = 0 for watchIndex = 1, 25 do blockIndex = blockIndex + 1 if watchIndex <= numWatched then local info = self:GetInfo(watchIndex) if info then local currentBlock = self:UpdateBlock(blockIndex, info) currentBlock:SetPoint('TOPLEFT', self.currentAnchor, 'BOTTOMLEFT', 0, 0) currentBlock:SetPoint('RIGHT', tracker,'RIGHT', 0, 0) self.currentAnchor = currentBlock print(' |cFFFFFF00'..watchIndex..'|r', '|cFF00FF00'..currentBlock:GetName()..'|r', currentBlock.height, trackerHeight) trackerHeight = trackerHeight + currentBlock.height numBlocks = max(numBlocks, watchIndex) actualBlocks = actualBlocks + 1 else print(' |cFFFF0000bad GetInfo data for #'..watchIndex) end elseif watchIndex <= numBlocks then local used = self.usedBlocks local free = self.freeBlocks print('clean up dead quest block') if used[blockIndex] then used[blockIndex]:Hide() used[blockIndex]:ClearAllPoints() free[#free+1]= used[blockIndex] used[blockIndex] = nil end else print(' |cFFFF9900END|r @', blockIndex) break -- done with quest stuff end end self.numWatched = numWatched self.numBlocks = numBlocks self.actualBlocks = actualBlocks tracker.previousHeight = tracker.height if numBlocks >= 1 then previousBlock = nil if tracker.isEmpty then tracker.headerFade:Play() tracker.isEmpty = nil end tracker.height = trackerHeight tracker:SetHeight(tracker.height) tracker:Show() else tracker.isEmpty = true tracker.height = 0 tracker:Hide() end return tracker.numWatched, tracker.numAll end --- Updates the selected block frame to display the given info batch -- If `previousBlock` is set, it will attempt to anchor to that -- @param blockNum the ordered block to be updated, not a watchIndex value -- @param info the reference returned by the GetXInfo functions -- REMEMBER: t.info and questData[questID] are the same table Default.UpdateBlock = function (handler, blockIndex, info) local print = bprint print(' Read list item |cFF00FFFF'..blockIndex..'|r') if not blockIndex or not info then return end local frame = handler.frame local block = T.GetBlock(handler, blockIndex) block.handler = handler block.info = info block.mainStyle = info.mainStyle or 'Normal' block.subStyle = info.subStyle info.blockIndex = blockIndex if info.questID then handler.QuestBlock[info.questID] = block end if info.questLogIndex then handler.LogBlock[info.questLogIndex] = block end if info.watchIndex then handler.WatchBlock[info.watchIndex] = block end handler.BlockInfo[blockIndex] = info block.endPoint = block.titlebg block.attachmentHeight = 0 handler:UpdateObjectives(block) block.title:SetText(info.title) local titleHeight = floor(block.title:GetHeight()+.5) local statusHeight = floor(block.status:GetHeight()+.5) local attachmentHeight =floor(block.attachmentHeight + .5) local titlebgHeight = titleHeight + titleSpacing*2 local statusbgHeight = statusHeight + textSpacing*2 block.titlebg:SetHeight(titlebgHeight) print(' |cFF0088FFanchor to', handler.currentAnchor:GetName()) print(' |cFF00FF00total sizes:') print(' attachment:', attachmentHeight) print(' title:', titlebgHeight, '('.. titleHeight..')') --block.titlebg:SetHeight(block.title:GetHeight() + T.Conf.Wrapper.TitleSpacing) block.height = titlebgHeight + attachmentHeight if statusHeight > 1 then block.height = block.height + statusbgHeight print(' status:', statusbgHeight, '('.. statusHeight..')') else print(' |cFFFF0088 skipped') end block:SetHeight(block.height) print(' |cFFFFFF00height|r:', block.height) print(' |cFF00FFFF)|r -> ', block, block:GetHeight()) block:Show() if info.specialItem and not info.itemButton then print(' - |cFF00FFFFgenerating item button for info set') info.itemButton = T.SetItemButton(block, info) else --info.itemButton = nil end local tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', block, 'TOPRIGHT' if info.rewardInfo then print('has immediate reward') if info.rewardInfo[1].type == 'currency' or info.rewardInfo[1].type == 'item' then block.icon:Show() block.iconLabel:SetText(info.rewardInfo[1].count) block.icon:SetPoint(tagPoint, tagAnchor, tagRelative, -2, -2) tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', block.icon, 'TOPLEFT' block.icon:SetTexture(info.rewardInfo[1].texture) end else block.icon:Hide() end if info.selected then block.SelectionOverlay:Show() else block.SelectionOverlay:Hide() end -- workaround for scrollchild issue where layers fall out of sync: in this case, it's by 1 vertical pixel --block.highlight:SetPoint('TOPLEFT', block, 'TOPLEFT', 0, 1) --block.lowlight:SetPoint('BOTTOMLEFT', block, 'BOTTOMLEFT', 0, 1) tagPoint, tagAnchor, tagRelative = T.AddTag(block, 'frequencyTag', tagPoint, tagAnchor, tagRelative) tagPoint, tagAnchor, tagRelative = T.AddTag(block, 'typeTag', tagPoint, tagAnchor, tagRelative) tagPoint, tagAnchor, tagRelative = T.AddTag(block, 'completionTag', tagPoint, tagAnchor, tagRelative) return block end ---------- --- Top level methods local tick = 0 function T:Update (reason, ...) tick = tick + 1 local print = tprint reason = reason or OBJECTIVE_TRACKER_UPDATE_REASON local updateWrapper = 0 local hasStuff local insertingStuff print(format('%d |cFFFF%04X Update()', tick, lshift(reason, 4)), reason, ...) currentPosition = 0 anchorPoint = 'TOP' anchorFrame = Scroll local wrapperHeight = 0 for id, handler in pairs(T.orderedHandlers) do local frame = handler.frame print(format('|cFF00FFFF%s and(%04X vs %04x+%04x) = %04X|r', handler.name, reason, handler.updateReasonModule, handler.updateReasonEvents, band(reason, handler.updateReasonModule + handler.updateReasonEvents))) if band(reason, handler.updateReasonModule + handler.updateReasonEvents) > 0 then handler:Update(reason, ...) print(' |cFF00FF00'..id..'|r', handler.displayName, 'count:', handler.numWatched) insertingStuff = true else print(' |cFFFF0088'..id..'|r', 'no reason to update') end if handler.numWatched >= 1 then hasStuff = true currentPosition = currentPosition + 1 frame:SetParent(Scroll) frame:SetPoint('TOP', anchorFrame, anchorPoint, 0, 0) print(' |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint) anchorFrame = handler.frame anchorPoint = 'BOTTOM' print('current frame height:', frame.height) wrapperHeight = wrapperHeight + frame.height print('|cFFFF0088total height:', wrapperHeight) else handler.frame:Hide() end end if hasStuff or insertingStuff then print('updating height to', wrapperHeight) Wrapper:SetHeight(wrapperHeight) Scroller:SetHeight(wrapperHeight) Scroll:SetHeight(wrapperHeight) Scroller:SetVerticalScroll(B.Conf.ObjectiveScroll or 0) print('|cFFFF8800Wrapper:', Wrapper:GetSize()) for i = 1, Wrapper:GetNumPoints() do print(' ', Wrapper:GetPoint(i)) end print(' |cFF00FFFFScroller:', Scroller:GetSize()) for i = 1, Scroller:GetNumPoints() do print(' ', Scroller:GetPoint(i)) end print(' |cFF00FFFFScroll:', Scroll:GetSize()) for i = 1, Scroll:GetNumPoints() do print(' ', Scroll:GetPoint(i)) end Wrapper:Show() Scroller:Show() Scroll:Show() end Quest.GetClosest() --T.UpdateActionButtons(reason) end --- Queue any active item buttons for update for that frame local iprint = B.print('ItemButton') T.UpdateActionButtons = function(updateReason) local print = iprint Scroller.snap_upper = 0 Scroller.snap_lower = 0 local print = B.print('ItemButton') if updateReason then print = B.print('IB_'..updateReason) end local previousItem for questID, itemButton in pairs(Quest.itemButtons) do local info= T.Quest.Info[questID] print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName()) local block = T.Quest.QuestBlock[questID] if block then -- Dispatch the probe if IsQuestWatched(info.questLogIndex) then itemButton.previousItem = previousItem print(' |cFFFFFF00probing', block:GetName()) block:SetScript('OnUpdate', function() if block:GetBottom() and not InCombatLockdown() then print(' '..block:GetName()..' |cFF00FF00probe hit!') T.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope block:SetScript('OnUpdate', nil) end end) previousItem = itemButton else print('hidden block or unwatched quest') itemButton.previousItem = nil itemButton:Hide() end elseif itemButton:IsVisible() then print(' |cFFFF0088hiding unwatched quest button', itemButton:GetName()) itemButton.previousItem = nil itemButton:Hide() else print(' |cFFBBBBBBignoring hidden log quest button', itemButton:GetName()) end end end T.UpdateBlockAction = function (block, itemButton) local print = iprint 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 local unitLevel = UnitLevel('player')