# HG changeset patch # User Nenue # Date 1472309468 14400 # Node ID 51f248dc02762adec13fa88d3f89db97334f6e9e # Parent 83b3cdaae6a53730fe364641f2ed04dd5e6a55c0 setup working copy dingaling diff -r 83b3cdaae6a5 -r 51f248dc0276 Veneer_Objectives/ObjectiveTracker.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Veneer_Objectives/ObjectiveTracker.lua Sat Aug 27 10:51:08 2016 -0400 @@ -0,0 +1,559 @@ +-- Veneer +-- ObjectiveTracker.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 \ No newline at end of file diff -r 83b3cdaae6a5 -r 51f248dc0276 Veneer_Objectives/Veneer_Objectives.iml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Veneer_Objectives/Veneer_Objectives.iml Sat Aug 27 10:51:08 2016 -0400 @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff -r 83b3cdaae6a5 -r 51f248dc0276 Veneer_Objectives/Veneer_Objectives.toc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Veneer_Objectives/Veneer_Objectives.toc Sat Aug 27 10:51:08 2016 -0400 @@ -0,0 +1,13 @@ +## Interface: 70000 +## Title: Veneer |cFF00FF00Objective Tracker|r +## Notes: Objectives frame hooker-upper +## Author: Krakyn +## Version: 1.0-@project-revision@ +## SavedVariables: VeneerData +## X-Category: Interface Enhancements +## DefaultState: Enabled +## LoadOnDemand: 0 +## Dependencies: Veneer + +Veneer_Objectives.xml +ObjectiveTracker.lua \ No newline at end of file diff -r 83b3cdaae6a5 -r 51f248dc0276 Veneer_Objectives/Veneer_Objectives.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Veneer_Objectives/Veneer_Objectives.xml Sat Aug 27 10:51:08 2016 -0400 @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file