Nenue@30: -- WorldPlan Nenue@30: -- FilterBar.lua Nenue@30: -- Created: 10/27/2016 8:55 PM Nenue@30: -- %file-revision% Nenue@30: -- Nenue@30: Nenue@30: local print = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or nop Nenue@31: local wipe, ipairs, pairs = table.wipe, ipairs, pairs Nenue@30: Nenue@30: local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD Nenue@30: local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER Nenue@30: local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT Nenue@30: local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES Nenue@30: local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS Nenue@30: Nenue@30: Nenue@30: local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP Nenue@30: local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE Nenue@30: local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON Nenue@30: local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION Nenue@30: local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL Nenue@30: local DEFAULT_FILTER_LAYOUT = { Nenue@30: PinSize = 22, Nenue@30: Border = 3, Nenue@30: TrackingBorder = 2, Nenue@30: TagSize = 12, Nenue@30: TimeleftStage = 3, Nenue@30: showNumber = true, Nenue@30: numberFontObject = 'WorldPlanNumberFontThin' Nenue@30: } Nenue@30: local DEFAULT_FILTER_LIST = { Nenue@30: { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" }, Nenue@30: { filterKey= 'rewardType', cVar = 'worldQuestFilterArtifactPower', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" }, Nenue@31: { filterKey= 'rewardType', cVar = 'worldQuestFilterOrderResources', filterValue = REWARD_CURRENCY,label = 'Order Resources', texture = "Interface\\Icons\\inv_orderhall_orderresources" }, Nenue@30: { filterKey= 'rewardType', cVar = 'worldQuestFilterEquipment', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" }, Nenue@30: { filterKey= 'rewardType', cVar = 'worldQuestFilterProfessionMaterials', filterValue = REWARD_REAGENT, label = 'Materials', texture = 1417744 }, Nenue@30: { filterKey= 'rewardType', cVar = 'worldQuestFilterGold', filterValue = REWARD_CASH, label = 'Gold', texture = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" }, Nenue@30: { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 }, Nenue@30: { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", }, Nenue@30: { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", }, Nenue@30: { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", }, Nenue@30: } Nenue@30: local defaults = {} Nenue@30: Nenue@30: WorldPlanSummaryMixin = { Nenue@30: selectedBountyIndex = {}, Nenue@30: bounties = {}, Nenue@30: filterList = {}, Nenue@30: buttons = {}, Nenue@30: } Nenue@30: WorldPlanFilterPinMixin = {} Nenue@30: Nenue@30: function WorldPlanSummaryMixin:OnLoad() Nenue@30: self:RegisterEvent('QUEST_LOG_UPDATE') Nenue@30: self:RegisterEvent('WORLD_MAP_UPDATE') Nenue@30: Nenue@30: WorldPlan:AddHandler(self, defaults) Nenue@30: Nenue@30: for index, info in ipairs(DEFAULT_FILTER_LIST) do Nenue@30: info.zone = DEFAULT_FILTER_LAYOUT Nenue@30: info.continent = DEFAULT_FILTER_LAYOUT Nenue@30: info.pinMask = "Interface\\Minimap\\UI-Minimap-Background" Nenue@30: Nenue@30: WorldPlan:AddTypeInfo(self,index, info) Nenue@30: end Nenue@30: Nenue@30: end Nenue@30: Nenue@30: Nenue@30: function WorldPlanSummaryMixin:OnEvent(event) Nenue@32: self:Refresh() Nenue@30: end Nenue@30: Nenue@30: local bountyIndex Nenue@30: local debug_headers = {} Nenue@30: Nenue@30: function WorldPlanSummaryMixin:Setup() Nenue@30: self:GetFilters() Nenue@30: end Nenue@30: Nenue@30: Nenue@30: function WorldPlanSummaryMixin:OnEvent(event,...) Nenue@30: self.isStale = true Nenue@30: end Nenue@32: function WorldPlanSummaryMixin:OnUpdate() Nenue@32: if self.isStale then Nenue@32: self:Refresh() Nenue@32: end Nenue@32: end Nenue@30: Nenue@30: function WorldPlanSummaryMixin:OnShow() Nenue@30: self:Refresh() Nenue@30: end Nenue@30: Nenue@30: function WorldPlanSummaryMixin:GetFilters() Nenue@30: Nenue@30: Nenue@30: wipe(self.filterList) Nenue@30: Nenue@30: for index, info in ipairs(DEFAULT_FILTER_LIST) do Nenue@30: tinsert(self.filterList, info) Nenue@30: end Nenue@30: self.bounties, self.numBounties = GetQuestBountyInfoForMapID(WorldPlan.currentMapID) Nenue@30: self.BountyFilters = {} Nenue@30: for index, data in ipairs(self.bounties) do Nenue@30: local info = self.BountyFilters[index] Nenue@30: if not info then Nenue@30: info = {} Nenue@30: self.BountyFilters[index] = info Nenue@30: end Nenue@30: Nenue@30: local questTitle = GetQuestLogTitle(GetQuestLogIndexByID(data.questID)) Nenue@30: Nenue@30: info.filterKey = 'factionID' Nenue@30: info.filterValue = data.factionID Nenue@30: info.label = questTitle Nenue@30: info.texture = data.icon Nenue@30: print('loading emissary', questTitle) Nenue@30: Nenue@30: tinsert(self.filterList, info) Nenue@30: --{ filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", }, Nenue@30: end Nenue@30: end Nenue@30: Nenue@30: function WorldPlanSummaryMixin:Reset() Nenue@30: self.pinLayout = self:GetTypeInfo(255) Nenue@30: self:GetFilters() Nenue@30: end Nenue@30: Nenue@30: function WorldPlanSummaryMixin:Refresh(forced) Nenue@30: self:Update(forced) Nenue@30: end Nenue@30: Nenue@30: local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64" Nenue@30: local filterMask = "Interface\\Minimap\\UI-Minimap-Background" Nenue@31: Nenue@31: local questResults = {{}} Nenue@30: function WorldPlanSummaryMixin:Update(forced) Nenue@30: local blocks = self.buttons Nenue@30: local relativeFrame = WorldMapFrame.UIElementsFrame.TrackingOptionsButton Nenue@30: local numHeaders = 0 Nenue@30: print('|cFF00FF88'..tostring(self)..':Refresh()|r', 'currentMap=',self.currentMapID) Nenue@30: Nenue@30: Nenue@30: local quests = WorldPlanQuests.QuestsByZone[self.currentMapID] or WorldPlanQuests.QuestsByID Nenue@31: local foundQuests = questResults[1] Nenue@30: for index, info in ipairs(self.filterList) do Nenue@30: local numQuests = 0 Nenue@31: local resultIndex = numHeaders + 1 Nenue@31: questResults[resultIndex] = questResults[resultIndex] or {} Nenue@31: wipe(questResults[resultIndex]) Nenue@30: for questID, pin in pairs(quests) do Nenue@30: if pin.used then Nenue@30: if not info.filterKey then Nenue@30: numQuests = numQuests + 1 Nenue@30: elseif pin[info.filterKey] == info.filterValue then Nenue@30: numQuests = numQuests + 1 Nenue@31: tinsert(questResults[resultIndex], pin) Nenue@30: end Nenue@30: end Nenue@30: end Nenue@30: print(tostring(index).. ' ("'..tostring(info.label)..'" f('.. tostring(info.filterKey).. '='..tostring(info.filterValue) .. '), '..tostring(numQuests)..')') Nenue@30: Nenue@30: if numQuests >= 1 then Nenue@30: numHeaders = numHeaders + 1 Nenue@30: local button = blocks[numHeaders] Nenue@30: if not blocks[numHeaders] then Nenue@30: button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin') Nenue@30: Nenue@30: button:SetSize(24,24) Nenue@30: button.icon:ClearAllPoints() Nenue@30: button.icon:SetAllPoints(button) Nenue@30: Nenue@30: button.iconBorder:SetPoint('TOPLEFT', button, 'TOPLEFT', -2, 2) Nenue@30: button.iconBorder:SetPoint('BOTTOMRIGHT', button, 'BOTTOMRIGHT', 2, -2) Nenue@30: button.iconBorder:SetMask(filterMask) Nenue@30: button.iconBorder:SetTexture(filterFill) Nenue@30: button.iconBorder:SetDesaturated(true) Nenue@30: Nenue@30: button.supertrackBorder:Hide() Nenue@30: blocks[numHeaders] = button Nenue@30: end Nenue@30: Nenue@30: button.info = info Nenue@31: button.questList = questResults[resultIndex] Nenue@30: button:SetID(index) Nenue@30: button.spacing = ((info.filterKey ~= relativeFrame.filterKey) and 10) or 0 Nenue@30: button.relativeFrame = relativeFrame Nenue@30: button:Refresh((numHeaders == 1), numQuests) Nenue@30: button:Show() Nenue@30: relativeFrame = button Nenue@30: end Nenue@30: Nenue@30: end Nenue@30: Nenue@30: self.numHeaders = numHeaders Nenue@30: for i = numHeaders + 1, #blocks do Nenue@30: if blocks[i] then Nenue@30: blocks[i]:Hide() Nenue@30: end Nenue@31: if questResults[i] then Nenue@31: wipe(questResults[i]) Nenue@31: end Nenue@30: end Nenue@32: self.isStale = nil Nenue@30: end Nenue@30: Nenue@30: function WorldPlanSummaryMixin:Cleanup() Nenue@30: -- hide trailing buttons Nenue@30: end Nenue@30: Nenue@31: local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF'} Nenue@30: function WorldPlanFilterPinMixin:OnEnter() Nenue@31: if self.questList and #self.questList >= 1 then Nenue@31: GameTooltip:SetOwner(self, 'ANCHOR_LEFT') Nenue@31: GameTooltip_ClearInsertedFrames(GameTooltip) Nenue@31: GameTooltip:AddLine(self.info.label) Nenue@31: for index, pin in ipairs(self.questList) do Nenue@31: local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite Nenue@31: GameTooltip:AddLine(pin.title ..(pin.cheevos and " |cFFFFFF00!|R" or ''), colorInfo.r, colorInfo.g, colorInfo.b) Nenue@31: GameTooltip:AddTexture(pin.itemTexture) Nenue@31: local cLine = GameTooltip:NumLines() - 1 Nenue@32: --print(cLine, _G['GameTooltipTexture'..cLine]:GetTexture()) Nenue@31: if type(pin.itemTexture) == 'number' then Nenue@31: --- voodoo workaround for IDs getting coerced to string Nenue@31: _G['GameTooltipTexture'..cLine]:Show() Nenue@31: _G['GameTooltipTexture'..cLine]:SetTexture(pin.itemTexture) Nenue@31: end Nenue@31: GameTooltip:Show() Nenue@31: end Nenue@31: end Nenue@30: end Nenue@30: Nenue@31: function WorldPlanFilterPinMixin:OnLeave() Nenue@31: if GameTooltip:IsOwned(self) then Nenue@31: GameTooltip:Hide() Nenue@31: end Nenue@31: end Nenue@30: Nenue@30: function WorldPlanFilterPinMixin:Refresh(isFirst, numQuests) Nenue@30: isFirst = isFirst or self.isFirst Nenue@30: numQuests = numQuests or self.numQuests Nenue@30: Nenue@30: local info = self.info Nenue@30: Nenue@30: self.isFirst = isFirst Nenue@30: self.numQuests = numQuests Nenue@30: self.filterKey = info.filterKey Nenue@30: self.filterValue = info.filterValue Nenue@30: self.tagID = info.tagID Nenue@30: Nenue@30: self.icon:SetMask(filterMask) Nenue@30: self.icon:SetTexture(info.texture) Nenue@30: self.count:SetText(numQuests) Nenue@30: self.cVar = info.cVar Nenue@30: Nenue@30: self.itemTexture = self.texture Nenue@30: Nenue@30: if isFirst then Nenue@30: self:SetPoint('TOP', self.relativeFrame, 'BOTTOM', 0, -5) Nenue@30: else Nenue@30: self:SetPoint('TOPRIGHT', self.relativeFrame, 'BOTTOMRIGHT', 0, -(3 + (self.spacing or 0))) Nenue@30: end Nenue@30: print('anchor to', self.relativeFrame:GetName(), info.mask) Nenue@30: Nenue@30: local r, g, b, a = 1,1,1,1 Nenue@31: local desaturated = false Nenue@31: if self.cVar then Nenue@31: self.iconBorder:SetVertexColor(1, 1, 1, 1) Nenue@31: if GetCVarBool(self.cVar) == true then Nenue@31: self.icon:SetVertexColor(1,1,1,1) Nenue@31: self:SetAlpha(1) Nenue@31: else Nenue@31: self.icon:SetVertexColor(.5, .5, .5, 1) Nenue@31: self:SetAlpha(0.5) Nenue@30: end Nenue@30: else Nenue@31: self:SetAlpha(1) Nenue@31: if WorldPlan.UsedFilters[self.filterKey] then Nenue@31: if WorldPlan.UsedFilters[self.filterKey] == self.filterValue then Nenue@31: self.iconBorder:SetVertexColor(0, 1, 0) Nenue@31: else Nenue@31: self.iconBorder:SetVertexColor(1, 0, 0) Nenue@31: end Nenue@31: else Nenue@31: self.iconBorder:SetVertexColor(1, 1, 1, 1) Nenue@30: end Nenue@30: end Nenue@31: Nenue@30: --self:UpdateSize() Nenue@30: end Nenue@30: Nenue@30: function WorldPlanFilterPinMixin:OnLoad() Nenue@30: self:RegisterForClicks('AnyUp') Nenue@30: self:SetFrameStrata('HIGH') Nenue@30: self:SetFrameLevel(151) Nenue@30: self:SetScript('OnUpdate', nil) Nenue@30: end Nenue@30: Nenue@30: function WorldPlanFilterPinMixin:OnUpdate () Nenue@30: end Nenue@30: Nenue@30: function WorldPlanFilterPinMixin:OnLeave () Nenue@30: if GameTooltip:IsOwned(self) then Nenue@30: GameTooltip:Hide() Nenue@30: end Nenue@30: end Nenue@30: Nenue@30: -- shift-click: reset filter Nenue@30: -- click: rotate through include(1), exclude(-1), ignore(nil) Nenue@30: function WorldPlanFilterPinMixin:OnClick (button) Nenue@30: Nenue@31: print('|cFF00FF88'..self:GetName()..':OnClick()|r', filterKey, filterValue, operation) Nenue@30: local filterKey = self.filterKey Nenue@30: local filterValue = self.filterValue Nenue@30: Nenue@30: Nenue@30: local operation = opPrefix Nenue@30: Nenue@30: Nenue@30: if not filterKey then Nenue@30: wipe(WorldPlan.UsedFilters) Nenue@31: elseif self.cVar then Nenue@31: SetCVar(self.cVar, (GetCVarBool(self.cVar) and 0) or 1) Nenue@30: else Nenue@31: local setInclude = (button == 'LeftButton') Nenue@31: local flushValue Nenue@31: print('') Nenue@31: if WorldPlan.UsedFilters[filterKey] == filterValue then Nenue@31: WorldPlan.UsedFilters[filterKey] = nil Nenue@31: else Nenue@31: WorldPlan.UsedFilters[filterKey] = filterValue Nenue@30: end Nenue@30: end Nenue@30: WorldPlan:Refresh() Nenue@30: end