annotate ObjectiveUI.lua @ 7:5301c68f28d8

TrackerBlock - use IsModifiedClick function to determine appropriate OnClick actions - handle 'CHATLINK' modifier - handle 'TOGGLEQUESTWATCH' modifier TrackerBlockObjectives - use a generic framework to manage frame creation for various criteria tracker types: - ProgressBar when Blizzard flag data indicates so - skip when Blizzard flag data indicates so - DynamicText otherwise - events related to the criteria are registered in the criteria frame, and unregistered when the frame is hidden, either by destruction of its parent or completion
author Nenue
date Fri, 01 Apr 2016 12:27:05 -0400
parents 589de8ea05b9
children 7923243ae972
rev   line source
Nenue@0 1 --- ${PACKAGE_NAME}
Nenue@0 2 -- @file-author@
Nenue@0 3 -- @project-revision@ @project-hash@
Nenue@0 4 -- @file-revision@ @file-hash@
Nenue@0 5 -- Created: 3/29/2016 7:07 PM
Nenue@0 6 local B = select(2,...).frame
Nenue@0 7 local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
Nenue@0 8 local print = B.print('Objectives')
Nenue@0 9 local Tracker, AutoQuest, Quest, Cheevs = mod.Tracker, mod.AutoQuest, mod.Quest, mod.Cheevs
Nenue@6 10 local itemButtonSize, itemButtonSpacing = 36, 1
Nenue@7 11 local tremove, tremovebyval = table.remove, table.removebyval
Nenue@0 12
Nenue@0 13 --------------------------------------------------------------------
Nenue@3 14 --- Tracker-specific widgets and their handlers
Nenue@0 15 --------------------------------------------------------------------
Nenue@0 16
Nenue@0 17 Tracker.Select = function(self) end
Nenue@0 18 Tracker.Open = function(self) end
Nenue@0 19 Tracker.Remove = function(self) end
Nenue@0 20 Tracker.Report = function(self)
Nenue@0 21 print('Stats:', self.numWatched,'items tracked,', self.numBlocks,'blocks assigned.')
Nenue@0 22 end
Nenue@0 23
Nenue@0 24 Tracker.OnMouseUp = function(self, button)
Nenue@1 25 if self.initialButton == 'LeftButton' then
Nenue@7 26 if self.modChatLink and ChatEdit_GetActiveWindow() then
Nenue@7 27 self:Link()
Nenue@7 28 elseif self.modQuestWatch then
Nenue@1 29 self:Remove()
Nenue@7 30 else
Nenue@7 31 self:Select()
Nenue@1 32 end
Nenue@0 33 elseif button == 'RightButton' then
Nenue@0 34 self:Open()
Nenue@0 35 end
Nenue@1 36 self.initialButton = nil
Nenue@7 37 self.modChatLink = nil
Nenue@7 38 self.modQuestWatch = nil
Nenue@0 39 print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r ->',self.info.trackingID)
Nenue@0 40 end
Nenue@0 41
Nenue@0 42 Tracker.OnMouseDown = function(self, button)
Nenue@1 43 self.initialButton = button
Nenue@7 44 self.modChatLink = IsModifiedClick("CHATLINK")
Nenue@7 45 self.modQuestWatch = IsModifiedClick("QUESTWATCHTOGGLE")
Nenue@7 46 self:SetStyle('Active')
Nenue@0 47 print(self.info.title)
Nenue@0 48 end
Nenue@0 49
Nenue@0 50 -----------------------------
Nenue@0 51 --- AUTO_QUEST
Nenue@0 52 AutoQuest.name = "Remote Quests"
Nenue@0 53 AutoQuest.GetNumWatched = GetNumAutoQuestPopUps
Nenue@0 54
Nenue@0 55 -----------------------------
Nenue@0 56 --- QUEST
Nenue@0 57 Quest.name = "Quests"
Nenue@0 58 Quest.Select = function(self)
Nenue@0 59 SetSuperTrackedQuestID(self.info.questID)
Nenue@7 60 mod.UpdateWrapper()
Nenue@7 61 end
Nenue@7 62 Quest.Link = function(self)
Nenue@7 63 local questLink = GetQuestLink(block.questLogIndex);
Nenue@7 64 if ( questLink ) then
Nenue@7 65 ChatEdit_InsertLink(questLink);
Nenue@7 66 end
Nenue@0 67 end
Nenue@0 68 Quest.Open = function(self)
Nenue@1 69 QuestMapFrame_OpenToQuestDetails(self.info.questID)
Nenue@1 70 end
Nenue@1 71
Nenue@1 72 Quest.Remove = function(self)
Nenue@5 73 print('removing', self.info.questLogIndex, 'from watcher')
Nenue@5 74 RemoveQuestWatch(self.info.questLogIndex)
Nenue@5 75
Nenue@5 76 mod.Quest.LogBlock[self.info.questLogIndex] = nil
Nenue@5 77 mod.Quest.QuestBlock[self.info.questID] = nil
Nenue@1 78 QuestPOIUpdateIcons()
Nenue@5 79 mod.UpdateWrapper()
Nenue@0 80 end
Nenue@0 81
Nenue@0 82
Nenue@0 83 -----------------------------
Nenue@0 84 --- CHEEVS
Nenue@0 85 Cheevs.Select = function(self)
Nenue@0 86 end
Nenue@7 87 Cheevs.Link = function(self)
Nenue@7 88 local achievementLink = GetAchievementLink(self.info.cheevID);
Nenue@7 89 if ( achievementLink ) then
Nenue@7 90 ChatEdit_InsertLink(achievementLink);
Nenue@7 91 end
Nenue@7 92 self:SetStyle('CheevNormal')
Nenue@7 93 end
Nenue@0 94
Nenue@0 95 Cheevs.Open = function(self)
Nenue@3 96 if ( not AchievementFrame ) then
Nenue@3 97 AchievementFrame_LoadUI();
Nenue@3 98 end
Nenue@3 99 if ( not AchievementFrame:IsShown() ) then
Nenue@3 100 AchievementFrame_ToggleAchievementFrame();
Nenue@3 101 end
Nenue@3 102 AchievementFrame_SelectAchievement(self.info.cheevID);
Nenue@0 103 end
Nenue@0 104
Nenue@1 105 ----------------------------------------------------------------------------------------
Nenue@1 106 --- frame template and scripts lifted from "QuestKing 2" by Barjack
Nenue@1 107 --- url: http://mods.curse.com/addons/wow/questking
Nenue@1 108 ----------------------------------------------------------------------------------------
Nenue@1 109 local usedButtons = mod.Quest.itemButtons
Nenue@1 110 local freeButtons = mod.Quest.freeButtons
Nenue@1 111 mod.SetItemButton = function(block, info)
Nenue@1 112 local itemInfo = info.specialItem
Nenue@1 113 if not itemInfo then
Nenue@1 114 return
Nenue@1 115 end
Nenue@1 116 --- .specialItem :: {link = link, charges = charges, icon = icon, start = start, duration = duration, enable = enable}
Nenue@1 117
Nenue@1 118
Nenue@1 119 local itemButton
Nenue@1 120 if not info.itemButton then
Nenue@1 121 if #freeButtons >= 1 then
Nenue@2 122 print(' |cFF00FFFFfound a free button')
Nenue@1 123 itemButton = freeButtons[#freeButtons]
Nenue@1 124 freeButtons[#freeButtons] = nil
Nenue@2 125 if itemButton.block then
Nenue@2 126 itemButton.block.itemButton = nil
Nenue@2 127 itemButton.block = nil
Nenue@2 128 end
Nenue@1 129 else
Nenue@1 130 local buttonIndex = mod.Quest.numButtons + #freeButtons + 1
Nenue@1 131 itemButton = CreateFrame('Button', 'VeneerQuestItemButton' .. buttonIndex, UIParent, 'VeneerItemButtonTemplate')
Nenue@1 132 itemButton.buttonIndex = buttonIndex
Nenue@6 133 itemButton:SetSize(itemButtonSize, itemButtonSize)
Nenue@6 134 itemButton:GetNormalTexture():SetSize(itemButtonSize * (5/3), itemButtonSize * (5/3))
Nenue@5 135 print(' |cFFFF4400starting new button', itemButton:GetName())
Nenue@1 136 end
Nenue@1 137 mod.Quest.numButtons = mod.Quest.numButtons + 1
Nenue@1 138 else
Nenue@1 139 itemButton = info.itemButton
Nenue@5 140 print(' |cFF00FF00found assigned button', itemButton:GetName())
Nenue@2 141
Nenue@1 142 end
Nenue@1 143 -- set values
Nenue@2 144
Nenue@5 145 info.itemButton = itemButton
Nenue@5 146 usedButtons[info.questID] = itemButton
Nenue@5 147 print(' |cFF8800FFassigning|r', itemButton:GetName(), 'to quest|cFF00FF00', info.questID, '|rat|cFFFFFF00', block:GetName(),'|r')
Nenue@2 148
Nenue@5 149 for k,v in pairs(usedButtons) do
Nenue@5 150 print('|cFFFF44DD'..k..'|r', v:GetName())
Nenue@5 151 end
Nenue@1 152
Nenue@1 153 itemButton:SetAttribute("type", "item")
Nenue@1 154 itemButton:SetAttribute("item", itemInfo.link)
Nenue@1 155
Nenue@2 156 itemButton.questID = info.questID
Nenue@1 157 itemButton.questLogIndex = info.questLogIndex
Nenue@1 158 itemButton.charges = itemInfo.charges
Nenue@1 159 itemButton.rangeTimer = -1
Nenue@1 160 itemButton.block = block
Nenue@1 161
Nenue@1 162 SetItemButtonTexture(itemButton, itemInfo.icon)
Nenue@1 163 SetItemButtonCount(itemButton, itemInfo.charges)
Nenue@1 164 Veneer_QuestObjectiveItem_UpdateCooldown(itemButton);
Nenue@1 165
Nenue@1 166 return itemButton
Nenue@1 167 end
Nenue@1 168 --- Clear an itemButton from the given block
Nenue@2 169 mod.FreeItemButtons = function(block)
Nenue@2 170
Nenue@2 171 if block.itemButton then
Nenue@2 172 local itemButton = block.itemButton
Nenue@5 173 if itemButton.questID ~= block.info.questID then
Nenue@5 174 block.itemButton = nil
Nenue@5 175 itemButton.block = mod.Quest.InfoBlock[itemButton.questID]
Nenue@5 176 else
Nenue@5 177 itemButton.block = nil
Nenue@5 178 itemButton:Hide()
Nenue@2 179
Nenue@5 180 usedButtons[itemButton.questID] = nil
Nenue@5 181 freeButtons[#freeButtons + 1] = itemButton
Nenue@5 182 mod.Quest.numButtons = mod.Quest.numButtons - 1
Nenue@5 183 print('|cFFFF0088released', itemButton:GetName(),'and', block:GetName())
Nenue@5 184 end
Nenue@1 185 end
Nenue@1 186 end
Nenue@1 187
Nenue@1 188 function Veneer_QuestObjectiveItem_OnUpdate (self, elapsed)
Nenue@1 189 -- Handle range indicator
Nenue@1 190 local rangeTimer = self.rangeTimer
Nenue@1 191 if (rangeTimer) then
Nenue@1 192 rangeTimer = rangeTimer - elapsed
Nenue@1 193 if (rangeTimer <= 0) then
Nenue@1 194 local link, item, charges, showItemWhenComplete = GetQuestLogSpecialItemInfo(self.questLogIndex)
Nenue@1 195 if ((not charges) or (charges ~= self.charges)) then
Nenue@2 196 mod.UpdateWrapper()
Nenue@1 197 return
Nenue@1 198 end
Nenue@1 199
Nenue@1 200 local count = self.HotKey
Nenue@1 201 local valid = IsQuestLogSpecialItemInRange(self.questLogIndex)
Nenue@1 202 if (valid == 0) then
Nenue@1 203 count:Show()
Nenue@1 204 count:SetVertexColor(1.0, 0.1, 0.1)
Nenue@1 205 elseif (valid == 1) then
Nenue@1 206 count:Show()
Nenue@1 207 count:SetVertexColor(0.6, 0.6, 0.6)
Nenue@1 208 else
Nenue@1 209 count:Hide()
Nenue@1 210 end
Nenue@1 211 rangeTimer = TOOLTIP_UPDATE_TIME
Nenue@1 212 end
Nenue@1 213
Nenue@1 214 self.rangeTimer = rangeTimer
Nenue@1 215 end
Nenue@1 216 end
Nenue@1 217
Nenue@1 218 function Veneer_QuestObjectiveItem_UpdateCooldown (itemButton)
Nenue@1 219 local start, duration, enable = GetQuestLogSpecialItemCooldown(itemButton.questLogIndex)
Nenue@1 220 if (start) then
Nenue@1 221 CooldownFrame_SetTimer(itemButton.Cooldown, start, duration, enable)
Nenue@1 222 if (duration > 0 and enable == 0) then
Nenue@1 223 SetItemButtonTextureVertexColor(itemButton, 0.4, 0.4, 0.4)
Nenue@1 224 else
Nenue@1 225 SetItemButtonTextureVertexColor(itemButton, 1, 1, 1)
Nenue@1 226 end
Nenue@1 227 end
Nenue@3 228 end
Nenue@3 229
Nenue@3 230 -----------------------------------------
Nenue@7 231 -- Criteria frames
Nenue@7 232
Nenue@7 233 --[[
Nenue@7 234 text = description,
Nenue@7 235 type = type,
Nenue@7 236 finished = completed,
Nenue@7 237 quantity = quantity,
Nenue@7 238 requiredQuantity = requiredQuantity,
Nenue@7 239 characterName = characterName,
Nenue@7 240 flags = flags,
Nenue@7 241 assetID = assetID,
Nenue@7 242 quantityString = quantityString,
Nenue@7 243 criteriaID = criteriaID,
Nenue@7 244 ]]
Nenue@7 245 local newWidgetID = 0
Nenue@7 246 mod.WidgetRegistry = {}
Nenue@7 247 local wr = mod.WidgetRegistry
Nenue@7 248
Nenue@7 249 --- Get a usable widget for the given achievement criteria set.
Nenue@7 250 -- Returns a frame object with dimensioning parameters needed to size the receiving tracker block
Nenue@7 251 mod.SetWidget = function(obj, info)
Nenue@7 252 local widgetType = obj.type
Nenue@7 253 local widget
Nenue@7 254
Nenue@7 255 if not wr[widgetType] or #wr[widgetType].free == 0 then
Nenue@7 256 print('VeneerObjectiveCriteria' .. widgetType)
Nenue@7 257 widget = CreateFrame('Frame', nil, VeneerObjectiveScroll, 'VeneerObjectiveCriteria' .. widgetType)
Nenue@7 258 end
Nenue@7 259 local free = wr[widgetType].free
Nenue@7 260 local used = wr[widgetType].used
Nenue@7 261
Nenue@7 262 widget = tremove(free)
Nenue@7 263 local index = #used+1
Nenue@7 264 used[index] = widget
Nenue@7 265 wr[widgetType].usedIndex[widget] = index
Nenue@7 266 widget.info = obj
Nenue@7 267 widget.parentInfo = info
Nenue@7 268 mod.InitializeWidget(widget)
Nenue@7 269
Nenue@7 270 return widget
Nenue@3 271 end
Nenue@3 272
Nenue@7 273 --- Fired by OnLoad() when a new frame is spawned
Nenue@7 274 mod.RegisterWidget = function(frame)
Nenue@7 275 local widgetType = frame.widgetType
Nenue@7 276 local obj = frame.info
Nenue@7 277 if not wr[frame.widgetType] then
Nenue@7 278 print('|cFFFF4400[[WidgetTemplate]]|r', widgetType)
Nenue@7 279 wr[widgetType] = { lastn = 0, free = {}, used = {}, usedIndex = {}, freeIndex = {} }
Nenue@3 280 end
Nenue@7 281 tinsert(wr[frame.widgetType].free, frame)
Nenue@7 282 end
Nenue@7 283 mod.InitializeWidget = setmetatable({}, {
Nenue@7 284 __call = function(t, frame)
Nenue@7 285 -- todo: config pull
Nenue@7 286 local maxWidth = 250
Nenue@3 287
Nenue@7 288 frame:SetWidth(maxWidth)
Nenue@7 289 mod.UpdateWidget[frame.widgetType](frame)
Nenue@7 290 frame:SetScript('OnEvent', mod.UpdateWidget[frame.widgetType])
Nenue@7 291 if frame.info.isCurrency then
Nenue@7 292 frame:RegisterEvent('CHAT_MSG_CURRENCY')
Nenue@7 293 frame:RegisterEvent('CURRENCY_LIST_UPDATE')
Nenue@7 294 end
Nenue@7 295 frame:RegisterEvent('TRACKED_ACHIEVEMENT_UPDATE')
Nenue@7 296 frame:RegisterEvent('TRACKED_ACHIEVEMENT_LIST_CHANGED')
Nenue@7 297 frame:RegisterEvent('CRITERIA_UPDATE')
Nenue@7 298 frame:RegisterEvent('CRITERIA_COMPLETE')
Nenue@7 299 frame:RegisterEvent('CRITERIA_EARNED')
Nenue@7 300
Nenue@7 301 return t[frame.widgetType](frame)
Nenue@7 302 end,
Nenue@7 303 })
Nenue@7 304 mod.UpdateWidget = setmetatable({}, {
Nenue@7 305 __call = function(t, frame)
Nenue@7 306 if not frame.widgetType then
Nenue@7 307 error('Invalid widget template, needs .widgetType')
Nenue@7 308 return
Nenue@7 309 end
Nenue@7 310
Nenue@7 311 return t[frame.widgetType](frame)
Nenue@7 312 end
Nenue@7 313 })
Nenue@7 314
Nenue@7 315 mod.ReleaseWidget = function(frame)
Nenue@7 316 local reg = wr[frame.widgetType]
Nenue@7 317 if reg and reg.usedIndex[frame] then
Nenue@7 318 tremove(reg.used, reg.usedIndex[frame])
Nenue@7 319 reg.usedIndex[frame] = nil
Nenue@7 320 frame:UnregisterAllEvents()
Nenue@7 321 tinsert(reg.free, frame)
Nenue@3 322 end
Nenue@3 323 end
Nenue@7 324
Nenue@7 325 mod.WidgetParams = {
Nenue@7 326 ['ProgressBar'] = {
Nenue@7 327 height = 20,
Nenue@7 328 caption = {},
Nenue@7 329 quantityString = {SetFontObject = _G.VeneerFontNormal}
Nenue@7 330 }
Nenue@7 331 }
Nenue@7 332
Nenue@7 333 mod.InitializeWidget.ProgressBar = function(self)
Nenue@7 334 local params = mod.WidgetParams[self.widgetType]
Nenue@7 335 self.height = params.height
Nenue@7 336 self:SetHeight(20)
Nenue@7 337 self.bg:SetHeight(20)
Nenue@7 338 self.fg:SetHeight(18)
Nenue@7 339 self.fg:SetPoint('BOTTOMLEFT', self.bg, 'BOTTOMLEFT', 1, 1)
Nenue@7 340 self.quantityString:SetFontObject(params.quantityString.SetFontObject)
Nenue@7 341 self.quantityString:SetText(self.info.quantityString)
Nenue@3 342 end
Nenue@7 343
Nenue@7 344 mod.UpdateWidget.ProgressBar = function (self)
Nenue@7 345 local quantity, requiredQuantity = self.info.quantity, self.info.requiredQuantity
Nenue@7 346 self.fg:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 0)
Nenue@7 347 if self.info.finished then
Nenue@7 348 self.fg:SetWidth(self.bg:GetWidth() - 2)
Nenue@7 349 elseif quantity == 0 then
Nenue@7 350 self.fg:Hide()
Nenue@7 351 else
Nenue@7 352 self.fg:Show()
Nenue@7 353 self.fg:SetWidth(self:GetWidth() * (quantity / requiredQuantity))
Nenue@7 354 end
Nenue@3 355
Nenue@3 356 end