annotate FilterBar.lua @ 31:d0114b51cdea

WorldPlan: - Reworking filters to utilize newly added CVars - Fleshed out POI tooltip for WQ's associated with Family Familiars - Filter button tooltip includes reward icons - Respond to tracking menu clicks when they change filter options
author Nenue
date Fri, 28 Oct 2016 19:54:00 -0400
parents 8cb750e79952
children e8679ecb48d8
rev   line source
Nenue@30 1 -- WorldPlan
Nenue@30 2 -- FilterBar.lua
Nenue@30 3 -- Created: 10/27/2016 8:55 PM
Nenue@30 4 -- %file-revision%
Nenue@30 5 --
Nenue@30 6
Nenue@30 7 local print = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or nop
Nenue@31 8 local wipe, ipairs, pairs = table.wipe, ipairs, pairs
Nenue@30 9
Nenue@30 10 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD
Nenue@30 11 local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER
Nenue@30 12 local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT
Nenue@30 13 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES
Nenue@30 14 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS
Nenue@30 15
Nenue@30 16
Nenue@30 17 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
Nenue@30 18 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
Nenue@30 19 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON
Nenue@30 20 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION
Nenue@30 21 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL
Nenue@30 22 local DEFAULT_FILTER_LAYOUT = {
Nenue@30 23 PinSize = 22,
Nenue@30 24 Border = 3,
Nenue@30 25 TrackingBorder = 2,
Nenue@30 26 TagSize = 12,
Nenue@30 27 TimeleftStage = 3,
Nenue@30 28 showNumber = true,
Nenue@30 29 numberFontObject = 'WorldPlanNumberFontThin'
Nenue@30 30 }
Nenue@30 31 local DEFAULT_FILTER_LIST = {
Nenue@30 32 { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" },
Nenue@30 33 { filterKey= 'rewardType', cVar = 'worldQuestFilterArtifactPower', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" },
Nenue@31 34 { filterKey= 'rewardType', cVar = 'worldQuestFilterOrderResources', filterValue = REWARD_CURRENCY,label = 'Order Resources', texture = "Interface\\Icons\\inv_orderhall_orderresources" },
Nenue@30 35 { filterKey= 'rewardType', cVar = 'worldQuestFilterEquipment', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" },
Nenue@30 36 { filterKey= 'rewardType', cVar = 'worldQuestFilterProfessionMaterials', filterValue = REWARD_REAGENT, label = 'Materials', texture = 1417744 },
Nenue@30 37 { filterKey= 'rewardType', cVar = 'worldQuestFilterGold', filterValue = REWARD_CASH, label = 'Gold', texture = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" },
Nenue@30 38 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 },
Nenue@30 39 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", },
Nenue@30 40 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
Nenue@30 41 { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", },
Nenue@30 42 }
Nenue@30 43 local defaults = {}
Nenue@30 44
Nenue@30 45 WorldPlanSummaryMixin = {
Nenue@30 46 selectedBountyIndex = {},
Nenue@30 47 bounties = {},
Nenue@30 48 filterList = {},
Nenue@30 49 buttons = {},
Nenue@30 50 }
Nenue@30 51 WorldPlanFilterPinMixin = {}
Nenue@30 52
Nenue@30 53 function WorldPlanSummaryMixin:OnLoad()
Nenue@30 54 self:RegisterEvent('QUEST_LOG_UPDATE')
Nenue@30 55 self:RegisterEvent('WORLD_MAP_UPDATE')
Nenue@30 56
Nenue@30 57 WorldPlan:AddHandler(self, defaults)
Nenue@30 58
Nenue@30 59 for index, info in ipairs(DEFAULT_FILTER_LIST) do
Nenue@30 60 info.zone = DEFAULT_FILTER_LAYOUT
Nenue@30 61 info.continent = DEFAULT_FILTER_LAYOUT
Nenue@30 62 info.pinMask = "Interface\\Minimap\\UI-Minimap-Background"
Nenue@30 63
Nenue@30 64 WorldPlan:AddTypeInfo(self,index, info)
Nenue@30 65 end
Nenue@30 66
Nenue@30 67 end
Nenue@30 68
Nenue@30 69
Nenue@30 70 function WorldPlanSummaryMixin:OnEvent(event)
Nenue@30 71 end
Nenue@30 72
Nenue@30 73 local bountyIndex
Nenue@30 74 local debug_headers = {}
Nenue@30 75
Nenue@30 76 function WorldPlanSummaryMixin:Setup()
Nenue@30 77 self:GetFilters()
Nenue@30 78 end
Nenue@30 79
Nenue@30 80
Nenue@30 81 function WorldPlanSummaryMixin:OnEvent(event,...)
Nenue@30 82 self.isStale = true
Nenue@30 83 end
Nenue@30 84
Nenue@30 85 function WorldPlanSummaryMixin:OnShow()
Nenue@30 86 self:Refresh()
Nenue@30 87 end
Nenue@30 88
Nenue@30 89 function WorldPlanSummaryMixin:GetFilters()
Nenue@30 90
Nenue@30 91
Nenue@30 92 wipe(self.filterList)
Nenue@30 93
Nenue@30 94 for index, info in ipairs(DEFAULT_FILTER_LIST) do
Nenue@30 95 tinsert(self.filterList, info)
Nenue@30 96 end
Nenue@30 97 self.bounties, self.numBounties = GetQuestBountyInfoForMapID(WorldPlan.currentMapID)
Nenue@30 98 self.BountyFilters = {}
Nenue@30 99 for index, data in ipairs(self.bounties) do
Nenue@30 100 local info = self.BountyFilters[index]
Nenue@30 101 if not info then
Nenue@30 102 info = {}
Nenue@30 103 self.BountyFilters[index] = info
Nenue@30 104 end
Nenue@30 105
Nenue@30 106 local questTitle = GetQuestLogTitle(GetQuestLogIndexByID(data.questID))
Nenue@30 107
Nenue@30 108 info.filterKey = 'factionID'
Nenue@30 109 info.filterValue = data.factionID
Nenue@30 110 info.label = questTitle
Nenue@30 111 info.texture = data.icon
Nenue@30 112 print('loading emissary', questTitle)
Nenue@30 113
Nenue@30 114 tinsert(self.filterList, info)
Nenue@30 115 --{ filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
Nenue@30 116 end
Nenue@30 117 end
Nenue@30 118
Nenue@30 119 function WorldPlanSummaryMixin:Reset()
Nenue@30 120 self.pinLayout = self:GetTypeInfo(255)
Nenue@30 121 self:GetFilters()
Nenue@30 122 end
Nenue@30 123
Nenue@30 124 function WorldPlanSummaryMixin:Refresh(forced)
Nenue@30 125 self:Update(forced)
Nenue@30 126 end
Nenue@30 127
Nenue@30 128 local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64"
Nenue@30 129 local filterMask = "Interface\\Minimap\\UI-Minimap-Background"
Nenue@31 130
Nenue@31 131 local questResults = {{}}
Nenue@30 132 function WorldPlanSummaryMixin:Update(forced)
Nenue@30 133 local blocks = self.buttons
Nenue@30 134 local relativeFrame = WorldMapFrame.UIElementsFrame.TrackingOptionsButton
Nenue@30 135 local numHeaders = 0
Nenue@30 136 print('|cFF00FF88'..tostring(self)..':Refresh()|r', 'currentMap=',self.currentMapID)
Nenue@30 137
Nenue@30 138
Nenue@30 139 local quests = WorldPlanQuests.QuestsByZone[self.currentMapID] or WorldPlanQuests.QuestsByID
Nenue@31 140 local foundQuests = questResults[1]
Nenue@30 141 for index, info in ipairs(self.filterList) do
Nenue@30 142 local numQuests = 0
Nenue@31 143 local resultIndex = numHeaders + 1
Nenue@31 144 questResults[resultIndex] = questResults[resultIndex] or {}
Nenue@31 145 wipe(questResults[resultIndex])
Nenue@30 146 for questID, pin in pairs(quests) do
Nenue@30 147 if pin.used then
Nenue@30 148 if not info.filterKey then
Nenue@30 149 numQuests = numQuests + 1
Nenue@30 150 elseif pin[info.filterKey] == info.filterValue then
Nenue@30 151 numQuests = numQuests + 1
Nenue@31 152 tinsert(questResults[resultIndex], pin)
Nenue@30 153 end
Nenue@30 154 end
Nenue@30 155 end
Nenue@30 156 print(tostring(index).. ' ("'..tostring(info.label)..'" f('.. tostring(info.filterKey).. '='..tostring(info.filterValue) .. '), '..tostring(numQuests)..')')
Nenue@30 157
Nenue@30 158 if numQuests >= 1 then
Nenue@30 159 numHeaders = numHeaders + 1
Nenue@30 160 local button = blocks[numHeaders]
Nenue@30 161 if not blocks[numHeaders] then
Nenue@30 162 button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin')
Nenue@30 163
Nenue@30 164 button:SetSize(24,24)
Nenue@30 165 button.icon:ClearAllPoints()
Nenue@30 166 button.icon:SetAllPoints(button)
Nenue@30 167
Nenue@30 168 button.iconBorder:SetPoint('TOPLEFT', button, 'TOPLEFT', -2, 2)
Nenue@30 169 button.iconBorder:SetPoint('BOTTOMRIGHT', button, 'BOTTOMRIGHT', 2, -2)
Nenue@30 170 button.iconBorder:SetMask(filterMask)
Nenue@30 171 button.iconBorder:SetTexture(filterFill)
Nenue@30 172 button.iconBorder:SetDesaturated(true)
Nenue@30 173
Nenue@30 174 button.supertrackBorder:Hide()
Nenue@30 175 blocks[numHeaders] = button
Nenue@30 176 end
Nenue@30 177
Nenue@30 178 button.info = info
Nenue@31 179 button.questList = questResults[resultIndex]
Nenue@30 180 button:SetID(index)
Nenue@30 181 button.spacing = ((info.filterKey ~= relativeFrame.filterKey) and 10) or 0
Nenue@30 182 button.relativeFrame = relativeFrame
Nenue@30 183 button:Refresh((numHeaders == 1), numQuests)
Nenue@30 184 button:Show()
Nenue@30 185 relativeFrame = button
Nenue@30 186 end
Nenue@30 187
Nenue@30 188 end
Nenue@30 189
Nenue@30 190 self.numHeaders = numHeaders
Nenue@30 191 for i = numHeaders + 1, #blocks do
Nenue@30 192 if blocks[i] then
Nenue@30 193 blocks[i]:Hide()
Nenue@30 194 end
Nenue@31 195 if questResults[i] then
Nenue@31 196 wipe(questResults[i])
Nenue@31 197 end
Nenue@30 198 end
Nenue@30 199 end
Nenue@30 200
Nenue@30 201 function WorldPlanSummaryMixin:Cleanup()
Nenue@30 202 -- hide trailing buttons
Nenue@30 203 end
Nenue@30 204
Nenue@31 205 local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF'}
Nenue@30 206 function WorldPlanFilterPinMixin:OnEnter()
Nenue@31 207 if self.questList and #self.questList >= 1 then
Nenue@31 208 GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
Nenue@31 209 GameTooltip_ClearInsertedFrames(GameTooltip)
Nenue@31 210 GameTooltip:AddLine(self.info.label)
Nenue@31 211 for index, pin in ipairs(self.questList) do
Nenue@31 212 local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite
Nenue@31 213 GameTooltip:AddLine(pin.title ..(pin.cheevos and " |cFFFFFF00!|R" or ''), colorInfo.r, colorInfo.g, colorInfo.b)
Nenue@31 214 GameTooltip:AddTexture(pin.itemTexture)
Nenue@31 215 local cLine = GameTooltip:NumLines() - 1
Nenue@31 216 print(cLine, _G['GameTooltipTexture'..cLine]:GetTexture())
Nenue@31 217 if type(pin.itemTexture) == 'number' then
Nenue@31 218 --- voodoo workaround for IDs getting coerced to string
Nenue@31 219 _G['GameTooltipTexture'..cLine]:Show()
Nenue@31 220 _G['GameTooltipTexture'..cLine]:SetTexture(pin.itemTexture)
Nenue@31 221 end
Nenue@31 222 GameTooltip:Show()
Nenue@31 223 end
Nenue@31 224 end
Nenue@30 225 end
Nenue@30 226
Nenue@31 227 function WorldPlanFilterPinMixin:OnLeave()
Nenue@31 228 if GameTooltip:IsOwned(self) then
Nenue@31 229 GameTooltip:Hide()
Nenue@31 230 end
Nenue@31 231 end
Nenue@30 232
Nenue@30 233 function WorldPlanFilterPinMixin:Refresh(isFirst, numQuests)
Nenue@30 234 isFirst = isFirst or self.isFirst
Nenue@30 235 numQuests = numQuests or self.numQuests
Nenue@30 236
Nenue@30 237 local info = self.info
Nenue@30 238
Nenue@30 239 self.isFirst = isFirst
Nenue@30 240 self.numQuests = numQuests
Nenue@30 241 self.filterKey = info.filterKey
Nenue@30 242 self.filterValue = info.filterValue
Nenue@30 243 self.tagID = info.tagID
Nenue@30 244
Nenue@30 245 self.icon:SetMask(filterMask)
Nenue@30 246 self.icon:SetTexture(info.texture)
Nenue@30 247 self.count:SetText(numQuests)
Nenue@30 248 self.cVar = info.cVar
Nenue@30 249
Nenue@30 250 self.itemTexture = self.texture
Nenue@30 251
Nenue@30 252 if isFirst then
Nenue@30 253 self:SetPoint('TOP', self.relativeFrame, 'BOTTOM', 0, -5)
Nenue@30 254 else
Nenue@30 255 self:SetPoint('TOPRIGHT', self.relativeFrame, 'BOTTOMRIGHT', 0, -(3 + (self.spacing or 0)))
Nenue@30 256 end
Nenue@30 257 print('anchor to', self.relativeFrame:GetName(), info.mask)
Nenue@30 258
Nenue@30 259 local r, g, b, a = 1,1,1,1
Nenue@31 260 local desaturated = false
Nenue@31 261 if self.cVar then
Nenue@31 262 self.iconBorder:SetVertexColor(1, 1, 1, 1)
Nenue@31 263 if GetCVarBool(self.cVar) == true then
Nenue@31 264 self.icon:SetVertexColor(1,1,1,1)
Nenue@31 265 self:SetAlpha(1)
Nenue@31 266 else
Nenue@31 267 self.icon:SetVertexColor(.5, .5, .5, 1)
Nenue@31 268 self:SetAlpha(0.5)
Nenue@30 269 end
Nenue@30 270 else
Nenue@31 271 self:SetAlpha(1)
Nenue@31 272 if WorldPlan.UsedFilters[self.filterKey] then
Nenue@31 273 if WorldPlan.UsedFilters[self.filterKey] == self.filterValue then
Nenue@31 274 self.iconBorder:SetVertexColor(0, 1, 0)
Nenue@31 275 else
Nenue@31 276 self.iconBorder:SetVertexColor(1, 0, 0)
Nenue@31 277 end
Nenue@31 278 else
Nenue@31 279 self.iconBorder:SetVertexColor(1, 1, 1, 1)
Nenue@30 280 end
Nenue@30 281 end
Nenue@31 282
Nenue@30 283 --self:UpdateSize()
Nenue@30 284 end
Nenue@30 285
Nenue@30 286 function WorldPlanFilterPinMixin:OnLoad()
Nenue@30 287 self:RegisterForClicks('AnyUp')
Nenue@30 288 self:SetFrameStrata('HIGH')
Nenue@30 289 self:SetFrameLevel(151)
Nenue@30 290 self:SetScript('OnUpdate', nil)
Nenue@30 291 end
Nenue@30 292
Nenue@30 293 function WorldPlanFilterPinMixin:OnUpdate ()
Nenue@30 294 end
Nenue@30 295
Nenue@30 296 function WorldPlanFilterPinMixin:OnLeave ()
Nenue@30 297 if GameTooltip:IsOwned(self) then
Nenue@30 298 GameTooltip:Hide()
Nenue@30 299 end
Nenue@30 300 end
Nenue@30 301
Nenue@30 302 -- shift-click: reset filter
Nenue@30 303 -- click: rotate through include(1), exclude(-1), ignore(nil)
Nenue@30 304 function WorldPlanFilterPinMixin:OnClick (button)
Nenue@30 305
Nenue@31 306 print('|cFF00FF88'..self:GetName()..':OnClick()|r', filterKey, filterValue, operation)
Nenue@30 307 local filterKey = self.filterKey
Nenue@30 308 local filterValue = self.filterValue
Nenue@30 309
Nenue@30 310
Nenue@30 311 local operation = opPrefix
Nenue@30 312
Nenue@30 313
Nenue@30 314 if not filterKey then
Nenue@30 315 wipe(WorldPlan.UsedFilters)
Nenue@31 316 elseif self.cVar then
Nenue@31 317 SetCVar(self.cVar, (GetCVarBool(self.cVar) and 0) or 1)
Nenue@30 318 else
Nenue@31 319 local setInclude = (button == 'LeftButton')
Nenue@31 320 local flushValue
Nenue@31 321 print('')
Nenue@31 322 if WorldPlan.UsedFilters[filterKey] == filterValue then
Nenue@31 323 WorldPlan.UsedFilters[filterKey] = nil
Nenue@31 324 else
Nenue@31 325 WorldPlan.UsedFilters[filterKey] = filterValue
Nenue@30 326 end
Nenue@30 327 end
Nenue@30 328 WorldPlan:Refresh()
Nenue@30 329 end