Mercurial > wow > buffalo2
comparison ObjectiveTracker/TrackerBlock.lua @ 40:03ed70f846de
- move block accessors into a new file
- define a tMove function for reconciling the free/used tables as needed
- when retrieving an old block frame, confirm ID still matches; resolves multiple watch items on one block
- stop any animations when a block is freed; resolves stuck flare graphics
| author | Nenue |
|---|---|
| date | Sun, 24 Apr 2016 14:15:25 -0400 |
| parents | |
| children | 7a65ed86e4dd |
comparison
equal
deleted
inserted
replaced
| 39:92534dc793f2 | 40:03ed70f846de |
|---|---|
| 1 --- ${PACKAGE_NAME} | |
| 2 -- @file-author@ | |
| 3 -- @project-revision@ @project-hash@ | |
| 4 -- @file-revision@ @file-hash@ | |
| 5 -- Created: 4/24/2016 11:30 AM | |
| 6 --- These functions deal with propagating and managing block/line templates | |
| 7 local B = select(2,...).frame | |
| 8 local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') | |
| 9 local _G, ipairs, max, tostring = _G, ipairs, max, tostring | |
| 10 local tinsert, tremove, tContains = table.insert, table.remove, tContains | |
| 11 local Default = T.DefaultHandler | |
| 12 local CreateFrame = CreateFrame | |
| 13 local print = B.print('Layout') | |
| 14 local bprint = B.print('Block') | |
| 15 local lprint = B.print('Layout') | |
| 16 local fprint = B.print('Frame') | |
| 17 local used, free | |
| 18 | |
| 19 local blockFadeOut_OnPlay = function(self) | |
| 20 fprint(self:GetName(), '|cFF00FF00PLAY|r', debugstack(1,3,1)) | |
| 21 end | |
| 22 local blockFadeOut_OnFinished = function(self) | |
| 23 fprint(self:GetName(), '|cFF00FF00FINISHED|r', debugstack(1,3, 1)) | |
| 24 end | |
| 25 | |
| 26 local tMove = function(source, dest, frame) | |
| 27 -- if it's already in the stack, sanity check source stack | |
| 28 local removed | |
| 29 if tContains(dest, frame) then | |
| 30 for i, entry in ipairs(source) do | |
| 31 if entry == frame then | |
| 32 removed = i | |
| 33 tremove(source, i) | |
| 34 break | |
| 35 end | |
| 36 end | |
| 37 -- still need to resolve position | |
| 38 for i, entry in ipairs(dest) do | |
| 39 if entry == frame then | |
| 40 bprint('tMove result:', (removed and ('|cFFFF4400a|r['..removed .. '] is now ') or '') .. '|cFF00FF00b|r[' .. i..']') | |
| 41 return i | |
| 42 end | |
| 43 end | |
| 44 else | |
| 45 -- if it's not, then pull from source stack | |
| 46 for i, entry in ipairs(source) do | |
| 47 if entry == frame then | |
| 48 removed = i | |
| 49 tremove(source, i) | |
| 50 break | |
| 51 end | |
| 52 end | |
| 53 tinsert(dest, frame) | |
| 54 bprint('tMove result:', (removed and ('|cFFFF4400a|r['..removed .. '] is now ') or '') .. '|cFF00FF00b|r[' .. #dest..']') | |
| 55 return #dest | |
| 56 end | |
| 57 end | |
| 58 | |
| 59 | |
| 60 --- Creates or retrieves a complete line data object | |
| 61 Default.GetLine = function(handler, block, lineIndex) | |
| 62 local print = lprint | |
| 63 local blockIndex = block.index | |
| 64 local lines = block.lines | |
| 65 if not lineIndex then | |
| 66 lineIndex = block.currentLine + 1 | |
| 67 print(' |cFFFFFF00generating a frame') | |
| 68 end | |
| 69 | |
| 70 block.numLines = max(block.numLines, lineIndex) | |
| 71 | |
| 72 if not lines[lineIndex] then | |
| 73 print(' |cFF00FF88created line #'..lineIndex..' from for '..handler.name..' block #'..blockIndex) | |
| 74 lines[lineIndex] = CreateFrame('Frame', 'Vn'..handler.name .. blockIndex..'ObjectiveLine'..lineIndex, block, 'VeneerTrackerObjective') | |
| 75 local line = lines[lineIndex] | |
| 76 line.index = lineIndex | |
| 77 line.height = 0 | |
| 78 line.schema = '' | |
| 79 B.SetConfigLayers(line) | |
| 80 | |
| 81 if debug then | |
| 82 for _, region in ipairs(lines[lineIndex].debug) do | |
| 83 region:Show() | |
| 84 end | |
| 85 end | |
| 86 | |
| 87 end | |
| 88 return lines[lineIndex] | |
| 89 end | |
| 90 | |
| 91 | |
| 92 | |
| 93 --- Creates or retrieves a complete block frame object | |
| 94 --- todo: make it use data index to avoid re-coloring every block | |
| 95 Default.GetBlock = function(handler, index) | |
| 96 local print = bprint | |
| 97 print('|cFF0088FF'..handler.name..':GetBlock', index) | |
| 98 local block = handler.InfoBlock[index] | |
| 99 local used = handler.usedBlocks | |
| 100 local free = handler.freeBlocks | |
| 101 | |
| 102 if block then | |
| 103 print(block.info.id, index) | |
| 104 end | |
| 105 | |
| 106 -- if the frame entry is still good, sort heaps | |
| 107 if block and block.info.id == index then | |
| 108 block.posIndex = tMove(free, used, block) | |
| 109 print(' |cFFFFFF00using '..handler.name..'|r.|cFF00FFBBusedBlocks['..tostring(block.posIndex)..'] ('.. block:GetName()..', "'..tostring(block.info.title)..'")') | |
| 110 else | |
| 111 local source = 'cache' | |
| 112 if #handler.freeBlocks >= 1 then | |
| 113 block = tremove(handler.freeBlocks) | |
| 114 print(' |cFF00FF00 assigning from free heap', block:GetName()) | |
| 115 else | |
| 116 | |
| 117 local blockIndex = (#handler.usedBlocks + #handler.freeBlocks) + 1 | |
| 118 block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, handler.frame, 'VeneerTrackerBlock') | |
| 119 --block:SetParent() | |
| 120 block.schema = '' | |
| 121 block.lines = {} | |
| 122 block.numLines = 0 | |
| 123 block.currentLine = 0 | |
| 124 block.attachmentHeight = 0 | |
| 125 block.offset = 0 | |
| 126 B.SetConfigLayers(block) | |
| 127 --- methods for event handlers | |
| 128 | |
| 129 block.Select = handler.Select | |
| 130 block.Open = handler.Open | |
| 131 block.Remove = handler.Remove | |
| 132 block.Link = handler.Link | |
| 133 block.clickZone:SetScript('OnMouseUp', function(self, ...) handler.OnMouseUp(block, ...) end) | |
| 134 block.clickZone:SetScript('OnMouseDown', function(self, ...) handler.OnMouseDown(block, ...) end) | |
| 135 block:ClearAllPoints() | |
| 136 block.index = blockIndex | |
| 137 | |
| 138 block.blockFadeOut:SetScript('OnPlay', blockFadeOut_OnPlay) | |
| 139 | |
| 140 source = 'new' | |
| 141 end | |
| 142 handler.InfoBlock[index] = block | |
| 143 block.posIndex = tMove(free, used, block) | |
| 144 print(' |cFF00FF00('..source..')|r |cFF0088FF'..handler.name..'|r.|cFF00FFBBusedBlocks['..block.posIndex..'] =|r', block:GetName()) | |
| 145 end | |
| 146 block.blockFadeOut:SetScript('OnFinished', blockFadeOut_OnFinished) | |
| 147 block:SetScript('OnHide', function(self) | |
| 148 self.blockFadeOut:SetScript('OnFinished', blockFadeOut_OnFinished) | |
| 149 end) | |
| 150 print(' used/free: |cFFFFFF00' .. #handler.usedBlocks .. '|r/|cFF00FFFF'..#handler.freeBlocks ..'|r') | |
| 151 return block | |
| 152 end | |
| 153 | |
| 154 --- begins a blockFadeOut animation and fires FreeBlock when that's done | |
| 155 Default.ClearBlock = function(handler, block) | |
| 156 if block.isAnimating then | |
| 157 return | |
| 158 end | |
| 159 | |
| 160 block.isAnimating = true | |
| 161 block.blockFadeOut:SetScript('OnFinished', nil) | |
| 162 block.blockFadeOut:SetScript('OnFinished', function(self) | |
| 163 fprint(self:GetName(), '|cFFFFFF00FINISHED|r', debugstack()) | |
| 164 handler:FreeBlock(block) | |
| 165 self:SetScript('OnFinished', blockFadeOut_OnFinished) | |
| 166 block.isAnimating = nil | |
| 167 end) | |
| 168 block.blockFadeOut:Play() | |
| 169 end | |
| 170 | |
| 171 --- remove a block from visible existence; not called directly | |
| 172 Default.FreeBlock = function(handler, block) | |
| 173 bprint('|cFFFF4400FreeBlock|r', block:GetName()) | |
| 174 local used = handler.usedBlocks | |
| 175 local free = handler.freeBlocks | |
| 176 tMove(used, free, block) | |
| 177 | |
| 178 bprint(' |cFFFF4444used/free:|r |cFFFFFF00' .. #used .. '|r/|cFF00FFFF'..#free ..'|r') | |
| 179 | |
| 180 block:Hide() | |
| 181 local animations = {block:GetAnimationGroups() } | |
| 182 for i, animGroup in ipairs(animations) do | |
| 183 bprint(' animGroup', i, animGroup:GetName()) | |
| 184 animGroup:Stop() | |
| 185 end | |
| 186 end | |
| 187 | |
| 188 | |
| 189 | |
| 190 --- Get a usable widget for the given achievement criteria set. | |
| 191 -- Returns a frame object with dimensioning parameters needed to size the receiving tracker block | |
| 192 local wr = T.WidgetRegistry | |
| 193 T.GetWidget = function(data, objectiveType, objectiveKey) | |
| 194 local print = B.print('ObjectiveWidgets') | |
| 195 local widgetType = objectiveType | |
| 196 local widget | |
| 197 local isNew | |
| 198 if wr[widgetType] and wr[widgetType].used[objectiveKey] then | |
| 199 widget = wr[widgetType].used[objectiveKey] | |
| 200 print('|cFF00FF00Updating ('..objectiveKey..')', widget) | |
| 201 elseif not wr[widgetType] or #wr[widgetType].free == 0 then | |
| 202 -- creating a new frame | |
| 203 isNew = true | |
| 204 widget = CreateFrame(widgetType, 'VeneerObjective' .. widgetType .. (wr[widgetType] and (wr[widgetType].lastn+1) or (1)), VeneerObjectiveScroll, 'VeneerObjectiveCriteria' .. widgetType) | |
| 205 print('|cFFFF0088Creating `'..widget:GetName()..'` id', wr[widgetType].lastn) | |
| 206 T.UpdateSchema(widgetType, data.schema or 'default') | |
| 207 else | |
| 208 -- recycling for a different criteria set | |
| 209 isNew = true | |
| 210 widget = tremove(wr[widgetType].free) | |
| 211 print('|cFFFFFF00Acquiring released widget', widget:GetName()) | |
| 212 end | |
| 213 | |
| 214 for k,v in pairs(data) do | |
| 215 if not widget[k] then | |
| 216 widget[k] = v | |
| 217 tprint('widget', widget:GetName(), k, v) | |
| 218 end | |
| 219 end | |
| 220 | |
| 221 wr[widgetType].used[objectiveKey] = widget | |
| 222 widget.objective = data | |
| 223 widget.key = objectiveKey | |
| 224 T.InitializeWidget(widget, isNew) | |
| 225 return widget | |
| 226 end |
