Nenue@28: --- ${PACKAGE_NAME} Nenue@28: -- @file-author@ Nenue@28: -- @project-revision@ @project-hash@ Nenue@28: -- @file-revision@ @file-hash@ Nenue@28: -- Created: 3/30/2016 12:49 AM Nenue@28: local B = select(2,...).frame Nenue@30: local Module = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') Nenue@28: local _G, ipairs, max, min, unpack, floor, pairs, tostring, type, band = _G, ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band Nenue@28: local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion Nenue@28: local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent Nenue@28: local GetAutoQuestPopUp, GetQuestLogCompletionText = GetAutoQuestPopUp, GetQuestLogCompletionText Nenue@28: local PERCENTAGE_STRING, GetQuestProgressBarPercent = PERCENTAGE_STRING, GetQuestProgressBarPercent Nenue@30: local Default, AutoQuest, Quest, Bonus, Cheevs = Module.DefaultHandler, Module.AutoQuest, Module.Quest, Module.Bonus, Module.Cheevs Nenue@28: local InCombatLockdown, format, lshift, CreateFrame = InCombatLockdown, format, bit.lshift, CreateFrame Nenue@29: local IsModifiedClick, ChatEdit_GetActiveWindow = IsModifiedClick, ChatEdit_GetActiveWindow Nenue@28: local print = B.print('Tracker') Nenue@28: local unitLevel = 1 Nenue@28: local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_REASON Nenue@28: local debug = false Nenue@28: Nenue@28: --- Upvalues Nenue@28: local Wrapper = _G.VeneerObjectiveWrapper Nenue@28: local Scroller = Wrapper.scrollArea Nenue@28: local Scroll = _G.VeneerObjectiveScroll Nenue@30: local orderedHandlers = Module.orderedHandlers Nenue@30: local orderedNames = Module.orderedNames Nenue@28: Nenue@28: --- Temp values set during updates Nenue@28: local wrapperWidth, wrapperHeight Nenue@28: local scrollWidth, scrollHeight Nenue@28: local previousBlock Nenue@28: local currentBlock Nenue@28: --- todo: source these from config Nenue@28: local itemButtonSize, itemButtonSpacing = 36, 1 Nenue@28: Nenue@30: local headerHeight, headerColor, headerSpacing = 16, {1,.75,0,1}, 2 Nenue@28: local headerbg = {'VERTICAL', 1, 1, 0.5, 0.5, 1, 1, 0.5, 0} Nenue@28: local headerFont, headerSize, headerOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 14, 'OUTLINE' Nenue@28: Nenue@31: local titlebg = {'HORIZONTAL', 1, 0, .7, 0, 1, 0, .7, .2} Nenue@31: local titlebg_daily = {'HORIZONTAL', 0, .7, 1, 0, 0, 1, .7, .2 } Nenue@31: local titlebg_account = {'HORIZONTAL', 0, .45, 1, 0, 0, .45, 1, .2} Nenue@28: local titleFont, titleSize, titleOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE' Nenue@28: Nenue@28: local textbg = {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 } Nenue@28: local textbg_daily = {'HORIZONTAL', 0, .7, 1, .1, 0, 1, .7, .075 } Nenue@28: local textbg_account = {'HORIZONTAL', 0, .45, 1, 0.4, 0, .41, 1, .085 } Nenue@28: local textFont, textSize, textOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE' Nenue@28: Nenue@28: Nenue@28: local selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225} Nenue@28: local titleSpacing, textSpacing, blockSpacing = 3, 3, 1 Nenue@28: local titleIndent, textIndent,selectionIndent = 2, 5, 50 Nenue@28: Nenue@30: local lineColors = { Nenue@31: normal = { Nenue@31: text = {.5,.75,1}, Nenue@31: }, Nenue@31: completed = { Nenue@31: text = {1,0,.1} Nenue@31: }, Nenue@31: failed = { Nenue@31: text = {1,0,0 } Nenue@31: }, Nenue@31: autocomplete = { Nenue@31: text = {0,1,0 } Nenue@31: }, Nenue@31: object = { Nenue@31: text = {0,1,1} Nenue@31: }, Nenue@31: monster = { Nenue@31: text = {1,1,0} Nenue@31: }, Nenue@31: item = { Nenue@31: text = {1,.25,.5} Nenue@31: } Nenue@30: } Nenue@30: Nenue@28: local wrapperMaxWidth, wrapperMaxHeight = 270, 490 -- these are the hard bounds, actual *Height variables are changed Nenue@28: local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE' Nenue@28: local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0 } Nenue@32: local rewardSize = 24 Nenue@28: local oprint = B.print('Objectives') Nenue@28: local bprint = B.print('Block') Nenue@28: local tprint = B.print('Tracker') Nenue@28: local lprint = B.print('Line') Nenue@28: Nenue@30: Default.AddBlock = function(self, block, blockIndex) Nenue@30: local blockIndex = blockIndex or (self.currentBlock + 1) Nenue@28: local print = bprint Nenue@28: local tracker = self.frame Nenue@28: local info = block.info Nenue@30: Nenue@30: block.index = blockIndex Nenue@30: block:SetPoint('TOPLEFT', self.frame, 'TOPLEFT', 0, block.offset) Nenue@29: block:SetPoint('RIGHT', tracker,'RIGHT', 0, 0) Nenue@30: self.currentBlock = blockIndex Nenue@29: self.currentAnchor = block Nenue@29: print(' |cFFFFFF00'..tracker.height..'|r', '|cFF00FF00'..block:GetName()..'|r', block.height, tracker.height) Nenue@29: tracker.height = tracker.height + block.height Nenue@30: self.numBlocks = max(self.numBlocks, blockIndex) Nenue@29: self.actualBlocks = self.actualBlocks + 1 Nenue@28: end Nenue@28: Nenue@28: --- Used as an iterator of sorts for cascaded tag icon placements (the daily/faction/account icons) Nenue@30: Default.AddTag = function (handler, block, tagInfo, tagPoint, tagAnchor, tagRelative) Nenue@28: local print = bprint Nenue@30: Nenue@30: for order, tagName in ipairs(block.info.tagInfo) do Nenue@30: local tag = block[tagName] Nenue@30: if block.tagCoords[tagName] and tag then Nenue@30: tag:SetTexCoord(unpack(block.tagCoords[tagName])) Nenue@30: tag:Show() Nenue@30: tag:SetPoint(tagPoint, tagAnchor, tagRelative, 0, 0) Nenue@30: tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', tag, 'TOPLEFT' Nenue@30: else Nenue@30: block[tagName]:Hide() Nenue@30: end Nenue@28: end Nenue@30: Nenue@28: return tagPoint, tagAnchor, tagRelative Nenue@28: end Nenue@28: Nenue@28: --- Adds the given line to the current content and advances the anchor pointer to that new line for the following call. Nenue@30: Default.AddLine = function(handler, block, text, attachment, template) Nenue@28: local print = lprint Nenue@30: local lineIndex = block.currentLine + 1 Nenue@30: local line = handler:GetLine(block) Nenue@31: line.index = lineIndex Nenue@28: line:ClearAllPoints() Nenue@28: line:SetPoint('LEFT', block, 'LEFT', 0, 0) Nenue@31: line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, 0) Nenue@28: line:SetPoint('RIGHT', block, 'RIGHT', 0, 0) Nenue@28: line:Show() Nenue@28: Nenue@31: print(' |cFF0088FFAddLine >>|r', block, '::', block.endPoint:GetName(),'"'.. text .. '"', attachment, template) Nenue@30: line.status:SetText(text) Nenue@30: line.height = floor(line.status:GetStringHeight()+.5) + textSpacing Nenue@30: line:SetHeight(line.height) Nenue@31: Nenue@31: local r, g, b, a = 1, 1, 1, 1 Nenue@31: if lineColors[template] then Nenue@31: r, g, b = unpack(lineColors[template].text) Nenue@31: end Nenue@30: line.status:SetTextColor(r, g, b, a) Nenue@30: Nenue@30: -- For progressbar and timer lines, status text may be used as the title heading Nenue@30: if attachment then Nenue@31: local widgetOffset = 0 Nenue@31: if text and #text >= 1 then Nenue@31: widgetOffset = line.status:GetHeight() + textSpacing Nenue@31: line.height = floor(line.status:GetStringHeight()+.5) + textSpacing + attachment.height Nenue@31: print(' |cFFFF0088doing things with captioned widget') Nenue@31: else Nenue@31: print(' |cFFFF0088doing things with a widget') Nenue@31: end Nenue@31: attachment:SetPoint('TOP', line, 'TOP', 0, -widgetOffset) Nenue@30: attachment:Show() Nenue@30: end Nenue@30: Nenue@31: block.attachmentHeight = block.attachmentHeight + line.height Nenue@30: print(' |cFF0088FFsetting line #'..lineIndex..' for|r', block.info.title, "\n |cFF0088FFsize:|r", line.height, Nenue@28: "|cFF0088FFpoint:|r", line:GetPoint(1), "|cFF0088FFwidget:|r", (line.widget and 'Y' or 'N')) Nenue@30: block.currentLine = lineIndex Nenue@31: block.endPoint = line.statusbg -- edge used for the next block Nenue@31: Nenue@31: return lineIndex Nenue@28: end Nenue@28: Nenue@28: --- Creates or retrieves a complete line data object Nenue@30: Default.GetLine = function(handler, block, lineIndex) Nenue@28: local print = lprint Nenue@28: local blockIndex = block.index Nenue@30: local lines = block.lines Nenue@30: if not lineIndex then Nenue@30: lineIndex = block.currentLine + 1 Nenue@31: print(' fetching the "next" line:', lineIndex) Nenue@30: else Nenue@31: print(' fetching explicit offset:', lineIndex) Nenue@28: end Nenue@30: Nenue@30: block.numLines = max(block.numLines, lineIndex) Nenue@31: print(' |cFF00FFFFposition|r', block.currentLine, '|cFF00FFFFof|r|cFFFFFF00' , block.numLines) Nenue@30: Nenue@28: if not lines[lineIndex] then Nenue@28: print(' |cFF00FF88created line #'..lineIndex..' from for '..handler.name..' block #'..blockIndex) Nenue@28: lines[lineIndex] = CreateFrame('Frame', 'Vn'..handler.name .. blockIndex..'ObjectiveLine'..lineIndex, block, 'VeneerTrackerObjective') Nenue@28: local line = lines[lineIndex] Nenue@28: line.index = lineIndex Nenue@28: line.height = 0 Nenue@28: line.status:SetSpacing(textSpacing) Nenue@28: line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0) Nenue@28: B.SetConfigLayers(line) Nenue@28: Nenue@28: if lines[lineIndex+1] then Nenue@28: lines[lineIndex+1]:ClearAllPoints() Nenue@28: end Nenue@28: Nenue@28: if debug then Nenue@28: for _, region in ipairs(lines[lineIndex].debug) do Nenue@28: region:Show() Nenue@28: end Nenue@28: end Nenue@28: Nenue@28: end Nenue@28: return lines[lineIndex] Nenue@28: end Nenue@28: Nenue@29: Nenue@29: Nenue@28: --- Creates or retrieves a complete block frame object Nenue@30: Default.GetBlock = function(handler, blockIndex) Nenue@28: local print = bprint Nenue@28: local block = handler.usedBlocks[blockIndex] Nenue@28: Nenue@28: if not handler.usedBlocks[blockIndex] then Nenue@28: if #handler.freeBlocks >= 1 then Nenue@28: block = handler.freeBlocks[#handler.freeBlocks] Nenue@28: handler.freeBlocks[#handler.freeBlocks] = nil Nenue@28: else Nenue@30: block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, handler.frame, 'VeneerTrackerBlock') Nenue@28: Nenue@30: local c = Module.Conf.Wrapper Nenue@28: block.index = blockIndex Nenue@30: block.lines = {} Nenue@30: block.numLines = 0 Nenue@30: block.currentLine = 0 Nenue@28: block:SetWidth(c.Width) Nenue@28: Nenue@28: block.title:SetSpacing(c.TitleSpacing) Nenue@28: block.title:SetPoint('TOP', block, 'TOP', 0, -titleSpacing) Nenue@28: Nenue@28: block.titlebg:SetTexture(1,1,1,1) Nenue@31: block.titlebg:SetGradientAlpha(unpack(titlebg)) Nenue@28: block.titlebg:SetPoint('TOP', block, 'TOP', 0, 0) Nenue@28: block.titlebg:SetPoint('BOTTOM', block.title, 'BOTTOM', 0, -titleSpacing) Nenue@28: Nenue@28: block.status:SetSpacing(c.TextSpacing) Nenue@28: block.status:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, -textSpacing) Nenue@28: block.status:SetPoint('LEFT', block.titlebg, 'LEFT', textIndent, 0) Nenue@28: Nenue@28: block.statusbg:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, 0) Nenue@28: block.statusbg:SetPoint('BOTTOM', block, 'BOTTOM', 0, 0) Nenue@28: block.statusbg:SetTexture(1,1,1,1) Nenue@31: block.statusbg:SetGradientAlpha(unpack(textbg)) Nenue@28: Nenue@30: block.SelectionOverlay:SetGradientAlpha(unpack(Module.colors.default.selectionbg)) Nenue@28: block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0) Nenue@28: block.SelectionOverlay:SetPoint('BOTTOMRIGHT') Nenue@28: Nenue@32: --block.icon:SetSize(rewardSize, rewardSize) Nenue@32: --block.icon:SetPoint() Nenue@32: local anchor, target, point, x, y = 'TOPRIGHT', block, 'TOPRIGHT', -2, -2 Nenue@32: for i, tile in ipairs(block.rewardTile) do Nenue@32: print(rewardSize) Nenue@32: tile:SetSize(rewardSize, rewardSize) Nenue@32: tile:ClearAllPoints() Nenue@32: tile:SetPoint(anchor, target, point, x, y) Nenue@32: block.rewardLabel[i]:SetPoint('TOP', tile, 'TOP', 0, -2) Nenue@32: anchor, target, point, x, y = 'TOPRIGHT', tile, 'TOPLEFT', -2, 0 Nenue@32: end Nenue@28: Nenue@28: Nenue@28: --- methods for event handlers Nenue@28: Nenue@28: block.Select = handler.Select Nenue@28: block.Open = handler.Open Nenue@28: block.Remove = handler.Remove Nenue@28: block.Link = handler.Link Nenue@28: block.clickZone:SetScript('OnMouseUp', function(self, ...) handler.OnMouseUp(block, ...) end) Nenue@28: block.clickZone:SetScript('OnMouseDown', function(self, ...) handler.OnMouseDown(block, ...) end) Nenue@28: block.attachmentHeight = 0 Nenue@28: block:ClearAllPoints() Nenue@28: Nenue@28: B.SetConfigLayers(block) Nenue@28: Nenue@28: if debug then Nenue@28: for _, region in ipairs(block.debug) do Nenue@28: region:Show() Nenue@28: end Nenue@28: end Nenue@28: end Nenue@28: handler.usedBlocks[blockIndex] = block Nenue@28: end Nenue@28: return handler.usedBlocks[blockIndex] Nenue@28: end Nenue@28: Nenue@30: local currentPosition, anchorFrame, anchorPoint Nenue@30: --- Positioning and stuff Nenue@30: local tick = 0 Nenue@30: local maxReason = 0 Nenue@30: function Module:Update (reason, ...) Nenue@30: tick = tick + 1 Nenue@30: -- is this the first time updating? Nenue@30: if maxReason == 0 then Nenue@30: reason = OBJECTIVE_TRACKER_UPDATE_ALL Nenue@30: elseif not reason then Nenue@30: reason = OBJECTIVE_TRACKER_UPDATE_REASON Nenue@30: end Nenue@30: Nenue@30: local print = tprint Nenue@30: local updateWrapper = 0 Nenue@30: local hasStuff Nenue@30: local insertingStuff Nenue@30: Nenue@30: print(format('%d |cFFFF%04X Update()', tick, lshift(reason, 4)), reason, ...) Nenue@30: currentPosition = 0 Nenue@30: anchorPoint = 'TOP' Nenue@30: anchorFrame = Scroll Nenue@30: Nenue@30: local wrapperHeight = 0 Nenue@30: for id, handler in pairs(Module.orderedHandlers) do Nenue@30: local frame = handler.frame Nenue@30: Nenue@30: print(format('|cFF00FFFF%s and(%04X vs %04x+%04x) = %04X|r', handler.name, reason, handler.updateReasonModule, handler.updateReasonEvents, band(reason, handler.updateReasonModule + handler.updateReasonEvents))) Nenue@30: if band(reason, handler.updateReasonModule + handler.updateReasonEvents) > 0 then Nenue@30: handler:UpdateTracker(reason, ...) Nenue@30: print(' |cFF00FF00'..id..'|r', handler.displayName, 'count:', handler.numWatched) Nenue@30: insertingStuff = true Nenue@30: else Nenue@30: print(' |cFFFF0088'..id..'|r', 'no reason to update') Nenue@30: end Nenue@30: Nenue@30: if handler.numWatched >= 1 then Nenue@30: hasStuff = true Nenue@30: currentPosition = currentPosition + 1 Nenue@30: frame.destinationOffset = -wrapperHeight Nenue@30: if frame.previousOffset ~= wrapperHeight and frame:IsVisible() then Nenue@30: print(frame.SlideIn.translation) Nenue@30: local postFrame, postPoint = anchorFrame, anchorPoint Nenue@30: local delta = frame.destinationOffset - frame.previousOffset Nenue@30: local _, _, _, _, offset = frame:GetPoint(1) Nenue@30: print(' |cFF00BBFFstart slide for', delta, 'pixels, from', frame.previousOffset, '(', offset, ')') Nenue@30: frame.SlideIn.translation:SetTarget(frame) Nenue@30: frame.SlideIn.translation:SetOffset(0, delta) Nenue@30: frame.SlideIn:Play() Nenue@30: for i, b in ipairs(handler.usedBlocks) do Nenue@30: b.SlideIn.translation:SetOffset(0, delta) Nenue@30: b.SlideIn:Play() Nenue@30: end Nenue@30: frame.SlideIn:SetScript('OnFinished', function() Nenue@30: print(' |cFF00BBFFsliding finished:', delta, 'pixels covered') Nenue@30: frame:SetParent(Scroll) Nenue@30: frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset) Nenue@30: frame.previousOffset = frame.destinationOffset Nenue@30: frame.SlideIn:SetScript('OnFinished', nil) Nenue@30: if Wrapper.destinationHeight then Nenue@30: Wrapper:SetHeight(Wrapper.destinationHeight) Nenue@30: Scroller:SetHeight(Wrapper.destinationHeight) Nenue@30: Scroll:SetHeight(Wrapper.destinationHeight) Nenue@30: Wrapper.previousHeight = Wrapper.destinationHeight Nenue@30: Wrapper.destinationHeight = nil Nenue@30: end Nenue@30: Nenue@30: end) Nenue@30: else Nenue@30: print(' |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint) Nenue@30: frame:SetParent(Scroll) Nenue@30: frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset) Nenue@30: end Nenue@30: Nenue@30: frame:Show() Nenue@30: anchorFrame = handler.frame Nenue@30: anchorPoint = 'BOTTOM' Nenue@30: Nenue@30: print('current frame height:', frame.height) Nenue@30: wrapperHeight = wrapperHeight + frame.height Nenue@30: print('|cFFFF0088total height:', wrapperHeight) Nenue@30: else Nenue@30: frame:SetPoint('TOP', Scroll, 'TOP', 0, 0) Nenue@30: frame.destinationOffset = 0 Nenue@30: frame.previousOffset = 0 Nenue@30: handler.frame:Hide() Nenue@30: end Nenue@30: end Nenue@30: Nenue@30: Nenue@30: if hasStuff or insertingStuff then Nenue@30: print('updating height to', wrapperHeight) Nenue@30: if wrapperHeight > Wrapper.previousHeight then Nenue@30: Wrapper:SetHeight(wrapperHeight) Nenue@30: Scroller:SetHeight(wrapperHeight) Nenue@30: Scroll:SetHeight(wrapperHeight) Nenue@30: Wrapper.previousHeight = wrapperHeight Nenue@30: Wrapper.destinationHeight = wrapperHeight Nenue@30: end Nenue@30: Scroller:SetVerticalScroll(B.Conf.ObjectiveScroll or 0) Nenue@30: print('|cFFFF8800Wrapper:', Wrapper:GetSize()) Nenue@30: for i = 1, Wrapper:GetNumPoints() do Nenue@30: print(' ', Wrapper:GetPoint(i)) Nenue@30: end Nenue@30: print(' |cFF00FFFFScroller:', Scroller:GetSize()) Nenue@30: for i = 1, Scroller:GetNumPoints() do Nenue@30: print(' ', Scroller:GetPoint(i)) Nenue@30: end Nenue@30: print(' |cFF00FFFFScroll:', Scroll:GetSize()) Nenue@30: for i = 1, Scroll:GetNumPoints() do Nenue@30: print(' ', Scroll:GetPoint(i)) Nenue@30: end Nenue@30: Nenue@30: Wrapper:Show() Nenue@30: Scroller:Show() Nenue@30: Scroll:Show() Nenue@30: end Nenue@30: Quest.GetClosest() Nenue@30: --Module.UpdateActionButtons(reason) Nenue@30: end Nenue@30: Nenue@28: --- Content generator base Nenue@30: Default.UpdateTracker = function (handler, reason, id, isNew) Nenue@28: local print = tprint Nenue@30: local tracker = handler.frame Nenue@28: local blockIndex = 0 Nenue@28: tracker.previousHeight = tracker.height Nenue@28: tracker.height = 0 Nenue@28: Nenue@28: tracker.title:SetFont(headerFont, headerSize, headerOutline) Nenue@28: tracker.titlebg:SetHeight(headerHeight) Nenue@28: tracker.title:SetTextColor(unpack(headerColor)) Nenue@28: Nenue@30: handler.updateReason = reason Nenue@30: handler.numWatched = handler:GetNumWatched() Nenue@30: handler.currentBlock = 0 Nenue@30: handler.currentAnchor = tracker.titlebg Nenue@30: local blockPosition = -headerHeight Nenue@30: for blockIndex = 1, handler.numWatched do Nenue@30: local currentBlock = handler:UpdateBlock(blockIndex, id, isNew) Nenue@30: if currentBlock then Nenue@30: currentBlock.offset = blockPosition Nenue@30: handler:AddBlock(currentBlock) Nenue@30: blockPosition = blockPosition - currentBlock.height Nenue@28: else Nenue@28: print(' |cFFFF9900END|r @', blockIndex) Nenue@28: break -- done with quest stuff Nenue@28: end Nenue@28: end Nenue@28: Nenue@30: for i = handler.currentBlock+1, handler.numBlocks do Nenue@30: local used = handler.usedBlocks Nenue@30: local free = handler.freeBlocks Nenue@30: print('clean up dead quest block') Nenue@30: if used[i] then Nenue@30: used[i]:Hide() Nenue@30: used[i]:ClearAllPoints() Nenue@30: free[#free+1]= used[blockIndex] Nenue@30: used[i] = nil Nenue@30: end Nenue@30: end Nenue@28: Nenue@30: Nenue@30: if handler.currentBlock >= 1 then Nenue@28: tracker.height = tracker.height + headerHeight Nenue@28: tracker:Show() Nenue@28: Nenue@28: if tracker.wasEmpty then Nenue@28: tracker.headerFade:Play() Nenue@28: tracker.wasEmpty = nil Nenue@28: end Nenue@28: if tracker.height ~= tracker.previousHeight then Nenue@28: tracker:SetHeight(tracker.height) Nenue@28: end Nenue@29: print(' |cFFFFFF00', tracker.height, tracker:GetWidth()) Nenue@28: else Nenue@28: tracker:Hide() Nenue@28: tracker.wasEmpty = true Nenue@28: end Nenue@28: Nenue@28: return tracker.numWatched, tracker.numAll Nenue@28: end Nenue@28: Nenue@28: --- Updates the selected block frame to display the given info batch Nenue@28: -- If `previousBlock` is set, it will attempt to anchor to that Nenue@28: -- @param blockNum the ordered block to be updated, not a watchIndex value Nenue@28: -- @param info the reference returned by the GetXInfo functions Nenue@28: -- REMEMBER: t.info and questData[questID] are the same table Nenue@30: Default.UpdateBlock = function (handler, blockIndex, id, added) Nenue@28: local print = bprint Nenue@30: print(' Updating |cFF00FF00'..handler.displayName..'|r|cFF00FFFF'..blockIndex..'|r') Nenue@30: if not blockIndex then Nenue@30: return Nenue@30: end Nenue@30: local info = handler:GetInfo(blockIndex) -- should match up with whatever the internal watch list has Nenue@30: if not info then Nenue@28: return Nenue@28: end Nenue@28: local frame = handler.frame Nenue@30: local block = handler:GetBlock(blockIndex) Nenue@30: Nenue@30: block.questID = info.questID Nenue@30: if id == info.questID then Nenue@30: --block.questFadeIn:Play() Nenue@30: end Nenue@30: Nenue@28: block.handler = handler Nenue@28: block.info = info Nenue@28: block.mainStyle = info.mainStyle or 'Normal' Nenue@28: block.subStyle = info.subStyle Nenue@28: Nenue@28: info.blockIndex = blockIndex Nenue@28: if info.questID then handler.QuestBlock[info.questID] = block end Nenue@28: if info.questLogIndex then handler.LogBlock[info.questLogIndex] = block end Nenue@28: if info.watchIndex then handler.WatchBlock[info.watchIndex] = block end Nenue@28: handler.BlockInfo[blockIndex] = info Nenue@28: handler:UpdateObjectives(block) Nenue@28: Nenue@28: block.title:SetText(info.title) Nenue@28: local titleHeight = floor(block.title:GetHeight()+.5) Nenue@28: local titlebgHeight = titleHeight + titleSpacing*2 Nenue@28: block.titlebg:SetHeight(titlebgHeight) Nenue@28: Nenue@30: local statusHeight = floor(block.status:GetHeight()+.5) Nenue@30: local statusbgHeight = statusHeight + textSpacing*2 Nenue@30: local attachmentHeight =floor(block.attachmentHeight + .5) Nenue@28: Nenue@28: print(' |cFF0088FFanchor to', handler.currentAnchor:GetName()) Nenue@30: print(' |cFF00FF00attachment:|r', attachmentHeight, '|cFF00FF00title:|r', titlebgHeight, '('.. titleHeight..')') Nenue@30: --block.titlebg:SetHeight(block.title:GetHeight() + Module.Conf.Wrapper.TitleSpacing) Nenue@30: block.height = titlebgHeight + attachmentHeight Nenue@28: Nenue@28: if statusHeight > 1 then Nenue@28: block.height = block.height + statusbgHeight Nenue@28: print(' status:', statusbgHeight, '('.. statusHeight..')') Nenue@28: else Nenue@28: print(' |cFFFF0088 skipped') Nenue@28: end Nenue@28: block:SetHeight(block.height) Nenue@28: Nenue@28: print(' |cFFFFFF00height|r:', block.height) Nenue@28: print(' |cFF00FFFF)|r -> ', block, block:GetHeight()) Nenue@28: Nenue@28: block:Show() Nenue@28: Nenue@28: if info.specialItem and not info.itemButton then Nenue@28: print(' - |cFF00FFFFgenerating item button for info set') Nenue@30: info.itemButton = Module.SetItemButton(block, info) Nenue@28: else Nenue@28: --info.itemButton = nil Nenue@28: end Nenue@28: Nenue@32: local tagPoint, tagAnchor, tagRelative, x, y = 'TOPRIGHT', block, 'TOPRIGHT', -2, -2 Nenue@28: Nenue@32: local numCurrency = 0 Nenue@32: for i, rewardTile in ipairs(block.rewardTile) do Nenue@32: local reward = info.rewardInfo[i] Nenue@32: if reward then Nenue@32: --rewardTile:SetPoint(tagPoint, tagAnchor, tagRelative, -2, -2) Nenue@32: rewardTile:SetTexture(reward.texture) Nenue@32: rewardTile:Show() Nenue@32: Nenue@32: print('updating reward tile #'.. i, reward.type, reward.count, reward.text, reward.texture) Nenue@32: if reward.count and reward.count > 1 then Nenue@32: block.rewardLabel[i]:SetText(reward.count) Nenue@32: block.rewardLabel[i]:Show() Nenue@32: end Nenue@32: Nenue@32: rewardTile:ClearAllPoints() Nenue@32: rewardTile:SetPoint(tagPoint, tagAnchor, tagRelative, x, y) Nenue@32: tagPoint, tagAnchor, tagRelative, x, y = 'TOPRIGHT', rewardTile, 'TOPLEFT', -2, 0 Nenue@32: else Nenue@32: rewardTile:Hide() Nenue@32: block.rewardLabel[i]:Hide() Nenue@28: end Nenue@28: end Nenue@28: Nenue@28: if info.selected then Nenue@28: block.SelectionOverlay:Show() Nenue@28: else Nenue@28: block.SelectionOverlay:Hide() Nenue@28: end Nenue@28: -- workaround for scrollchild issue where layers fall out of sync: in this case, it's by 1 vertical pixel Nenue@28: --block.highlight:SetPoint('TOPLEFT', block, 'TOPLEFT', 0, 1) Nenue@28: --block.lowlight:SetPoint('BOTTOMLEFT', block, 'BOTTOMLEFT', 0, 1) Nenue@28: Nenue@31: if info.tagInfo then Nenue@31: tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'frequencyTag', tagPoint, tagAnchor, tagRelative) Nenue@31: tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'typeTag', tagPoint, tagAnchor, tagRelative) Nenue@31: tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'completionTag', tagPoint, tagAnchor, tagRelative) Nenue@31: end Nenue@28: return block Nenue@28: end Nenue@28: Nenue@28: Nenue@28: Nenue@28: Nenue@28: --- Does the main iterations for populating block content. Nenue@28: -- Hooked by corresponding handler functions where additional details need to be sorted. Nenue@28: Default.UpdateObjectives = function(handler, block) Nenue@28: local print = lprint Nenue@28: local info = block.info Nenue@31: print('|cFF00FF00default.objectives', block:GetName()) Nenue@31: -- reset the starting positions Nenue@30: block.endPoint = block.titlebg Nenue@30: block.attachmentHeight = 0 Nenue@30: block.currentLine = 0 Nenue@28: Nenue@28: local displayObjectiveHeader = false Nenue@28: Nenue@31: block.attachmentHeight = 0 Nenue@31: local text, attachment, template Nenue@28: Nenue@28: Nenue@28: if info.description and #info.description >= 1 then Nenue@28: print(' |cFF00FFFF header line:|r', info.description) Nenue@30: text = info.description Nenue@30: handler:AddLine(block, text, nil) Nenue@28: end Nenue@28: Nenue@28: if (info.isComplete or info.numObjectives == 0) and info.completionText then Nenue@28: print(' overriding line #1 for completion text:', info.completionText) Nenue@30: text = info.completionText Nenue@31: handler:AddLine(block, text, nil) Nenue@28: else Nenue@28: if info.objectives then Nenue@28: for i, data in ipairs(info.objectives) do Nenue@30: local line = handler:GetLine(block) Nenue@28: displayObjectiveHeader = true Nenue@28: line.height = 0 Nenue@31: text, attachment, template = handler:UpdateLine(block, line, data) Nenue@30: print(' |cFF88FF00#', i, data.type, text) Nenue@31: handler:AddLine(block, text, attachment, template) Nenue@28: Nenue@28: end Nenue@28: end Nenue@28: end Nenue@28: Nenue@32: if info.statusKey and (Devian and Devian.InWorkspace()) then Nenue@32: handler:AddLine(block, info.statusKey, nil) Nenue@32: end Nenue@32: Nenue@30: for i = block.currentLine + 1, block.numLines do Nenue@30: print(i, block.numLines) Nenue@30: print(' - hide |cFFFF0088'..i..'|r', block.lines[i]) Nenue@30: block.lines[i]:ClearAllPoints() Nenue@30: block.lines[i]:Hide() Nenue@28: end Nenue@28: Nenue@30: if block.currentLine > 0 then Nenue@31: block.attachmentHeight = block.attachmentHeight + textSpacing Nenue@28: print(' |cFF00FF00attachment:', block.attachmentHeight) Nenue@28: end Nenue@28: end Nenue@28: Nenue@28: Nenue@28: --- Module-specific display variables Nenue@28: -- * height - height of whatever display widget is involved in conveying the task Nenue@28: -- * money - boolean that determines listening for money events or not Nenue@28: -- * progress - number ranging 0 to 2 indicating none/partial/full completion respectively Nenue@28: Nenue@28: Nenue@31: Default.UpdateLine = function(handler, block, line, data) Nenue@28: if line.finished then Nenue@28: line.progress = 2 Nenue@28: elseif line.quantity > 0 then Nenue@28: line.progress = 1 Nenue@28: else Nenue@28: line.progress = 0 Nenue@28: end Nenue@31: return data.text, line.widget, 'normal' Nenue@28: end Nenue@28: ---------- Nenue@28: --- Top level methods Nenue@28: Nenue@28: --- Queue any active item buttons for update for that frame Nenue@28: local iprint = B.print('ItemButton') Nenue@30: Module.UpdateActionButtons = function(updateReason) Nenue@28: local print = iprint Nenue@28: Scroller.snap_upper = 0 Nenue@28: Scroller.snap_lower = 0 Nenue@28: local print = B.print('ItemButton') Nenue@28: if updateReason then Nenue@28: print = B.print('IB_'..updateReason) Nenue@28: end Nenue@28: Nenue@28: local previousItem Nenue@28: for questID, itemButton in pairs(Quest.itemButtons) do Nenue@30: local info= Module.Quest.Info[questID] Nenue@28: Nenue@28: print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName()) Nenue@30: local block = Module.Quest.QuestBlock[questID] Nenue@28: if block then Nenue@28: -- Dispatch the probe Nenue@28: if IsQuestWatched(info.questLogIndex) then Nenue@28: itemButton.previousItem = previousItem Nenue@28: print(' |cFFFFFF00probing', block:GetName()) Nenue@28: block:SetScript('OnUpdate', function() Nenue@28: if block:GetBottom() and not InCombatLockdown() then Nenue@28: print(' '..block:GetName()..' |cFF00FF00probe hit!') Nenue@30: Module.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope Nenue@28: block:SetScript('OnUpdate', nil) Nenue@28: Nenue@28: end Nenue@28: end) Nenue@28: previousItem = itemButton Nenue@28: else Nenue@28: print('hidden block or unwatched quest') Nenue@28: itemButton.previousItem = nil Nenue@28: itemButton:Hide() Nenue@28: end Nenue@28: elseif itemButton:IsVisible() then Nenue@28: print(' |cFFFF0088hiding unwatched quest button', itemButton:GetName()) Nenue@28: itemButton.previousItem = nil Nenue@28: itemButton:Hide() Nenue@28: else Nenue@28: print(' |cFFBBBBBBignoring hidden log quest button', itemButton:GetName()) Nenue@28: end Nenue@28: end Nenue@28: end Nenue@28: Nenue@30: Module.UpdateBlockAction = function (block, itemButton) Nenue@28: local print = iprint Nenue@28: print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()') Nenue@28: if itemButton.questID ~= block.info.questID then Nenue@28: print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID) Nenue@28: -- something happened between this and last frame, go back and set new probes Nenue@30: return Module.UpdateActionButtons() Nenue@28: end Nenue@28: Nenue@28: local previousItem = itemButton.previousItem Nenue@28: local upper_bound = Scroller:GetTop() + Scroller.snap_upper Nenue@28: local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize Nenue@28: local point, anchor, relative Nenue@28: Nenue@28: if block:GetBottom() < lower_bound then Nenue@28: print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5)) Nenue@28: if previousItem then Nenue@28: print('adjusting', previousItem:GetName()) Nenue@28: previousItem:ClearAllPoints() Nenue@28: previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing) Nenue@28: end Nenue@28: itemButton:ClearAllPoints() Nenue@28: itemButton.x = Wrapper:GetLeft() -4 Nenue@28: itemButton.y = Wrapper:GetBottom() Nenue@28: point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT' Nenue@28: Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing Nenue@28: Nenue@28: elseif block:GetTop() > upper_bound then Nenue@28: print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5)) Nenue@28: itemButton:ClearAllPoints() Nenue@28: if previousItem then Nenue@28: print('latch onto another piece') Nenue@28: point, anchor, relative ='TOP', previousItem, 'BOTTOM' Nenue@28: itemButton.x = 0 Nenue@28: itemButton.y = -itemButtonSpacing Nenue@28: else Nenue@28: print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop()) Nenue@28: point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' Nenue@28: itemButton.x = Scroller:GetLeft() -4 Nenue@28: itemButton.y = Scroller:GetTop() Nenue@28: end Nenue@28: itemButton:Show() Nenue@28: Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing) Nenue@28: else Nenue@28: print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5)) Nenue@28: itemButton:ClearAllPoints() Nenue@28: itemButton.x = block:GetLeft() - itemButtonSpacing Nenue@28: itemButton.y = block:GetTop() Nenue@28: point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT' Nenue@28: end Nenue@28: Nenue@28: itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y) Nenue@28: itemButton:Show() Nenue@28: end Nenue@28: Nenue@30: Module.UpdateItemButtonCooldown = function(button) Nenue@28: Nenue@28: end Nenue@28: Nenue@29: Default.Select = function(handler, block) Nenue@30: Module:Update(handler.watchReasonModule) Nenue@28: end Nenue@29: Default.Open = function(handler, block) Nenue@30: Module:Update(handler.watchReasonModule) Nenue@28: end Nenue@29: Default.Remove = function(handler, block) Nenue@30: Module:Update(handler.watchReasonModule) Nenue@28: end Nenue@29: Default.Report = function(handler, block) Nenue@29: print('Stats:', handler.numWatched,'items tracked,', handler.numBlocks,'blocks assigned.') Nenue@28: end Nenue@28: Nenue@28: Default.OnMouseUp = function(self, button) Nenue@28: print(self.handler.name, self.mainStyle, self.subStyle) Nenue@28: if button == 'LeftButton' then Nenue@28: if IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() then Nenue@29: self.Link(self.handler, self) Nenue@28: elseif IsModifiedClick("QUESTWATCHTOGGLE") then Nenue@29: self.Remove(self.handler, self) Nenue@28: else Nenue@29: self.Select(self.handler, self) Nenue@28: end Nenue@28: elseif button == 'RightButton' then Nenue@29: self.Open(self.handler, self) Nenue@28: end Nenue@28: self.initialButton = nil Nenue@28: self.modChatLink = nil Nenue@28: self.modQuestWatch = nil Nenue@30: Module:Update(self.handler.updateReasonModule) Nenue@28: print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r') Nenue@28: end Nenue@28: Default.OnMouseDown = function(self, button) Nenue@28: print(self.info.title) Nenue@28: end