--[[
AdiBags - Adirelle's bag addon.
Copyright 2013-2014 Adirelle (adirelle@gmail.com)
All rights reserved.
This file is part of AdiBags.
AdiBags is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
AdiBags is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AdiBags. If not, see .
--]]
local addonName, addon = ...
local L = addon.L
--
local mod = addon:NewModule('ItemLevel', 'AceEvent-3.0')
mod.uiName = L['Item level']
mod.uiDesc = L['Display the level of equippable item in the top left corner of the button.']
local colorSchemes = {
none = function() return mod.db.profile.text.r, mod.db.profile.text.g, mod.db.profile.text.b end
}
local texts = {}
local ItemUpgradeInfo = LibStub('LibItemUpgradeInfo-1.0')
local SyLevel = _G.SyLevel
local SyLevelBypass
if SyLevel then
function SyLevelBypass() return mod:IsEnabled() and mod.db.profile.useSyLevel end
else
function SyLevelBypass() return false end
end
local function UpdateFont()
local fontName, fontSize = mod.font:GetFont()
mod.font:SetFont(fontName, fontSize, "OUTLINE")
if mod.db.profile.colorScheme == "none" then
for button, text in pairs(texts) do
text:SetTextColor(colorSchemes[mod.db.profile.colorScheme]())
end
end
end
function mod:OnInitialize()
self.db = addon.db:RegisterNamespace(self.moduleName, {
profile = {
useSyLevel = false,
equippableOnly = true,
colorScheme = 'level',
minLevel = 1,
ignoreJunk = true,
ignoreHeirloom = true,
anchor = 'BOTTOMLEFT',
offsetX = 2,
offsetY = 1,
text = addon:GetFontDefaults(NumberFontNormalLarge),
},
})
self.font = addon:CreateFont(
self.name..'Font',
NumberFontNormalLarge,
function() return self.db.profile.text end
)
self.font.SettingHook = UpdateFont
if self.db.profile.colored == true then
self.db.profile.colorScheme = 'original'
self.db.profile.colored = nil
elseif self.db.profile.colored == false then
self.db.profile.colorScheme = 'none'
self.db.profile.colored = nil
end
if SyLevel then
SyLevel:RegisterPipe(
'Adibags',
function() self.db.profile.useSyLevel = true end,
function() self.db.profile.useSyLevel = false end,
function() self:SendMessage('AdiBags_UpdateAllButtons') end,
'AdiBags'
)
SyLevel:RegisterFilterOnPipe('Adibags', 'Item level text')
SyLevelDB.EnabledFilters['Item level text']['Adibags'] = true
end
end
local function UpdateTextLocation()
local anchor = mod.db.profile.anchor or mod.db.defaults.profile.anchor
local offsetX = mod.db.profile.offsetX or mod.db.defaults.profile.offsetX
local offsetY = mod.db.profile.offsetY or mod.db.defaults.profile.offsetY
for button, text in pairs(texts) do
text:ClearAllPoints()
text:SetPoint(anchor, button, offsetX, offsetY)
end
end
function mod:OnEnable()
self:RegisterMessage('AdiBags_UpdateButton', 'UpdateButton')
if SyLevel and self.db.profile.useSyLevel and not SyLevel:IsPipeEnabled('Adibags') then
SyLevel:EnablePipe('Adibags')
end
self:SendMessage('AdiBags_UpdateAllButtons')
self.font:ApplySettings()
UpdateFont()
UpdateTextLocation()
end
function mod:OnDisable()
for _, text in pairs(texts) do
text:Hide()
end
end
local function CreateText(button)
local text = button:CreateFontString(nil, "OVERLAY", "NumberFontNormal")
local anchor = mod.db.profile.anchor or mod.db.defaults.profile.anchor
local offsetX = mod.db.profile.offsetX or mod.db.defaults.profile.offsetX
local offsetY = mod.db.profile.offsetY or mod.db.defaults.profile.offsetY
text:SetPoint(anchor, button, offsetX, offsetY)
text:SetFontObject(mod.font)
text:Hide()
texts[button] = text
return text
end
function mod:UpdateButton(event, button)
local settings = self.db.profile
local link = button:GetItemLink()
local text = texts[button]
if link then
local _, _, quality, _, reqLevel, _, _, _, loc = GetItemInfo(link)
local level = ItemUpgradeInfo:GetUpgradedItemLevel(link) or 0 -- Ugly workaround
if level >= settings.minLevel
and (quality > 0 or not settings.ignoreJunk)
and (loc ~= "" or not settings.equippableOnly)
and (quality ~= 7 or not settings.ignoreHeirloom)
then
if SyLevel then
if settings.useSyLevel then
if text then
text:Hide()
end
SyLevel:CallFilters('Adibags', button, link)
return
else
SyLevel:CallFilters('Adibags', button, nil)
end
end
if not text then
text = CreateText(button)
end
text:SetText(level)
text:SetTextColor(colorSchemes[settings.colorScheme](level, quality, reqLevel, (loc ~= "")))
return text:Show()
end
end
if SyLevel then
SyLevel:CallFilters('Adibags', button, nil)
end
if text then
text:Hide()
end
end
function mod:GetOptions()
local options =
{
useSyLevel = SyLevel and {
name = L['Use SyLevel'],
desc = L['Let SyLevel handle the the display.'],
type = 'toggle',
order = 5,
} or nil,
equippableOnly = {
name = L['Only equippable items'],
desc = L['Do not show level of items that cannot be equipped.'],
type = 'toggle',
order = 10,
},
colorScheme = {
name = L['Color scheme'],
desc = L['Which color scheme should be used to display the item level ?'],
type = 'select',
hidden = SyLevelBypass,
values = {
none = L['Manual'],
original = L['Same as InventoryItemLevels'],
level = L['Related to player level'],
qualityColor = L['Same as quality color'],
},
order = 20,
},
minLevel = {
name = L['Mininum level'],
desc = L['Do not show levels under this threshold.'],
type = 'range',
min = 1,
max = 1000,
step = 1,
bigStep = 10,
order = 30,
},
ignoreJunk = {
name = L['Ignore low quality items'],
desc = L['Do not show level of poor quality items.'],
type = 'toggle',
order = 40,
},
ignoreHeirloom = {
name = L['Ignore heirloom items'],
desc = L['Do not show level of heirloom items.'],
type = 'toggle',
order = 50,
},
positionHeader = {
name = L['Text Position'],
type = 'header',
order = 70,
},
anchor = {
name = L['Anchor'],
type = 'select',
values = {
TOPLEFT = "TOPLEFT",
TOP = "TOP",
TOPRIGHT = "TOPRIGHT",
LEFT = "LEFT",
CENTER = "CENTER",
RIGHT = "RIGHT",
BOTTOMLEFT = "BOTTOMLEFT",
BOTTOM = "BOTTOM",
BOTTOMRIGHT = "BOTTOMRIGHT",
},
-- sorting = {
-- [1] = "TOPLEFT",
-- [2] = "TOP",
-- [3] = "TOPRIGHT",
-- [4] = "LEFT",
-- [5] = "CENTER",
-- [6] = "RIGHT",
-- [7] = "BOTTOMLEFT",
-- [8] = "BOTTOM",
-- [9] = "BOTTOMRIGHT",
-- },
order = 71,
set = function(info,value) mod.db.profile[info[#info]] = value; UpdateTextLocation() end,
},
offsetX = {
name = L["X Offset"],
desc = L["Offset in X direction (horizontal) from the given anchor point."],
type = 'range',
min = -20,
max = 20,
step = 1,
bigStep = 1,
order = 72,
set = function(info,value) mod.db.profile[info[#info]] = value; UpdateTextLocation() end,
},
offsetY = {
name = L["Y Offset"] ,
desc = L["Offset in Y direction (vertical) from the given anchor point."],
type = 'range',
min = -20,
max = 20,
step = 1,
bigStep = 1,
order = 73,
set = function(info,value) mod.db.profile[info[#info]] = value; UpdateTextLocation() end,
},
text = addon:CreateFontOptions(self.font, nil, 80),
}
options.text.args.size.step = 1
options.text.args.color.disabled = function() return mod.db.profile.colorScheme ~= "none" end
return options, addon:GetOptionHandler(self)
end
-- Color scheme inspired from InventoryItemLevels
do
local colors = {
-- { upper bound, r, g, b }
{ 30, 0.55, 0.55, 0.55 }, -- gray
{ 54, 1.00, 0.00, 0.00 }, -- red
{ 72, 1.00, 0.70, 0.00 }, -- orange
{ 140, 1.00, 1.00, 0.00 }, -- yellow
{ 158, 0.00, 1.00, 0.00 }, -- green
{ 188, 0.00, 1.00, 1.00 }, -- cyan
{ 218, 0.00, 0.80, 1.00 }, -- blue
{ 233, 1.00, 0.50, 1.00 }, -- purple,
{ 273, 1.00, 0.75, 1.00 }, -- pink
{ 999, 1.00, 1.00, 1.00 }, -- white
}
colorSchemes.original = function(level)
for i, tuple in pairs(colors) do
if level < tuple[1] then
return unpack(tuple, 2, 4)
end
end
end
end
-- Color scheme based on player Level
do
-- Color gradient function taken from my customized oUF
local colorGradient
do
local function GetY(r, g, b)
return 0.3 * r + 0.59 * g + 0.11 * b
end
local function RGBToHCY(r, g, b)
local min, max = min(r, g, b), max(r, g, b)
local chroma = max - min
local hue
if chroma > 0 then
if r == max then
hue = ((g - b) / chroma) % 6
elseif g == max then
hue = (b - r) / chroma + 2
elseif b == max then
hue = (r - g) / chroma + 4
end
hue = hue / 6
end
return hue, chroma, GetY(r, g, b)
end
local function HCYtoRGB(hue, chroma, luma)
local r, g, b = 0, 0, 0
if hue then
local h2 = hue * 6
local x = chroma * (1 - abs(h2 % 2 - 1))
if h2 < 1 then
r, g, b = chroma, x, 0
elseif h2 < 2 then
r, g, b = x, chroma, 0
elseif h2 < 3 then
r, g, b = 0, chroma, x
elseif h2 < 4 then
r, g, b = 0, x, chroma
elseif h2 < 5 then
r, g, b = x, 0, chroma
else
r, g, b = chroma, 0, x
end
end
local m = luma - GetY(r, g, b)
return r + m, g + m, b + m
end
colorGradient = function(a, b, ...)
local perc
if(b == 0) then
perc = 0
else
perc = a / b
end
if perc >= 1 then
local r, g, b = select(select('#', ...) - 2, ...)
return r, g, b
elseif perc <= 0 then
local r, g, b = ...
return r, g, b
end
local num = select('#', ...) / 3
local segment, relperc = modf(perc*(num-1))
local r1, g1, b1, r2, g2, b2 = select((segment*3)+1, ...)
local h1, c1, y1 = RGBToHCY(r1, g1, b1)
local h2, c2, y2 = RGBToHCY(r2, g2, b2)
local c = c1 + (c2-c1) * relperc
local y = y1 + (y2-y1) * relperc
if h1 and h2 then
local dh = h2 - h1
if dh < -0.5 then
dh = dh + 1
elseif dh > 0.5 then
dh = dh - 1
end
return HCYtoRGB((h1 + dh * relperc) % 1, c, y)
else
return HCYtoRGB(h1 or h2, c, y)
end
end
end
local maxLevelRanges = {
[60] = { 66, 92 },
[70] = { 100, 164 },
[80] = { 187, 284 },
[85] = { 333, 416 },
[90] = { 450, 616 },
[100] = { 615, 735 },
[110] = { 805, 905 },
[120] = { 310, 350 },
}
local maxLevelColors = {}
do
local t = maxLevelColors
t[1], t[2], t[3] = GetItemQualityColor(2)
t[4], t[5], t[6] = GetItemQualityColor(3)
t[7], t[8], t[9] = GetItemQualityColor(4)
t[10], t[11], t[12] = GetItemQualityColor(5)
end
colorSchemes.level = function(level, quality, reqLevel, equipabble)
if not equipabble then return 1,1,1 end
local playerLevel = UnitLevel('player')
if playerLevel == _G.MAX_PLAYER_LEVEL then
-- Use the item level range for that level
local minLevel, maxLevel = unpack(maxLevelRanges[playerLevel])
if level < minLevel then
return GetItemQualityColor(0)
else
return colorGradient(level - minLevel, maxLevel - minLevel, unpack(maxLevelColors))
end
elseif reqLevel and reqLevel > 1 then
-- Use the
local delta, color = playerLevel - reqLevel
if delta < 0 then
color = QuestDifficultyColors.trivial
elseif delta == 0 then
color = QuestDifficultyColors.standard
elseif delta == 1 then
color = QuestDifficultyColors.difficult
elseif delta == 2 then
color = QuestDifficultyColors.verydifficult
else
color = QuestDifficultyColors.impossible
end
return color.r, color.g, color.b
else
-- Would this happen ?
return 1, 1, 1
end
end
-- Color scheme for quality colors
do
colorSchemes.qualityColor = function(level, quality)
r, g, b, hex = GetItemQualityColor(quality)
return r,g,b
end
end
end