Mercurial > wow > buffalo2
view Veneer_Objectives/ObjectiveTracker.lua @ 89:74e714637d6a
WorldStateProgress fade-in is called for all visibility check falses
author | Nenue |
---|---|
date | Fri, 21 Oct 2016 18:03:35 -0400 |
parents | 0784b87f9722 |
children |
line wrap: on
line source
-- Veneer -- Veneer_WorldQuests.lua -- Created: 8/16/2016 8:19 AM -- %file-revision% -- This is more or less a copy of the blizzard code with some customization stuff added local plugin = VeneerObjectives local vn, print = LibStub("LibKraken").register(Veneer, VeneerObjectives) local ot local otvn local band, floor, min = bit.band, math.floor, math.min local X_QUEST = 0x00001; local X_QUEST_ADDED = 0x00002; local X_TASK_ADDED = 0x00004; local X_WORLD_QUEST_ADDED = 0x00008; local X_SCENARIO = 0x00010; local X_SCENARIO_NEW_STAGE = 0x00020; local X_ACHIEVEMENT = 0x00040; local X_ACHIEVEMENT_ADDED = 0x00080; local X_SCENARIO_BONUS_DELAYED = 0x00100; local X_SUPER_TRACK_CHANGED = 0x00200; -- these are for the specific module ONLY! local X_MODULE_QUEST = 0x00400; local X_MODULE_AUTO_QUEST_POPUP = 0x00800; local X_MODULE_BONUS_OBJECTIVE = 0x01000; local X_MODULE_WORLD_QUEST = 0x02000; local X_MODULE_SCENARIO = 0x04000; local X_MODULE_ACHIEVEMENT = 0x08000; local X_SCENARIO_SPELLS = 0x10000; -- special updates local X_STATIC = 0x0000; local X_ALL = 0xFFFF; -- state information local X_REASON = X_ALL; -- default local X_MONEY = 0 local X_ANIMATION = 0 local X_ID = 0; local INSET_V = -20 local trackerWidth = 240 local blockIndent = 12 local blockSpacing = 3 local tracker = { freeBlocks = {}, usedBlocks = {}, freeProgressBars = {}, usedProgressBars = {}, freeTimers = {}, usedTimers = {}, freeLines = {}, headerText = 'Default Header', contentHeight = 0, animationHeight = 0, updateReasonModule = 0, updateReasonEvents = 0, } local GetTrackerHandler = function(handler) handler = handler or {} setmetatable(handler, {__index=tracker}) return handler end local Header_OnAnimationStart = function (self, forced) local header = self:GetParent() header.animating = true plugin:UpdateAnimation(header) end local Header_OnAnimationFinished = function (self, forced) local header = self:GetParent() header.animating = nil plugin:Update(X_ANIMATION) end -- reset generic flags for layout compilation function tracker:InitLayout (isStatic) print('|cFF00FFFFlayout|r', self.headerText) self.firstBlock = nil self.lastBlock = nil self.currentBlock = nil self.oldContentHeight = self.contentHeight self.oldAnimationHeight = self.animationHeight self.numBlocks = 0 for id, block in pairs(self.usedBlocks) do block.used = nil end if not isStatic then self.hasSkippedBlocks = false end if not self.header then self:SetHeader(self.headerText, X_REASON) self.header:SetPoint('TOPLEFT', plugin, 'TOPLEFT', 0, -plugin.contentHeight) plugin.contentHeight = plugin.contentHeight + self.header:GetHeight() end self.contentHeight = 0 end -- clear out generic flags and set aside block frames for re-use tracker.EndLayout = function(self) self.lastBlock = self.currentBlock for id, block in pairs(self.usedBlocks) do if not block.used then self:FreeBlock(block) end end end function tracker:SetHeader (text, animateReason) if self.header then return self.header end local block = CreateFrame('Button', nil, plugin, 'VeneerObjectiveHeader') block.handler = self block.text:SetText(self.headerText) self.currentBlock = block self.header = block return block end function tracker:FreeBlock(block) self.usedBlocks[block.id] = nil print('|cFF0088FFfree|r', block:GetName()) tinsert(self.freeBlocks, block) block.numLines = 0 block:SetHeight(0) block:Hide() end -- should only be used in an N-lastN loop function tracker:FreeLine(line) if line.block then line.block.lines[line.index] = nil end print('|cFF0088FFfree|r', line:GetName()) local freeLines = line.type or self.freeLines tinsert(freeLines, line) end local blocksn = 0 tracker.GetBlock = function(self, id) local block = self.usedBlocks[id] if not block then local numFree = #self.freeBlocks if numFree >= 1 then block = tremove(self.freeBlocks, numFree) else blocksn = blocksn + 1 block = CreateFrame('Button', 'OTVNBlock'..blocksn, plugin, 'VeneerObjectiveBlock') block.lines = {} end self.usedBlocks[id] = block block.id = id block.handler = self end block.used = true block.currentLine = nil block.numLines = 0 if block.lines then for i, line in ipairs(block.lines) do line.used = nil end end block.contentHeight = blockSpacing block:SetWidth(trackerWidth) block:SetHeight(0) return block end -- obtain line local linesn = 0 function tracker:GetLine(block, index, lineType) local line = block.lines[index] if line and line.lineType ~= lineType then tinsert(self.freeLines, line) line = nil end if not line then local freeLines = (lineType and lineType.freeLines) or self.freeLines local numFreeLines = #freeLines if numFreeLines >= 1 then line = tremove(freeLines, numFreeLines) else linesn = linesn + 1 line = CreateFrame('Frame', 'OTVNLine'.. linesn, block, (lineType and lineType.template) or 'VeneerObjectiveLine') end line:SetParent(block) end line.type = lineType line.index = index line.used = true line.block = block line.text:SetPoint('TOPLEFT', line, 'TOPLEFT', blockIndent, 0) line:SetHeight(0) -- in order for GetStringHeight to be useful block.lines[index] = line return line end function tracker:AddProgressBar(block, line, questID) end function tracker:FreeProgressBar(block, line) end function tracker:AddTimerBar(block, line, duration, startTime) end function tracker:FreeTimerBar(block, line) end -- Checks for space and anchors or frees the block accordingly function tracker:AddBlock (block, force) local anchor = self.currentBlock or self.header self.numBlocks = self.numBlocks + 1 if block.header then print('header!', floor(block.contentHeight), '+', floor(block.header:GetStringHeight())) block.contentHeight = block.contentHeight + block.header:GetStringHeight() self.used = true end if self.currentBlock then self.currentBlock.nextBlock = block block.prevBlock = self.currentBlock else self.firstBlock = block end self.contentHeight = self.contentHeight + block.contentHeight self.currentBlock = block if not plugin.currentBlock then plugin.firstBlock = block end plugin.currentBlock = block block:SetHeight(block.contentHeight) print('block|cFF88FF00', self.numBlocks, block, '|rto', anchor, 'size', block.contentHeight) block:ClearAllPoints() block:SetPoint('TOPLEFT', anchor, 'BOTTOMLEFT', 0, -blockSpacing) block:Show() -- free unused lines local numLines = #block.lines for i = 1, numLines do local line = block.lines[i] if not line.used or block.collapsed then print('|cFFFF4400!|r') self:FreeLine(line) else if not line:IsShown() then line:Show() end end end return true end function tracker:SetLine(block, index, lineType, textOrFunc) local anchor = block.currentLine or block.header local line = self:GetLine(block, index, lineType) if line.ticker then line.ticker:Cancel() line.ticker = nil end local text = textOrFunc if type(textOrFunc) == 'function' then text = textOrFunc() line.ticker = C_Timer.NewTicker(10, function() line.height = tracker:SetLineText(line.text, textOrTextFunc()) line:SetHeight(line.height) end) end line.height = tracker:SetLineText(line.text, text) line:SetHeight(line.height) print('line|cFFFFFF00', line:GetName(), '|rto', anchor:GetName(), 'size', line.height) line:SetPoint('TOPLEFT', anchor, 'BOTTOMLEFT', 0, 0) block.contentHeight = block.contentHeight + line.height block.numLines = block.numLines + 1 if block.currentLine then line.prevLine = block.currentLine block.currentLine.nextLine = line else block.firstLine = line end block.currentLine = line plugin.currentLine = line end function tracker:SetLineText(fontString, text) fontString:SetText(text) return fontString:GetStringHeight() end -- Update lite function tracker:ResetAnchors () self:InitLayout() self:EndLayout() end local UpdateQuestTracker = function(watchIndex, logIndex) return true end -- top-down updaters local questTracker = GetTrackerHandler({ headerText = 'Quests', updateReasonModule = X_MODULE_QUEST, updateReasonEvents = (X_QUEST + X_QUEST_ADDED), }) function questTracker:Update () self:InitLayout() for watchIndex = 1, GetNumQuestWatches() do local questID, title, questLogIndex, numObjectives, requiredMoney, isComplete, startEvent, isAutoComplete, failureTime, timeElapsed, questType, isTask, isBounty, isStory, isOnMap, hasLocalPOI = GetQuestWatchInfo(watchIndex) if not questID then -- stop parsing; end of data or variables haven't completely loaded break end local showQuest = true if isTask or (isBounty and not IsQuestComplete(questID)) then -- do nothing else -- obtain a block local block = self:GetBlock(questID) block.header:SetText(title) for i = 1, numObjectives do local text, objectiveType, finished = GetQuestLogLeaderBoard(i, questLogIndex) if text then self:SetLine(block, i, nil, text) end end block:SetScript('OnClick', self.OnClick) block:RegisterForClicks('AnyDown') self:AddBlock(block) end end self:EndLayout() end questTracker.OnClick = function(block, button) if button == 'RightButton' then ObjectiveTracker_ToggleDropDown(block, QuestObjectiveTracker_OnOpenDropDown) else CloseDropDownMenus() local questLogIndex = GetQuestLogIndexByID(block.id) if ( IsModifiedClick("QUESTWATCHTOGGLE") ) then QuestObjectiveTracker_UntrackQuest(nil, block.id); else if ( IsQuestComplete(block.id) and GetQuestLogIsAutoComplete(questLogIndex) ) then AutoQuestPopupTracker_RemovePopUp(block.id); ShowQuestComplete(questLogIndex); else QuestLogPopupDetailFrame_Show(questLogIndex); end end end end local UpdateAchievementTracker = function() end local UpdateTaskTracker = function() end local UpdateScenarioTracker = function() end function plugin:Update(reason, id) print('update', reason, #plugin.trackers) if plugin.minimized then for i, tracker in ipairs(plugin.trackers) do tracker:Hide() end return end local X_REASON = reason or X_ALL local X_ID = id plugin.maxHeight = plugin:GetHeight() plugin.oldContentsHeight = plugin.contentHeight plugin.contentHeight = 0 plugin.currentBlock = nil plugin.firstBlock = nil plugin:SetWidth(trackerWidth) -- pad for header plugin.contentHeight = plugin.header:GetHeight() for i, header in ipairs(plugin.trackers) do header.used = nil end local addedSpace = false for i, tracker in ipairs(plugin.trackers) do if ( band(X_REASON, tracker.updateReasonModule + tracker.updateReasonEvents ) > 0 ) then print('->', tracker.headerText) tracker:Update() if tracker.oldContentHeight - tracker.contentHeight >= 1 then addedSpace = true end else -- if we can fit another header or an animation handler popped, contents need to be generated if addedSpace or (tracker.header and tracker.header.animating) then print('->', tracker.headerText, 'added space') tracker:Update() else print('->', tracker.headerText, 'lite update') -- otherwise, measure contents and hide anything that won't fit tracker:ResetAnchors() end end end for i, tracker in ipairs(plugin.trackers) do if tracker.currentBlock then if not tracker.header:IsShown() then tracker.header:Show() end else if tracker.header:IsShown() then tracker.header:Hide() end end end if VeneerBuffFrame and VeneerBuffFrame.lastBuff then plugin:ClearAllPoints() plugin:SetPoint('TOP', VeneerBuffFrame.lastBuff, 'BOTTOM', 0, -4) plugin:SetPoint('RIGHT', UIParent, 'RIGHT', -6, 0) else plugin:ClearAllPoints() plugin:SetPoint('TOPRIGHT', UIParent, 'TOPRIGHT', -6, -120) end plugin:Show() end plugin.init = function() plugin:RegisterEvent("QUEST_LOG_UPDATE") plugin:RegisterEvent("TRACKED_ACHIEVEMENT_LIST_CHANGED") plugin:RegisterEvent("QUEST_WATCH_LIST_CHANGED") plugin:RegisterEvent("QUEST_AUTOCOMPLETE") plugin:RegisterEvent("QUEST_ACCEPTED") plugin:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED") plugin:RegisterEvent("SCENARIO_UPDATE") plugin:RegisterEvent("SCENARIO_CRITERIA_UPDATE") plugin:RegisterEvent("SCENARIO_SPELL_UPDATE") plugin:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE") plugin:RegisterEvent("ZONE_CHANGED_NEW_AREA"); plugin:RegisterEvent("ZONE_CHANGED"); plugin:RegisterEvent("QUEST_POI_UPDATE"); plugin:RegisterEvent("VARIABLES_LOADED"); plugin:RegisterEvent("QUEST_TURNED_IN"); plugin:RegisterEvent("PLAYER_MONEY"); plugin.trackers = { questTracker, } print('bub') end function plugin:event(event, ...) print('|cFFFF0088' .. event, ...) if event == 'QUEST_WATCH_LIST_CHANGED' then local questID, added = ... if added then if not IsQuestBounty(questID) or IsQuestComplete(questId) then print(questID, added) plugin:Update(X_QUEST_ADDED, questID) end else print() plugin:Update(X_QUEST) end elseif event == 'QUEST_LOG_UPDATE' then plugin:Update(X_MODULE_QUEST) elseif event == 'QUEST_POI_UPDATE' then if GetCVar("trackQuestSorting") == "proximity" then -- todo: sort blocks end plugin:Update(X_MODULE_QUEST) elseif event == 'PLAYER_MONEY' then plugin:Update(X_MONEY) end end -- adjusts money events bitcode when a tracker is displaying money data function plugin:UpdateMoneyFlag(watchMoney, reason) if watchMoney then if (band(X_MONEY, reason) == 0) then X_MONEY = X_MONEY - reason end else if (band(X_MONEY, reason) > 0) then X_MONEY = X_MONEY + reason end end end -- used by framescripts to poke the updater when an animation has ended function plugin:UpdateAnimation(block) local reason = block.handler.updateReasonEvents if block.animating then if (band(X_ANIMATION, reason) == 0) then X_ANIMATION = X_ANIMATION - reason end else if (band(X_ANIMATION, reason) > 0) then X_ANIMATION = X_ANIMATION + reason end end end