Mercurial > wow > worldplan
view FilterBar.lua @ 103:8cdd62e7a224
- Solved the quest pins remaining visible issue
author | Nenue |
---|---|
date | Sun, 28 May 2017 19:50:42 -0400 |
parents | b29b35cb8539 |
children | b67ba1078824 |
line wrap: on
line source
-- WorldPlan -- FilterBar.lua -- Created: 10/27/2016 8:55 PM -- %file-revision% -- local _, db = ... local print = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or nop local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end local wipe, ipairs, pairs = table.wipe, ipairs, pairs local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS local filtersUsed local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64" local filterMask = "Interface\\Minimap\\UI-Minimap-Background" local HEADERS_SPACING = 3 local BUTTONS_SPACING = 1 local BUTTONS_HEIGHT = 20 local TOGGLE_SIZE = 20 local HEADERS_HEIGHT = 24 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION local barMouseOver local filtersDirty = true local layoutDirty = true local matchesDirty -- don't flag until first filter loadout local familiars = { [42159] = {npc = 106552, name = 'Nightwatcher Merayl'}, [40277] = {npc = 97804, name = 'Tiffany Nelson'}, [40298] = {npc = 99182, name = 'Sir Galveston'}, [40282] = {npc= 99150, name = 'Grixis Tinypop'}, [40278] = {npc = 98270, name = 'Robert Craig'}, [48195] = {npc = 105250, name = 'Aulier'}, [41990] = {npc = 105674, name = 'Varenne'}, [41860] = {npc = 104970, name = 'Xorvasc'}, [40299] = {npc = 99210, name = 'Bodhi Sunwayver'}, [42442] = {npc = 107489, name = 'Amalia'}, [40280] = {npc = 99077, name = 'Bredda Tenderhide'}, [41687] = {npc = 104553, name = 'Odrogg'}, [41944] = {npc = 105455, name = 'Trapper Jarrun'}, [40337] = {npc = 97709, name = 'Master Tamer Flummox'}, [40279] = {npc = 99035, name = 'Durian Strongfruit'} } local familiars_id = 9696 db.DefaultFilterType = { iconWidth = 24, iconHeight = 18, borderWidth = 3, highlightWidth = 2, TagSize = 12, TimeleftStage = 3, showNumber = true, numberFontObject = 'WorldPlanNumberFontThin' } local headerNames = { ['rewardType'] = 'Reward Type', ['worldQuestType'] = 'Quest Type', ['isElite'] = 'Elite', ['factionID'] = 'Bounties' } db.DefaultFilters = { { filterKey= 'rewardType', cVar = 'worldQuestFilterArtifactPower', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" }, { filterKey= 'rewardType', cVar = 'worldQuestFilterOrderResources', filterValue = REWARD_CURRENCY,label = 'Order Resources', texture = "Interface\\Icons\\inv_orderhall_orderresources" }, { filterKey= 'rewardType', cVar = 'worldQuestFilterEquipment', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" }, { filterKey= 'rewardType', cVar = 'worldQuestFilterProfessionMaterials', filterValue = REWARD_REAGENT, label = 'Materials', texture = 1417744 }, { filterKey= 'rewardType', cVar = 'worldQuestFilterGold', filterValue = REWARD_CASH, label = 'Gold', texture = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\BattlenetWorking0", }, { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", }, --{ filterKey = 'isElite', filterValue = true, label = 'Elite', texture = "", desaturated = false}, --{ filterKey = 'isElite', filterValue = false, label = 'Not-Elite', texture = "", desaturated = false}, } local defaults = {} WorldPlanSummaryMixin = WorldPlanSummaryMixin or {} local Module = WorldPlanSummaryMixin Module.selectedBountyIndex = {} Module.bounties = {} Module.filterList = {} Module.Buttons = {} Module.Headers = {} Module.cvarFiltersDirty = false WorldPlanFilterButtonMixin = {} local Pin = WorldPlanFilterButtonMixin function Module:OnLoad() --self:SetParent(WorldMapFrame.UIElementsFrame) WorldPlan:AddHandler(self) --[[for index, info in ipairs(db.DefaultFilters) do info.zone = db.DefaultFilterType info.continent = db.DefaultFilterType info.pinMask = "Interface\\Minimap\\UI-Minimap-Background" WorldPlan:AddTypeInfo(self,index, info) end --]] end function Module:OnEvent(event, arg) print('|cFF00FF88'..self:GetName()..':OnEvent()', event) if (event == 'QUEST_LOG_UPDATE') and arg then filtersDirty = true self:Refresh() end end local bountyIndex local debug_headers = {} local ToggleButton = {} function Module:Setup() print('|cFF00FF88'..self:GetName()..':Setup()') self.isStale = true self:SetParent(WorldMapFrame.UIElementsFrame) --self:SetPoint('BOTTOMLEFT') for k,v in pairs( ToggleButton) do self.Toggle:SetScript(k,v) end self.Toggle:SetSize(TOGGLE_SIZE, TOGGLE_SIZE) end function Module:OnUpdate(sinceLast) if self.isStale then print('|cFF00FF00pushing update') self:Refresh() end barMouseOver = self:IsMouseOver() if barMouseOver or filtersUsed then self.toAlpha = 1 self.Backdrop:Show() else self.toAlpha = 0.25 self.Backdrop:Hide() end local cAlpha = self:GetAlpha() if cAlpha ~= self.toAlpha then if cAlpha > self.toAlpha then cAlpha = cAlpha - sinceLast*4 if cAlpha <= self.toAlpha then cAlpha = self.toAlpha end else cAlpha = cAlpha + sinceLast*4 if cAlpha >= self.toAlpha then cAlpha = self.toAlpha end end end self:SetAlpha(cAlpha) end function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen) print('|cFFFFFF00OnMapInfo()', isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen) if not isBrokenIsle then self:SetShown(false) else self:SetShown(true) if isMapOpen then self:Refresh() else matchesDirty = true layoutDirty = true end end end function Module:OnShow() print('|cFF00FF88'..self:GetName()..':OnShow()') self:Refresh() end local IsBountyCriteria = function(poiFrame, questID) return IsQuestCriteriaForBounty(poiFrame.questID, questID) end local tinsert, GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID = tinsert, GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID function Module:OnConfigUpdate() ToggleButton.OnShow(self.Toggle) end function Module:Reset() self:UpdateFilters('SUMMARY_RESET') self:UpdateMatches('SUMMARY_RESET') self:UpdateLayout('SUMMARY_RESET') end function Module:Refresh() self:UpdateFilters('SUMMARY_REFRESH') self:UpdateMatches('SUMMARY_REFRESH') self:UpdateLayout('SUMMARY_REFRESH') end local questResults = {{} } db.FilterList = {} function Module:UpdateFilters(event) print('|cFF00FFFF'..self:GetName()..':GetFilters()', event) wipe(db.FilterList) for index, info in ipairs(db.DefaultFilters) do info.used = true tinsert(db.FilterList, info) end self.bounties = db.Bounties self.BountyFilters = {} local numBounties = 0 for index, data in ipairs(self.bounties) do if not IsQuestComplete(data.questID) then numBounties = numBounties + 1 local info = self.BountyFilters[index] if not info then info = {} self.BountyFilters[index] = info layoutDirty = true else if info.questID ~= data.questID then layoutDirty = true end end local questTitle = GetQuestLogTitle(GetQuestLogIndexByID(data.questID)) info.used = true info.filterKey = 'factionID' info.filterFunc = IsBountyCriteria info.filterValue = data.questID info.label = questTitle info.texture = data.icon print('loading emissary', questTitle) tinsert(db.FilterList, info) --{ filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", }, end end for i = numBounties + 1, #self.BountyFilters do self.BountyFilters[i].used = nil end end function Module:UpdateMatches(event) print('|cFF00FF00UpdateMatches()', event) local quests = db.QuestsByID local questsForMap = db.QuestsByZone[db.currentMapID] or quests for index, info in ipairs(db.FilterList) do info.GlobalMatches = info.GlobalMatches or {} info.LocalMatches = info.LocalMatches or {} wipe(info.GlobalMatches) wipe(info.LocalMatches) print(info.filterKey, info.filterValue, info.filterFunc and 'func test' or 'compare') for questID, pin in pairs(quests) do print('', questID, pin.dataLoaded, (not IsQuestComplete(questID))) if pin.dataLoaded and (not IsQuestComplete(questID)) then local keyName, keyValue = info.filterKey, info.filterValue local isMatch if info.filterFunc then isMatch = info.filterFunc(pin, keyValue) print(' running special function, result =', isMatch) elseif pin[keyName] and (pin[keyName] == keyValue) then isMatch = true print(' rote match') end if isMatch then tinsert(info.GlobalMatches, pin) if questsForMap[questID] then print(' local map') tinsert(info.LocalMatches, pin) end end end end print('global', #info.GlobalMatches, 'local', #info.LocalMatches) end end function Module:UpdateLayout(event) print('|cFF00FF88UpdateLayout()|r', event, 'currentMap=',db.currentMapID) self.filtersSelected = nil local currentHeader local relativeFrame = self local lastKey local numHeaders = 0 local numButtons = 0 local layoutWidth = TOGGLE_SIZE + HEADERS_SPACING * 2 local headerWidth = HEADERS_SPACING local layout = db.DefaultFilterType local borderWidth = layout.iconWidth + (layout.borderWidth * 2) local highlightWidth = borderWidth + (layout.highlightWidth * 2) local mapQuests = db.QuestsByZone[db.currentMapID] or db.QuestsByID local n = 0 for _ in pairs(mapQuests) do n = n + 1 end print(n, 'pins to work with') filtersUsed = nil local firstCvar, lastCvar local isFirst = true for index, info in ipairs(db.FilterList) do --print('num here', numQuestsHere, numQuestsTotal) --print(tostring(index).. ' ("'..tostring(info.label)..'" f('.. tostring(info.filterKey).. '='..tostring(info.filterValue) .. '), '..tostring(numQuests)..')') if #info.GlobalMatches >= 1 then if info.filterKey ~= lastKey then numHeaders = numHeaders + 1 local nextHeader = self.Headers[numHeaders] or CreateFrame('Frame', 'FilterHeader' .. numHeaders, self, 'WorldPlanFilterHeader') if currentHeader then nextHeader:SetPoint('TOPLEFT', currentHeader, 'TOPRIGHT', 0, 0) currentHeader:SetSize(headerWidth - BUTTONS_SPACING + HEADERS_SPACING, HEADERS_HEIGHT) layoutWidth = layoutWidth + headerWidth headerWidth = HEADERS_SPACING else nextHeader:SetPoint('TOPLEFT', TOGGLE_SIZE + HEADERS_SPACING * 2, 0) end print(' begin header '..numHeaders, 'layout width =', floor(layoutWidth+.5)) isFirst = true currentHeader = nextHeader currentHeader.Backdrop:SetHeight(BUTTONS_HEIGHT *2) currentHeader.Label:SetText(headerNames[info.filterKey]) relativeFrame = currentHeader end numButtons = numButtons + 1 local button = self.Buttons[numButtons] if not button then button = CreateFrame('Button', 'FilterButton'..numButtons, self, 'WorldPlanFilterButton') button:SetSize(32,BUTTONS_HEIGHT) button.icon:SetTexCoord(0.1,.9,.1,(1 * (BUTTONS_HEIGHT/32))) button.RewardBorder:ClearAllPoints() button.RewardBorder:SetPoint('TOPLEFT', button, 'TOPLEFT') button.RewardBorder:SetPoint('BOTTOMRIGHT', button, 'BOTTOMRIGHT') end button.info = info button.numQuestsTotal = #info.GlobalMatches button.numQuestsHere = #info.LocalMatches button.GlobalMatches = info.GlobalMatches button.LocalMatches = info.LocalMatches button.isFirst = isFirst button:SetID(index) button:SetParent(currentHeader) button.relativeFrame = relativeFrame button:Refresh() button:Show() relativeFrame = button headerWidth = headerWidth + button:GetWidth() + BUTTONS_SPACING isFirst = false if info.cVar then firstCvar = firstCvar or button lastCvar = button end lastKey = info.filterKey end end self.numHeaders = numHeaders for i = numButtons + 1, #self.Buttons do if self.Buttons[i] then self.Buttons[i]:Hide() wipe(self.Buttons[i].LocalMatches) wipe(self.Buttons[i].GlobalMatches) end end for i = numHeaders + 1, #self.Headers do if self.Headers[i] then self.Headers[i]:Hide() end end if currentHeader then currentHeader:SetSize(headerWidth - BUTTONS_SPACING + HEADERS_SPACING, HEADERS_HEIGHT) layoutWidth = layoutWidth + headerWidth + HEADERS_SPACING end self:SetSize(layoutWidth, BUTTONS_HEIGHT + (BUTTONS_SPACING * 2)) self:ClearAllPoints() self:SetPoint('BOTTOM') self.isStale = nil layoutDirty = nil end function Module:Cleanup() -- hide trailing buttons end local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF' } local found = {} function Pin:OnEnter() if #self.GlobalMatches >= 1 then GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT') GameTooltip:AddLine(self.info.label) wipe(found) if self.numQuestsHere >= 1 then if self.numQuestsHere < self.numQuestsTotal then GameTooltip:AddLine('This Zone', 1, 1, 0) end for index, pin in ipairs(self.LocalMatches) do local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite found[pin] = pin GameTooltip:AddLine('|T'.. tostring(pin.itemTexture)..':16:16|t ' .. tostring(pin.title) ..(pin.cheevos and " |cFFFFFF00!|R" or ''), 0, 1, 0) end end if self.numQuestsHere < self.numQuestsTotal then if self.numQuestsHere >= 1 then GameTooltip:AddLine(' ') end GameTooltip:AddLine('Other Maps', 1, 1, 0) for index, pin in ipairs(self.GlobalMatches) do if not found[pin] then local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite found[pin] = pin GameTooltip:AddLine('|T'.. tostring(pin.itemTexture)..':16:16|t ' .. tostring(pin.title) ..(pin.cheevos and " |cFFFFFF00!|R" or ''), 1, 1, 1) end end end GameTooltip:AddLine(self.numQuestsTotal .. ' total') GameTooltip:Show() end end function Pin:OnLeave() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function Pin:Refresh() local info = self.info self.filterKey = info.filterKey self.filterValue = info.filterValue self.tagID = info.tagID self.icon:SetTexture(info.texture) if (self.numQuestsHere == 0) and (self.numQuestsTotal >= 1) then self.count:SetText('*'..self.numQuestsTotal) self.count:SetTextColor(0,1,1) elseif self.numQuestsHere < self.numQuestsTotal then self.count:SetText(self.numQuestsHere..'+') self.count:SetTextColor(1,1,0) else self.count:SetText(self.numQuestsHere) self.count:SetTextColor(1,1,1) end self.cVar = info.cVar self.itemTexture = self.texture self:ClearAllPoints() if self.isFirst then self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', HEADERS_SPACING, -HEADERS_SPACING) else self:SetPoint('LEFT', self.relativeFrame, 'RIGHT', BUTTONS_SPACING, 0) end --print('anchor', self.relativeFrame:IsShown(), self:GetPoint(1)) self.icon:SetDesaturated(self.numQuestsHere == 0) local r, g, b, a = 0,0,0,1 local desaturated = false if (self.numQuestsHere > 0) or db.UsedFilters[self.filterKey] then if self.cVar then if GetCVarBool(self.cVar) then --self.count:SetTextColor(1,1,1) r,g,b,a = 0, 0, 0, 1 else filtersUsed = true --self.count:SetTextColor(1,0,0) self.icon:SetDesaturated(true) r,g,b,a = 1, 0, 0, 0.5 end else if db.UsedFilters[self.filterKey] then filtersUsed = true if db.UsedFilters[self.filterKey] == self.filterValue then --self.count:SetTextColor(0,1,0) r, g, b = 0, 1, 0 else --self.count:SetTextColor(1,0,0) r, g, b = 1, 0, 0 end else --self.count:SetTextColor(1,1,1) if self.filterKey == 'worldQuestType' then r, g, b = 0, 0, 1 elseif self.filterKey == 'factionID' then r, g, b = 1, 1, 0 end end end end self.RewardBorder:SetColorTexture(r, g, b) self:SetAlpha(a) --self:UpdateSize() end function Pin:OnLoad() self:RegisterForClicks('AnyUp') self:SetFrameStrata('HIGH') self:SetFrameLevel(151) self.questList = {} -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level end function Pin:OnUpdate () local group = self:GetParent() if group:IsMouseOver() and barMouseOver then group.Backdrop:Show() group.Label:Show() else group.Backdrop:Hide() group.Label:Hide() end end -- shift-click: reset filter -- click: rotate through include(1), exclude(-1), ignore(nil) local filtered_report = {} local RESET_FILTER = "|cFFFFFFFF+%s|r" local FILTER_EXCLUDE_TYPE = '|cFFFF0000-%s|r' local FILTER_INCLUDE_TYPE = '|cFF00FF00+%s|r' function Pin:OnClick (button) local filterKey = self.filterKey local filterValue = self.filterValue local cVar = self.cVar local parent = self:GetParent() local setDirty print('|cFF00FF88'..self:GetName()..':OnClick()|r', filterKey, filterValue, cVar, parent) local resetMode = (button == 'RightButton') wipe(filtered_report) if not (filterKey or cVar) then for i, info in ipairs(db.DefaultFilters) do if info.cVar then SetCVar(info.cVar, 1) elseif info.filterKey then if db.UsedFilters[info.filterKey] then db.UsedFilters[info.filterKey] = nil end end end parent.cvarFiltersDirty = false --WorldPlan:print('All filters reset.') elseif cVar then if resetMode then print('|cFFFF4400cleaning dirty') for i, info in ipairs(db.DefaultFilters) do if info.cVar then parent.cvarFiltersDirty = false SetCVar(info.cVar, 1) end end --WorldPlan:print('Reward filters reset.') elseif parent.cvarFiltersDirty == true then if GetCVarBool(cVar) then tinsert(filtered_report, FILTER_EXCLUDE_TYPE:format(tostring(self.info.label))) SetCVar(cVar, 0) else tinsert(filtered_report, FILTER_INCLUDE_TYPE:format(tostring(self.info.label))) SetCVar(cVar, 1) end -- check the visible filters and consider it clean if they're all lit parent.cvarFiltersDirty = false for i, info in ipairs(db.FilterList) do if info.cVar and (#info.GlobalMatches >= 1) then print(info.cVar, GetCVarBool(info.cVar)) if GetCVarBool(info.cVar) == false then parent.cvarFiltersDirty = true print('|cFFFF4400still dirty') break end end end else print('|cFFFF4400making dirty') for i, info in ipairs(db.DefaultFilters) do if info.cVar then local msgType = (cVar == info.cVar) and FILTER_INCLUDE_TYPE or FILTER_EXCLUDE_TYPE SetCVar(info.cVar, ((cVar == info.cVar) and 1) or 0) tinsert(filtered_report, msgType:format(info.label)) end end parent.cvarFiltersDirty = true end else if resetMode then wipe(db.UsedFilters) --WorldPlan:print('Type filters reset.') else if (db.UsedFilters[filterKey] == filterValue) or resetMode then db.UsedFilters[filterKey] = nil tinsert(filtered_report, FILTER_INCLUDE_TYPE:format(tostring(filterKey))) else db.UsedFilters[filterKey] = filterValue tinsert(filtered_report, FILTER_EXCLUDE_TYPE:format(tostring(filterKey))) end end end if #filtered_report >= 1 then --WorldPlan:print('Setting filter(s):', table.concat(filtered_report, ', ')) end WorldPlan:Refresh(true) end function ToggleButton:OnEnter() GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT') GameTooltip:AddLine('Toggle Pins') GameTooltip:Show() end function ToggleButton:OnLeave() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function ToggleButton:OnShow() self:SetChecked(db.Config.EnablePins and true or false) end function ToggleButton:OnHide() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function ToggleButton:OnClick() --print(self:GetChecked()) db.Config.EnablePins = self:GetChecked() _G.WorldPlan:OnConfigUpdate() end