view FilterBar.lua @ 38:a93cae445d3f v1.0-rc9

WorldPlan: - Quest pins are now placed on the flight map. Their visibility rules will mirror the filter options from the world map. - Filter controls polish: - First click negates other reward type filters. Subsequent clicks will then toggle individual reward types until the filters are reset via Right-click. - Adheres to the Blizzard CVars added in patch 7.1 - Numerous optimizations to how data and visual updates are handled; should see an even better load time, and snappier world map interaction. ClassPlan: - The 'Available Missions' list is now recorded. It can be reviewed by clicking on the mission list heading. - Information filtering by character and realm.
author Nenue
date Fri, 04 Nov 2016 02:53:57 -0400
parents 21bcff08b0f4
children 589c444d4837
line wrap: on
line source
-- WorldPlan
-- FilterBar.lua
-- Created: 10/27/2016 8:55 PM
-- %file-revision%
--

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 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 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

local DEFAULT_FILTER_LAYOUT = {
  iconWidth = 24,
  borderWidth = 3,
  highlightWidth = 2,
  TagSize = 12,
  TimeleftStage = 3,
  showNumber = true,
  numberFontObject = 'WorldPlanNumberFontThin'
}
local DEFAULT_FILTER_LIST = {
  { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" },
  { 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\\UI-LFR-PORTRAIT", },
  { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", },
}
local defaults = {}

WorldPlanSummaryMixin = {
  selectedBountyIndex = {},
  bounties = {},
  filterList = {},
  buttons = {},
}
WorldPlanFilterPinMixin = {}

function WorldPlanSummaryMixin:OnLoad()
  WorldPlan:AddHandler(self, defaults)
  for index, info in ipairs(DEFAULT_FILTER_LIST) do
    info.zone = DEFAULT_FILTER_LAYOUT
    info.continent = DEFAULT_FILTER_LAYOUT
    info.pinMask =  "Interface\\Minimap\\UI-Minimap-Background"

    WorldPlan:AddTypeInfo(self,index, info)
  end

end


function WorldPlanSummaryMixin:OnEvent(event)
  print('|cFF00FF88'..self:GetName()..':OnEvent()', event)
  self.isStale = true
end

local bountyIndex
local debug_headers = {}

function WorldPlanSummaryMixin:Setup()
  print('|cFF00FF88'..self:GetName()..':Setup()')
  self:GetFilters()
end


function WorldPlanSummaryMixin:OnUpdate()
  if self.isStale then
    wprint('|cFF00FF00pushing update')
    self:Refresh()
  end
end

function WorldPlanSummaryMixin:OnShow()
  print('|cFF00FF88'..self:GetName()..':OnShow()')
  if self.isStale then
    self:Refresh()
  end
end

function WorldPlanSummaryMixin:GetFilters()

  print('|cFF00FFFF'..self:GetName()..':GetFilters()')

  wipe(self.filterList)

  for index, info in ipairs(DEFAULT_FILTER_LIST) do
    tinsert(self.filterList, info)
  end
  self.bounties, self.numBounties = GetQuestBountyInfoForMapID(WorldPlan.currentMapID)
  self.BountyFilters = {}
  for index, data in ipairs(self.bounties) do
    local info = self.BountyFilters[index]
    if not info then
      info  = {}
      self.BountyFilters[index] = info
    end

    local questTitle = GetQuestLogTitle(GetQuestLogIndexByID(data.questID))

    info.filterKey = 'factionID'
    info.filterValue = data.factionID
    info.label = questTitle
    info.texture = data.icon
    print('loading emissary', questTitle)

    tinsert(self.filterList, info)
    --{ filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
  end
end

function WorldPlanSummaryMixin:Reset()
  self.pinLayout = self:GetTypeInfo(255)
  self:GetFilters()
end

function WorldPlanSummaryMixin:Refresh()
  self:Update()
end

local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64"
local filterMask = "Interface\\Minimap\\UI-Minimap-Background"

local questResults = {{}}
function WorldPlanSummaryMixin:Update()
  local blocks = self.buttons
  local relativeFrame = WorldMapFrame.UIElementsFrame.TrackingOptionsButton
  local numHeaders = 0
  print('|cFF00FF88'..self:GetName()..':Update()|r', 'currentMap=',WorldPlan.currentMapID)

  local layout = DEFAULT_FILTER_LAYOUT
  local borderWidth = layout.iconWidth + (layout.borderWidth * 2)
  local highlightWidth = borderWidth + (layout.highlightWidth * 2)
  local quests = WorldPlanQuests.QuestsByZone[WorldPlan.currentMapID] or WorldPlanQuests.QuestsByID
  local foundQuests = questResults[1]
  for index, info in ipairs(self.filterList) do
    local numQuests = 0
    local resultIndex = numHeaders + 1
    questResults[resultIndex] = questResults[resultIndex] or  {}
    wipe(questResults[resultIndex])
    for questID, pin in pairs(quests) do
      if pin.used then
        if not info.filterKey then
          numQuests = numQuests + 1
        elseif pin[info.filterKey] == info.filterValue then
          numQuests = numQuests + 1
          tinsert(questResults[resultIndex], pin)
        end
      end
    end
    print(tostring(index).. ' ("'..tostring(info.label)..'" f('.. tostring(info.filterKey).. '='..tostring(info.filterValue) .. '), '..tostring(numQuests)..')')

    if numQuests >= 1 then
      numHeaders = numHeaders + 1
      local button = blocks[numHeaders]
      if not blocks[numHeaders] then
        button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, WorldMapScrollFrame, 'WorldPlanFilterPin')
        button:SetSize(borderWidth, borderWidth)

        button.icon:SetSize(layout.iconWidth, layout.iconWidth)
        button.RewardBorder:SetSize(borderWidth, borderWidth)
        button.HighlightBorder:SetSize(highlightWidth, highlightWidth)
        button.RewardBorder:SetMask(filterMask)
        button.RewardBorder:SetDesaturated(true)

        button.HighlightBorder:Hide()
        blocks[numHeaders] = button
      end

      button.info = info
      button.questList = questResults[resultIndex]
      button:SetID(index)
      button.spacing = ((relativeFrame.cVar and (not info.cVar)) or (relativeFrame.filterKey ~= info.filterKey)) and 5 or 0
      button.relativeFrame = relativeFrame
      button:Refresh((numHeaders == 1), numQuests)
      button:Show()
      relativeFrame = button
    end

  end

  self.numHeaders = numHeaders
  for i = numHeaders + 1, #blocks do
    if blocks[i] then
      blocks[i]:Hide()
    end
    if questResults[i] then
      wipe(questResults[i])
    end
  end
  self.isStale = nil
end

function WorldPlanSummaryMixin:Cleanup()
  -- hide trailing buttons
end

local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF'}
function WorldPlanFilterPinMixin:OnEnter()
  if self.questList and #self.questList >= 1 then
    GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
    GameTooltip:AddLine(self.info.label)
    for index, pin in ipairs(self.questList) do
      local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite
      GameTooltip:AddLine('|T'.. tostring(pin.itemTexture)..':16:16|t ' .. pin.title ..(pin.cheevos and " |cFFFFFF00!|R" or ''), colorInfo.r, colorInfo.g, colorInfo.b)
    end
    GameTooltip:Show()
  end
end

function WorldPlanFilterPinMixin:OnLeave()
  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end
end

function WorldPlanFilterPinMixin:Refresh(isFirst, numQuests)
  isFirst = isFirst or self.isFirst
  numQuests = numQuests or self.numQuests

  local info = self.info

  self.isFirst = isFirst
  self.numQuests = numQuests
  self.filterKey = info.filterKey
  self.filterValue = info.filterValue
  self.tagID = info.tagID

  self.icon:SetMask(filterMask)
  self.icon:SetTexture(info.texture)
  self.count:SetText(numQuests)
  self.cVar = info.cVar

  self.itemTexture = self.texture

  if isFirst then
    self:SetPoint('TOP', self.relativeFrame, 'BOTTOM', 0, -5)
  else
    self:SetPoint('TOPRIGHT', self.relativeFrame, 'BOTTOMRIGHT', 0, -(self.spacing or 0))
  end
  print('anchor to', self.relativeFrame:GetName(), info.mask)

  local r, g, b, a = 1,1,1,1
  local desaturated = false
  if self.cVar then
    self.RewardBorder:SetVertexColor(1, 1, 1, 1)
    if GetCVarBool(self.cVar) then
      self.icon:SetVertexColor(1,1,1,1)
      self:SetAlpha(1)
    else
      self.icon:SetVertexColor(.5, .5, .5, 1)
      self:SetAlpha(0.5)
    end
  else
    self:SetAlpha(1)
    if WorldPlan.UsedFilters[self.filterKey] then
      if WorldPlan.UsedFilters[self.filterKey] == self.filterValue then
        self.RewardBorder:SetVertexColor(0, 1, 0)
      else
        self.RewardBorder:SetVertexColor(1, 0, 0)
      end
    else
      if self.filterKey == 'worldQuestType' then
        self.RewardBorder:SetVertexColor(0, 1, 1)
      elseif self.filterKey == 'factionID' then
        self.RewardBorder:SetVertexColor(1, 1, 0)
      else

        self.RewardBorder:SetVertexColor(0.5, 0.5, 0.5)
      end

    end
  end

  --self:UpdateSize()
end

function WorldPlanFilterPinMixin:OnLoad()
  self:RegisterForClicks('AnyUp')
  self:SetFrameStrata('HIGH')
  self:SetFrameLevel(151)
  self:SetScript('OnUpdate', nil)
  WorldPlanPOIMixin.OnLoad(self)
end

function WorldPlanFilterPinMixin:OnUpdate ()
end


function WorldPlanFilterPinMixin:OnLeave ()
  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end
end

-- shift-click: reset filter
-- click: rotate through include(1), exclude(-1), ignore(nil)
local filtered_report = {}
function WorldPlanFilterPinMixin:OnClick (button)

  print('|cFF00FF88'..self:GetName()..':OnClick()|r', filterKey, filterValue, operation)
  local filterKey = self.filterKey
  local filterValue = self.filterValue
  local cVar = self.cVar
  local parent = self:GetParent()
  local operation = opPrefix
  local setDirty = false

  local resetMode = (button == 'RightButton')
  wipe(filtered_report)
  if not (filterKey or cVar) then
    wipe(WorldPlan.UsedFilters)
    for i, info in ipairs(DEFAULT_FILTER_LIST) do
      if info.cVar then
        if GetCVar(info.cVar) ~= 1 then
          tinsert(filtered_report, '|cFF888888'.. tostring(info.label) ..'|r')
        end
        SetCVar(info.cVar, 1)
      end
    end

  elseif cVar then
    WorldPlan:print('Toggling cvar filter:', cVar)
    if (not parent.isDirty) or resetMode then
      for i, info in ipairs(DEFAULT_FILTER_LIST) do
        if info.cVar then
          local value = GetCVar(info.cVar)
          if resetMode then
            value = 1
            parent.isDirty = nil
          else

              if (cVar ~= info.cVar) then
                value = 0
              else
                value = 1
              end
              setDirty = true

          end
          SetCVar(info.cVar, value)
        end
      end
      if setDirty then
        parent.isDirty = true
      end
    else
      SetCVar(cVar, (GetCVarBool(cVar) and 0) or 1)
    end
  else
    local flushValue
    print('')
    if WorldPlan.UsedFilters[filterKey] == filterValue then
      WorldPlan.UsedFilters[filterKey] = nil
      tinsert(filtered_report,  '|cFFFF0000'.. tostring(filterKey) ..'|r')
    else
      WorldPlan.UsedFilters[filterKey] = filterValue
      tinsert(filtered_report,  '|cFF00FF00'.. tostring(filterKey) ..'|r')
    end
  end
  WorldPlan:print('Changed:', table.concat(filtered_report, ', '))
  WorldPlan:Refresh(true)
end