annotate ObjectiveFrame.lua @ 8:7923243ae972

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
author Nenue
date Fri, 01 Apr 2016 14:40:14 -0400
parents 5301c68f28d8
children 2698173edd40
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 r == 0 then return end
Nenue@2 165 if s >= r then
Nenue@2 166 s = r
Nenue@2 167 elseif s < 1 then
Nenue@2 168 s = 0
Nenue@2 169 end
Nenue@2 170 self:SetVerticalScroll(s)
Nenue@7 171 B.Conf.ObjectiveScroll = s
Nenue@7 172 print('|cFF00FF00OnMouseWheel', 'from = ', from, 'scroll =', s, ' range =', r, 'current =', self:GetVerticalScroll())
Nenue@2 173
Nenue@6 174 mod.UpdateActionButtons('SCROLLING')
Nenue@2 175 end
Nenue@2 176
Nenue@2 177 local WrapperCloseButton_OnClick = function(self)
Nenue@2 178 if Scroller:IsVisible() then
Nenue@2 179 Scroller:Hide()
Nenue@2 180 else
Nenue@2 181 Scroller:Show()
Nenue@2 182 end
Nenue@2 183 end
Nenue@2 184
Nenue@2 185 mod.InitializeTrackers = function()
Nenue@2 186
Nenue@2 187 local c = mod.defaults.ObjectiveHeaderStyle.Normal
Nenue@2 188 local g1, g2, g3, g4 = unpack(c.Gradient.MinColor)
Nenue@2 189 local h1, h2, h3, h4 = unpack(c.Gradient.MaxColor)
Nenue@2 190
Nenue@2 191 for i, name in ipairs(orderedNames) do
Nenue@2 192 if not mod.orderedHandlers[i] then
Nenue@2 193 if mod.Tracker(name, i) then
Nenue@2 194 local handler = mod[name]
Nenue@2 195
Nenue@2 196 local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate')
Nenue@2 197 tracker.header:SetText(handler.name)
Nenue@2 198 tracker.header:SetHeight(headerHeight)
Nenue@2 199 tracker.header:SetFont(unpack(c.Font))
Nenue@2 200 tracker.header:SetTextColor(unpack(headerColor))
Nenue@2 201
Nenue@2 202 tracker.headerbg:SetGradientAlpha('HORIZONTAL', g1, g2 ,g3, g4, h1, h2, h3, h4)
Nenue@2 203 tracker.headerbg:SetHeight(headerHeight)
Nenue@2 204
Nenue@2 205 handler.Tracker = tracker
Nenue@2 206 mod.orderedTrackers[i] = tracker
Nenue@2 207 mod.namedTrackers[name] = tracker
Nenue@2 208 mod.indexedTrackers[handler] = tracker
Nenue@2 209 print('created new tracker frames for new handler')
Nenue@2 210 end
Nenue@2 211 end
Nenue@2 212 end
Nenue@2 213
Nenue@2 214 Scroller:SetScrollChild(Scroll)
Nenue@2 215 Scroller:SetScript('OnMouseWheel', Scroller_OnMouseWheel)
Nenue@2 216 Scroller:SetScript('OnShow', Scroller_OnShow)
Nenue@2 217 Scroller:SetScript('OnHide', Scroller_OnHide)
Nenue@2 218 Wrapper.close:SetScript('OnClick', WrapperCloseButton_OnClick)
Nenue@2 219 Wrapper:SetPoint(unpack(wrapperPosition))
Nenue@2 220 Scroller_OnShow(Scroller)
Nenue@2 221
Nenue@2 222 mod.UpdateWrapperStyle()
Nenue@2 223 end
Nenue@2 224
Nenue@2 225 mod.InitializeXPTracker = function()
Nenue@2 226 local XPBar = Wrapper.XPBar
Nenue@2 227 if UnitLevel('player') == 100 then
Nenue@2 228 XPBar:Hide()
Nenue@2 229 return
Nenue@2 230 end
Nenue@2 231
Nenue@2 232 --- xp bar
Nenue@6 233 XPBar:SetWidth(wrapperWidth - Wrapper.close:GetWidth())
Nenue@6 234 XPBar.bg:SetAllPoints(XPBar)
Nenue@6 235 XPBar:RegisterEvent('DISABLE_XP_GAIN')
Nenue@6 236 XPBar:RegisterEvent('ENABLE_XP_GAIN')
Nenue@2 237 XPBar:SetScript('OnEvent', mod.UpdateXP)
Nenue@6 238
Nenue@6 239 if not IsXPUserDisabled() then
Nenue@6 240 mod.EnableXP(XPBar)
Nenue@6 241 else
Nenue@6 242 mod.DisableXP(XPBar)
Nenue@6 243 end
Nenue@6 244
Nenue@6 245 mod.UpdateXP(XPBar)
Nenue@2 246 end
Nenue@2 247
Nenue@6 248 mod.EnableXP = function(self)
Nenue@6 249 self:RegisterEvent('PLAYER_XP_UPDATE')
Nenue@6 250 self:RegisterEvent('PLAYER_LEVEL_UP')
Nenue@6 251 self:RegisterEvent('PLAYER_UPDATE_RESTING')
Nenue@6 252 self.bg:SetTexture(0,0,0,.25)
Nenue@6 253 self:Show()
Nenue@6 254 end
Nenue@2 255
Nenue@6 256 mod.DisableXP = function(self)
Nenue@6 257 self:UnregisterEvent('PLAYER_XP_UPDATE')
Nenue@6 258 self:UnregisterEvent('PLAYER_LEVEL_UP')
Nenue@6 259 self:UnregisterEvent('PLAYER_UPDATE_RESTING')
Nenue@6 260 self.bg:SetTexture(0.5,0.5,0.5,0.5)
Nenue@6 261 self:Hide()
Nenue@6 262 end
Nenue@2 263
Nenue@6 264 mod.UpdateXP = function(self, event)
Nenue@6 265 if event == 'DISABLE_XP_GAIN' then
Nenue@6 266 mod.DisableXP(self)
Nenue@6 267 elseif event == 'ENABLE_XP_GAIN' then
Nenue@6 268 mod.EnableXP(self)
Nenue@2 269 end
Nenue@2 270
Nenue@6 271 if not IsXPUserDisabled() then
Nenue@6 272
Nenue@6 273 local xp = UnitXP('player')
Nenue@6 274 local xpmax = UnitXPMax('player')
Nenue@6 275 local rest = GetXPExhaustion()
Nenue@6 276 self.fg:SetWidth((xp/xpmax) * self:GetWidth())
Nenue@6 277 if rest then
Nenue@6 278 self.rested:ClearAllPoints()
Nenue@6 279 if xp == 0 then
Nenue@6 280 self.rested:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 0)
Nenue@6 281 else
Nenue@6 282 self.rested:SetPoint('TOPLEFT', self.fg, 'TOPRIGHT', 0, 0)
Nenue@6 283 end
Nenue@6 284
Nenue@6 285 if (xp + rest) > xpmax then
Nenue@6 286 self.rested:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, 0)
Nenue@6 287 else
Nenue@6 288 self.rested:SetWidth((rest/xpmax) * self:GetWidth())
Nenue@6 289 end
Nenue@6 290 self.rested:SetPoint('BOTTOM', self, 'BOTTOM')
Nenue@6 291 self.rested:Show()
Nenue@2 292 else
Nenue@6 293 self.rested:Hide()
Nenue@2 294 end
Nenue@2 295
Nenue@6 296 if IsResting() then
Nenue@6 297 self.bg:SetTexture(.2,.8,.2,.5)
Nenue@2 298 else
Nenue@6 299 self.bg:SetTexture(0,0,0,.25)
Nenue@2 300 end
Nenue@6 301 self.xpText:SetText(xp .. '/'.. xpmax .. (rest and (' ('..tostring(rest)..')') or ''))
Nenue@2 302 end
Nenue@2 303 end
Nenue@2 304
Nenue@2 305 mod.UpdateReputation = function(self)
Nenue@2 306 end
Nenue@1 307
Nenue@1 308 --- Argument containers
Nenue@1 309 local a1, a2, a3, a4, b1, b2, b3, b4, f1, f2, f3, w1, w2
Nenue@1 310 mod.SetBlockStyle = function(block, name)
Nenue@1 311 -- var names intended to reflect argument order
Nenue@2 312 --@debug@
Nenue@1 313 local c = mod.defaults.ObjectiveTrackerStyle[name]
Nenue@2 314 --@end-debug@
Nenue@2 315 --[===[@non-debug
Nenue@2 316 local c = mod.Conf
Nenue@2 317 --@end-non-debug]===]
Nenue@1 318 a1, a2, a3, a4 = unpack(c.Title.Gradient.MinColor)
Nenue@1 319 b1, b2, b3, b4 = unpack(c.Title.Gradient.MaxColor)
Nenue@1 320 block.titlebg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
Nenue@1 321
Nenue@1 322 a1, a2, a3, a4 = unpack(c.Text.Gradient.MinColor)
Nenue@1 323 b1, b2, b3, b4 = unpack(c.Text.Gradient.MaxColor)
Nenue@1 324 block.bg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
Nenue@1 325
Nenue@1 326 f1, f2, f3 = unpack(c.Title.Font)
Nenue@1 327 block.title:SetFont(f1, f2, f3)
Nenue@1 328
Nenue@1 329 f1, f2 ,f3 = unpack(c.Text.Font)
Nenue@1 330 block.objectives:SetFont(f1,f2,f3)
Nenue@1 331
Nenue@1 332 w1 = Wrapper:GetWidth()
Nenue@1 333 w2 = (c.Title.BackgroundFullWidth and w1 or block.title:GetStringWidth())
Nenue@1 334
Nenue@1 335 local titleSpacing, titleSpacing2 = c.Title.Spacing, (c.Title.Spacing * 2)
Nenue@1 336 local textSpacing, textSpacing2 = c.Text.Spacing, (c.Text.Spacing * 2)
Nenue@1 337
Nenue@1 338 if block.info.isTrivial then
Nenue@1 339 block.title:SetTextColor(0.7, 0.7, 0.7, 1)
Nenue@1 340 elseif block.info.isComplete then
Nenue@1 341 block.title:SetTextColor(1,1,1,1)
Nenue@1 342 else
Nenue@1 343 block.title:SetTextColor(0,.7,1,1)
Nenue@1 344 end
Nenue@1 345 block.title:SetSpacing(titleSpacing)
Nenue@1 346 block.objectives:SetSpacing(textSpacing)
Nenue@1 347 block.objectives:SetWordWrap(true)
Nenue@1 348
Nenue@7 349 local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight() + block.attachmentHeight
Nenue@1 350 local blockHeight = titleHeight + titleSpacing2 + textHeight + textSpacing2
Nenue@1 351 local blockWidth = wrapperMaxWidth
Nenue@1 352
Nenue@1 353 block.titlebg:SetSize(min(w1, w2), titleHeight + titleSpacing2)
Nenue@1 354 block.bg:SetSize(w1, textHeight + textSpacing2)
Nenue@1 355 block:SetSize(blockWidth, blockHeight)
Nenue@1 356
Nenue@1 357 block.title:SetPoint('TOPLEFT', block.titlebg, 'TOPLEFT', 0, -titleSpacing)
Nenue@1 358 block.objectives:SetPoint('TOPLEFT', block.titlebg, 'BOTTOMLEFT', textIndent, -textSpacing)
Nenue@1 359
Nenue@1 360 -- store
Nenue@1 361 block.titleHeight = titleHeight
Nenue@1 362 block.textHeight = textHeight
Nenue@1 363 block.width = blockWidth
Nenue@1 364 block.height = blockHeight
Nenue@1 365
Nenue@2 366 print(' |cFF00FFFF'..block:GetName()..'|r:|cFF0088FFSetStyle|r(', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
Nenue@2 367 end
Nenue@2 368
Nenue@2 369 local segments = {'Left', 'Right', 'Tile'}
Nenue@2 370 mod.UpdateWrapperStyle = function()
Nenue@2 371 local c = mod.defaults.WrapperStyle
Nenue@2 372 for _, segment in ipairs(segments) do
Nenue@2 373 Wrapper['Background'..segment]:SetAtlas(c.Header.Background[segment])
Nenue@2 374 Wrapper['Background'..segment]:SetTexCoord(unpack(c.Header.BackgroundCrop[segment]))
Nenue@2 375 if c.Header.BackgroundScale[segment] then
Nenue@2 376 Wrapper['Background'..segment]:SetWidth(c.Header.BackgroundScale[segment])
Nenue@2 377 end
Nenue@2 378 end
Nenue@1 379 end
Nenue@1 380
Nenue@1 381 --- Updates the selected block frame to display the given info batch
Nenue@1 382 -- If `previousBlock` is set, it will attempt to anchor to that
Nenue@1 383 -- @param blockNum the ordered block to be updated, not a watchIndex value
Nenue@1 384 -- @param info the reference returned by the GetXInfo functions
Nenue@1 385 -- REMEMBER: t.info and questData[questID] are the same table
Nenue@1 386 mod.UpdateTrackerBlock = function (handler, blockIndex, info)
Nenue@2 387 print(' |cFF00FFFFUpdateTrackerBlock('..blockIndex..'|r')
Nenue@1 388 if not blockIndex or not info then
Nenue@1 389 return
Nenue@1 390 end
Nenue@1 391
Nenue@1 392 local tracker = handler.Tracker
Nenue@1 393
Nenue@1 394 local t = handler:GetBlock(blockIndex)
Nenue@1 395 if previousBlock then
Nenue@1 396 if blockIndex == 1 then
Nenue@1 397 t:SetPoint('TOPLEFT', previousBlock, 'TOPLEFT', 0, -headerHeight)
Nenue@1 398 else
Nenue@1 399 t:SetPoint('TOPLEFT', previousBlock, 'BOTTOMLEFT', 0, 0)
Nenue@1 400 end
Nenue@1 401 t:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
Nenue@1 402 end
Nenue@2 403 --print(t:GetName(), t:GetSize())
Nenue@2 404 --print(t:GetPoint(1))
Nenue@1 405
Nenue@1 406 t.info = info
Nenue@1 407
Nenue@5 408 if info.questID then handler.QuestBlock[info.questID] = t end
Nenue@1 409 if info.questLogIndex then handler.LogBlock[info.questLogIndex] = t end
Nenue@1 410 if info.watchIndex then handler.WatchBlock[info.watchIndex] = t end
Nenue@1 411
Nenue@1 412 info.blockIndex = blockIndex
Nenue@1 413 handler.BlockInfo[blockIndex] = info
Nenue@7 414
Nenue@1 415 t.Select = handler.Select
Nenue@1 416 t.Open = handler.Open
Nenue@1 417 t.Remove = handler.Remove
Nenue@1 418 t.Link = handler.Link
Nenue@1 419 t:SetScript('OnMouseUp', handler.OnMouseUp)
Nenue@1 420 t:SetScript('OnMouseDown', handler.OnMouseDown)
Nenue@1 421 t.title:SetText(info.title)
Nenue@1 422
Nenue@7 423 t.attachmentHeight = 0
Nenue@1 424 if info.isComplete then
Nenue@1 425 t.objectives:Show()
Nenue@1 426 t.objectives:SetText(info.completionText)
Nenue@1 427 elseif info.numObjectives >= 1 then
Nenue@7 428 t.attachmentHeight = textSpacing
Nenue@1 429 t.objectives:Show()
Nenue@2 430 print(' - objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
Nenue@3 431
Nenue@1 432 local text = ''
Nenue@3 433
Nenue@3 434 --- todo: implement objective displays
Nenue@3 435 -- in an accumulator loop, call upon handler for the appropriate display frame, each defining:
Nenue@3 436 -- * height of whatever display widget is involved in conveying the task
Nenue@3 437 -- * number of non-wrapped text lines to account for line space; may be discarded depending on things
Nenue@3 438 -- * boolean that determines listening for money events or not
Nenue@4 439 t.attachmentHeight, text = mod.UpdateObjectives(t, info, text)
Nenue@3 440
Nenue@1 441 t.objectives:SetText(text)
Nenue@3 442 t.objectives:SetWordWrap(true)
Nenue@1 443
Nenue@1 444
Nenue@1 445
Nenue@1 446 elseif info.description then
Nenue@1 447 t.objectives:SetText(info.description)
Nenue@1 448 t.objectives:SetWordWrap(true)
Nenue@1 449 else
Nenue@1 450 t.objectives:SetText(nil)
Nenue@1 451 end
Nenue@1 452 local style = 'Normal'
Nenue@1 453 if info.isComplete then
Nenue@1 454 style = 'Complete'
Nenue@1 455 elseif info.superTracked then
Nenue@1 456 style = 'Super'
Nenue@1 457 end
Nenue@1 458
Nenue@5 459 if info.specialItem and not info.itemButton then
Nenue@5 460 print(' - |cFF00FFFFgenerating item button for info set')
Nenue@4 461 info.itemButton = mod.SetItemButton(t, info)
Nenue@4 462 else
Nenue@4 463 --info.itemButton = nil
Nenue@4 464 end
Nenue@4 465
Nenue@6 466 if Devian and Devian.InWorkspace() then
Nenue@6 467 t.debugText:Show()
Nenue@6 468 t.debugText:SetText(tostring(blockIndex) .. '\n' .. tostring(info.itemButton and info.itemButton:GetName()))
Nenue@6 469 end
Nenue@6 470
Nenue@3 471 --- metrics are calculated in SetStyle
Nenue@1 472 t:SetStyle(style)
Nenue@3 473 t:Show()
Nenue@1 474
Nenue@3 475 print(' |cFF00FFFF)|r -> ', t, t:GetHeight())
Nenue@1 476 return t
Nenue@1 477 end
Nenue@1 478
Nenue@4 479 mod.UpdateObjectives = function(block, info, text)
Nenue@7 480 local attachmentHeight = block.attachmentHeight
Nenue@7 481 if info.description then
Nenue@7 482 print(' -- has description text:', select('#', info.description), info.description)
Nenue@7 483 text = info.description
Nenue@7 484 end
Nenue@4 485 for o, obj in ipairs(info.objectives) do
Nenue@4 486 --- achievement criteria
Nenue@4 487 if obj.flags then
Nenue@4 488
Nenue@4 489
Nenue@4 490 if bit.band(obj.flags, 0x00000001) > 0 then
Nenue@4 491 obj.type = 'ProgressBar'
Nenue@4 492 elseif bit.band(obj.flags, 0x00000002) then
Nenue@4 493 obj.type = 'Hidden'
Nenue@4 494 obj.widget = nil
Nenue@4 495 else
Nenue@4 496 obj.type = 'Text'
Nenue@4 497 obj.widget = nil
Nenue@4 498 text = text .. ((text == '') and "" or "\n") .. obj.text
Nenue@4 499 end
Nenue@4 500
Nenue@7 501 print('obj.type =', obj.type)
Nenue@7 502 print(' ** qtyStr:', obj.quantityString, 'qty:', obj.quantity, 'assetID:', obj.assetID)
Nenue@7 503 obj.widget = mod.SetWidget(obj, info)
Nenue@4 504 --- none of the above (most quests)
Nenue@4 505 else
Nenue@4 506 local line = obj.text
Nenue@4 507 local color = '00FFFF'
Nenue@4 508 if obj.finished then
Nenue@4 509 color = 'FFFFFF'
Nenue@4 510 elseif obj.type == 'monster' then
Nenue@4 511 color = 'FFFF00'
Nenue@4 512 elseif obj.type == 'item' then
Nenue@4 513 color = '44DDFF'
Nenue@4 514 elseif obj.type == 'object' then
Nenue@4 515 color = 'FF44DD'
Nenue@4 516 end
Nenue@4 517 text = text .. ((text == '') and "" or "\n") .. '|cFF'..color.. line .. '|r'
Nenue@4 518 end
Nenue@4 519
Nenue@4 520 if obj.widget then
Nenue@7 521
Nenue@7 522 obj.widget:Show()
Nenue@7 523 obj.widget:SetPoint('TOPLEFT', block.objectives, 'BOTTOMLEFT', 0, -attachmentHeight)
Nenue@7 524 print('have a widget, height is', obj.widget.height)
Nenue@4 525 attachmentHeight = attachmentHeight + obj.widget.height
Nenue@4 526 end
Nenue@4 527
Nenue@4 528 end
Nenue@4 529 return attachmentHeight, text
Nenue@4 530 end
Nenue@4 531
Nenue@1 532 mod.UpdateTracker = function(handler)
Nenue@1 533 print('|cFF00FF88UpdateTracker(|r|cFFFF4400' .. type(handler) .. '|r :: |cFF88FFFF' .. tostring(handler) .. '|r')
Nenue@1 534 local tracker = handler.Tracker
Nenue@1 535 local blockIndex = 0
Nenue@1 536 local trackerHeight = headerHeight
Nenue@1 537 local w = 300
Nenue@1 538
Nenue@1 539 previousBlock = handler.Tracker
Nenue@1 540 local numWatched = handler.GetNumWatched()
Nenue@1 541 local numBlocks = handler.numBlocks
Nenue@1 542 local actualBlocks = handler.actualBlocks
Nenue@1 543 for watchIndex = 1, 25 do
Nenue@1 544 blockIndex = blockIndex + 1
Nenue@1 545 if watchIndex <= numWatched then
Nenue@1 546 local info = handler:GetInfo(watchIndex)
Nenue@1 547 if info then
Nenue@1 548 local currentBlock = mod.UpdateTrackerBlock(handler, blockIndex, info)
Nenue@1 549 previousBlock = currentBlock
Nenue@1 550 trackerHeight = trackerHeight + currentBlock.height
Nenue@1 551 numBlocks = max(numBlocks, watchIndex)
Nenue@1 552 actualBlocks = actualBlocks + 1
Nenue@1 553 else
Nenue@1 554 print('|cFFFF0000Failed to draw info for index #'..watchIndex)
Nenue@1 555 end
Nenue@1 556
Nenue@1 557 elseif watchIndex <= numBlocks then
Nenue@1 558 local used = handler.usedBlocks
Nenue@1 559 local free = handler.freeBlocks
Nenue@1 560 print('clean up dead quest block')
Nenue@1 561 if used[blockIndex] then
Nenue@1 562 used[blockIndex]:Hide()
Nenue@1 563 used[blockIndex]:ClearAllPoints()
Nenue@1 564 free[#free+1]= used[blockIndex]
Nenue@1 565 used[blockIndex] = nil
Nenue@1 566 end
Nenue@1 567 else
Nenue@1 568 print('Stopping scan at', blockIndex)
Nenue@1 569 break -- done with quest stuff
Nenue@1 570 end
Nenue@1 571 end
Nenue@1 572 handler.numWatched = numWatched
Nenue@1 573 handler.numBlocks = numBlocks
Nenue@1 574 handler.actualBlocks = actualBlocks
Nenue@1 575 handler:Report()
Nenue@1 576 previousBlock = nil
Nenue@1 577 if numBlocks > 0 then
Nenue@1 578 tracker.height = trackerHeight
Nenue@1 579 else
Nenue@1 580 tracker.height = 0
Nenue@1 581 end
Nenue@1 582
Nenue@1 583 print('|cFF00FF88)|r ->', numBlocks, 'blocks; height', tracker.height, 'last block: ')
Nenue@1 584 end
Nenue@1 585
Nenue@1 586 mod.Quest.numButtons = 0
Nenue@1 587 local usedButtons = mod.Quest.itemButtons
Nenue@1 588 local freeButtons = mod.Quest.freeButtons
Nenue@1 589 mod.UpdateWrapper = function()
Nenue@1 590 wrapperWidth = wrapperMaxWidth
Nenue@1 591 scrollWidth = wrapperWidth
Nenue@1 592 local wrapperBlocks = 0
Nenue@1 593 -- Update scroll child vertical size
Nenue@1 594 scrollHeight = 0
Nenue@1 595 for i, handler in ipairs(orderedHandlers) do
Nenue@1 596 mod.UpdateTracker(handler)
Nenue@1 597 if handler.actualBlocks >= 1 then
Nenue@1 598 local tracker = handler.Tracker
Nenue@1 599 print('setting', handler.Tracker, 'to anchor to offset', -scrollHeight)
Nenue@1 600 tracker:SetParent(Scroll) -- this doesn't do anything that relativeTo doesn't
Nenue@1 601 tracker:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight)
Nenue@1 602 tracker:SetSize(wrapperWidth, tracker.height)
Nenue@1 603 print('adding ', tracker.height)
Nenue@1 604 scrollHeight = scrollHeight + tracker.height
Nenue@1 605 end
Nenue@1 606 wrapperBlocks = wrapperBlocks + handler.actualBlocks
Nenue@1 607 end
Nenue@1 608 print('final scrollHeight:', scrollHeight)
Nenue@1 609
Nenue@1 610
Nenue@1 611
Nenue@1 612 -- Update frame dimensions
Nenue@1 613 if scrollHeight > wrapperMaxHeight then
Nenue@1 614 print(' is larger than', wrapperMaxHeight)
Nenue@1 615 --ScrollBar:Show()
Nenue@1 616 --scrollWidth = wrapperMaxWidth - scrollBarWidth
Nenue@1 617 wrapperHeight = wrapperMaxHeight
Nenue@1 618 -- Make ThumbTexture reflect the viewing scale (smaller for longer scroll, bigger for shorter)
Nenue@1 619 --ScrollBar:GetThumbTexture():SetHeight((wrapperMaxHeight/scrollHeight) * (wrapperMaxHeight))
Nenue@1 620 --ScrollBar:SetWidth(scrollBarWidth)
Nenue@1 621 --ScrollBar:SetPoint('TOPRIGHT', Scroller, 'TOPRIGHT', 0, 0)
Nenue@1 622 --ScrollBar:SetPoint('BOTTOMLEFT', Scroller, 'BOTTOMRIGHT', -scrollBarWidth, 0)
Nenue@1 623 --ScrollBar:SetMinMaxValues(1, scrollHeight - wrapperMaxHeight)
Nenue@1 624 else
Nenue@1 625 --ScrollBar:Hide()
Nenue@1 626 wrapperHeight = scrollHeight
Nenue@1 627 end
Nenue@1 628 scrollWidth = floor(scrollWidth+.5)
Nenue@1 629 scrollHeight = floor(scrollHeight+.5)
Nenue@1 630 wrapperWidth = floor(wrapperWidth+.5)
Nenue@1 631 wrapperHeight = floor(wrapperHeight+.5)
Nenue@1 632 headerHeight = floor(headerHeight+.5)
Nenue@1 633
Nenue@1 634 if wrapperBlocks >= 1 then
Nenue@2 635 for i, region in ipairs(Wrapper.header) do
Nenue@2 636 region:Show()
Nenue@2 637 end
Nenue@1 638 else
Nenue@2 639 for i, region in ipairs(Wrapper.header) do
Nenue@2 640 region:Hide()
Nenue@2 641 end
Nenue@1 642 return
Nenue@1 643 end
Nenue@1 644 --wrapperHeight = scrollHeight
Nenue@1 645
Nenue@1 646 print('|cFFFFFF00params:|r scroller:', scrollWidth, 'x', scrollHeight)
Nenue@1 647 print('|cFFFFFF00params:|r scroll:', scrollWidth, 'x', scrollHeight)
Nenue@1 648 print('|cFFFFFF00params:|r wrapper:', wrapperWidth, 'x', wrapperHeight)
Nenue@1 649 print('|cFFFFFF00params:|r header:', headerHeight)
Nenue@1 650
Nenue@1 651 Scroller:SetSize(wrapperWidth, wrapperHeight)
Nenue@1 652 Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, -headerHeight)
Nenue@1 653 Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT')
Nenue@1 654
Nenue@7 655
Nenue@1 656 Scroll:SetSize(scrollWidth, scrollHeight)
Nenue@7 657 Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0)
Nenue@1 658 Scroll:SetPoint('RIGHT', Scroller, 'RIGHT')
Nenue@1 659
Nenue@1 660 --Scroller:UpdateScrollChildRect()
Nenue@1 661 Wrapper:SetSize(wrapperWidth, wrapperHeight + headerHeight)
Nenue@1 662
Nenue@1 663 -- update action buttons
Nenue@6 664 print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(),
Nenue@6 665 '|cFF00FF00'..Scroller:GetName()..'|r:', Scroller:GetWidth(), Scroller:GetHeight(),
Nenue@6 666 '|cFF00FF00'..Wrapper:GetName()..'|r:', Wrapper:GetWidth(), Wrapper:GetHeight(),
Nenue@6 667 '|cFF0088FFvScrollRange|r:', floor(Scroller:GetVerticalScrollRange()+.5)
Nenue@6 668 )
Nenue@6 669 mod.UpdateActionButtons('FULL_UPDATE')
Nenue@1 670
Nenue@1 671 end
Nenue@1 672
Nenue@1 673 --- Queue any active item buttons for update for that frame
Nenue@6 674 mod.UpdateActionButtons = function(updateReason)
Nenue@6 675 Scroller.snap_upper = 0
Nenue@6 676 Scroller.snap_lower = 0
Nenue@6 677 local print = B.print('ItemButton')
Nenue@6 678 if updateReason then
Nenue@6 679 print = B.print('IB_'..updateReason)
Nenue@6 680 end
Nenue@6 681
Nenue@1 682 local previousItem
Nenue@2 683 for questID, itemButton in pairs(usedButtons) do
Nenue@6 684 local info= mod.Quest.Info[questID]
Nenue@6 685
Nenue@5 686 print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName())
Nenue@5 687 local block = mod.Quest.QuestBlock[questID]
Nenue@1 688 if block then
Nenue@5 689 -- Dispatch the probe
Nenue@6 690 if IsQuestWatched(info.questLogIndex) then
Nenue@6 691 itemButton.previousItem = previousItem
Nenue@5 692 print(' |cFFFFFF00probing', block:GetName())
Nenue@1 693 block:SetScript('OnUpdate', function()
Nenue@5 694 if block:GetBottom() and not InCombatLockdown() then
Nenue@5 695 print(' '..block:GetName()..' |cFF00FF00probe hit!')
Nenue@6 696 mod.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope
Nenue@5 697 block:SetScript('OnUpdate', nil)
Nenue@5 698 end
Nenue@5 699 end)
Nenue@6 700 previousItem = itemButton
Nenue@1 701 else
Nenue@5 702 print('hidden block or unwatched quest')
Nenue@6 703 itemButton.previousItem = nil
Nenue@5 704 itemButton:Hide()
Nenue@1 705 end
Nenue@8 706 elseif itemButton:IsVisible() then
Nenue@8 707 print(' |cFFFF0088hiding unwatched quest button', itemButton:GetName())
Nenue@6 708 itemButton.previousItem = nil
Nenue@6 709 itemButton:Hide()
Nenue@8 710 else
Nenue@8 711 print(' |cFFBBBBBBignoring hidden log quest button', itemButton:GetName())
Nenue@1 712 end
Nenue@1 713 end
Nenue@1 714 end
Nenue@1 715
Nenue@6 716 mod.UpdateBlockAction = function (block, itemButton)
Nenue@5 717 print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()')
Nenue@5 718 if itemButton.questID ~= block.info.questID then
Nenue@5 719 print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID)
Nenue@6 720 -- something happened between this and last frame, go back and set new probes
Nenue@5 721 return mod.UpdateActionButtons()
Nenue@2 722 end
Nenue@2 723
Nenue@6 724 local previousItem = itemButton.previousItem
Nenue@6 725 local upper_bound = Scroller:GetTop() + Scroller.snap_upper
Nenue@6 726 local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize
Nenue@6 727 local point, anchor, relative
Nenue@6 728
Nenue@6 729 if block:GetBottom() < lower_bound then
Nenue@6 730 print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5))
Nenue@1 731 if previousItem then
Nenue@6 732 print('adjusting', previousItem:GetName())
Nenue@1 733 previousItem:ClearAllPoints()
Nenue@6 734 previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing)
Nenue@1 735 end
Nenue@1 736 itemButton:ClearAllPoints()
Nenue@6 737 itemButton.x = Wrapper:GetLeft() -4
Nenue@6 738 itemButton.y = Wrapper:GetBottom()
Nenue@6 739 point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@6 740 Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing
Nenue@6 741
Nenue@6 742 elseif block:GetTop() > upper_bound then
Nenue@6 743 print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5))
Nenue@6 744 itemButton:ClearAllPoints()
Nenue@6 745 if previousItem then
Nenue@6 746 print('latch onto another piece')
Nenue@6 747 point, anchor, relative ='TOP', previousItem, 'BOTTOM'
Nenue@6 748 itemButton.x = 0
Nenue@6 749 itemButton.y = -itemButtonSpacing
Nenue@6 750 else
Nenue@6 751 print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop())
Nenue@6 752 point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@6 753 itemButton.x = Scroller:GetLeft() -4
Nenue@6 754 itemButton.y = Scroller:GetTop()
Nenue@6 755 end
Nenue@1 756 itemButton:Show()
Nenue@6 757 Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing)
Nenue@1 758 else
Nenue@6 759 print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5))
Nenue@1 760 itemButton:ClearAllPoints()
Nenue@6 761 itemButton.x = block:GetLeft() - itemButtonSpacing
Nenue@6 762 itemButton.y = block:GetTop()
Nenue@6 763 point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@1 764 end
Nenue@6 765
Nenue@6 766 itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y)
Nenue@6 767 itemButton:Show()
Nenue@1 768 end
Nenue@1 769
Nenue@1 770 mod.UpdateItemButtonCooldown = function(button)
Nenue@1 771
Nenue@1 772 end