Nenue@1: --- ${PACKAGE_NAME} Nenue@1: -- @file-author@ Nenue@1: -- @project-revision@ @project-hash@ Nenue@1: -- @file-revision@ @file-hash@ Nenue@1: -- Created: 3/30/2016 12:49 AM Nenue@1: local B = select(2,...).frame Nenue@10: local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') Nenue@14: local ipairs, max, min, unpack, floor, pairs, tostring, type, band = ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band Nenue@2: local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion Nenue@2: local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent Nenue@21: local Default, AutoQuest, Quest, Bonus, Cheevs = mod.DefaultHandler, mod.AutoQuest, mod.Quest, mod.Bonus, mod.Cheevs Nenue@1: local CreateFrame = CreateFrame Nenue@21: local print = B.print('Tracker') Nenue@13: local unitLevel = 1 Nenue@19: local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_REASON Nenue@21: local debug = false Nenue@1: -------------------------------------------------------------------- Nenue@1: --- Global frame layout Nenue@1: -------------------------------------------------------------------- Nenue@1: Nenue@1: --- Upvalues Nenue@2: local Wrapper = VeneerObjectiveWrapper Nenue@1: local Scroller = Wrapper.scrollArea Nenue@2: local Scroll = VeneerObjectiveScroll Nenue@1: local orderedHandlers = mod.orderedHandlers Nenue@1: local orderedNames = mod.orderedNames Nenue@1: Nenue@1: --- Temp values set during updates Nenue@1: local wrapperWidth, wrapperHeight Nenue@1: local scrollWidth, scrollHeight Nenue@1: local previousBlock Nenue@1: local currentBlock Nenue@10: --- todo: source these from config Nenue@6: local itemButtonSize, itemButtonSpacing = 36, 1 Nenue@1: local titleFont, textFont = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]] Nenue@21: local titleSize, textSize = 16, 16 Nenue@21: local titlebg, textbg = {'HORIZONTAL', 1, 0, .7, .25, 1, 0, .7, .125}, {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0} Nenue@1: local titleOutline, textOutline = "OUTLINE", "OUTLINE" Nenue@21: local titleSpacing, textSpacing = 3, 3 Nenue@21: local titleIndent, textIndent = 2, 5 Nenue@21: local blockSpacing = 1 Nenue@12: local wrapperMaxWidth, wrapperMaxHeight = 270, 490 -- these are the hard bounds, actual *Height variables are changed Nenue@2: local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE' Nenue@1: local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24 Nenue@2: local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2 Nenue@1: local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0} Nenue@21: local oprint = B.print('Objectives') Nenue@21: local bprint = B.print('Block') Nenue@21: local tprint = B.print('Tracker') Nenue@21: local lprint = B.print('Line') Nenue@1: Nenue@19: local band = bit.band Nenue@19: local currentPosition, anchorFrame, anchorPoint Nenue@3: Nenue@21: Default.GetLine = function(handler, blockIndex, lineIndex) Nenue@21: local print = lprint Nenue@21: if not handler.lines[blockIndex] then Nenue@21: handler.lines[blockIndex] = {} Nenue@21: end Nenue@21: local lines = handler.lines[blockIndex] Nenue@21: if not lines[lineIndex] then Nenue@21: print(' |cFF00FF88created line #'..lineIndex..' from for '..handler.name..' block #'..blockIndex) Nenue@21: lines[lineIndex] = CreateFrame('Frame', 'Vn'..handler.name .. blockIndex..'ObjectiveLine'..lineIndex, handler:GetBlock(blockIndex), 'VeneerTrackerObjective') Nenue@21: local line = lines[lineIndex] Nenue@21: line.index = lineIndex Nenue@21: line.height = 0 Nenue@21: line.status:SetSpacing(textSpacing) Nenue@21: line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0) Nenue@21: B.SetConfigLayers(line) Nenue@2: Nenue@21: if lines[lineIndex+1] then Nenue@21: lines[lineIndex+1]:ClearAllPoints() Nenue@19: end Nenue@19: Nenue@21: if debug then Nenue@21: for _, region in ipairs(lines[lineIndex].debug) do Nenue@21: region:Show() Nenue@21: end Nenue@19: end Nenue@19: Nenue@13: end Nenue@21: return lines[lineIndex] Nenue@2: end Nenue@2: Nenue@21: Default.GetBlock = function(handler, blockIndex) Nenue@21: local print = bprint Nenue@19: local block = handler.usedBlocks[blockIndex] Nenue@21: Nenue@19: if not handler.usedBlocks[blockIndex] then Nenue@19: if #handler.freeBlocks >= 1 then Nenue@19: block = handler.freeBlocks[#handler.freeBlocks] Nenue@19: handler.freeBlocks[#handler.freeBlocks] = nil Nenue@19: else Nenue@19: block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, Scroll, 'VeneerTrackerBlock') Nenue@21: block.GetLine = function(block, lineIndex, data) return handler:GetLine(blockIndex, lineIndex, data) end Nenue@21: block.UpdateLine = function(block, lineIndex, data) return handler:UpdateLine(block, lineIndex, data) end Nenue@21: block.UpdateObjectives = function(block) return handler:UpdateObjectives(block) end Nenue@21: block.SetTag = function(block, ...) return handler.SetTag(block, ...) end Nenue@21: Nenue@21: local c = mod.Conf.Wrapper Nenue@21: block.blockIndex = blockIndex Nenue@19: block.SetStyle = mod.SetBlockStyle Nenue@21: block:SetWidth(c.Width) Nenue@21: Nenue@21: block.title:SetSpacing(c.TitleSpacing) Nenue@21: block.title:SetPoint('TOP', block, 'TOP', 0, -titleSpacing) Nenue@21: Nenue@21: block.titlebg:SetTexture(1,1,1,1) Nenue@21: block.titlebg:SetGradientAlpha(unpack(titlebg)) Nenue@21: block.titlebg:SetPoint('TOP', block, 'TOP', 0, 0) Nenue@21: block.titlebg:SetPoint('BOTTOM', block.title, 'BOTTOM', 0, -titleSpacing) Nenue@21: Nenue@21: block.status:SetSpacing(c.TextSpacing) Nenue@21: block.status:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, -textSpacing) Nenue@21: block.status:SetPoint('LEFT', block.titlebg, 'LEFT', textIndent, 0) Nenue@21: Nenue@21: block.statusbg:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, 0) Nenue@21: block.statusbg:SetPoint('BOTTOM', block, 'BOTTOM', 0, 0) Nenue@21: block.statusbg:SetTexture(1,1,1,1) Nenue@21: block.statusbg:SetGradientAlpha(unpack(textbg)) Nenue@21: Nenue@21: block.SelectionOverlay:SetPoint('TOPLEFT') Nenue@21: block.SelectionOverlay:SetPoint('BOTTOMRIGHT') Nenue@21: Nenue@21: Nenue@21: Nenue@21: --- methods for event handlers Nenue@21: Nenue@19: block.Select = handler.Select Nenue@19: block.Open = handler.Open Nenue@19: block.Remove = handler.Remove Nenue@19: block.Link = handler.Link Nenue@19: block:SetScript('OnMouseUp', handler.OnMouseUp) Nenue@19: block:SetScript('OnMouseDown', handler.OnMouseDown) Nenue@19: block.attachmentHeight = 0 Nenue@19: block:ClearAllPoints() Nenue@21: Nenue@21: B.SetConfigLayers(block) Nenue@21: Nenue@21: if debug then Nenue@21: for _, region in ipairs(block.debug) do Nenue@21: region:Show() Nenue@21: end Nenue@21: end Nenue@19: end Nenue@19: handler.usedBlocks[blockIndex] = block Nenue@2: end Nenue@19: return handler.usedBlocks[blockIndex] Nenue@2: end Nenue@2: Nenue@21: Default.SetTag = function (block, tagName, tagPoint, tagAnchor, tagRelative) Nenue@21: local print = bprint Nenue@21: local tag = block[tagName] Nenue@21: if block.info[tagName] and tag then Nenue@21: tag:SetTexCoord(unpack(block.info[tagName])) Nenue@21: tag:Show() Nenue@21: tag:SetPoint(tagPoint, tagAnchor, tagRelative, 0, 0) Nenue@21: tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', tag, 'TOPLEFT' Nenue@21: else Nenue@21: block[tagName]:Hide() Nenue@21: end Nenue@21: return tagPoint, tagAnchor, tagRelative Nenue@21: end Nenue@14: Nenue@21: Default.UpdateObjectives = function(handler, block) Nenue@21: local print = lprint Nenue@21: local info = block.info Nenue@1: Nenue@21: print(' |cFF00FF00doing objectives', block:GetName()) Nenue@21: Nenue@21: -- set the starting positions Nenue@21: block.endPoint = block.status Nenue@21: local completionScore, completionMax = 0, 0 Nenue@21: local displayObjectiveHeader = false Nenue@21: Nenue@21: if info.description and #info.description >= 1 then Nenue@21: print(' |cFF00FFFF header line:|r', info.description) Nenue@21: block.status:SetText(info.description) Nenue@21: displayObjectiveHeader = true Nenue@21: end Nenue@21: Nenue@21: local attachmentHeight = 0 Nenue@21: if info.objectives then Nenue@21: for i, data in ipairs(info.objectives) do Nenue@21: print(' |cFF88FF00#', i, data.type, data.text) Nenue@21: displayObjectiveHeader = true Nenue@21: local line = block:GetLine(i) Nenue@21: line.height = 0 Nenue@21: block:UpdateLine(line, data) Nenue@21: Nenue@21: line:ClearAllPoints() Nenue@21: if line.displayText then Nenue@21: line.status:SetText(line.displayText) Nenue@21: line.height = floor(line.status:GetStringHeight()+.5) Nenue@1: end Nenue@1: Nenue@21: if line.widget then Nenue@21: line.widget:SetPoint('TOP', line, 'TOP', 0, 0) Nenue@21: line.widget:Show() Nenue@1: end Nenue@14: Nenue@19: Nenue@21: line:Show() Nenue@19: Nenue@21: line:SetPoint('LEFT', block, 'LEFT', 0, 0) Nenue@21: line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, 0) Nenue@21: line:SetPoint('RIGHT', block, 'RIGHT', 0, 0) Nenue@21: line:SetHeight(line.height) Nenue@19: Nenue@21: attachmentHeight = attachmentHeight + line.height Nenue@21: print(' sz', line:GetSize()) Nenue@21: print(' pt', line:GetPoint(1)) Nenue@21: print(' |cFF44BBFF#', i, 'anchoring line, size:', line.height, 'current endpoint:', line.statusbg) Nenue@1: Nenue@21: block.endPoint = line Nenue@14: end Nenue@14: Nenue@21: if attachmentHeight > 0 then Nenue@21: block.attachmentHeight = attachmentHeight + textSpacing * 2 Nenue@21: print(' |cFF00FF00attachment:', block.attachmentHeight) Nenue@14: end Nenue@14: Nenue@21: local lines = handler.lines[block.blockIndex] Nenue@21: local numObjectives = info.numObjectives Nenue@21: local numLines = #lines Nenue@21: if numLines > numObjectives then Nenue@21: print(' has extra lines, need to clean up;', numLines, numObjectives) Nenue@21: for i = numObjectives+1, numLines do Nenue@21: print(' hide', i, lines[i]:GetName()) Nenue@21: lines[i]:Hide() Nenue@21: end Nenue@14: end Nenue@14: end Nenue@14: Nenue@19: Nenue@19: Nenue@21: print(' displayHeader:', displayObjectiveHeader) Nenue@21: Nenue@21: if debug then Nenue@21: for i, region in ipairs(block.debug) do Nenue@21: for j = 1, region:GetNumPoints() do Nenue@21: local _, target = region:GetPoint(j) Nenue@21: if target:IsVisible() then Nenue@21: region:Hide() Nenue@21: else Nenue@21: region:Show() Nenue@21: end Nenue@21: end Nenue@21: end Nenue@21: end Nenue@21: Nenue@14: block.completionScore = completionScore / completionMax Nenue@21: end Nenue@14: Nenue@21: Bonus.UpdateObjectives = function(handler, block) Nenue@21: Default.UpdateObjectives(handler, block) Nenue@21: end Nenue@21: Nenue@21: local CLICK_TO_COMPLETE = 'Click to Complete' Nenue@21: local CLICK_TO_ACCEPT = 'Click to Accept' Nenue@21: Nenue@21: AutoQuest.UpdateObjectives = function(handler, block) Nenue@21: local print = lprint Nenue@21: if block.info.type == 'OFFER' then Nenue@21: block.status:SetText(CLICK_TO_ACCEPT) Nenue@18: end Nenue@18: Nenue@14: end Nenue@14: Nenue@21: Quest.UpdateObjectives = function(handler, block) Nenue@21: local print = lprint Nenue@21: print('|cFF00FFFFUpdateObjectives()') Nenue@21: Default.UpdateObjectives(handler, block) Nenue@21: local info = block.info Nenue@21: local completionText Nenue@21: if info.isAutoComplete then Nenue@21: local questID, popupType = GetAutoQuestPopUp(info.questLogIndex) Nenue@21: if popupType == 'COMPLETE' then Nenue@21: completionText = CLICK_TO_COMPLETE Nenue@21: end Nenue@21: end Nenue@21: if not completionText then Nenue@21: completionText = GetQuestLogCompletionText(info.questLogIndex) Nenue@21: end Nenue@21: Nenue@21: block.status:SetText() Nenue@21: end Nenue@21: Nenue@21: --- Module-specific display variables Nenue@14: -- * height - height of whatever display widget is involved in conveying the task Nenue@14: -- * money - boolean that determines listening for money events or not Nenue@14: -- * progress - number ranging 0 to 2 indicating none/partial/full completion respectively Nenue@14: Nenue@21: Quest.UpdateLine = function(handler, block, line, data) Nenue@21: local print = lprint Nenue@21: print(' |cFFFF0088', block:GetName(), line.index, data.type) Nenue@21: local objectiveType = data.type Nenue@21: local r, g, b, a = 0, 1, 1, 1 Nenue@21: line.progress = 0 Nenue@21: if data.finished then Nenue@21: line.progress = 2 Nenue@21: r, g, b, a = 0, 1, 0, 1 Nenue@21: elseif objectiveType == 'monster' then Nenue@21: r, g, b, a = 1, 0, .45, 1 Nenue@21: elseif objectiveType == 'item' then Nenue@21: r, g, b, a = .8, .8, .8, 1 Nenue@21: elseif objectiveType == 'object' then Nenue@21: r, g, b, a = 1, 1, 1, 1 Nenue@21: elseif objectiveType == 'player' then Nenue@21: r, g, b, a = 0, 0.8, 1, 1 Nenue@21: end Nenue@21: Nenue@21: line.displayColor = {r, g, b, a} Nenue@21: line.status:SetTextColor(r, g, b, a) Nenue@21: line.displayText = data.text Nenue@21: return line Nenue@21: end Nenue@21: Nenue@21: Bonus.UpdateLine = function(handler, block, line, data) Nenue@21: local info = block.info Nenue@21: local print = lprint Nenue@21: Nenue@21: Nenue@21: line.displayColor = 'FFFFFF' Nenue@21: if data.text and not info.title then Nenue@21: print('using first text item as title') Nenue@21: info.title = data.text Nenue@21: else Nenue@21: line.displayText = data.text Nenue@21: end Nenue@21: Nenue@21: line.progress = 0 Nenue@21: print(' ', data.objectiveIndex,'|cFFFF0088-|r', data.objectiveType, data.text) Nenue@21: if data.objectiveType == 'progressbar' then Nenue@21: line.widgetType = 'ProgressBar' Nenue@21: print(' |cFFFF44DDpercent='..tostring(GetQuestProgressBarPercent(info.questID))) Nenue@21: data.value = GetQuestProgressBarPercent(info.questID) or 0 Nenue@21: data.maxValue = 100 Nenue@21: if data.value >= data.maxValue then Nenue@21: line.progress = 1 Nenue@21: elseif data.value > 0 then Nenue@21: line.progress = 2 Nenue@21: end Nenue@21: line.format = PERCENTAGE_STRING Nenue@21: local widget = mod.SetWidget(line, data, 'ProgressBar', info.questID..'-'..data.objectiveIndex) Nenue@21: print(' |cFFFF0022** text:|r', data.text, '|cFFFF0022value:|r', data.value, '|cFFFF0022max:|r', data.maxValue) Nenue@21: widget:SetPoint('CENTER', line, 'CENTER', 0, 0) Nenue@21: Nenue@21: line.widget = widget Nenue@21: line.height = widget.height Nenue@21: else Nenue@21: line.displayText = data.text Nenue@21: line.widget = nil Nenue@21: end Nenue@21: return line Nenue@21: end Nenue@21: Nenue@21: Cheevs.UpdateLine = function(handler, block, line, data) Nenue@21: local print = B.print('CheevsLine') Nenue@21: line.progress = 0 Nenue@21: print(' ', data.objectiveIndex,'|cFF0088FF-|r', data.objectiveType, data.text) Nenue@21: if data.flags then Nenue@21: if band(data.flags, 0x00000001) > 0 then Nenue@21: line.format = "%d/%d" Nenue@21: line.widget = mod.SetWidget(line, data, 'ProgressBar', data.criteriaID) Nenue@21: line.height = line.widget.height Nenue@21: elseif band(data.flags, 0x00000002) then Nenue@21: line.widget = nil Nenue@21: else Nenue@21: line.widget = nil Nenue@21: line.displayColor = 'FFFFFF' Nenue@21: line.displayText = line.text Nenue@21: Nenue@21: end Nenue@21: else Nenue@21: Nenue@21: line.displayText = data.text Nenue@21: end Nenue@21: print('line.type =', data.type) Nenue@21: print(' ** qtyStr:', data.quantityString, 'qty:', data.quantity, 'assetID:', data.assetID) Nenue@21: end Nenue@21: Default.UpdateLine = function(block, line) Nenue@14: if line.finished then Nenue@14: line.progress = 2 Nenue@14: elseif line.quantity > 0 then Nenue@14: line.progress = 1 Nenue@14: else Nenue@14: line.progress = 0 Nenue@14: end Nenue@21: return line Nenue@14: end Nenue@14: Nenue@14: Nenue@1: mod.Quest.numButtons = 0 Nenue@1: local usedButtons = mod.Quest.itemButtons Nenue@1: local freeButtons = mod.Quest.freeButtons Nenue@19: --[=[ Nenue@16: mod.UpdateWrapper = function(reason) Nenue@16: print('|cFF00FFFFUpdateWrapper:|r', reason) Nenue@13: unitLevel = UnitLevel('player') Nenue@14: wrapperWidth = mod.Conf.Wrapper.WrapperWidth Nenue@14: scrollWidth = mod.Conf.Wrapper.WrapperWidth Nenue@1: local wrapperBlocks = 0 Nenue@1: -- Update scroll child vertical size Nenue@1: scrollHeight = 0 Nenue@1: for i, handler in ipairs(orderedHandlers) do Nenue@1: mod.UpdateTracker(handler) Nenue@19: local frame = handler.frame Nenue@1: if handler.actualBlocks >= 1 then Nenue@19: frame:SetParent(Scroll) Nenue@19: frame:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight) Nenue@19: frame:SetSize(wrapperWidth, frame.height) Nenue@19: print('|cFF00FFFF'..frame:GetName()..'|r h:|cFF00FF00', frame.height, '|r y:|cFF00FF00', -scrollHeight) Nenue@19: scrollHeight = scrollHeight + frame.height Nenue@19: frame:Show() Nenue@14: else Nenue@19: frame:Hide() Nenue@1: end Nenue@1: wrapperBlocks = wrapperBlocks + handler.actualBlocks Nenue@1: end Nenue@1: print('final scrollHeight:', scrollHeight) Nenue@1: Nenue@1: Nenue@1: Nenue@1: -- Update frame dimensions Nenue@1: if scrollHeight > wrapperMaxHeight then Nenue@1: print(' is larger than', wrapperMaxHeight) Nenue@1: wrapperHeight = wrapperMaxHeight Nenue@1: else Nenue@1: wrapperHeight = scrollHeight Nenue@9: B.Conf.ObjectiveScroll = 0 Nenue@1: end Nenue@1: scrollWidth = floor(scrollWidth+.5) Nenue@1: scrollHeight = floor(scrollHeight+.5) Nenue@1: wrapperWidth = floor(wrapperWidth+.5) Nenue@1: wrapperHeight = floor(wrapperHeight+.5) Nenue@1: headerHeight = floor(headerHeight+.5) Nenue@1: Nenue@1: if wrapperBlocks >= 1 then Nenue@10: for i, region in ipairs(Wrapper.headerComplex) do Nenue@2: region:Show() Nenue@2: end Nenue@1: else Nenue@10: for i, region in ipairs(Wrapper.headerComplex) do Nenue@2: region:Hide() Nenue@2: end Nenue@1: return Nenue@1: end Nenue@14: --[[wrapperHeight = scrollHeight Nenue@1: Nenue@14: print('|cFFFFFF00params:|r scroller:', scrollWidth .. ',' .. scrollHeight, 'scroll:', scrollWidth .. ',' .. scrollHeight, Nenue@14: 'wrapper:', wrapperWidth .. ',' .. wrapperHeight, Nenue@14: 'header:', headerHeight)]] Nenue@1: Nenue@14: --Scroller:SetSize(wrapperWidth, wrapperHeight) Nenue@13: Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, 0) Nenue@1: Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT') Nenue@1: Nenue@7: Nenue@1: Scroll:SetSize(scrollWidth, scrollHeight) Nenue@7: Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0) Nenue@1: Scroll:SetPoint('RIGHT', Scroller, 'RIGHT') Nenue@1: Nenue@1: --Scroller:UpdateScrollChildRect() Nenue@13: Wrapper:SetSize(wrapperWidth, wrapperHeight) Nenue@1: Nenue@14: --[[ update action buttons Nenue@6: print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(), Nenue@6: '|cFF00FF00'..Scroller:GetName()..'|r:', Scroller:GetWidth(), Scroller:GetHeight(), Nenue@6: '|cFF00FF00'..Wrapper:GetName()..'|r:', Wrapper:GetWidth(), Wrapper:GetHeight(), Nenue@6: '|cFF0088FFvScrollRange|r:', floor(Scroller:GetVerticalScrollRange()+.5) Nenue@6: ) Nenue@18: --]] Nenue@14: mod.UpdateActionButtons() Nenue@1: Nenue@1: end Nenue@19: --]=] Nenue@1: Nenue@21: Nenue@21: Default.Update = function (self, reason, ...) Nenue@21: local print = tprint Nenue@21: local tracker = self.frame Nenue@21: print('|cFFFF4400'..tracker:GetName().. '|r:Update()', reason, ...) Nenue@21: local blockIndex = 0 Nenue@21: local trackerHeight = floor(tracker.titlebg:GetHeight()+.5) Nenue@21: Nenue@21: self.currentAnchor = tracker.titlebg Nenue@21: local numWatched = self:GetNumWatched() Nenue@21: local numBlocks = self.numBlocks Nenue@21: local actualBlocks = 0 Nenue@21: for watchIndex = 1, 25 do Nenue@21: blockIndex = blockIndex + 1 Nenue@21: if watchIndex <= numWatched then Nenue@21: local info = self:GetInfo(watchIndex) Nenue@21: if info then Nenue@21: local currentBlock = self:UpdateBlock(blockIndex, info) Nenue@21: currentBlock:SetPoint('TOPLEFT', self.currentAnchor, 'BOTTOMLEFT', 0, -1) Nenue@21: currentBlock:SetPoint('RIGHT', tracker,'RIGHT', 0, 0) Nenue@21: self.currentAnchor = currentBlock Nenue@21: print(' |cFFFFFF00'..watchIndex..'|r', '|cFF00FF00'..currentBlock:GetName()..'|r', currentBlock.height) Nenue@21: trackerHeight = trackerHeight + currentBlock.height Nenue@21: numBlocks = max(numBlocks, watchIndex) Nenue@21: actualBlocks = actualBlocks + 1 Nenue@21: else Nenue@21: print(' |cFFFF0000bad GetInfo data for #'..watchIndex) Nenue@21: end Nenue@21: Nenue@21: elseif watchIndex <= numBlocks then Nenue@21: local used = self.usedBlocks Nenue@21: local free = self.freeBlocks Nenue@21: print('clean up dead quest block') Nenue@21: if used[blockIndex] then Nenue@21: used[blockIndex]:Hide() Nenue@21: used[blockIndex]:ClearAllPoints() Nenue@21: free[#free+1]= used[blockIndex] Nenue@21: used[blockIndex] = nil Nenue@21: end Nenue@21: else Nenue@21: print(' |cFFFF9900END|r @', blockIndex) Nenue@21: break -- done with quest stuff Nenue@21: end Nenue@21: end Nenue@21: self.numWatched = numWatched Nenue@21: self.numBlocks = numBlocks Nenue@21: self.actualBlocks = actualBlocks Nenue@21: Nenue@21: tracker.previousHeight = tracker.height Nenue@21: if numBlocks >= 1 then Nenue@21: previousBlock = nil Nenue@21: Nenue@21: tracker.height = trackerHeight + tracker.titlebg:GetHeight() Nenue@21: tracker:SetHeight(tracker.height) Nenue@21: tracker:Show() Nenue@21: Nenue@21: Nenue@21: else Nenue@21: tracker.height = 0 Nenue@21: tracker:Hide() Nenue@21: end Nenue@21: Nenue@21: return tracker.numWatched, tracker.numAll Nenue@21: end Nenue@21: Nenue@21: --- Updates the selected block frame to display the given info batch Nenue@21: -- If `previousBlock` is set, it will attempt to anchor to that Nenue@21: -- @param blockNum the ordered block to be updated, not a watchIndex value Nenue@21: -- @param info the reference returned by the GetXInfo functions Nenue@21: -- REMEMBER: t.info and questData[questID] are the same table Nenue@21: Default.UpdateBlock = function (self, blockIndex, info) Nenue@21: local print = bprint Nenue@21: print(' Read list item |cFF00FFFF'..blockIndex..'|r') Nenue@21: if not blockIndex or not info then Nenue@21: return Nenue@21: end Nenue@21: local frame = self.frame Nenue@21: local block = self:GetBlock(blockIndex) Nenue@21: block.handler = self Nenue@21: block.info = info Nenue@21: block.mainStyle = info.mainStyle or 'Normal' Nenue@21: block.subStyle = info.subStyle Nenue@21: Nenue@21: info.blockIndex = blockIndex Nenue@21: if info.questID then self.QuestBlock[info.questID] = block end Nenue@21: if info.questLogIndex then self.LogBlock[info.questLogIndex] = block end Nenue@21: if info.watchIndex then self.WatchBlock[info.watchIndex] = block end Nenue@21: self.BlockInfo[blockIndex] = info Nenue@21: Nenue@21: block.endPoint = block.titlebg Nenue@21: block.attachmentHeight = 0 Nenue@21: block:UpdateObjectives() Nenue@21: Nenue@21: block.title:SetText(info.title) Nenue@21: local titleHeight = floor(block.title:GetHeight()+.5) Nenue@21: local statusHeight = floor(block.status:GetHeight()+.5) Nenue@21: local attachmentHeight =floor(block.attachmentHeight + .5) Nenue@21: local titlebgHeight = titleHeight + titleSpacing*2 Nenue@21: local statusbgHeight = statusHeight + textSpacing*2 Nenue@21: Nenue@21: block.titlebg:SetHeight(titlebgHeight) Nenue@21: Nenue@21: Nenue@21: print(' |cFF0088FFanchor to', self.currentAnchor:GetName()) Nenue@21: Nenue@21: print(' |cFF00FF00total sizes:') Nenue@21: print(' attachment:', attachmentHeight) Nenue@21: print(' title:', titlebgHeight, '('.. titleHeight..')') Nenue@21: --block.titlebg:SetHeight(block.title:GetHeight() + mod.Conf.Wrapper.TitleSpacing) Nenue@21: block.height = titlebgHeight + attachmentHeight Nenue@21: if statusHeight > 1 then Nenue@21: block.height = block.height + statusbgHeight Nenue@21: print(' status:', statusbgHeight, '('.. statusHeight..')') Nenue@21: else Nenue@21: print(' |cFFFF0088 skipped') Nenue@21: end Nenue@21: block:SetHeight(block.height) Nenue@21: Nenue@21: print(' |cFFFFFF00height|r:', block.height) Nenue@21: print(' |cFF00FFFF)|r -> ', block, block:GetHeight()) Nenue@21: Nenue@21: block:Show() Nenue@21: Nenue@21: Nenue@21: if info.specialItem and not info.itemButton then Nenue@21: print(' - |cFF00FFFFgenerating item button for info set') Nenue@21: info.itemButton = mod.SetItemButton(block, info) Nenue@21: else Nenue@21: --info.itemButton = nil Nenue@21: end Nenue@21: Nenue@21: local tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', block, 'TOPRIGHT' Nenue@21: if info.rewardInfo then Nenue@21: print('has immediate reward') Nenue@21: if info.rewardInfo[1].type == 'currency' or info.rewardInfo[1].type == 'item' then Nenue@21: block.icon:Show() Nenue@21: block.iconLabel:SetText(info.rewardInfo[1].count) Nenue@21: block.icon:SetSize(block.height, block.height) Nenue@21: block.icon:SetPoint(tagPoint, tagAnchor, tagRelative, 0, 0) Nenue@21: tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', block.icon, 'TOPLEFT' Nenue@21: block.icon:SetTexture(info.rewardInfo[1].texture) Nenue@21: end Nenue@21: else Nenue@21: block.icon:Hide() Nenue@21: end Nenue@21: Nenue@21: if info.selected then Nenue@21: block.SelectionOverlay:Show() Nenue@21: else Nenue@21: block.SelectionOverlay:Hide() Nenue@21: end Nenue@21: Nenue@21: -- workaround for scrollchild issue where layers fall out of sync: in this case, it's by 1 vertical pixel Nenue@21: block.highlight:SetPoint('TOPLEFT', block, 'TOPLEFT', 0, 1) Nenue@21: block.lowlight:SetPoint('BOTTOMLEFT', block, 'BOTTOMLEFT', 0, 1) Nenue@21: Nenue@21: tagPoint, tagAnchor, tagRelative = block:SetTag('frequencyTag', tagPoint, tagAnchor, tagRelative) Nenue@21: tagPoint, tagAnchor, tagRelative = block:SetTag('typeTag', tagPoint, tagAnchor, tagRelative) Nenue@21: tagPoint, tagAnchor, tagRelative = block:SetTag('completionTag', tagPoint, tagAnchor, tagRelative) Nenue@21: Nenue@21: return block Nenue@21: end Nenue@21: ---------- Nenue@21: --- Top level methods Nenue@21: Nenue@21: local tick = 0 Nenue@21: function mod:Update (reason, ...) Nenue@21: tick = tick + 1 Nenue@21: local print = tprint Nenue@21: reason = reason or OBJECTIVE_TRACKER_UPDATE_REASON Nenue@21: local updateWrapper = 0 Nenue@21: local hasStuff Nenue@21: local insertingStuff Nenue@21: Nenue@21: print(format('%d |cFFFF%04X Update()', tick, bit.lshift(reason, 4)), reason, ...) Nenue@21: currentPosition = 0 Nenue@21: anchorPoint = 'TOP' Nenue@21: anchorFrame = Scroll Nenue@21: Nenue@21: local wrapperHeight = 0 Nenue@21: for id, handler in pairs(mod.orderedHandlers) do Nenue@21: local frame = handler.frame Nenue@21: Nenue@21: print(format(' |cFF00FFFFbitcheck (%04X vs %04x+%04x):|r', reason, handler.updateReasonModule, handler.updateReasonEvents), band(reason, handler.updateReasonModule + handler.updateReasonEvents)) Nenue@21: if band(reason, handler.updateReasonModule + handler.updateReasonEvents) > 0 then Nenue@21: handler:Update(reason, ...) Nenue@21: print(' |cFF00FF00'..id..'|r', handler.displayName, 'count:', handler.numWatched) Nenue@21: insertingStuff = true Nenue@21: else Nenue@21: print(' |cFFFF0088'..id..'|r', 'no reason to update') Nenue@21: end Nenue@21: Nenue@21: if handler.numWatched >= 1 then Nenue@21: hasStuff = true Nenue@21: currentPosition = currentPosition + 1 Nenue@21: frame:SetParent(Scroll) Nenue@21: frame:SetPoint('TOP', anchorFrame, anchorPoint, 0, 0) Nenue@21: print(' |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint) Nenue@21: anchorFrame = handler.frame Nenue@21: anchorPoint = 'BOTTOM' Nenue@21: Nenue@21: print('current frame height:', frame.height) Nenue@21: wrapperHeight = wrapperHeight + frame.height Nenue@21: print('|cFFFF0088total height:', wrapperHeight) Nenue@21: else Nenue@21: handler.frame:Hide() Nenue@21: end Nenue@21: end Nenue@21: Nenue@21: Nenue@21: if hasStuff or insertingStuff then Nenue@21: print('updating height to', wrapperHeight) Nenue@21: Wrapper:SetHeight(wrapperHeight) Nenue@21: Scroller:SetHeight(wrapperHeight) Nenue@21: Scroll:SetHeight(wrapperHeight) Nenue@21: Scroller:SetVerticalScroll(B.Conf.ObjectiveScroll or 0) Nenue@21: print('|cFFFF8800Wrapper:', Wrapper:GetSize()) Nenue@21: for i = 1, Wrapper:GetNumPoints() do Nenue@21: print(' ', Wrapper:GetPoint(i)) Nenue@21: end Nenue@21: print(' |cFF00FFFFScroller:', Scroller:GetSize()) Nenue@21: for i = 1, Scroller:GetNumPoints() do Nenue@21: print(' ', Scroller:GetPoint(i)) Nenue@21: end Nenue@21: print(' |cFF00FFFFScroll:', Scroll:GetSize()) Nenue@21: for i = 1, Scroll:GetNumPoints() do Nenue@21: print(' ', Scroll:GetPoint(i)) Nenue@21: end Nenue@21: Nenue@21: Wrapper:Show() Nenue@21: Scroller:Show() Nenue@21: Scroll:Show() Nenue@21: end Nenue@21: Nenue@21: end Nenue@21: Nenue@1: --- Queue any active item buttons for update for that frame Nenue@6: mod.UpdateActionButtons = function(updateReason) Nenue@6: Scroller.snap_upper = 0 Nenue@6: Scroller.snap_lower = 0 Nenue@6: local print = B.print('ItemButton') Nenue@6: if updateReason then Nenue@6: print = B.print('IB_'..updateReason) Nenue@6: end Nenue@6: Nenue@1: local previousItem Nenue@2: for questID, itemButton in pairs(usedButtons) do Nenue@6: local info= mod.Quest.Info[questID] Nenue@6: Nenue@5: print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName()) Nenue@5: local block = mod.Quest.QuestBlock[questID] Nenue@1: if block then Nenue@5: -- Dispatch the probe Nenue@6: if IsQuestWatched(info.questLogIndex) then Nenue@6: itemButton.previousItem = previousItem Nenue@5: print(' |cFFFFFF00probing', block:GetName()) Nenue@1: block:SetScript('OnUpdate', function() Nenue@5: if block:GetBottom() and not InCombatLockdown() then Nenue@5: print(' '..block:GetName()..' |cFF00FF00probe hit!') Nenue@6: mod.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope Nenue@5: block:SetScript('OnUpdate', nil) Nenue@5: end Nenue@5: end) Nenue@6: previousItem = itemButton Nenue@1: else Nenue@5: print('hidden block or unwatched quest') Nenue@6: itemButton.previousItem = nil Nenue@5: itemButton:Hide() Nenue@1: end Nenue@8: elseif itemButton:IsVisible() then Nenue@8: print(' |cFFFF0088hiding unwatched quest button', itemButton:GetName()) Nenue@6: itemButton.previousItem = nil Nenue@6: itemButton:Hide() Nenue@8: else Nenue@8: print(' |cFFBBBBBBignoring hidden log quest button', itemButton:GetName()) Nenue@1: end Nenue@1: end Nenue@1: end Nenue@1: Nenue@6: mod.UpdateBlockAction = function (block, itemButton) Nenue@5: print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()') Nenue@5: if itemButton.questID ~= block.info.questID then Nenue@5: print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID) Nenue@6: -- something happened between this and last frame, go back and set new probes Nenue@5: return mod.UpdateActionButtons() Nenue@2: end Nenue@2: Nenue@6: local previousItem = itemButton.previousItem Nenue@6: local upper_bound = Scroller:GetTop() + Scroller.snap_upper Nenue@6: local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize Nenue@6: local point, anchor, relative Nenue@6: Nenue@6: if block:GetBottom() < lower_bound then Nenue@6: print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5)) Nenue@1: if previousItem then Nenue@6: print('adjusting', previousItem:GetName()) Nenue@1: previousItem:ClearAllPoints() Nenue@6: previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing) Nenue@1: end Nenue@1: itemButton:ClearAllPoints() Nenue@6: itemButton.x = Wrapper:GetLeft() -4 Nenue@6: itemButton.y = Wrapper:GetBottom() Nenue@6: point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT' Nenue@6: Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing Nenue@6: Nenue@6: elseif block:GetTop() > upper_bound then Nenue@6: print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5)) Nenue@6: itemButton:ClearAllPoints() Nenue@6: if previousItem then Nenue@6: print('latch onto another piece') Nenue@6: point, anchor, relative ='TOP', previousItem, 'BOTTOM' Nenue@6: itemButton.x = 0 Nenue@6: itemButton.y = -itemButtonSpacing Nenue@6: else Nenue@6: print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop()) Nenue@6: point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' Nenue@6: itemButton.x = Scroller:GetLeft() -4 Nenue@6: itemButton.y = Scroller:GetTop() Nenue@6: end Nenue@1: itemButton:Show() Nenue@6: Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing) Nenue@1: else Nenue@6: print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5)) Nenue@1: itemButton:ClearAllPoints() Nenue@6: itemButton.x = block:GetLeft() - itemButtonSpacing Nenue@6: itemButton.y = block:GetTop() Nenue@6: point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' Nenue@1: end Nenue@6: Nenue@6: itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y) Nenue@6: itemButton:Show() Nenue@1: end Nenue@1: Nenue@1: mod.UpdateItemButtonCooldown = function(button) Nenue@1: Nenue@1: end Nenue@18: Nenue@18: local unitLevel = UnitLevel('player') Nenue@18: Nenue@18: