|
|
|
|
local _, S = ...
|
|
|
|
|
local pairs, ipairs, string, type, time = pairs, ipairs, string, type, time
|
|
|
|
|
|
|
|
|
|
S.IconPicker = {}
|
|
|
|
|
|
|
|
|
|
local buttonSize = 40
|
|
|
|
|
local padding = 3
|
|
|
|
|
local rows = 10
|
|
|
|
|
local cols = 12
|
|
|
|
|
local scrollStep = 2
|
|
|
|
|
|
|
|
|
|
local f = CreateFrame("Frame", "SortedIconPicker", UIParent)
|
|
|
|
|
table.insert(UISpecialFrames, "SortedIconPicker")
|
|
|
|
|
f:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
|
|
|
f:SetFrameLevel(10)
|
|
|
|
|
f:SetSize(cols * (buttonSize + padding) + 40, rows * (buttonSize + padding) + 16 + 40)
|
|
|
|
|
f:SetScript("OnMouseDown", function(self) end)
|
|
|
|
|
S.FrameTools.AddSortedBackdrop(f)
|
|
|
|
|
S.FrameTools.AddOuterShadow(f, 64)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if S.WoWVersion() > 1 then
|
|
|
|
|
f:RegisterEvent("GLOBAL_MOUSE_DOWN")
|
|
|
|
|
f:SetScript("OnEvent", function(self, event)
|
|
|
|
|
if event == "GLOBAL_MOUSE_DOWN" then
|
|
|
|
|
if not self:IsMouseOver() then
|
|
|
|
|
self:Hide()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
f.inner = CreateFrame("Frame", nil, f)
|
|
|
|
|
f.inner:SetPoint("TOPLEFT", 8, -8)
|
|
|
|
|
f.inner:SetPoint("BOTTOMRIGHT", -8, 8)
|
|
|
|
|
|
|
|
|
|
f = f.inner
|
|
|
|
|
f.buttons = {}
|
|
|
|
|
for y = 1, rows do
|
|
|
|
|
f.buttons[y] = {}
|
|
|
|
|
for x = 1, cols do
|
|
|
|
|
local b = CreateFrame("Button", nil, f)
|
|
|
|
|
b:SetSize(buttonSize, buttonSize)
|
|
|
|
|
b:SetPoint("CENTER", f, "TOPLEFT", padding / 2 + (x - 1) * (buttonSize + padding) + buttonSize / 2, -40 - padding / 2 - (y - 1) * (buttonSize + padding) - buttonSize / 2)
|
|
|
|
|
|
|
|
|
|
b.iconShadow = b:CreateTexture(nil, "ARTWORK")
|
|
|
|
|
b.iconShadow:SetTexture("Interface\\Addons\\Sorted\\Textures\\Item_Shadow")
|
|
|
|
|
b.iconShadow:SetPoint("TOPLEFT", -16, 16)
|
|
|
|
|
b.iconShadow:SetPoint("BOTTOMRIGHT", 16, -16)
|
|
|
|
|
--b.iconGlow:SetBlendMode("ADD")
|
|
|
|
|
b.iconShadow:Hide()
|
|
|
|
|
|
|
|
|
|
b:SetScript("OnClick", function(self, button)
|
|
|
|
|
SortedIconPicker.func(self.icon)
|
|
|
|
|
SortedIconPicker:Hide()
|
|
|
|
|
end)
|
|
|
|
|
b:SetScript("OnEnter", function(self, button)
|
|
|
|
|
self:SetSize(buttonSize * 1.6, buttonSize * 1.6)
|
|
|
|
|
self.iconShadow:Show()
|
|
|
|
|
self.iconShadow:SetDrawLayer("BACKGROUND")
|
|
|
|
|
self:SetFrameStrata("TOOLTIP")
|
|
|
|
|
self:GetNormalTexture():SetVertexColor(1, 1, 1, 1)
|
|
|
|
|
self:GetNormalTexture():SetTexCoord(0,1,0,1)
|
|
|
|
|
S.Tooltip.Schedule(function()
|
|
|
|
|
GameTooltip:SetOwner(self, "ANCHOR_LEFT")
|
|
|
|
|
GameTooltip:ClearLines()
|
|
|
|
|
GameTooltip:AddLine("|cffffffff"..self.icon)
|
|
|
|
|
GameTooltip:Show()
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
b:SetScript("OnLeave", function(self, button)
|
|
|
|
|
self:SetSize(buttonSize, buttonSize)
|
|
|
|
|
self.iconShadow:Hide()
|
|
|
|
|
self:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
|
|
|
self:GetNormalTexture():SetVertexColor(0.9, 0.9, 0.9, 1)
|
|
|
|
|
self:GetNormalTexture():SetTexCoord(0.1,0.9,0.1,0.9)
|
|
|
|
|
S.Tooltip.Cancel()
|
|
|
|
|
end)
|
|
|
|
|
b:HookScript("OnMouseDown", function(self, button)
|
|
|
|
|
if button == "LeftButton" then
|
|
|
|
|
self:SetSize(buttonSize * 1.3, buttonSize * 1.3)
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
f.buttons[y][x] = b
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
f:SetScript("OnHide", function(self)
|
|
|
|
|
self.icons = nil
|
|
|
|
|
self.filteredIcons = nil
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
function SortedIconPicker.inner:FilterIcons()
|
|
|
|
|
self.filteredIcons = {}
|
|
|
|
|
self.count = 0
|
|
|
|
|
if self.icons then
|
|
|
|
|
local text = self.searchBox.editBox:GetText()
|
|
|
|
|
local s2 = text:lower():gsub("%s+", ""):gsub("%p+", "")
|
|
|
|
|
for k, v in pairs(self.icons) do
|
|
|
|
|
local s1 = v:lower():gsub("%s+", ""):gsub("%p+", "")
|
|
|
|
|
if text == "" or s1:find(s2) then
|
|
|
|
|
table.insert(self.filteredIcons, k)
|
|
|
|
|
self.count = self.count + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
local max = math.ceil(self.count / (cols * scrollStep) - math.floor(rows / scrollStep) + 1)
|
|
|
|
|
if max < 1 then max = 1 end
|
|
|
|
|
self.scrollBar:SetMinMaxValues(1, max)
|
|
|
|
|
self:UpdateButtons()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function SortedIconPicker.inner:UpdateButtons()
|
|
|
|
|
if self.count then
|
|
|
|
|
local index = self.scrollBar:GetValue() * cols * scrollStep - cols * scrollStep + 1
|
|
|
|
|
for y = 1, rows do
|
|
|
|
|
for x = 1, cols do
|
|
|
|
|
local b = self.buttons[y][x]
|
|
|
|
|
if self.filteredIcons[index] then
|
|
|
|
|
b.icon = self.icons[self.filteredIcons[index]]
|
|
|
|
|
b:SetNormalTexture("Interface\\Icons\\"..b.icon)
|
|
|
|
|
b:Show()
|
|
|
|
|
if b:IsMouseOver() then
|
|
|
|
|
GameTooltip:SetOwner(b, "ANCHOR_LEFT")
|
|
|
|
|
GameTooltip:ClearLines()
|
|
|
|
|
GameTooltip:AddLine("|cffffffff"..b.icon)
|
|
|
|
|
GameTooltip:Show()
|
|
|
|
|
b:GetNormalTexture():SetVertexColor(1, 1, 1, 1)
|
|
|
|
|
b:GetNormalTexture():SetTexCoord(0,1,0,1)
|
|
|
|
|
else
|
|
|
|
|
b:GetNormalTexture():SetVertexColor(0.9, 0.9, 0.9, 1)
|
|
|
|
|
b:GetNormalTexture():SetTexCoord(0.1,0.9,0.1,0.9)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
b:Hide()
|
|
|
|
|
end
|
|
|
|
|
index = index + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
f.scrollBar = CreateFrame("Slider", nil, SortedIconPicker, "MinimalScrollBarTemplate")
|
|
|
|
|
f.scrollBar.trackBG:Hide()
|
|
|
|
|
f.scrollBar:SetPoint("TOPRIGHT", -8, -64)
|
|
|
|
|
f.scrollBar:SetPoint("BOTTOM", 0, 24)
|
|
|
|
|
f.scrollBar:SetValueStep(1)
|
|
|
|
|
f.scrollBar.ScrollUpButton:SetScript("OnClick", function(self, button)
|
|
|
|
|
end)
|
|
|
|
|
f.scrollBar.ScrollDownButton:SetScript("OnClick", function(self, button)
|
|
|
|
|
end)
|
|
|
|
|
f.scrollBar:SetScript("OnValueChanged", function(self)
|
|
|
|
|
self:SetValue(math.floor(self:GetValue()))
|
|
|
|
|
SortedIconPicker.inner:UpdateButtons()
|
|
|
|
|
end)
|
|
|
|
|
f.scrollBar:SetMinMaxValues(1, 1)
|
|
|
|
|
f.scrollBar:SetValue(1)
|
|
|
|
|
|
|
|
|
|
f:EnableMouseWheel(1)
|
|
|
|
|
f:SetScript("OnMouseWheel", function(self, delta)
|
|
|
|
|
self.scrollBar:SetValue(self.scrollBar:GetValue() - delta)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
f.searchBox = S.FrameTools.CreateEditBox(SortedIconPicker.inner, nil, SEARCH)
|
|
|
|
|
f.searchBox:SetPoint("TOPLEFT", 4, 40)
|
|
|
|
|
f.searchBox.editBox:SetWidth(480)
|
|
|
|
|
f.searchBox.editBox:HookScript("OnTextChanged", function(self, userInput)
|
|
|
|
|
SortedIconPicker.inner:FilterIcons()
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
f.closeButton = S.FrameTools.CreateCloseButton(SortedIconPicker)
|
|
|
|
|
f.closeButton:SetSize(24, 24)
|
|
|
|
|
f.closeButton:SetNormalTexture("Interface\\Addons\\Sorted\\Textures\\redbutton2x-Clean")
|
|
|
|
|
f.closeButton:SetHighlightTexture("Interface\\Addons\\Sorted\\Textures\\redbutton2x-Clean")
|
|
|
|
|
f.closeButton:GetHighlightTexture():SetTexCoord(0.1484375, 0.296875, 0, 0.3125)
|
|
|
|
|
f.closeButton:GetHighlightTexture():SetAlpha(0.6)
|
|
|
|
|
f.closeButton:SetPushedTexture("Interface\\Addons\\Sorted\\Textures\\redbutton2x-Clean")
|
|
|
|
|
|
|
|
|
|
--f.closeButton = CreateFrame("Button", "SortntIconPickerCloseButton", SortedIconPicker, "UIPanelCloseButton")
|
|
|
|
|
--f.closeButton:SetPoint("TOPRIGHT", -4, -4)
|
|
|
|
|
|
|
|
|
|
-- Load icons table
|
|
|
|
|
-- Game assets exported from title screen with console command 'ExportInterfaceFiles art'
|
|
|
|
|
-- Custom python script generates lua table from the file names in '...BlizzardInterfaceArt/Interface/ICONS/'
|
|
|
|
|
function S.IconPicker.Show(parent, func)
|
|
|
|
|
if S.WoWVersion() <= 3 then
|
|
|
|
|
SortedIconPicker.inner.icons = {"Ability_Ambush","Ability_BackStab","Ability_BullRush","Ability_CheapShot","Ability_Creature_Cursed_01","Ability_Creature_Cursed_02","Ability_Creature_Cursed_03","Ability_Creature_Cursed_04","Ability_Creature_Cursed_05","Ability_Creature_Disease_01","Ability_Creature_Disease_02","Ability_Creature_Disease_03","Ability_Creature_Disease_04","Ability_Creature_Disease_05","Ability_Creature_Poison_01","Ability_Creature_Poison_02","Ability_Creature_Poison_03","Ability_Creature_Poison_04","Ability_Creature_Poison_05","Ability_Creature_Poison_06","Ability_CriticalStrike","Ability_Defend","Ability_Devour","Ability_Druid_AquaticForm","Ability_Druid_BalanceofPower","Ability_Druid_Bash","ability_druid_berserk","Ability_Druid_CatForm","Ability_Druid_CatFormAttack","Ability_Druid_ChallangingRoar","Ability_Druid_Cower","Ability_Druid_Cyclone","Ability_Druid_Dash","ABILITY_DRUID_DEMORALIZINGROAR","Ability_Druid_Disembowel","Ability_Druid_Dreamstate","ability_druid_earthandsky","ability_druid_eclipse","ability_druid_eclipseorange","Ability_Druid_EmpoweredRejuvination","Ability_Druid_EmpoweredTouch","Ability_Druid_Enrage","Ability_Druid_FerociousBite","Ability_Druid_FlightForm","ability_druid_flourish","Ability_Druid_ForceofNature","ability_druid_galewinds","ability_druid_giftoftheearthmother","Ability_Druid_HealingInstincts","ability_druid_improvedmoonkinform","ability_druid_improvedtreeform","ability_druid_infectedwound","ability_druid_kingofthejungle","Ability_Druid_Lacerate","Ability_Druid_LunarGuidance","ability_druid_manatree","Ability_Druid_Mangle","Ability_Druid_Mangle","Ability_Druid_Mangle2","ability_druid_mastershapeshifter","Ability_Druid_Maul","Ability_Druid_NaturalPerfection","ability_druid_nourish","ability_druid_owlkinfrenzy","Ability_Druid_PredatoryInstincts","ability_druid_primalagression","ability_druid_primalprecision","Ability_Druid_PrimalTenacity","Ability_Druid_Rake","Ability_Druid_Ravage","ability_druid_replenish","ability_druid_skinteeth","ability_druid_starfall","Ability_Druid_SupriseAttack","Ability_Druid_Swipe","ability_druid_tigersroar","Ability_Druid_TravelForm","Ability_Druid_TreeofLife","Ability_Druid_TwilightsWrath","ability_druid_typhoon","Ability_DualWield","Ability_DualWieldSpecialization","Ability_Ensnare","Ability_EyeOfTheOwl","Ability_FiegnDead","Ability_GhoulFrenzy","Ability_GolemStormBolt","Ability_GolemThunderClap","Ability_Gouge","ability_heroicleap","Ability_Hibernation","Ability_Hunter_AimedShot","Ability_Hunter_AnimalHandler","ability_hunter_aspectmastery","Ability_Hunter_AspectOfTheMonkey","Ability_Hunter_AspectoftheViper","ability_hunter_assassinate","ability_hunter_assassinate2","Ability_Hunter_BeastCall","Ability_Hunter_BeastCall02","ability_hunter_beastmastery","Ability_Hunter_BeastSoothe","Ability_Hunter_BeastTaming","Ability_Hunter_BeastTraining","Ability_Hunter_BeastWithin","Ability_Hunter_CatlikeReflexes","ability_hunter_chimerashot2","ability_hunter_cobrastrikes","Ability_Hunter_CombatExperience","Ability_Hunter_CriticalShot","Ability_Hunter_DisarmingShot","Ability_Hunter_Displacement","Ability_Hunter_EagleEye","ability_hunter_explosiveshot","Ability_Hunter_FerociousInspiration","ability_hunter_focusedaim","Ability_Hunter_GoForTheThroat","Ability_Hunter_Harass","ability_hunter_huntervswild","ability_hunter_huntingparty","ability_hunter_improvedsteadyshot","ability_hunter_improvedtracking","ability_hunter_invigeration","Ability_Hunter_KillCommand","ability_hunter_lockandload","ability_hunter_longevity","ability_hunter_longshots","ability_hunter_markedfordeath","Ability_Hunter_MasterMarksman","ability_hunter_masterscall","Ability_Hunter_MasterTactitian","Ability_Hunter_MendPet","Ability_Hunter_Misdirection","Ability_Hunter_Pathfinding","Ability_Hunter_Pet_Bat","Ability_Hunter_Pet_Bear","Ability_Hunter_Pet_Boar","Ability_Hunter_Pet_Cat","ability_hunter_pet_chimera","ability_hunter_pet_corehound","Ability_Hunter_Pet_Crab","Ability_Hunter_Pet_Crocolisk","ability_hunter_pet_devilsaur","Ability_Hunter_Pet_DragonHawk","Ability_Hunter_Pet_Gorilla","Ability_Hu
|
|
|
|
|
else
|
|
|
|
|
SortedIconPicker.inner.icons = {"6BF_Blackrock_Nova","6BF_Explosive_Shard","6BF_Retched_Blackrock","6BF_Rolling_Fury","6IH_IronHorde_Stone_Base_StonewallEdge","6OR_Garrison_BlackIron","6OR_Garrison_BlackIron_Light","6OR_Garrison_BlackIron_Spec","6OR_Garrison_ClothRoof","6OR_Garrison_HangingLeather","6OR_Garrison_Leatherstraps","6OR_Garrison_metalbracket","6OR_Garrison_Metaltiles","6OR_Garrison_metaltrim_02","6OR_Garrison_OrcWindvane3","6OR_Garrison_Roof","6OR_Garrison_Roof_Darkblend","6OR_Garrison_Sign","6OR_Garrison_spikes","6OR_Garrison_Stair_01","6OR_Garrison_Stonewall","70_inscription_deck_dominion","70_inscription_deck_dominion_2","70_inscription_deck_dominion_3","70_inscription_deck_dominion_4","70_inscription_deck_dominion_5","70_inscription_deck_dominion_6","70_inscription_deck_dominion_7","70_inscription_deck_dominion_8","70_inscription_deck_dominion_a","70_inscription_deck_Hellfire","70_inscription_deck_Hellfire_2","70_inscription_deck_Hellfire_3","70_inscription_deck_Hellfire_4","70_inscription_deck_Hellfire_5","70_inscription_deck_Hellfire_6","70_inscription_deck_Hellfire_7","70_inscription_deck_Hellfire_8","70_inscription_deck_Hellfire_a","70_inscription_deck_Immortality","70_inscription_deck_Immortality_2","70_inscription_deck_Immortality_3","70_inscription_deck_Immortality_4","70_inscription_deck_Immortality_5","70_inscription_deck_Immortality_6","70_inscription_deck_Immortality_7","70_inscription_deck_Immortality_8","70_inscription_deck_Immortality_a","70_inscription_deck_Promises","70_inscription_deck_Promises_2","70_inscription_deck_Promises_3","70_inscription_deck_Promises_4","70_inscription_deck_Promises_5","70_inscription_deck_Promises_6","70_inscription_deck_Promises_7","70_inscription_deck_Promises_8","70_inscription_deck_Promises_a","70_inscription_glyph_demonhunter_major","70_inscription_glyph_demonhunter_minor","70_inscription_pigment_roseate","70_inscription_pigment_sallow","70_inscription_steamy_romance_novel_kit","70_inscription_vantus_rune_azure","70_inscription_vantus_rune_light","70_inscription_vantus_rune_nightmare","70_inscription_vantus_rune_odyn","70_inscription_vantus_rune_suramar","70_inscription_vantus_rune_tomb","70_professions_scroll_01","70_professions_scroll_02","70_professions_scroll_03","7FX_AlphaMask_Glow_Teal_Blend","8XP_VulperaFlute","9XP_Sigil_Ardenweald01","9XP_Sigil_Maldraxxus01","Ability_Accretion","Ability_Ambush","Ability_AnimusDraw","Ability_AnimusOrbs","Ability_Arakkoa_Spinning_Blade","Ability_Ardenweald_DeathKnight","Ability_Ardenweald_DemonHunter","Ability_Ardenweald_Druid","Ability_Ardenweald_Hunter","Ability_Ardenweald_Mage","Ability_Ardenweald_Monk","Ability_Ardenweald_Paladin_Autumn","Ability_Ardenweald_Paladin_Spring","Ability_Ardenweald_Paladin_Summer","Ability_Ardenweald_Paladin_Winter","Ability_Ardenweald_Priest","Ability_Ardenweald_Rogue","Ability_Ardenweald_Shaman","Ability_Ardenweald_Warlock","Ability_Ardenweald_Warrior","Ability_Argus_BlightOrb","Ability_Argus_DeathFog","Ability_Argus_EdgeOfObliteration","Ability_Argus_SoulBombDebuffLarge","Ability_Argus_SoulBombDebuffSmall","Ability_Argus_SoulBurst","Ability_Argus_WastingPlague","Ability_BackStab","Ability_Bastion_DeathKnight","Ability_Bastion_DemonHunter","Ability_Bastion_Druid","Ability_Bastion_Hunter","Ability_Bastion_Mage","Ability_Bastion_Monk","Ability_Bastion_Paladin","Ability_Bastion_Priest","Ability_Bastion_Rogue","Ability_Bastion_Shaman","Ability_Bastion_Warlock","Ability_Bastion_Warrior","Ability_Blackhand_AttachedSlagbombs","Ability_Blackhand_Demolition","Ability_Blackhand_Marked4Death","Ability_Blackhand_Slagbombs","Ability_BossAshvane_Icon01","Ability_BossAshvane_Icon02","Ability_BossAshvane_Icon03","Ability_BossDarkVindicator_AuraofContempt","Ability_BossDarkVindicator_AuraofMalice","Ability_BossDarkVindicator_AuraofOppression","Ability_BossFelLord_FelFissure","Ability_BossFelLord_FelSpike","Ability_BossFelMagnaron_Hand","Ability_BossFelMagnaron_HandEmpowered","Ability_BossFelMagnaron_Rune","Ability_BossFelMagnaron_RuneEmpowered","Ability_BossFelMagnaron_Wave","Ability_BossFelMagnaro
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
SortedIconPicker.func = func
|
|
|
|
|
SortedIconPicker:SetPoint("TOPLEFT", parent, "BOTTOMRIGHT")
|
|
|
|
|
SortedIconPicker:Show()
|
|
|
|
|
|
|
|
|
|
SortedIconPicker.inner.filteredIcons = {}
|
|
|
|
|
SortedIconPicker.inner:FilterIcons()
|
|
|
|
|
end
|