annotate ObjectiveFrame.lua @ 9:2698173edd40

ObjectiveUI & ObjectiveEvents - securehook to API calls for compatibility with addons that work with the objective tracking interface - let the API hooks invoke ObjectiveUI functions when possible - ObjectiveUI framescript handlers should use the corresponding API call if possible, so that addon space can be fully aware of our actions - Sanity check cached data when possible during 'Remove' hooks ObjectiveInfo - Add cheevID to criteria info ObjectiveCore - Index quest tracker blocks by their watch offset, and use that to verify whether the given block frame should be released into pool ObjectiveFrame - Differentiate between visible and non-visible unused buttons, and only release when their quest has been dropped - Reset 'actualBlocks' count during full updates - Reset scroll Position when the wrapper size shrinks
author Nenue
date Fri, 01 Apr 2016 14:54:01 -0400
parents 7923243ae972
children f03c75f63566
rev   line source
Nenue@1 1 --- ${PACKAGE_NAME}
Nenue@1 2 -- @file-author@
Nenue@1 3 -- @project-revision@ @project-hash@
Nenue@1 4 -- @file-revision@ @file-hash@
Nenue@1 5 -- Created: 3/30/2016 12:49 AM
Nenue@1 6 local B = select(2,...).frame
Nenue@2 7 local ipairs, max, min, unpack, floor, pairs, tostring, type = ipairs, max, min, unpack, floor, pairs, tostring, type
Nenue@2 8 local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion
Nenue@2 9 local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent
Nenue@1 10 local CreateFrame = CreateFrame
Nenue@1 11 local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
Nenue@1 12 local print = B.print('Objectives')
Nenue@1 13 --------------------------------------------------------------------
Nenue@1 14 --- Global frame layout
Nenue@1 15 --------------------------------------------------------------------
Nenue@1 16
Nenue@1 17 --- Upvalues
Nenue@2 18 local Wrapper = VeneerObjectiveWrapper
Nenue@1 19 local Scroller = Wrapper.scrollArea
Nenue@2 20 local Scroll = VeneerObjectiveScroll
Nenue@1 21 local orderedHandlers = mod.orderedHandlers
Nenue@1 22 local orderedNames = mod.orderedNames
Nenue@1 23
Nenue@1 24 --- Temp values set during updates
Nenue@1 25 local wrapperWidth, wrapperHeight
Nenue@1 26 local scrollWidth, scrollHeight
Nenue@1 27 local previousBlock
Nenue@1 28 local currentBlock
Nenue@1 29 --- todo: map these into config table when its sorted out
Nenue@6 30 local itemButtonSize, itemButtonSpacing = 36, 1
Nenue@1 31 local titleFont, textFont = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]]
Nenue@1 32 local titleSize, textSize = 15, 15
Nenue@1 33 local titleOutline, textOutline = "OUTLINE", "OUTLINE"
Nenue@1 34 local titleSpacing, textSpacing = 4, 3
Nenue@1 35 local textIndent = 5
Nenue@1 36 local wrapperMaxWidth, wrapperMaxHeight = 280, 490 -- these are the hard bounds, actual *Height variables are changed
Nenue@2 37 local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE'
Nenue@1 38 local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24
Nenue@2 39 local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2
Nenue@1 40 local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0}
Nenue@1 41
Nenue@2 42 --- These are mostly aesthetic choices so it lives here
Nenue@1 43 mod.defaults = {
Nenue@1 44 ObjectiveTrackerAnchor = {'BOTTOM', 'RIGHT'},
Nenue@1 45 ObjectiveTrackerParent = 'DebuffButton',
Nenue@1 46 ObjectiveTrackerSize = {250, 600},
Nenue@1 47 ObjectiveWrapperParent = '',
Nenue@2 48 WrapperStyle = {
Nenue@2 49 Header = {
Nenue@6 50 Background = {Left = '', Right = '', Tile = ''},
Nenue@2 51 BackgroundCrop = {Left = {0, 0.4, 0,1}, Right={0.6,1,0,1}, Tile = {0.4,.6,0,1,}},
Nenue@2 52 BackgroundScale = {Left = 100, Right = 100},
Nenue@2 53 Font = {wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline}
Nenue@2 54 }
Nenue@2 55 },
Nenue@2 56 ObjectiveHeaderStyle = {
Nenue@2 57 Normal = {
Nenue@6 58 Gradient = {MinColor = {.05,.15,0.5,0.7}, MaxColor = {.05,.15,0.5,.35}},
Nenue@2 59 Font = {headerFont, headerSize, headerOutline}, Spacing = headerSpacing,
Nenue@2 60 }
Nenue@2 61 },
Nenue@1 62 ObjectiveTrackerStyle = {
Nenue@1 63 Normal = {
Nenue@1 64 Title = {
Nenue@6 65 Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
Nenue@1 66 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@1 67 },
Nenue@1 68 Text = {
Nenue@6 69 Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
Nenue@1 70 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@1 71 },
Nenue@1 72 },
Nenue@1 73 Super = {
Nenue@1 74 Title = {
Nenue@1 75 Gradient = { MinColor = {0, .7, .6, .8}, MaxColor = {0, .7, .6, 0.2}},
Nenue@1 76 Font = {titleFont, titleSize, titleOutline},
Nenue@1 77 Spacing = titleSpacing, BackgroundFullWidth = true
Nenue@1 78 },
Nenue@1 79 Text = {
Nenue@1 80 Gradient = { MinColor = {0, .7, .6, 0.5}, MaxColor = {0, .7, .6, 0.1} },
Nenue@1 81 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@1 82 },
Nenue@1 83 },
Nenue@1 84 Active = {
Nenue@1 85 Title = {
Nenue@7 86 Gradient = { MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .4}, },
Nenue@1 87 Font = {titleFont, titleSize, titleOutline},
Nenue@1 88 Spacing = titleSpacing,
Nenue@1 89 BackgroundFullWidth = true
Nenue@1 90 },
Nenue@1 91 Text = {
Nenue@7 92 Gradient = { MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .2}, },
Nenue@1 93 Font = {textFont, textSize, textOutline},
Nenue@1 94 Spacing = textSpacing,
Nenue@1 95 BackgroundFullWidth = true
Nenue@1 96 }
Nenue@1 97 },
Nenue@1 98 Complete = {
Nenue@1 99 Title = {
Nenue@1 100 Gradient = { MinColor = {0, 1, 0, 0.34}, MaxColor = {0, 1, 0, .17}, },
Nenue@1 101 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@1 102 BackgroundFullWidth = true
Nenue@1 103 },
Nenue@1 104 Text = {
Nenue@1 105 Gradient = { MinColor = {0, 1, 0, .25}, MaxColor = {0, 1, 0, 0.12}, },
Nenue@1 106 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@1 107 BackgroundFullWidth = true
Nenue@1 108 }
Nenue@1 109 },
Nenue@7 110 CheevNormal = {
Nenue@7 111
Nenue@7 112 Title = {
Nenue@7 113 Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
Nenue@7 114 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@7 115 },
Nenue@7 116 Text = {
Nenue@7 117 Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
Nenue@7 118 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@7 119 },
Nenue@7 120 },
Nenue@7 121 CheevComplete = {
Nenue@7 122
Nenue@7 123 Title = {
Nenue@7 124 Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
Nenue@7 125 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@7 126 },
Nenue@7 127 Text = {
Nenue@7 128 Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
Nenue@7 129 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@7 130 },
Nenue@7 131 }
Nenue@1 132 }
Nenue@1 133 }
Nenue@1 134
Nenue@3 135 local FontBank = {
Nenue@3 136 ['Normal'] = VeneerCriteriaFontNormal,
Nenue@3 137 ['Progress'] = VeneerCriteriaFontProgress,
Nenue@3 138 ['Complete'] = VeneerCriteriaFontComplete,
Nenue@3 139 ['Failed'] = VeneerCriteriaFontFailed,
Nenue@3 140 }
Nenue@3 141
Nenue@2 142 local Scroller_OnShow = function()
Nenue@2 143 Wrapper.watchMoneyReasons = 0;
Nenue@2 144 mod.UpdateWrapper()
Nenue@2 145 mod.SetEvents()
Nenue@2 146 for i, region in ipairs(Wrapper.header) do
Nenue@2 147 region:Show()
Nenue@2 148 end
Nenue@2 149 end
Nenue@2 150
Nenue@2 151 local Scroller_OnHide = function()
Nenue@2 152 local self = Wrapper
Nenue@2 153 Wrapper:UnregisterAllEvents()
Nenue@2 154 Wrapper:SetScript('OnEvent', nil)
Nenue@2 155 for i, region in ipairs(Wrapper.header) do
Nenue@2 156 region:Hide()
Nenue@2 157 end
Nenue@2 158 end
Nenue@2 159
Nenue@2 160 local Scroller_OnMouseWheel = function(self, delta)
Nenue@2 161 local r = Scroll:GetHeight() - Scroller:GetHeight()
Nenue@7 162 local s = B.Conf.ObjectiveScroll - delta * floor(r/5+.5)
Nenue@7 163 local from = self:GetVerticalScroll()
Nenue@2 164 if s >= r then
Nenue@2 165 s = r
Nenue@2 166 elseif s < 1 then
Nenue@2 167 s = 0
Nenue@2 168 end
Nenue@2 169 self:SetVerticalScroll(s)
Nenue@7 170 B.Conf.ObjectiveScroll = s
Nenue@7 171 print('|cFF00FF00OnMouseWheel', 'from = ', from, 'scroll =', s, ' range =', r, 'current =', self:GetVerticalScroll())
Nenue@2 172
Nenue@6 173 mod.UpdateActionButtons('SCROLLING')
Nenue@2 174 end
Nenue@2 175
Nenue@2 176 local WrapperCloseButton_OnClick = function(self)
Nenue@2 177 if Scroller:IsVisible() then
Nenue@2 178 Scroller:Hide()
Nenue@2 179 else
Nenue@2 180 Scroller:Show()
Nenue@2 181 end
Nenue@2 182 end
Nenue@2 183
Nenue@2 184 mod.InitializeTrackers = function()
Nenue@2 185
Nenue@2 186 local c = mod.defaults.ObjectiveHeaderStyle.Normal
Nenue@2 187 local g1, g2, g3, g4 = unpack(c.Gradient.MinColor)
Nenue@2 188 local h1, h2, h3, h4 = unpack(c.Gradient.MaxColor)
Nenue@2 189
Nenue@2 190 for i, name in ipairs(orderedNames) do
Nenue@2 191 if not mod.orderedHandlers[i] then
Nenue@2 192 if mod.Tracker(name, i) then
Nenue@2 193 local handler = mod[name]
Nenue@2 194
Nenue@2 195 local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate')
Nenue@2 196 tracker.header:SetText(handler.name)
Nenue@2 197 tracker.header:SetHeight(headerHeight)
Nenue@2 198 tracker.header:SetFont(unpack(c.Font))
Nenue@2 199 tracker.header:SetTextColor(unpack(headerColor))
Nenue@2 200
Nenue@2 201 tracker.headerbg:SetGradientAlpha('HORIZONTAL', g1, g2 ,g3, g4, h1, h2, h3, h4)
Nenue@2 202 tracker.headerbg:SetHeight(headerHeight)
Nenue@2 203
Nenue@2 204 handler.Tracker = tracker
Nenue@2 205 mod.orderedTrackers[i] = tracker
Nenue@2 206 mod.namedTrackers[name] = tracker
Nenue@2 207 mod.indexedTrackers[handler] = tracker
Nenue@2 208 print('created new tracker frames for new handler')
Nenue@2 209 end
Nenue@2 210 end
Nenue@2 211 end
Nenue@2 212
Nenue@2 213 Scroller:SetScrollChild(Scroll)
Nenue@2 214 Scroller:SetScript('OnMouseWheel', Scroller_OnMouseWheel)
Nenue@2 215 Scroller:SetScript('OnShow', Scroller_OnShow)
Nenue@2 216 Scroller:SetScript('OnHide', Scroller_OnHide)
Nenue@2 217 Wrapper.close:SetScript('OnClick', WrapperCloseButton_OnClick)
Nenue@2 218 Wrapper:SetPoint(unpack(wrapperPosition))
Nenue@2 219 Scroller_OnShow(Scroller)
Nenue@2 220
Nenue@2 221 mod.UpdateWrapperStyle()
Nenue@2 222 end
Nenue@2 223
Nenue@2 224 mod.InitializeXPTracker = function()
Nenue@2 225 local XPBar = Wrapper.XPBar
Nenue@2 226 if UnitLevel('player') == 100 then
Nenue@2 227 XPBar:Hide()
Nenue@2 228 return
Nenue@2 229 end
Nenue@2 230
Nenue@2 231 --- xp bar
Nenue@6 232 XPBar:SetWidth(wrapperWidth - Wrapper.close:GetWidth())
Nenue@6 233 XPBar.bg:SetAllPoints(XPBar)
Nenue@6 234 XPBar:RegisterEvent('DISABLE_XP_GAIN')
Nenue@6 235 XPBar:RegisterEvent('ENABLE_XP_GAIN')
Nenue@2 236 XPBar:SetScript('OnEvent', mod.UpdateXP)
Nenue@6 237
Nenue@6 238 if not IsXPUserDisabled() then
Nenue@6 239 mod.EnableXP(XPBar)
Nenue@6 240 else
Nenue@6 241 mod.DisableXP(XPBar)
Nenue@6 242 end
Nenue@6 243
Nenue@6 244 mod.UpdateXP(XPBar)
Nenue@2 245 end
Nenue@2 246
Nenue@6 247 mod.EnableXP = function(self)
Nenue@6 248 self:RegisterEvent('PLAYER_XP_UPDATE')
Nenue@6 249 self:RegisterEvent('PLAYER_LEVEL_UP')
Nenue@6 250 self:RegisterEvent('PLAYER_UPDATE_RESTING')
Nenue@6 251 self.bg:SetTexture(0,0,0,.25)
Nenue@6 252 self:Show()
Nenue@6 253 end
Nenue@2 254
Nenue@6 255 mod.DisableXP = function(self)
Nenue@6 256 self:UnregisterEvent('PLAYER_XP_UPDATE')
Nenue@6 257 self:UnregisterEvent('PLAYER_LEVEL_UP')
Nenue@6 258 self:UnregisterEvent('PLAYER_UPDATE_RESTING')
Nenue@6 259 self.bg:SetTexture(0.5,0.5,0.5,0.5)
Nenue@6 260 self:Hide()
Nenue@6 261 end
Nenue@2 262
Nenue@6 263 mod.UpdateXP = function(self, event)
Nenue@6 264 if event == 'DISABLE_XP_GAIN' then
Nenue@6 265 mod.DisableXP(self)
Nenue@6 266 elseif event == 'ENABLE_XP_GAIN' then
Nenue@6 267 mod.EnableXP(self)
Nenue@2 268 end
Nenue@2 269
Nenue@6 270 if not IsXPUserDisabled() then
Nenue@6 271
Nenue@6 272 local xp = UnitXP('player')
Nenue@6 273 local xpmax = UnitXPMax('player')
Nenue@6 274 local rest = GetXPExhaustion()
Nenue@6 275 self.fg:SetWidth((xp/xpmax) * self:GetWidth())
Nenue@6 276 if rest then
Nenue@6 277 self.rested:ClearAllPoints()
Nenue@6 278 if xp == 0 then
Nenue@6 279 self.rested:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 0)
Nenue@6 280 else
Nenue@6 281 self.rested:SetPoint('TOPLEFT', self.fg, 'TOPRIGHT', 0, 0)
Nenue@6 282 end
Nenue@6 283
Nenue@6 284 if (xp + rest) > xpmax then
Nenue@6 285 self.rested:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, 0)
Nenue@6 286 else
Nenue@6 287 self.rested:SetWidth((rest/xpmax) * self:GetWidth())
Nenue@6 288 end
Nenue@6 289 self.rested:SetPoint('BOTTOM', self, 'BOTTOM')
Nenue@6 290 self.rested:Show()
Nenue@2 291 else
Nenue@6 292 self.rested:Hide()
Nenue@2 293 end
Nenue@2 294
Nenue@6 295 if IsResting() then
Nenue@6 296 self.bg:SetTexture(.2,.8,.2,.5)
Nenue@2 297 else
Nenue@6 298 self.bg:SetTexture(0,0,0,.25)
Nenue@2 299 end
Nenue@6 300 self.xpText:SetText(xp .. '/'.. xpmax .. (rest and (' ('..tostring(rest)..')') or ''))
Nenue@2 301 end
Nenue@2 302 end
Nenue@2 303
Nenue@2 304 mod.UpdateReputation = function(self)
Nenue@2 305 end
Nenue@1 306
Nenue@1 307 --- Argument containers
Nenue@1 308 local a1, a2, a3, a4, b1, b2, b3, b4, f1, f2, f3, w1, w2
Nenue@1 309 mod.SetBlockStyle = function(block, name)
Nenue@1 310 -- var names intended to reflect argument order
Nenue@2 311 --@debug@
Nenue@1 312 local c = mod.defaults.ObjectiveTrackerStyle[name]
Nenue@2 313 --@end-debug@
Nenue@2 314 --[===[@non-debug
Nenue@2 315 local c = mod.Conf
Nenue@2 316 --@end-non-debug]===]
Nenue@1 317 a1, a2, a3, a4 = unpack(c.Title.Gradient.MinColor)
Nenue@1 318 b1, b2, b3, b4 = unpack(c.Title.Gradient.MaxColor)
Nenue@1 319 block.titlebg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
Nenue@1 320
Nenue@1 321 a1, a2, a3, a4 = unpack(c.Text.Gradient.MinColor)
Nenue@1 322 b1, b2, b3, b4 = unpack(c.Text.Gradient.MaxColor)
Nenue@1 323 block.bg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
Nenue@1 324
Nenue@1 325 f1, f2, f3 = unpack(c.Title.Font)
Nenue@1 326 block.title:SetFont(f1, f2, f3)
Nenue@1 327
Nenue@1 328 f1, f2 ,f3 = unpack(c.Text.Font)
Nenue@1 329 block.objectives:SetFont(f1,f2,f3)
Nenue@1 330
Nenue@1 331 w1 = Wrapper:GetWidth()
Nenue@1 332 w2 = (c.Title.BackgroundFullWidth and w1 or block.title:GetStringWidth())
Nenue@1 333
Nenue@1 334 local titleSpacing, titleSpacing2 = c.Title.Spacing, (c.Title.Spacing * 2)
Nenue@1 335 local textSpacing, textSpacing2 = c.Text.Spacing, (c.Text.Spacing * 2)
Nenue@1 336
Nenue@1 337 if block.info.isTrivial then
Nenue@1 338 block.title:SetTextColor(0.7, 0.7, 0.7, 1)
Nenue@1 339 elseif block.info.isComplete then
Nenue@1 340 block.title:SetTextColor(1,1,1,1)
Nenue@1 341 else
Nenue@1 342 block.title:SetTextColor(0,.7,1,1)
Nenue@1 343 end
Nenue@1 344 block.title:SetSpacing(titleSpacing)
Nenue@1 345 block.objectives:SetSpacing(textSpacing)
Nenue@1 346 block.objectives:SetWordWrap(true)
Nenue@1 347
Nenue@7 348 local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight() + block.attachmentHeight
Nenue@1 349 local blockHeight = titleHeight + titleSpacing2 + textHeight + textSpacing2
Nenue@1 350 local blockWidth = wrapperMaxWidth
Nenue@1 351
Nenue@1 352 block.titlebg:SetSize(min(w1, w2), titleHeight + titleSpacing2)
Nenue@1 353 block.bg:SetSize(w1, textHeight + textSpacing2)
Nenue@1 354 block:SetSize(blockWidth, blockHeight)
Nenue@1 355
Nenue@1 356 block.title:SetPoint('TOPLEFT', block.titlebg, 'TOPLEFT', 0, -titleSpacing)
Nenue@1 357 block.objectives:SetPoint('TOPLEFT', block.titlebg, 'BOTTOMLEFT', textIndent, -textSpacing)
Nenue@1 358
Nenue@1 359 -- store
Nenue@1 360 block.titleHeight = titleHeight
Nenue@1 361 block.textHeight = textHeight
Nenue@1 362 block.width = blockWidth
Nenue@1 363 block.height = blockHeight
Nenue@1 364
Nenue@2 365 print(' |cFF00FFFF'..block:GetName()..'|r:|cFF0088FFSetStyle|r(', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
Nenue@2 366 end
Nenue@2 367
Nenue@2 368 local segments = {'Left', 'Right', 'Tile'}
Nenue@2 369 mod.UpdateWrapperStyle = function()
Nenue@2 370 local c = mod.defaults.WrapperStyle
Nenue@2 371 for _, segment in ipairs(segments) do
Nenue@2 372 Wrapper['Background'..segment]:SetAtlas(c.Header.Background[segment])
Nenue@2 373 Wrapper['Background'..segment]:SetTexCoord(unpack(c.Header.BackgroundCrop[segment]))
Nenue@2 374 if c.Header.BackgroundScale[segment] then
Nenue@2 375 Wrapper['Background'..segment]:SetWidth(c.Header.BackgroundScale[segment])
Nenue@2 376 end
Nenue@2 377 end
Nenue@1 378 end
Nenue@1 379
Nenue@1 380 --- Updates the selected block frame to display the given info batch
Nenue@1 381 -- If `previousBlock` is set, it will attempt to anchor to that
Nenue@1 382 -- @param blockNum the ordered block to be updated, not a watchIndex value
Nenue@1 383 -- @param info the reference returned by the GetXInfo functions
Nenue@1 384 -- REMEMBER: t.info and questData[questID] are the same table
Nenue@1 385 mod.UpdateTrackerBlock = function (handler, blockIndex, info)
Nenue@2 386 print(' |cFF00FFFFUpdateTrackerBlock('..blockIndex..'|r')
Nenue@1 387 if not blockIndex or not info then
Nenue@1 388 return
Nenue@1 389 end
Nenue@1 390
Nenue@1 391 local tracker = handler.Tracker
Nenue@1 392
Nenue@1 393 local t = handler:GetBlock(blockIndex)
Nenue@1 394 if previousBlock then
Nenue@1 395 if blockIndex == 1 then
Nenue@1 396 t:SetPoint('TOPLEFT', previousBlock, 'TOPLEFT', 0, -headerHeight)
Nenue@1 397 else
Nenue@1 398 t:SetPoint('TOPLEFT', previousBlock, 'BOTTOMLEFT', 0, 0)
Nenue@1 399 end
Nenue@1 400 t:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
Nenue@1 401 end
Nenue@2 402 --print(t:GetName(), t:GetSize())
Nenue@2 403 --print(t:GetPoint(1))
Nenue@1 404
Nenue@1 405 t.info = info
Nenue@1 406
Nenue@5 407 if info.questID then handler.QuestBlock[info.questID] = t end
Nenue@1 408 if info.questLogIndex then handler.LogBlock[info.questLogIndex] = t end
Nenue@1 409 if info.watchIndex then handler.WatchBlock[info.watchIndex] = t end
Nenue@1 410
Nenue@1 411 info.blockIndex = blockIndex
Nenue@1 412 handler.BlockInfo[blockIndex] = info
Nenue@7 413
Nenue@1 414 t.Select = handler.Select
Nenue@1 415 t.Open = handler.Open
Nenue@1 416 t.Remove = handler.Remove
Nenue@1 417 t.Link = handler.Link
Nenue@1 418 t:SetScript('OnMouseUp', handler.OnMouseUp)
Nenue@1 419 t:SetScript('OnMouseDown', handler.OnMouseDown)
Nenue@1 420 t.title:SetText(info.title)
Nenue@1 421
Nenue@7 422 t.attachmentHeight = 0
Nenue@1 423 if info.isComplete then
Nenue@1 424 t.objectives:Show()
Nenue@1 425 t.objectives:SetText(info.completionText)
Nenue@1 426 elseif info.numObjectives >= 1 then
Nenue@7 427 t.attachmentHeight = textSpacing
Nenue@1 428 t.objectives:Show()
Nenue@2 429 print(' - objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
Nenue@3 430
Nenue@1 431 local text = ''
Nenue@3 432
Nenue@3 433 --- todo: implement objective displays
Nenue@3 434 -- in an accumulator loop, call upon handler for the appropriate display frame, each defining:
Nenue@3 435 -- * height of whatever display widget is involved in conveying the task
Nenue@3 436 -- * number of non-wrapped text lines to account for line space; may be discarded depending on things
Nenue@3 437 -- * boolean that determines listening for money events or not
Nenue@4 438 t.attachmentHeight, text = mod.UpdateObjectives(t, info, text)
Nenue@3 439
Nenue@1 440 t.objectives:SetText(text)
Nenue@3 441 t.objectives:SetWordWrap(true)
Nenue@1 442
Nenue@1 443
Nenue@1 444
Nenue@1 445 elseif info.description then
Nenue@1 446 t.objectives:SetText(info.description)
Nenue@1 447 t.objectives:SetWordWrap(true)
Nenue@1 448 else
Nenue@1 449 t.objectives:SetText(nil)
Nenue@1 450 end
Nenue@1 451 local style = 'Normal'
Nenue@1 452 if info.isComplete then
Nenue@1 453 style = 'Complete'
Nenue@1 454 elseif info.superTracked then
Nenue@1 455 style = 'Super'
Nenue@1 456 end
Nenue@1 457
Nenue@5 458 if info.specialItem and not info.itemButton then
Nenue@5 459 print(' - |cFF00FFFFgenerating item button for info set')
Nenue@4 460 info.itemButton = mod.SetItemButton(t, info)
Nenue@4 461 else
Nenue@4 462 --info.itemButton = nil
Nenue@4 463 end
Nenue@4 464
Nenue@6 465 if Devian and Devian.InWorkspace() then
Nenue@6 466 t.debugText:Show()
Nenue@6 467 t.debugText:SetText(tostring(blockIndex) .. '\n' .. tostring(info.itemButton and info.itemButton:GetName()))
Nenue@6 468 end
Nenue@6 469
Nenue@3 470 --- metrics are calculated in SetStyle
Nenue@1 471 t:SetStyle(style)
Nenue@3 472 t:Show()
Nenue@1 473
Nenue@3 474 print(' |cFF00FFFF)|r -> ', t, t:GetHeight())
Nenue@1 475 return t
Nenue@1 476 end
Nenue@1 477
Nenue@4 478 mod.UpdateObjectives = function(block, info, text)
Nenue@7 479 local attachmentHeight = block.attachmentHeight
Nenue@7 480 if info.description then
Nenue@7 481 print(' -- has description text:', select('#', info.description), info.description)
Nenue@7 482 text = info.description
Nenue@7 483 end
Nenue@4 484 for o, obj in ipairs(info.objectives) do
Nenue@4 485 --- achievement criteria
Nenue@4 486 if obj.flags then
Nenue@4 487
Nenue@4 488
Nenue@4 489 if bit.band(obj.flags, 0x00000001) > 0 then
Nenue@4 490 obj.type = 'ProgressBar'
Nenue@4 491 elseif bit.band(obj.flags, 0x00000002) then
Nenue@4 492 obj.type = 'Hidden'
Nenue@4 493 obj.widget = nil
Nenue@4 494 else
Nenue@4 495 obj.type = 'Text'
Nenue@4 496 obj.widget = nil
Nenue@4 497 text = text .. ((text == '') and "" or "\n") .. obj.text
Nenue@4 498 end
Nenue@4 499
Nenue@7 500 print('obj.type =', obj.type)
Nenue@7 501 print(' ** qtyStr:', obj.quantityString, 'qty:', obj.quantity, 'assetID:', obj.assetID)
Nenue@7 502 obj.widget = mod.SetWidget(obj, info)
Nenue@4 503 --- none of the above (most quests)
Nenue@4 504 else
Nenue@4 505 local line = obj.text
Nenue@4 506 local color = '00FFFF'
Nenue@4 507 if obj.finished then
Nenue@4 508 color = 'FFFFFF'
Nenue@4 509 elseif obj.type == 'monster' then
Nenue@4 510 color = 'FFFF00'
Nenue@4 511 elseif obj.type == 'item' then
Nenue@4 512 color = '44DDFF'
Nenue@4 513 elseif obj.type == 'object' then
Nenue@4 514 color = 'FF44DD'
Nenue@4 515 end
Nenue@4 516 text = text .. ((text == '') and "" or "\n") .. '|cFF'..color.. line .. '|r'
Nenue@4 517 end
Nenue@4 518
Nenue@4 519 if obj.widget then
Nenue@7 520
Nenue@7 521 obj.widget:Show()
Nenue@7 522 obj.widget:SetPoint('TOPLEFT', block.objectives, 'BOTTOMLEFT', 0, -attachmentHeight)
Nenue@7 523 print('have a widget, height is', obj.widget.height)
Nenue@4 524 attachmentHeight = attachmentHeight + obj.widget.height
Nenue@4 525 end
Nenue@4 526
Nenue@4 527 end
Nenue@4 528 return attachmentHeight, text
Nenue@4 529 end
Nenue@4 530
Nenue@1 531 mod.UpdateTracker = function(handler)
Nenue@1 532 print('|cFF00FF88UpdateTracker(|r|cFFFF4400' .. type(handler) .. '|r :: |cFF88FFFF' .. tostring(handler) .. '|r')
Nenue@1 533 local tracker = handler.Tracker
Nenue@1 534 local blockIndex = 0
Nenue@1 535 local trackerHeight = headerHeight
Nenue@1 536 local w = 300
Nenue@1 537
Nenue@1 538 previousBlock = handler.Tracker
Nenue@1 539 local numWatched = handler.GetNumWatched()
Nenue@1 540 local numBlocks = handler.numBlocks
Nenue@9 541 local actualBlocks = 0
Nenue@1 542 for watchIndex = 1, 25 do
Nenue@1 543 blockIndex = blockIndex + 1
Nenue@1 544 if watchIndex <= numWatched then
Nenue@1 545 local info = handler:GetInfo(watchIndex)
Nenue@1 546 if info then
Nenue@1 547 local currentBlock = mod.UpdateTrackerBlock(handler, blockIndex, info)
Nenue@1 548 previousBlock = currentBlock
Nenue@1 549 trackerHeight = trackerHeight + currentBlock.height
Nenue@1 550 numBlocks = max(numBlocks, watchIndex)
Nenue@1 551 actualBlocks = actualBlocks + 1
Nenue@1 552 else
Nenue@1 553 print('|cFFFF0000Failed to draw info for index #'..watchIndex)
Nenue@1 554 end
Nenue@1 555
Nenue@1 556 elseif watchIndex <= numBlocks then
Nenue@1 557 local used = handler.usedBlocks
Nenue@1 558 local free = handler.freeBlocks
Nenue@1 559 print('clean up dead quest block')
Nenue@1 560 if used[blockIndex] then
Nenue@1 561 used[blockIndex]:Hide()
Nenue@1 562 used[blockIndex]:ClearAllPoints()
Nenue@1 563 free[#free+1]= used[blockIndex]
Nenue@1 564 used[blockIndex] = nil
Nenue@1 565 end
Nenue@1 566 else
Nenue@1 567 print('Stopping scan at', blockIndex)
Nenue@1 568 break -- done with quest stuff
Nenue@1 569 end
Nenue@1 570 end
Nenue@1 571 handler.numWatched = numWatched
Nenue@1 572 handler.numBlocks = numBlocks
Nenue@1 573 handler.actualBlocks = actualBlocks
Nenue@1 574 handler:Report()
Nenue@1 575 previousBlock = nil
Nenue@1 576 if numBlocks > 0 then
Nenue@1 577 tracker.height = trackerHeight
Nenue@1 578 else
Nenue@1 579 tracker.height = 0
Nenue@1 580 end
Nenue@1 581
Nenue@1 582 print('|cFF00FF88)|r ->', numBlocks, 'blocks; height', tracker.height, 'last block: ')
Nenue@1 583 end
Nenue@1 584
Nenue@1 585 mod.Quest.numButtons = 0
Nenue@1 586 local usedButtons = mod.Quest.itemButtons
Nenue@1 587 local freeButtons = mod.Quest.freeButtons
Nenue@1 588 mod.UpdateWrapper = function()
Nenue@1 589 wrapperWidth = wrapperMaxWidth
Nenue@1 590 scrollWidth = wrapperWidth
Nenue@1 591 local wrapperBlocks = 0
Nenue@1 592 -- Update scroll child vertical size
Nenue@1 593 scrollHeight = 0
Nenue@1 594 for i, handler in ipairs(orderedHandlers) do
Nenue@1 595 mod.UpdateTracker(handler)
Nenue@1 596 if handler.actualBlocks >= 1 then
Nenue@1 597 local tracker = handler.Tracker
Nenue@1 598 print('setting', handler.Tracker, 'to anchor to offset', -scrollHeight)
Nenue@1 599 tracker:SetParent(Scroll) -- this doesn't do anything that relativeTo doesn't
Nenue@1 600 tracker:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight)
Nenue@1 601 tracker:SetSize(wrapperWidth, tracker.height)
Nenue@1 602 print('adding ', tracker.height)
Nenue@1 603 scrollHeight = scrollHeight + tracker.height
Nenue@1 604 end
Nenue@1 605 wrapperBlocks = wrapperBlocks + handler.actualBlocks
Nenue@1 606 end
Nenue@1 607 print('final scrollHeight:', scrollHeight)
Nenue@1 608
Nenue@1 609
Nenue@1 610
Nenue@1 611 -- Update frame dimensions
Nenue@1 612 if scrollHeight > wrapperMaxHeight then
Nenue@1 613 print(' is larger than', wrapperMaxHeight)
Nenue@1 614 wrapperHeight = wrapperMaxHeight
Nenue@1 615 else
Nenue@1 616 wrapperHeight = scrollHeight
Nenue@9 617 B.Conf.ObjectiveScroll = 0
Nenue@1 618 end
Nenue@1 619 scrollWidth = floor(scrollWidth+.5)
Nenue@1 620 scrollHeight = floor(scrollHeight+.5)
Nenue@1 621 wrapperWidth = floor(wrapperWidth+.5)
Nenue@1 622 wrapperHeight = floor(wrapperHeight+.5)
Nenue@1 623 headerHeight = floor(headerHeight+.5)
Nenue@1 624
Nenue@1 625 if wrapperBlocks >= 1 then
Nenue@2 626 for i, region in ipairs(Wrapper.header) do
Nenue@2 627 region:Show()
Nenue@2 628 end
Nenue@1 629 else
Nenue@2 630 for i, region in ipairs(Wrapper.header) do
Nenue@2 631 region:Hide()
Nenue@2 632 end
Nenue@1 633 return
Nenue@1 634 end
Nenue@1 635 --wrapperHeight = scrollHeight
Nenue@1 636
Nenue@1 637 print('|cFFFFFF00params:|r scroller:', scrollWidth, 'x', scrollHeight)
Nenue@1 638 print('|cFFFFFF00params:|r scroll:', scrollWidth, 'x', scrollHeight)
Nenue@1 639 print('|cFFFFFF00params:|r wrapper:', wrapperWidth, 'x', wrapperHeight)
Nenue@1 640 print('|cFFFFFF00params:|r header:', headerHeight)
Nenue@1 641
Nenue@1 642 Scroller:SetSize(wrapperWidth, wrapperHeight)
Nenue@1 643 Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, -headerHeight)
Nenue@1 644 Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT')
Nenue@1 645
Nenue@7 646
Nenue@1 647 Scroll:SetSize(scrollWidth, scrollHeight)
Nenue@7 648 Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0)
Nenue@1 649 Scroll:SetPoint('RIGHT', Scroller, 'RIGHT')
Nenue@1 650
Nenue@1 651 --Scroller:UpdateScrollChildRect()
Nenue@1 652 Wrapper:SetSize(wrapperWidth, wrapperHeight + headerHeight)
Nenue@1 653
Nenue@1 654 -- update action buttons
Nenue@6 655 print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(),
Nenue@6 656 '|cFF00FF00'..Scroller:GetName()..'|r:', Scroller:GetWidth(), Scroller:GetHeight(),
Nenue@6 657 '|cFF00FF00'..Wrapper:GetName()..'|r:', Wrapper:GetWidth(), Wrapper:GetHeight(),
Nenue@6 658 '|cFF0088FFvScrollRange|r:', floor(Scroller:GetVerticalScrollRange()+.5)
Nenue@6 659 )
Nenue@6 660 mod.UpdateActionButtons('FULL_UPDATE')
Nenue@1 661
Nenue@1 662 end
Nenue@1 663
Nenue@1 664 --- Queue any active item buttons for update for that frame
Nenue@6 665 mod.UpdateActionButtons = function(updateReason)
Nenue@6 666 Scroller.snap_upper = 0
Nenue@6 667 Scroller.snap_lower = 0
Nenue@6 668 local print = B.print('ItemButton')
Nenue@6 669 if updateReason then
Nenue@6 670 print = B.print('IB_'..updateReason)
Nenue@6 671 end
Nenue@6 672
Nenue@1 673 local previousItem
Nenue@2 674 for questID, itemButton in pairs(usedButtons) do
Nenue@6 675 local info= mod.Quest.Info[questID]
Nenue@6 676
Nenue@5 677 print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName())
Nenue@5 678 local block = mod.Quest.QuestBlock[questID]
Nenue@1 679 if block then
Nenue@5 680 -- Dispatch the probe
Nenue@6 681 if IsQuestWatched(info.questLogIndex) then
Nenue@6 682 itemButton.previousItem = previousItem
Nenue@5 683 print(' |cFFFFFF00probing', block:GetName())
Nenue@1 684 block:SetScript('OnUpdate', function()
Nenue@5 685 if block:GetBottom() and not InCombatLockdown() then
Nenue@5 686 print(' '..block:GetName()..' |cFF00FF00probe hit!')
Nenue@6 687 mod.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope
Nenue@5 688 block:SetScript('OnUpdate', nil)
Nenue@5 689 end
Nenue@5 690 end)
Nenue@6 691 previousItem = itemButton
Nenue@1 692 else
Nenue@5 693 print('hidden block or unwatched quest')
Nenue@6 694 itemButton.previousItem = nil
Nenue@5 695 itemButton:Hide()
Nenue@1 696 end
Nenue@8 697 elseif itemButton:IsVisible() then
Nenue@8 698 print(' |cFFFF0088hiding unwatched quest button', itemButton:GetName())
Nenue@6 699 itemButton.previousItem = nil
Nenue@6 700 itemButton:Hide()
Nenue@8 701 else
Nenue@8 702 print(' |cFFBBBBBBignoring hidden log quest button', itemButton:GetName())
Nenue@1 703 end
Nenue@1 704 end
Nenue@1 705 end
Nenue@1 706
Nenue@6 707 mod.UpdateBlockAction = function (block, itemButton)
Nenue@5 708 print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()')
Nenue@5 709 if itemButton.questID ~= block.info.questID then
Nenue@5 710 print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID)
Nenue@6 711 -- something happened between this and last frame, go back and set new probes
Nenue@5 712 return mod.UpdateActionButtons()
Nenue@2 713 end
Nenue@2 714
Nenue@6 715 local previousItem = itemButton.previousItem
Nenue@6 716 local upper_bound = Scroller:GetTop() + Scroller.snap_upper
Nenue@6 717 local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize
Nenue@6 718 local point, anchor, relative
Nenue@6 719
Nenue@6 720 if block:GetBottom() < lower_bound then
Nenue@6 721 print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5))
Nenue@1 722 if previousItem then
Nenue@6 723 print('adjusting', previousItem:GetName())
Nenue@1 724 previousItem:ClearAllPoints()
Nenue@6 725 previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing)
Nenue@1 726 end
Nenue@1 727 itemButton:ClearAllPoints()
Nenue@6 728 itemButton.x = Wrapper:GetLeft() -4
Nenue@6 729 itemButton.y = Wrapper:GetBottom()
Nenue@6 730 point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@6 731 Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing
Nenue@6 732
Nenue@6 733 elseif block:GetTop() > upper_bound then
Nenue@6 734 print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5))
Nenue@6 735 itemButton:ClearAllPoints()
Nenue@6 736 if previousItem then
Nenue@6 737 print('latch onto another piece')
Nenue@6 738 point, anchor, relative ='TOP', previousItem, 'BOTTOM'
Nenue@6 739 itemButton.x = 0
Nenue@6 740 itemButton.y = -itemButtonSpacing
Nenue@6 741 else
Nenue@6 742 print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop())
Nenue@6 743 point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@6 744 itemButton.x = Scroller:GetLeft() -4
Nenue@6 745 itemButton.y = Scroller:GetTop()
Nenue@6 746 end
Nenue@1 747 itemButton:Show()
Nenue@6 748 Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing)
Nenue@1 749 else
Nenue@6 750 print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5))
Nenue@1 751 itemButton:ClearAllPoints()
Nenue@6 752 itemButton.x = block:GetLeft() - itemButtonSpacing
Nenue@6 753 itemButton.y = block:GetTop()
Nenue@6 754 point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@1 755 end
Nenue@6 756
Nenue@6 757 itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y)
Nenue@6 758 itemButton:Show()
Nenue@1 759 end
Nenue@1 760
Nenue@1 761 mod.UpdateItemButtonCooldown = function(button)
Nenue@1 762
Nenue@1 763 end