diff --git a/ElvUI/Bindings.xml b/ElvUI/Bindings.xml
new file mode 100644
index 0000000..7fa753a
--- /dev/null
+++ b/ElvUI/Bindings.xml
@@ -0,0 +1,17 @@
+
+
+ RaidMark_HotkeyPressed(keystate);
+
+
+ FarmMode();
+
+
+ HideLeftChat();
+
+
+ HideRightChat();
+
+
+ HideBothChat();
+
+
\ No newline at end of file
diff --git a/ElvUI/Core/ClassCache.lua b/ElvUI/Core/ClassCache.lua
new file mode 100644
index 0000000..c28d86e
--- /dev/null
+++ b/ElvUI/Core/ClassCache.lua
@@ -0,0 +1,463 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local CC = E:NewModule("ClassCache", "AceEvent-3.0");
+local LW = LibStub:GetLibrary("LibWho-2.0");
+
+--Cache global variables
+--Lua functions
+local split, upper = string.split, string.upper
+local wipe = table.wipe
+local pairs = pairs
+local select = select
+--WoW API / Variables
+local GetBattlefieldScore = GetBattlefieldScore
+local GetFriendInfo = GetFriendInfo
+local GetGuildRosterInfo = GetGuildRosterInfo
+local GetNumBattlefieldScores = GetNumBattlefieldScores
+local GetNumFriends = GetNumFriends
+local GetNumGuildMembers = GetNumGuildMembers
+local GetNumPartyMembers = GetNumPartyMembers
+local GetNumRaidMembers = GetNumRaidMembers
+local GetTime = GetTime
+local IsInGuild = IsInGuild
+local UnitClass = UnitClass
+local UnitExists = UnitExists
+local UnitIsPlayer = UnitIsPlayer
+local UnitName = UnitName
+
+local UNKNOWN = UNKNOWN
+
+local GAME_LOCALE = GetLocale()
+local ENGLISH_CLASS_NAMES
+
+local function GetEnglishClassName(class)
+ if class == UNKNOWN then
+ return class
+ elseif GAME_LOCALE == "enUS" then
+ return upper(class)
+ end
+
+ if not ENGLISH_CLASS_NAMES then
+ ENGLISH_CLASS_NAMES = {}
+
+ for english, localized in pairs(LOCALIZED_CLASS_NAMES_MALE) do
+ ENGLISH_CLASS_NAMES[localized] = english
+ end
+ for english, localized in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do
+ ENGLISH_CLASS_NAMES[localized] = english
+ end
+ end
+
+ return ENGLISH_CLASS_NAMES[class]
+end
+
+local function WhoCallback(result)
+ if result then
+ if result.NoLocaleClass then
+ CC:CachePlayer(result.Name, result.NoLocaleClass)
+ CC:SendMessage("ClassCacheQueryResult", result.Name, result.NoLocaleClass)
+ end
+ end
+end
+
+function CC:GetClassByName(name, realm)
+ if not name or name == "" then return end
+ if realm and realm == "" then return end
+
+ if E.db.general.classCacheStoreInDB then
+ if realm then
+ if self.cache[realm] and self.cache[realm][name] then
+ return self.cache[realm][name]
+ else
+ return
+ end
+ else
+ if self.cache[E.myrealm][name] then
+ return self.cache[E.myrealm][name]
+ end
+ end
+ else
+ if realm then
+ if self.tempCache[realm] and self.tempCache[realm][name] then
+ return self.tempCache[realm][name]
+ else
+ return
+ end
+ else
+ if self.tempCache[E.myrealm][name] then
+ return self.tempCache[E.myrealm][name]
+ end
+ end
+ end
+
+ if E.db.general.classCacheRequestInfo then
+ local result = LW:UserInfo(name, {
+ queue = LW.WHOLIB_QUEUE_QUIET,
+ timeout = 0,
+ callback = function(result)
+ WhoCallback(result)
+ end
+ })
+
+ if result and result.NoLocaleClass then
+ self:CachePlayer(result.Name, result.NoLocaleClass)
+ return result.NoLocaleClass
+ end
+ end
+end
+
+function CC:CachePlayer(name, class, realm)
+ if not (name and class and class ~= UNKNOWN) then return end
+
+ if realm and realm == "" then return end
+
+ if E.db.general.classCacheStoreInDB then
+ if realm and not self.cache[realm] then
+ self.cache[realm] = {}
+ end
+
+ if realm then
+ self.cache[realm][name] = class
+ else
+ self.cache[E.myrealm][name] = class
+ end
+ else
+ if realm and not self.tempCache[realm] then
+ self.tempCache[realm] = {}
+ end
+
+ if realm then
+ self.tempCache[realm][name] = class
+ else
+ self.tempCache[E.myrealm][name] = class
+ end
+ end
+end
+
+function CC:SwitchCacheType(init)
+ if E.db.general.classCacheStoreInDB then
+ if not self.cache[E.myrealm] then
+ self.cache[E.myrealm] = {}
+ end
+
+ if not self.cache[E.myrealm][E.myname] then
+ self.cache[E.myrealm][E.myname] = E.myclass
+ end
+
+ if not init then
+ for realm in pairs(self.tempCache) do
+ if not self.cache[realm] then
+ self.cache[realm] = {}
+ end
+
+ for name, class in pairs(self.tempCache[realm]) do
+ self.cache[realm][name] = class
+ end
+ end
+ end
+ else
+ if not self.tempCache[E.myrealm] then
+ self.tempCache[E.myrealm] = {}
+ end
+
+ if not self.tempCache[E.myrealm][E.myname] then
+ self.tempCache[E.myrealm][E.myname] = E.myclass
+ end
+
+ if not init then
+ for realm in pairs(self.cache) do
+ if not self.cache[realm] then
+ self.tempCache[realm] = {}
+ end
+
+ for name, class in pairs(self.cache[realm]) do
+ self.tempCache[realm][name] = class
+ end
+ end
+ end
+ end
+end
+
+function CC:GetCacheTable()
+ if E.db.general.classCacheStoreInDB then
+ return self.cache
+ else
+ return self.tempCache
+ end
+end
+
+function CC:GetCacheSize(global)
+ if global and not (self.cacheDBCalculationTime + 30 < GetTime()) then
+ return self.cacheDBSize > 1, self.cacheDBSize
+ elseif not global and not (self.cacheLocalCalculationTime + 30 < GetTime()) then
+ return self.cacheLocalSize > 1, self.cacheLocalSize
+ end
+
+ local size = 0
+
+ if global then
+ for realm in pairs(self.cache) do
+ for name in pairs(self.cache[realm]) do
+ size = size + 1
+ end
+ end
+
+ self.cacheDBSize = size
+ self.cacheDBCalculationTime = GetTime()
+ else
+ for realm in pairs(self.tempCache) do
+ for name in pairs(self.tempCache[realm]) do
+ size = size + 1
+ end
+ end
+
+ self.cacheLocalSize = size
+ self.cacheLocalCalculationTime = GetTime()
+ end
+
+ return size > 1, size
+end
+
+function CC:WipeCache(global)
+ if global then
+ for realm in pairs(self.cache) do
+ wipe(realm)
+ end
+
+ wipe(self.cache)
+ self:SwitchCacheType(true)
+ self.cacheDBCalculationTime = 0
+
+ E:Print(L["Class DB cache wiped."])
+ else
+ for realm in pairs(self.tempCache) do
+ wipe(realm)
+ end
+
+ wipe(self.tempCache)
+ self:SwitchCacheType(true)
+ self.cacheLocalCalculationTime = 0
+
+ E:Print(L["Class session cache wiped."])
+ end
+end
+
+function CC:PLAYER_ENTERING_WORLD()
+ local inInstance, instanceType = IsInInstance()
+ self.inInstance = inInstance
+
+ if instanceType == "arena" or instanceType == "pvp" then
+ self.inBattleground = true
+ else
+ self.inBattleground = false
+ end
+
+ if self.inInstance or self.inBattleground then
+ self.lastNumPlayers = 0
+
+ self:UnregisterEvent("PLAYER_TARGET_CHANGED")
+ self:UnregisterEvent("UPDATE_MOUSEOVER_UNIT")
+
+ self:UnregisterEvent("PARTY_MEMBERS_CHANGED")
+ self:UnregisterEvent("RAID_ROSTER_UPDATE")
+
+
+ self:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
+
+ if self.inBattleground then
+ self:UPDATE_BATTLEFIELD_SCORE()
+ end
+ else
+ self.lastNumPlayers = 0
+
+ self:RegisterEvent("PLAYER_TARGET_CHANGED")
+ self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
+
+ self:RegisterEvent("PARTY_MEMBERS_CHANGED")
+ self:RegisterEvent("RAID_ROSTER_UPDATE")
+
+ self:UnregisterEvent("UPDATE_BATTLEFIELD_SCORE")
+ end
+
+ self:PLAYER_GUILD_UPDATE()
+
+ if not self.initUpdate then
+ if GetNumRaidMembers() > 0 then
+ self:RAID_ROSTER_UPDATE()
+ elseif GetNumPartyMembers() > 0 then
+ self:PARTY_MEMBERS_CHANGED()
+ end
+
+ self:GUILD_ROSTER_UPDATE(nil, true)
+
+ self.initUpdate = true
+ end
+end
+
+function CC:PLAYER_GUILD_UPDATE()
+ if IsInGuild() then
+ self:RegisterEvent("GUILD_ROSTER_UPDATE")
+ else
+ self:UnregisterEvent("RAID_ROSTER_UPDATE")
+ end
+end
+
+function CC:FRIENDLIST_UPDATE()
+ local name, class, _
+
+ for i = 1, GetNumFriends() do
+ name, _, class = GetFriendInfo(i)
+
+ if class then
+ self:CachePlayer(name, GetEnglishClassName(class))
+ end
+ end
+end
+
+function CC:GUILD_ROSTER_UPDATE(_, update)
+ if not update then return end
+
+ local name, class, _
+
+ for i = 1, GetNumGuildMembers() do
+ name, _, _, _, _, _, _, _, _, _, class = GetGuildRosterInfo(i)
+
+ if class then
+ self:CachePlayer(name, class)
+ end
+ end
+end
+
+function CC:PARTY_MEMBERS_CHANGED()
+ local name, realm, class, _
+
+ for i = 1, GetNumPartyMembers() do
+ name, realm = UnitName("party"..i)
+ _, class = UnitClass("party"..i)
+
+ if not class then return end
+
+ if self.inBattleground then
+ self:CachePlayer(name, class, realm)
+ else
+ self:CachePlayer(name, class)
+ end
+ end
+end
+
+function CC:RAID_ROSTER_UPDATE()
+ local name, realm, class, _
+
+ for i = 1, GetNumRaidMembers() do
+ name, realm = UnitName("raid"..i)
+ _, class = UnitClass("raid"..i)
+
+ if not class then return end
+
+ if self.inBattleground then
+ self:CachePlayer(name, class, realm)
+ else
+ self:CachePlayer(name, class)
+ end
+ end
+end
+
+function CC:PLAYER_TARGET_CHANGED()
+ if not UnitExists("target") or not UnitIsPlayer("target") then return end
+
+ local _, class = UnitClass("target")
+ if not class then return end
+
+ local name, realm = UnitName("target")
+
+ if self.inBattleground then
+ self:CachePlayer(name, class, realm)
+ else
+ self:CachePlayer(name, class)
+ end
+end
+
+function CC:UPDATE_MOUSEOVER_UNIT()
+ if not UnitExists("mouseover") or not UnitIsPlayer("mouseover") then return end
+
+ local _, class = UnitClass("mouseover")
+ if not class then return end
+
+ local name, realm = UnitName("mouseover")
+
+ if self.inBattleground then
+ self:CachePlayer(name, class, realm)
+ else
+ self:CachePlayer(name, class)
+ end
+end
+
+function CC:UPDATE_BATTLEFIELD_SCORE()
+ local numPlayers = GetNumBattlefieldScores() or 0
+
+ if self.lastNumPlayers == numPlayers then
+ return
+ elseif self.lastNumPlayers > numPlayers then
+ self.lastNumPlayers = numPlayers
+ return
+ end
+
+ local name, realm, class, _
+
+ for i = 1, numPlayers do
+ name, _, _, _, _, _, _, _, _, class = GetBattlefieldScore(i)
+
+ if name and class then
+ name, realm = split("-", name)
+ self:CachePlayer(name, class, realm)
+ end
+ end
+end
+
+function CC:WHOLIB_QUERY_RESULT(_, query, results, complete)
+ for _, result in pairs(results) do
+ if result and result.NoLocaleClass then
+ self:CachePlayer(result.Name, result.NoLocaleClass)
+ end
+ end
+end
+
+function CC:ToggleModule()
+ if E.private.general.classCache then
+ if not self.initialized then
+ self:SwitchCacheType(true)
+ self.initialized = true
+ end
+
+ self:RegisterEvent("PLAYER_ENTERING_WORLD")
+ self:RegisterEvent("PLAYER_GUILD_UPDATE")
+
+ self:RegisterEvent("FRIENDLIST_UPDATE")
+ self:RegisterEvent("PARTY_MEMBERS_CHANGED")
+ self:RegisterEvent("RAID_ROSTER_UPDATE")
+
+ LW.RegisterCallback(self, "WHOLIB_QUERY_RESULT", "WHOLIB_QUERY_RESULT")
+ else
+ self:UnregisterAllEvents()
+ LW.UnregisterAllCallbacks(self)
+ end
+end
+
+function CC:Initialize()
+ self.cache = E.global.classCache
+ self.tempCache = {}
+
+ self.cacheLocalCalculationTime = 0
+ self.cacheDBCalculationTime = 0
+
+ LW:SetWhoLibDebug(false)
+
+ if E.private.general.classCache then
+ self:ToggleModule()
+ end
+end
+
+local function InitializeCallback()
+ CC:Initialize()
+end
+
+E:RegisterModule(CC:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Core/Commands.lua b/ElvUI/Core/Commands.lua
new file mode 100644
index 0000000..c8b9078
--- /dev/null
+++ b/ElvUI/Core/Commands.lua
@@ -0,0 +1,130 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local tonumber, type = tonumber, type
+local format, lower, match = string.format, string.lower, string.match
+--WoW API / Variables
+local UIFrameFadeOut, UIFrameFadeIn = UIFrameFadeOut, UIFrameFadeIn
+local EnableAddOn, DisableAddOn, DisableAllAddOns = EnableAddOn, DisableAddOn, DisableAllAddOns
+local SetCVar = SetCVar
+local ReloadUI = ReloadUI
+local GetAddOnInfo = GetAddOnInfo
+
+function E:EnableAddon(addon)
+ local _, _, _, _, _, reason, _ = GetAddOnInfo(addon)
+ if reason ~= "MISSING" then
+ EnableAddOn(addon)
+ ReloadUI()
+ else
+ E:Print(format("Addon '%s' not found.", addon))
+ end
+end
+
+function E:DisableAddon(addon)
+ local _, _, _, _, _, reason, _ = GetAddOnInfo(addon)
+ if reason ~= "MISSING" then
+ DisableAddOn(addon)
+ ReloadUI()
+ else
+ E:Print(format("Addon '%s' not found.", addon))
+ end
+end
+
+function FarmMode()
+ if E.private.general.minimap.enable ~= true then return end
+
+ if Minimap:IsShown() then
+ UIFrameFadeOut(Minimap, 0.3)
+ UIFrameFadeIn(FarmModeMap, 0.3)
+ Minimap.fadeInfo.finishedFunc = function() Minimap:Hide() _G.MinimapZoomIn:Click() _G.MinimapZoomOut:Click() Minimap:SetAlpha(1) end
+ FarmModeMap.enabled = true
+ else
+ UIFrameFadeOut(FarmModeMap, 0.3)
+ UIFrameFadeIn(Minimap, 0.3)
+ FarmModeMap.fadeInfo.finishedFunc = function() FarmModeMap:Hide() _G.MinimapZoomIn:Click() _G.MinimapZoomOut:Click() Minimap:SetAlpha(1) end
+ FarmModeMap.enabled = false
+ end
+end
+
+function E:FarmMode(msg)
+ if E.private.general.minimap.enable ~= true then return end
+ if msg and type(tonumber(msg)) == "number" and tonumber(msg) <= 500 and tonumber(msg) >= 20 then
+ E.db.farmSize = tonumber(msg)
+ FarmModeMap:SetWidth(tonumber(msg))
+ FarmModeMap:SetHeight(tonumber(msg))
+ end
+
+ FarmMode()
+end
+
+function E:Grid(msg)
+ if msg and type(tonumber(msg)) == "number" and tonumber(msg) <= 256 and tonumber(msg) >= 4 then
+ E.db.gridSize = msg
+ E:Grid_Show()
+ else
+ if EGrid then
+ E:Grid_Hide()
+ else
+ E:Grid_Show()
+ end
+ end
+end
+
+function E:LuaError(msg)
+ msg = lower(msg)
+ if msg == "on" then
+ DisableAllAddOns()
+ EnableAddOn("ElvUI")
+ EnableAddOn("ElvUI_Config")
+ SetCVar("ShowErrors", "1")
+ ReloadUI()
+ elseif msg == "off" then
+ SetCVar("ShowErrors", "0")
+ E:Print("Lua errors off.")
+ else
+ E:Print("/luaerror on - /luaerror off")
+ end
+end
+
+function E:BGStats()
+ local DT = E:GetModule("DataTexts")
+ DT.ForceHideBGStats = nil
+ DT:LoadDataTexts()
+
+ E:Print(L["Battleground datatexts will now show again if you are inside a battleground."])
+end
+
+local function OnCallback(command)
+ MacroEditBox:GetScript("OnEvent")(MacroEditBox, "EXECUTE_CHAT_LINE", command)
+end
+
+function E:DelayScriptCall(msg)
+ local secs, command = match(msg, "^([^%s]+)%s+(.*)$")
+ secs = tonumber(secs)
+ if (not secs) or (getn(command) == 0) then
+ self:Print("usage: /in ")
+ self:Print("example: /in 1.5 /say hi")
+ else
+ E:ScheduleTimer(OnCallback, secs, command)
+ end
+end
+
+function E:LoadCommands()
+ self:RegisterChatCommand("in", "DelayScriptCall")
+ self:RegisterChatCommand("ec", "ToggleConfig")
+ self:RegisterChatCommand("elvui", "ToggleConfig")
+ self:RegisterChatCommand("bgstats", "BGStats")
+ self:RegisterChatCommand("luaerror", "LuaError")
+ self:RegisterChatCommand("egrid", "Grid")
+ self:RegisterChatCommand("moveui", "ToggleConfigMode")
+ self:RegisterChatCommand("resetui", "ResetUI")
+ self:RegisterChatCommand("enable", "EnableAddon")
+ self:RegisterChatCommand("disable", "DisableAddon")
+ self:RegisterChatCommand("farmmode", "FarmMode")
+
+-- if E:GetModule("ActionBars") and E.private.actionbar.enable then
+-- self:RegisterChatCommand("kb", E:GetModule("ActionBars").ActivateBindMode)
+-- end
+end
\ No newline at end of file
diff --git a/ElvUI/Core/Config.lua b/ElvUI/Core/Config.lua
new file mode 100644
index 0000000..8e1c7f3
--- /dev/null
+++ b/ElvUI/Core/Config.lua
@@ -0,0 +1,497 @@
+local E, L, V, P, G = unpack(ElvUI); -- Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local type, ipairs, tonumber = type, ipairs, tonumber
+local floor = math.floor
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local IsAddOnLoaded = IsAddOnLoaded
+local GetScreenWidth = GetScreenWidth
+local GetScreenHeight = GetScreenHeight
+local RESET = RESET
+
+local grid
+local selectedValue = "ALL"
+
+E.ConfigModeLayouts = {
+ "ALL",
+ "GENERAL",
+ "SOLO",
+ "PARTY",
+ "RAID",
+ "ACTIONBARS"
+}
+
+E.ConfigModeLocalizedStrings = {
+ ALL = ALL,
+ GENERAL = GENERAL,
+ SOLO = SOLO,
+ PARTY = PARTY,
+ RAID = RAID,
+ ACTIONBARS = ACTIONBAR_LABEL
+}
+
+function E:Grid_Show()
+ if not grid then
+ E:Grid_Create()
+ elseif grid.boxSize ~= E.db.gridSize then
+ grid:Hide()
+ E:Grid_Create()
+ else
+ grid:Show()
+ end
+end
+
+function E:Grid_Hide()
+ if grid then
+ grid:Hide()
+ end
+end
+
+function E:ToggleConfigMode(override, configType)
+ if override ~= nil and override ~= "" then E.ConfigurationMode = override end
+
+ if E.ConfigurationMode ~= true then
+ if not grid then
+ E:Grid_Create()
+ elseif grid.boxSize ~= E.db.gridSize then
+ grid:Hide()
+ E:Grid_Create()
+ else
+ grid:Show()
+ end
+
+ if not ElvUIMoverPopupWindow then
+ E:CreateMoverPopup()
+ end
+
+ ElvUIMoverPopupWindow:Show()
+ if(IsAddOnLoaded("ElvUI_Config")) then
+ LibStub("AceConfigDialog-3.0"):Close("ElvUI")
+ GameTooltip:Hide()
+ end
+
+ E.ConfigurationMode = true
+ else
+ if ElvUIMoverPopupWindow then
+ ElvUIMoverPopupWindow:Hide()
+ end
+
+ if grid then
+ grid:Hide()
+ end
+
+ E.ConfigurationMode = false
+ end
+
+ if type(configType) ~= "string" then
+ configType = nil
+ end
+
+ self:ToggleMovers(E.ConfigurationMode, configType or "ALL")
+end
+
+function E:Grid_Create()
+ grid = CreateFrame("Frame", "EGrid", UIParent)
+ grid.boxSize = E.db.gridSize
+ grid:SetAllPoints(E.UIParent)
+ grid:Show()
+
+ local size = 1
+ local width = E.eyefinity or GetScreenWidth()
+ local ratio = width / GetScreenHeight()
+ local height = GetScreenHeight() * ratio
+
+ local wStep = width / E.db.gridSize
+ local hStep = height / E.db.gridSize
+
+ for i = 0, E.db.gridSize do
+ local tx = grid:CreateTexture(nil, "BACKGROUND")
+ if i == E.db.gridSize / 2 then
+ tx:SetTexture(1, 0, 0)
+ else
+ tx:SetTexture(0, 0, 0)
+ end
+ tx:SetPoint("TOPLEFT", grid, "TOPLEFT", i*wStep - (size/2), 0)
+ tx:SetPoint("BOTTOMRIGHT", grid, "BOTTOMLEFT", i*wStep + (size/2), 0)
+ end
+ height = GetScreenHeight()
+
+ do
+ local tx = grid:CreateTexture(nil, "BACKGROUND")
+ tx:SetTexture(1, 0, 0)
+ tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2) + (size/2))
+ tx:SetPoint("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2 + size/2))
+ end
+
+ for i = 1, floor((height/2)/hStep) do
+ local tx = grid:CreateTexture(nil, "BACKGROUND")
+ tx:SetTexture(0, 0, 0)
+
+ tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2+i*hStep) + (size/2))
+ tx:SetPoint("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2+i*hStep + size/2))
+
+ tx = grid:CreateTexture(nil, "BACKGROUND")
+ tx:SetTexture(0, 0, 0)
+
+ tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2-i*hStep) + (size/2))
+ tx:SetPoint("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2-i*hStep + size/2))
+ end
+end
+
+local function ConfigMode_OnClick()
+ selectedValue = this.value
+ E:ToggleConfigMode(false, this.value)
+ UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, this.value)
+end
+
+local function ConfigMode_Initialize()
+ local info = {}
+ info.func = ConfigMode_OnClick
+
+ for _, configMode in ipairs(E.ConfigModeLayouts) do
+ info.text = E.ConfigModeLocalizedStrings[configMode]
+ info.value = configMode
+ UIDropDownMenu_AddButton(info)
+ end
+
+ UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, selectedValue)
+end
+
+function E:NudgeMover(nudgeX, nudgeY)
+ local mover = ElvUIMoverNudgeWindow.child
+
+ local x, y, point = E:CalculateMoverPoints(mover, nudgeX, nudgeY)
+
+ mover:ClearAllPoints()
+ mover:SetPoint(mover.positionOverride or point, E.UIParent, mover.positionOverride and "BOTTOMLEFT" or point, x, y)
+ E:SaveMoverPosition(mover.name)
+
+ E:UpdateNudgeFrame(mover, x, y)
+end
+
+function E:UpdateNudgeFrame(mover, x, y)
+ if not(x and y) then
+ x, y = E:CalculateMoverPoints(mover)
+ end
+
+ x = E:Round(x, 0)
+ y = E:Round(y, 0)
+
+ ElvUIMoverNudgeWindow.xOffset:SetText(x)
+ ElvUIMoverNudgeWindow.yOffset:SetText(y)
+ ElvUIMoverNudgeWindow.xOffset.currentValue = x
+ ElvUIMoverNudgeWindow.yOffset.currentValue = y
+ ElvUIMoverNudgeWindowHeader.title:SetText(mover.textString)
+end
+
+function E:AssignFrameToNudge()
+ ElvUIMoverNudgeWindow.child = self
+ E:UpdateNudgeFrame(self)
+end
+
+function E:CreateMoverPopup()
+ local f = CreateFrame("Frame", "ElvUIMoverPopupWindow", UIParent)
+ f:SetFrameStrata("DIALOG")
+ f:SetToplevel(true)
+ f:EnableMouse(true)
+ f:SetMovable(true)
+ f:SetFrameLevel(99)
+ f:SetClampedToScreen(true)
+ f:SetWidth(360)
+ f:SetHeight(170)
+ E:SetTemplate(f, "Transparent")
+ f:SetPoint("BOTTOM", UIParent, "CENTER", 0, 100)
+ f:SetScript("OnHide", function()
+ if ElvUIMoverPopupWindowDropDown then
+ UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, "ALL")
+ end
+ end)
+ f:Hide()
+
+ local S = E:GetModule("Skins")
+
+ local header = CreateFrame("Button", nil, f)
+ E:SetTemplate(header, "Default", true)
+ header:SetWidth(100) header:SetHeight(25)
+ header:SetPoint("CENTER", f, "TOP")
+ header:SetFrameLevel(header:GetFrameLevel() + 2)
+ header:EnableMouse(true)
+ header:RegisterForClicks("AnyUp", "AnyDown")
+ header:SetScript("OnMouseDown", function() f:StartMoving() end)
+ header:SetScript("OnMouseUp", function() f:StopMovingOrSizing() end)
+
+ local title = header:CreateFontString("OVERLAY")
+ E:FontTemplate(title)
+ title:SetPoint("CENTER", header, "CENTER")
+ title:SetText("ElvUI")
+
+ local desc = f:CreateFontString("ARTWORK")
+ desc:SetFontObject("GameFontHighlight")
+ desc:SetJustifyV("TOP")
+ desc:SetJustifyH("LEFT")
+ desc:SetPoint("TOPLEFT", 18, -32)
+ desc:SetPoint("BOTTOMRIGHT", -18, 48)
+ desc:SetText(L["DESC_MOVERCONFIG"])
+
+ local snapping = CreateFrame("CheckButton", f:GetName().."CheckButton", f, "OptionsCheckButtonTemplate")
+ _G[snapping:GetName().."Text"]:SetText(L["Sticky Frames"])
+
+ snapping:SetScript("OnShow", function()
+ this:SetChecked(E.db.general.stickyFrames)
+ end)
+
+ snapping:SetScript("OnClick", function()
+ E.db.general.stickyFrames = this:GetChecked()
+ end)
+
+ local lock = CreateFrame("Button", f:GetName().."CloseButton", f, "OptionsButtonTemplate")
+ _G[lock:GetName().."Text"]:SetText(L["Lock"])
+
+ lock:SetScript("OnClick", function()
+ E:ToggleConfigMode(true)
+
+ if(IsAddOnLoaded("ElvUI_Config")) then
+ LibStub("AceConfigDialog-3.0"):Open("ElvUI")
+ end
+
+ selectedValue = "ALL"
+ UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, selectedValue)
+ end)
+
+ local align = CreateFrame("EditBox", f:GetName().."EditBox", f, "InputBoxTemplate")
+ align:SetWidth(32)
+ align:SetHeight(17)
+ align:SetAutoFocus(false)
+ align:SetScript("OnEscapePressed", function()
+ this:SetText(E.db.gridSize)
+ this:ClearFocus()
+ end)
+ align:SetScript("OnEnterPressed", function()
+ local text = this:GetText()
+ if tonumber(text) then
+ if tonumber(text) <= 256 and tonumber(text) >= 4 then
+ E.db.gridSize = tonumber(text)
+ else
+ this:SetText(E.db.gridSize)
+ end
+ else
+ this:SetText(E.db.gridSize)
+ end
+ E:Grid_Show()
+ this:ClearFocus()
+ end)
+ align:SetScript("OnEditFocusLost", function()
+ this:SetText(E.db.gridSize)
+ end)
+ align:SetScript("OnShow", function()
+ this:ClearFocus()
+ this:SetText(E.db.gridSize)
+ end)
+
+ align.text = align:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ align.text:SetPoint("RIGHT", align, "LEFT", -4, 0)
+ align.text:SetText(L["Grid Size:"])
+
+ --position buttons
+ snapping:SetPoint("BOTTOMLEFT", 14, 10)
+ lock:SetPoint("BOTTOMRIGHT", -14, 14)
+ align:SetPoint("TOPRIGHT", lock, "TOPLEFT", -4, -2)
+
+ S:HandleCheckBox(snapping)
+ S:HandleButton(lock)
+ S:HandleEditBox(align)
+
+ f:RegisterEvent("PLAYER_REGEN_DISABLED")
+ f:SetScript("OnEvent", function()
+ if this:IsShown() then
+ this:Hide()
+ E:Grid_Hide()
+ E:ToggleConfigMode(true)
+ end
+ end)
+
+ local configMode = CreateFrame("Frame", f:GetName().."DropDown", f, "UIDropDownMenuTemplate")
+ configMode:SetPoint("BOTTOMRIGHT", lock, "TOPRIGHT", 8, -5)
+ S:HandleDropDownBox(configMode, 148)
+ configMode.text = configMode:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ configMode.text:SetPoint("RIGHT", configMode.backdrop, "LEFT", -2, 0)
+ configMode.text:SetText(L["Config Mode:"])
+
+ UIDropDownMenu_Initialize(configMode, ConfigMode_Initialize)
+
+ local nudgeFrame = CreateFrame("Frame", "ElvUIMoverNudgeWindow", E.UIParent)
+ nudgeFrame:SetFrameStrata("DIALOG")
+ nudgeFrame:SetWidth(200)
+ nudgeFrame:SetHeight(110)
+ E:SetTemplate(nudgeFrame, "Transparent")
+ nudgeFrame:SetPoint("TOP", ElvUIMoverPopupWindow, "BOTTOM", 0, -15)
+ nudgeFrame:SetFrameLevel(100)
+ nudgeFrame:Hide()
+ nudgeFrame:EnableMouse(true)
+ nudgeFrame:SetClampedToScreen(true)
+ HookScript(ElvUIMoverPopupWindow, "OnHide", function() ElvUIMoverNudgeWindow:Hide() end)
+
+ header = CreateFrame("Button", "ElvUIMoverNudgeWindowHeader", nudgeFrame)
+ E:SetTemplate(header, "Default", true)
+ header:SetWidth(100) header:SetHeight(25)
+ header:SetPoint("CENTER", nudgeFrame, "TOP")
+ header:SetFrameLevel(header:GetFrameLevel() + 2)
+
+ title = header:CreateFontString("OVERLAY")
+ E:FontTemplate(title)
+ title:SetPoint("CENTER", header, "CENTER")
+ title:SetText(L["Nudge"])
+ header.title = title
+
+ local xOffset = CreateFrame("EditBox", nudgeFrame:GetName().."XEditBox", nudgeFrame, "InputBoxTemplate")
+ xOffset:SetWidth(50)
+ xOffset:SetHeight(17)
+ xOffset:SetAutoFocus(false)
+ xOffset.currentValue = 0
+ xOffset:SetScript("OnEscapePressed", function()
+ this:SetText(E:Round(xOffset.currentValue))
+ this:ClearFocus()
+ end)
+ xOffset:SetScript("OnEnterPressed", function()
+ local num = this:GetText()
+ if(tonumber(num)) then
+ local diff = num - xOffset.currentValue
+ xOffset.currentValue = num
+ E:NudgeMover(diff)
+ end
+ this:SetText(E:Round(xOffset.currentValue))
+ this:ClearFocus()
+ end)
+ xOffset:SetScript("OnEditFocusLost", function()
+ this:SetText(E:Round(xOffset.currentValue))
+ end)
+ xOffset:SetScript("OnShow", function()
+ this:ClearFocus()
+ this:SetText(E:Round(xOffset.currentValue))
+ end)
+
+ xOffset.text = xOffset:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ xOffset.text:SetPoint("RIGHT", xOffset, "LEFT", -4, 0)
+ xOffset.text:SetText("X:")
+ xOffset:SetPoint("BOTTOMRIGHT", nudgeFrame, "CENTER", -6, 8)
+ nudgeFrame.xOffset = xOffset
+ S:HandleEditBox(xOffset)
+
+ local yOffset = CreateFrame("EditBox", nudgeFrame:GetName().."YEditBox", nudgeFrame, "InputBoxTemplate")
+ yOffset:SetWidth(50)
+ yOffset:SetHeight(17)
+ yOffset:SetAutoFocus(false)
+ yOffset.currentValue = 0
+ yOffset:SetScript("OnEscapePressed", function()
+ this:SetText(E:Round(yOffset.currentValue))
+ this:ClearFocus()
+ end)
+ yOffset:SetScript("OnEnterPressed", function()
+ local num = this:GetText()
+ if(tonumber(num)) then
+ local diff = num - yOffset.currentValue
+ yOffset.currentValue = num
+ E:NudgeMover(nil, diff)
+ end
+ this:SetText(E:Round(yOffset.currentValue))
+ this:ClearFocus()
+ end)
+ yOffset:SetScript("OnEditFocusLost", function()
+ this:SetText(E:Round(yOffset.currentValue))
+ end)
+ yOffset:SetScript("OnShow", function()
+ this:ClearFocus()
+ this:SetText(E:Round(yOffset.currentValue))
+ end)
+
+ yOffset.text = yOffset:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ yOffset.text:SetPoint("RIGHT", yOffset, "LEFT", -4, 0)
+ yOffset.text:SetText("Y:")
+ yOffset:SetPoint("BOTTOMLEFT", nudgeFrame, "CENTER", 16, 8)
+ nudgeFrame.yOffset = yOffset
+ S:HandleEditBox(yOffset)
+
+ local resetButton = CreateFrame("Button", nudgeFrame:GetName().."ResetButton", nudgeFrame, "UIPanelButtonTemplate")
+ resetButton:SetText(RESET)
+ resetButton:SetPoint("TOP", nudgeFrame, "CENTER", 0, 2)
+ resetButton:SetWidth(100)
+ resetButton:SetHeight(25)
+ resetButton:SetScript("OnClick", function()
+ if(ElvUIMoverNudgeWindow.child.textString) then
+ E:ResetMovers(ElvUIMoverNudgeWindow.child.textString)
+ E:UpdateNudgeFrame(ElvUIMoverNudgeWindow.child)
+ end
+ end)
+ S:HandleButton(resetButton)
+ -- Up Button
+ local upButton = CreateFrame("Button", nudgeFrame:GetName().."PrevButton", nudgeFrame)
+ upButton:SetWidth(26)
+ upButton:SetHeight(26)
+ upButton:SetPoint("BOTTOMRIGHT", nudgeFrame, "BOTTOM", -6, 4)
+ upButton:SetScript("OnClick", function()
+ E:NudgeMover(nil, 1)
+ end)
+ upButton.icon = upButton:CreateTexture(nil, "ARTWORK")
+ upButton.icon:SetWidth(13)
+ upButton.icon:SetHeight(13)
+ upButton.icon:SetPoint("CENTER", 0, 0)
+ upButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
+ upButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
+
+ S:SquareButton_SetIcon(upButton, "UP")
+ S:HandleButton(upButton)
+ -- Down Button
+ local downButton = CreateFrame("Button", nudgeFrame:GetName().."DownButton", nudgeFrame)
+ downButton:SetWidth(26)
+ downButton:SetHeight(26)
+ downButton:SetPoint("BOTTOMLEFT", nudgeFrame, "BOTTOM", 6, 4)
+ downButton:SetScript("OnClick", function()
+ E:NudgeMover(nil, -1)
+ end)
+ downButton.icon = downButton:CreateTexture(nil, "ARTWORK")
+ downButton.icon:SetWidth(13)
+ downButton.icon:SetHeight(13)
+ downButton.icon:SetPoint("CENTER", 0, 0)
+ downButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
+ downButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
+
+ S:SquareButton_SetIcon(downButton, "DOWN")
+ S:HandleButton(downButton)
+ -- Left Button
+ local leftButton = CreateFrame("Button", nudgeFrame:GetName().."LeftButton", nudgeFrame)
+ leftButton:SetWidth(26)
+ leftButton:SetHeight(26)
+ leftButton:SetPoint("RIGHT", upButton, "LEFT", -6, 0)
+ leftButton:SetScript("OnClick", function()
+ E:NudgeMover(-1)
+ end)
+ leftButton.icon = leftButton:CreateTexture(nil, "ARTWORK")
+ leftButton.icon:SetWidth(13)
+ leftButton.icon:SetHeight(13)
+ leftButton.icon:SetPoint("CENTER", 0, 0)
+ leftButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
+ leftButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
+
+ S:SquareButton_SetIcon(leftButton, "LEFT")
+ S:HandleButton(leftButton)
+ -- Right Button
+ local rightButton = CreateFrame("Button", nudgeFrame:GetName().."RightButton", nudgeFrame)
+ rightButton:SetWidth(26)
+ rightButton:SetHeight(26)
+ rightButton:SetPoint("LEFT", downButton, "RIGHT", 6, 0)
+ rightButton:SetScript("OnClick", function()
+ E:NudgeMover(1)
+ end)
+ rightButton.icon = rightButton:CreateTexture(nil, "ARTWORK")
+ rightButton.icon:SetWidth(13)
+ rightButton.icon:SetHeight(13)
+ rightButton.icon:SetPoint("CENTER", 0, 0)
+ rightButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
+ rightButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
+
+ S:SquareButton_SetIcon(rightButton, "RIGHT")
+ S:HandleButton(rightButton)
+end
\ No newline at end of file
diff --git a/ElvUI/Core/Cooldowns.lua b/ElvUI/Core/Cooldowns.lua
new file mode 100644
index 0000000..5a59366
--- /dev/null
+++ b/ElvUI/Core/Cooldowns.lua
@@ -0,0 +1,140 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local floor = math.floor
+local format = string.format
+local GetTime = GetTime
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local hooksecurefunc = hooksecurefunc
+
+local ICON_SIZE = 36 --the normal size for an icon (don't change this)
+local FONT_SIZE = 20 --the base font size to use at a scale of 1
+local MIN_SCALE = 0.5 --the minimum scale we want to show cooldown counts at, anything below this will be hidden
+local MIN_DURATION = 1.5 --the minimum duration to show cooldown text for
+
+local TimeColors = {
+ [0] = "|cfffefefe",
+ [1] = "|cfffefefe",
+ [2] = "|cfffefefe",
+ [3] = "|cfffefefe",
+ [4] = "|cfffe0000"
+}
+
+local function Cooldown_OnUpdate(cd, elapsed)
+ if cd.nextUpdate > 0 then
+ cd.nextUpdate = cd.nextUpdate - elapsed
+ return
+ end
+
+ local remain = cd.duration - (GetTime() - cd.start)
+ if remain > 0.05 then
+ if (cd.fontScale * cd:GetEffectiveScale() / UIParent:GetScale()) < MIN_SCALE then
+ cd.text:SetText("")
+ cd.nextUpdate = 500
+ else
+ local timervalue, formatid
+ timervalue, formatid, cd.nextUpdate = E:GetTimeInfo(remain, E.db.cooldown.threshold)
+ cd.text:SetText(format("%s%s|r", TimeColors[formatid], format(E.TimeFormats[formatid][2], timervalue)))
+ end
+ else
+ E:Cooldown_StopTimer(cd)
+ end
+end
+
+function E:Cooldown_OnSizeChanged(cd, width)
+ local fontScale = floor(width +.5) / ICON_SIZE
+ local override = cd:GetParent():GetParent().SizeOverride
+ if override then
+ fontScale = override / FONT_SIZE
+ end
+
+ if fontScale == cd.fontScale then
+ return
+ end
+
+ cd.fontScale = fontScale
+ if fontScale < MIN_SCALE and not override then
+ cd:Hide()
+ else
+ cd:Show()
+ E:FontTemplate(cd.text, nil, fontScale * FONT_SIZE, "OUTLINE")
+ if cd.enabled then
+ self:Cooldown_ForceUpdate(cd)
+ end
+ end
+end
+
+function E:Cooldown_ForceUpdate(cd)
+ cd.nextUpdate = 0
+ cd:Show()
+end
+
+function E:Cooldown_StopTimer(cd)
+ cd.enabled = nil
+ cd:Hide()
+end
+
+function E:CreateCooldownTimer(parent)
+ local scaler = CreateFrame("Frame", nil, parent)
+ scaler:SetAllPoints()
+
+ local timer = CreateFrame("Frame", nil, scaler)
+ timer:Hide()
+ timer:SetAllPoints()
+ timer:SetScript("OnUpdate", function() Cooldown_OnUpdate(this, arg1) end)
+
+ local text = timer:CreateFontString(nil, "OVERLAY")
+ text:SetPoint("CENTER", 1, 1)
+ text:SetJustifyH("CENTER")
+ timer.text = text
+
+ self:Cooldown_OnSizeChanged(timer, parent:GetWidth(), parent:GetHeight())
+ parent:SetScript("OnSizeChanged", function() self:Cooldown_OnSizeChanged(timer, parent:GetWidth(), parent:GetHeight()) end)
+
+ parent.timer = timer
+ return timer
+end
+
+function E:OnSetCooldown(start, duration, enable)
+ if self.noOCC then return end
+
+ if start > 0 and duration > MIN_DURATION and enable > 0 then
+ local timer = self.timer or E:CreateCooldownTimer(self)
+ timer.start = start
+ timer.duration = duration
+ timer.enabled = true
+ timer.nextUpdate = 0
+ if timer.fontScale >= MIN_SCALE then timer:Show() end
+ else
+ local timer = self.timer
+ if timer then
+ E:Cooldown_StopTimer(timer)
+ return
+ end
+ end
+end
+
+function E:RegisterCooldown(cooldown)
+ if not E.private.cooldown.enable or cooldown.isHooked then return end
+ hooksecurefunc("CooldownFrame_SetTimer", E.OnSetCooldown)
+ cooldown.isHooked = true
+end
+
+function E:UpdateCooldownSettings()
+ local color = self.db.cooldown.expiringColor
+ TimeColors[4] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that are soon to expire
+
+ color = self.db.cooldown.secondsColor
+ TimeColors[3] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have seconds remaining
+
+ color = self.db.cooldown.minutesColor
+ TimeColors[2] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have minutes remaining
+
+ color = self.db.cooldown.hoursColor
+ TimeColors[1] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have hours remaining
+
+ color = self.db.cooldown.daysColor
+ TimeColors[0] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have days remaining
+end
\ No newline at end of file
diff --git a/ElvUI/Core/Load_Core.xml b/ElvUI/Core/Load_Core.xml
new file mode 100644
index 0000000..2a74520
--- /dev/null
+++ b/ElvUI/Core/Load_Core.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Core/Math.lua b/ElvUI/Core/Math.lua
new file mode 100644
index 0000000..acbbd1d
--- /dev/null
+++ b/ElvUI/Core/Math.lua
@@ -0,0 +1,421 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local select, unpack, assert, tonumber, type, pairs = select, unpack, assert, tonumber, type, pairs
+local getn, tinsert, tremove = table.getn, tinsert, tremove
+local abs, ceil, floor, modf, mod = math.abs, math.ceil, math.floor, math.modf, math.mod
+local find, format, byte, len, sub, gsub, upper, split, utf8sub = string.find, string.format, string.byte, string.len, string.sub, string.gsub, string.upper, string.split, string.utf8sub
+--WoW API / Variables
+local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
+local CreateFrame = CreateFrame
+
+--Return short value of a number
+local shortValueDec
+function E:ShortValue(v)
+ shortValueDec = format("%%.%df", E.db.general.decimalLength or 1)
+ if E.db.general.numberPrefixStyle == "METRIC" then
+ if abs(v) >= 1e9 then
+ return format(shortValueDec.."G", v / 1e9)
+ elseif abs(v) >= 1e6 then
+ return format(shortValueDec.."M", v / 1e6)
+ elseif abs(v) >= 1e3 then
+ return format(shortValueDec.."k", v / 1e3)
+ else
+ return format("%s", v)
+ end
+ elseif E.db.general.numberPrefixStyle == "CHINESE" then
+ if abs(v) >= 1e8 then
+ return format(shortValueDec.."Y", v / 1e8)
+ elseif abs(v) >= 1e4 then
+ return format(shortValueDec.."W", v / 1e4)
+ else
+ return format("%s", v)
+ end
+ elseif E.db.general.numberPrefixStyle == "KOREAN" then
+ if abs(v) >= 1e8 then
+ return format(shortValueDec.."억", v / 1e8)
+ elseif abs(v) >= 1e4 then
+ return format(shortValueDec.."만", v / 1e4)
+ elseif abs(v) >= 1e3 then
+ return format(shortValueDec.."천", v / 1e3)
+ else
+ return format("%s", v)
+ end
+ elseif E.db.general.numberPrefixStyle == "GERMAN" then
+ if abs(v) >= 1e9 then
+ return format(shortValueDec.."Mrd", v / 1e9)
+ elseif abs(v) >= 1e6 then
+ return format(shortValueDec.."Mio", v / 1e6)
+ elseif abs(v) >= 1e3 then
+ return format(shortValueDec.."Tsd", v / 1e3)
+ else
+ return format("%s", v)
+ end
+ else
+ if abs(v) >= 1e9 then
+ return format(shortValueDec.."B", v / 1e9)
+ elseif abs(v) >= 1e6 then
+ return format(shortValueDec.."M", v / 1e6)
+ elseif abs(v) >= 1e3 then
+ return format(shortValueDec.."K", v / 1e3)
+ else
+ return format("%s", v)
+ end
+ end
+end
+
+function E:IsEvenNumber(num)
+ return mod(num, 2) == 0
+end
+
+function E:ColorGradient(perc, r1, g1, b1, r2, g2, b2, r3, g3, b3)
+ if perc >= 1 then
+ return r3, g3, b3
+ elseif perc <= 0 then
+ return r1, g1, b1
+ end
+
+ local segment, relperc = modf(perc)
+ if segment > 0 then
+ r1, g1, b1, r2, g2, b2 = r2, g2, b2, r3, g3, b3
+ end
+
+ return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc
+end
+
+function E:Round(num, idp)
+ if idp and idp > 0 then
+ local mult = 10 ^ idp
+ return floor(num * mult + 0.5) / mult
+ end
+ return floor(num + 0.5)
+end
+
+function E:Truncate(v, decimals)
+ return v - (mod(v, 0.1 ^ (decimals or 0)))
+end
+
+function E:RGBToHex(r, g, b)
+ r = r <= 1 and r >= 0 and r or 0
+ g = g <= 1 and g >= 0 and g or 0
+ b = b <= 1 and b >= 0 and b or 0
+ return format("|cff%02x%02x%02x", r*255, g*255, b*255)
+end
+
+function E:HexToRGB(hex)
+ local rhex, ghex, bhex = sub(hex, 1, 2), sub(hex, 3, 4), sub(hex, 5, 6)
+ return tonumber(rhex, 16), tonumber(ghex, 16), tonumber(bhex, 16)
+end
+
+function E:FramesOverlap(frameA, frameB)
+ if not frameA or not frameB then return end
+
+ local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
+ if not sA or not sB then return end
+
+ local frameALeft = frameA:GetLeft()
+ local frameARight = frameA:GetRight()
+ local frameABottom = frameA:GetBottom()
+ local frameATop = frameA:GetTop()
+
+ local frameBLeft = frameB:GetLeft()
+ local frameBRight = frameB:GetRight()
+ local frameBBottom = frameB:GetBottom()
+ local frameBTop = frameB:GetTop()
+
+ if not frameALeft or not frameARight or not frameABottom or not frameATop then return end
+ if not frameBLeft or not frameBRight or not frameBBottom or not frameBTop then return end
+
+ return ((frameALeft*sA) < (frameBRight*sB))
+ and ((frameBLeft*sB) < (frameARight*sA))
+ and ((frameABottom*sA) < (frameBTop*sB))
+ and ((frameBBottom*sB) < (frameATop*sA))
+end
+
+function E:GetScreenQuadrant(frame)
+ local x, y = frame:GetCenter()
+ local screenWidth = GetScreenWidth()
+ local screenHeight = GetScreenHeight()
+ local point
+
+ if not frame:GetCenter() then
+ return "UNKNOWN", frame:GetName()
+ end
+
+ if (x > (screenWidth / 3) and x < (screenWidth / 3)*2) and y > (screenHeight / 3)*2 then
+ point = "TOP"
+ elseif x < (screenWidth / 3) and y > (screenHeight / 3)*2 then
+ point = "TOPLEFT"
+ elseif x > (screenWidth / 3)*2 and y > (screenHeight / 3)*2 then
+ point = "TOPRIGHT"
+ elseif (x > (screenWidth / 3) and x < (screenWidth / 3)*2) and y < (screenHeight / 3) then
+ point = "BOTTOM"
+ elseif x < (screenWidth / 3) and y < (screenHeight / 3) then
+ point = "BOTTOMLEFT"
+ elseif x > (screenWidth / 3)*2 and y < (screenHeight / 3) then
+ point = "BOTTOMRIGHT"
+ elseif x < (screenWidth / 3) and (y > (screenHeight / 3) and y < (screenHeight / 3)*2) then
+ point = "LEFT"
+ elseif x > (screenWidth / 3)*2 and y < (screenHeight / 3)*2 and y > (screenHeight / 3) then
+ point = "RIGHT"
+ else
+ point = "CENTER"
+ end
+ return point
+end
+
+function E:GetXYOffset(position, override)
+ local default = E.Spacing
+ local x, y = override or default, override or default
+
+ if position == "TOP" then
+ return 0, y
+ elseif position == "TOPLEFT" then
+ return x, y
+ elseif position == "TOPRIGHT" then
+ return -x, y
+ elseif position == "BOTTOM" then
+ return 0, -y
+ elseif(position == "BOTTOMLEFT") then
+ return x, -y
+ elseif position == "BOTTOMRIGHT" then
+ return -x, -y
+ elseif position == "LEFT" then
+ return -x, 0
+ elseif position == "RIGHT" then
+ return x, 0
+ elseif position == "CENTER" then
+ return 0, 0
+ end
+end
+
+local styles = {
+ -- keep percents in this table with `PERCENT` in the key, and `%.1f%%` in the value somewhere.
+ -- we use these two things to follow our setting for decimal length. they need to be EXACT.
+ ["CURRENT"] = "%s",
+ ["CURRENT_MAX"] = "%s - %s",
+ ["CURRENT_PERCENT"] = "%s - %.1f%%",
+ ["CURRENT_MAX_PERCENT"] = "%s - %s | %.1f%%",
+ ["PERCENT"] = "%.1f%%",
+ ["DEFICIT"] = "-%s"
+}
+
+function E:GetFormattedText(style, min, max)
+ assert(styles[style], "Invalid format style: "..style)
+ assert(min, "You need to provide a current value. Usage: E:GetFormattedText(style, min, max)")
+ assert(max, "You need to provide a maximum value. Usage: E:GetFormattedText(style, min, max)")
+
+ if max == 0 then max = 1 end
+
+ gftDec = E.db.general.decimalLength or 1
+ if gftDec ~= 1 and find(style, "PERCENT") then
+ gftUseStyle = gsub(styles[style], "%%%.1f%%%%", "%%."..gftDec.."f%%%%")
+ else
+ gftUseStyle = styles[style]
+ end
+
+ if style == "DEFICIT" then
+ gftDeficit = max - min
+ return ((gftDeficit > 0) and format(gftUseStyle, E:ShortValue(gftDeficit))) or ""
+ elseif style == "PERCENT" then
+ return format(gftUseStyle, min / max * 100)
+ elseif style == "CURRENT" or ((style == "CURRENT_MAX" or style == "CURRENT_MAX_PERCENT" or style == "CURRENT_PERCENT") and min == max) then
+ return format(styles["CURRENT"], E:ShortValue(min))
+ elseif style == "CURRENT_MAX" then
+ return format(gftUseStyle, E:ShortValue(min), E:ShortValue(max))
+ elseif style == "CURRENT_PERCENT" then
+ return format(gftUseStyle, E:ShortValue(min), min / max * 100)
+ elseif style == "CURRENT_MAX_PERCENT" then
+ return format(gftUseStyle, E:ShortValue(min), E:ShortValue(max), min / max * 100)
+ end
+end
+
+function E:AbbreviateString(string, allUpper)
+ local newString = ""
+ local words = {split(" ", string)}
+ for _, word in pairs(words) do
+ word = utf8sub(word, 1, 1)
+ if(allUpper) then
+ word = upper(word)
+ end
+ newString = newString..word
+ end
+
+ return newString
+end
+
+function E:ShortenString(string, numChars, dots)
+ local bytes = len(string)
+ if bytes <= numChars then
+ return string
+ else
+ local len, pos = 0, 1
+ while pos <= bytes do
+ len = len + 1
+ local c = byte(string, pos)
+ if c > 0 and c <= 127 then
+ pos = pos + 1
+ elseif c >= 192 and c <= 223 then
+ pos = pos + 2
+ elseif c >= 224 and c <= 239 then
+ pos = pos + 3
+ elseif c >= 240 and c <= 247 then
+ pos = pos + 4
+ end
+ if len == numChars then break end
+ end
+
+ if len == numChars and pos <= bytes then
+ return sub(string, 1, pos - 1)..(dots and "..." or "")
+ else
+ return string
+ end
+ end
+end
+
+local waitTable = {}
+local waitFrame
+function E:Delay(delay, func, ...)
+ if (type(delay) ~= "number") or (type(func) ~= "function") then
+ return false
+ end
+ if waitFrame == nil then
+ waitFrame = CreateFrame("Frame", "WaitFrame", E.UIParent)
+ waitFrame:SetScript("OnUpdate", function()
+ local waitRecord, waitDelay, waitFunc, waitParams
+ local i, count = 1, getn(waitTable)
+ while i <= count do
+ waitRecord = tremove(waitTable, i)
+ waitDelay = tremove(waitRecord, 1)
+ waitFunc = tremove(waitRecord, 1)
+ waitParams = tremove(waitRecord, 1)
+ if waitDelay > arg1 then
+ tinsert(waitTable, i, {waitDelay - arg1, waitFunc, waitParams})
+ i = i + 1
+ else
+ count = count - 1
+ waitFunc(unpack(waitParams))
+ end
+ end
+ end)
+ end
+ tinsert(waitTable, {delay, func, arg})
+ return true
+end
+
+function E:StringTitle(str)
+ return gsub(str, "(.)", upper, 1)
+end
+
+E.TimeColors = {
+ [0] = "|cffeeeeee",
+ [1] = "|cffeeeeee",
+ [2] = "|cffeeeeee",
+ [3] = "|cffeeeeee",
+ [4] = "|cfffe0000"
+}
+
+E.TimeFormats = {
+ [0] = {"%dd", "%dd"},
+ [1] = {"%dh", "%dh"},
+ [2] = {"%dm", "%dm"},
+ [3] = {"%ds", "%d"},
+ [4] = {"%.1fs", "%.1f"}
+}
+
+local DAY, HOUR, MINUTE = 86400, 3600, 60
+local DAYISH, HOURISH, MINUTEISH = HOUR * 23.5, MINUTE * 59.5, 59.5
+local HALFDAYISH, HALFHOURISH, HALFMINUTEISH = DAY/2 + 0.5, HOUR/2 + 0.5, MINUTE/2 + 0.5
+
+function E:GetTimeInfo(s, threshhold)
+ if s < MINUTE then
+ if s >= threshhold then
+ return floor(s), 3, 0.51
+ else
+ return s, 4, 0.051
+ end
+ elseif s < HOUR then
+ local minutes = floor((s/MINUTE)+.5)
+ return ceil(s / MINUTE), 2, minutes > 1 and (s - (minutes*MINUTE - HALFMINUTEISH)) or (s - MINUTEISH)
+ elseif s < DAY then
+ local hours = floor((s/HOUR)+.5)
+ return ceil(s / HOUR), 1, hours > 1 and (s - (hours*HOUR - HALFHOURISH)) or (s - HOURISH)
+ else
+ local days = floor((s/DAY)+.5)
+ return ceil(s / DAY), 0, days > 1 and (s - (days*DAY - HALFDAYISH)) or (s - DAYISH)
+ end
+end
+
+local COLOR_COPPER = "|cffeda55f"
+local COLOR_SILVER = "|cffc7c7cf"
+local COLOR_GOLD = "|cffffd700"
+
+function E:FormatMoney(amount, style)
+ local coppername = L.copperabbrev
+ local silvername = L.silverabbrev
+ local goldname = L.goldabbrev
+
+ local value = abs(amount)
+ local gold = floor(value / 10000)
+ local silver = floor(mod(value / 100, 100))
+ local copper = floor(mod(value, 100))
+
+ if not style or style == "SMART" then
+ local str = ""
+ if gold > 0 then
+ str = format("%d%s%s", gold, goldname, (silver > 0 or copper > 0) and " " or "")
+ end
+ if silver > 0 then
+ str = format("%s%d%s%s", str, silver, silvername, copper > 0 and " " or "")
+ end
+ if copper > 0 or value == 0 then
+ str = format("%s%d%s", str, copper, coppername)
+ end
+ return str
+ end
+
+ if style == "FULL" then
+ if gold > 0 then
+ return format("%d%s %d%s %d%s", gold, goldname, silver, silvername, copper, coppername)
+ elseif silver > 0 then
+ return format("%d%s %d%s", silver, silvername, copper, coppername)
+ else
+ return format("%d%s", copper, coppername)
+ end
+ elseif style == "SHORT" then
+ if gold > 0 then
+ return format("%.1f%s", amount / 10000, goldname)
+ elseif silver > 0 then
+ return format("%.1f%s", amount / 100, silvername)
+ else
+ return format("%d%s", amount, coppername)
+ end
+ elseif style == "SHORTINT" then
+ if gold > 0 then
+ return format("%d%s", gold, goldname)
+ elseif silver > 0 then
+ return format("%d%s", silver, silvername)
+ else
+ return format("%d%s", copper, coppername)
+ end
+ elseif style == "CONDENSED" then
+ if gold > 0 then
+ return format("%s%d|r.%s%02d|r.%s%02d|r", COLOR_GOLD, gold, COLOR_SILVER, silver, COLOR_COPPER, copper)
+ elseif silver > 0 then
+ return format("%s%d|r.%s%02d|r", COLOR_SILVER, silver, COLOR_COPPER, copper)
+ else
+ return format("%s%d|r", COLOR_COPPER, copper)
+ end
+ elseif style == "BLIZZARD" then
+ if gold > 0 then
+ return format("%s%s %d%s %d%s", gold, goldname, silver, silvername, copper, coppername)
+ elseif silver > 0 then
+ return format("%d%s %d%s", silver, silvername, copper, coppername)
+ else
+ return format("%d%s", copper, coppername)
+ end
+ end
+
+ return self:FormatMoney(amount, "SMART")
+end
\ No newline at end of file
diff --git a/ElvUI/Core/Movers.lua b/ElvUI/Core/Movers.lua
new file mode 100644
index 0000000..a134dfa
--- /dev/null
+++ b/ElvUI/Core/Movers.lua
@@ -0,0 +1,499 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local Sticky = LibStub("LibSimpleSticky-1.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local type, unpack, pairs = type, unpack, pairs
+local format, split, find = string.format, string.split, string.find
+--WoW API / Variables
+local CreateFrame = CreateFrame
+
+E.CreatedMovers = {}
+E.DisabledMovers = {}
+
+local function SizeChanged(self)
+ self.mover:SetWidth(self.dirtyWidth and self.dirtyWidth or self:GetWidth())
+ self.mover:SetHeight(self.dirtyHeight and self.dirtyHeight or self:GetHeight())
+end
+
+local function GetPoint(obj)
+ local point, anchor, secondaryPoint, x, y = obj:GetPoint()
+ if not anchor then anchor = ElvUIParent end
+
+ return format("%s,%s,%s,%d,%d", point, anchor:GetName(), secondaryPoint, E:Round(x), E:Round(y))
+end
+
+local function UpdateCoords(self)
+ local mover = self.child;
+ local x, y, _, nudgePoint, nudgeInversePoint = E:CalculateMoverPoints(mover);
+
+ local coordX, coordY = E:GetXYOffset(nudgeInversePoint, 1);
+ ElvUIMoverNudgeWindow:ClearAllPoints();
+ ElvUIMoverNudgeWindow:SetPoint(nudgePoint, mover, nudgeInversePoint, coordX, coordY);
+ E:UpdateNudgeFrame(mover, x, y);
+end
+
+local isDragging = false
+local coordFrame = CreateFrame("Frame")
+coordFrame:SetScript("OnUpdate", function() UpdateCoords(this) end)
+coordFrame:Hide()
+
+local function CreateMover(parent, name, text, overlay, snapOffset, postdrag, shouldDisable)
+ if not parent then return end --If for some reason the parent isnt loaded yet
+ if E.CreatedMovers[name].Created then return end
+
+ if overlay == nil then overlay = true end
+ local point, anchor, secondaryPoint, x, y = split(",", GetPoint(parent))
+
+ local width = parent.dirtyWidth or parent:GetWidth()
+ local height = parent.dirtyHeight or parent:GetHeight()
+
+ local f = CreateFrame("Button", name, E.UIParent)
+ f:SetClampedToScreen(true)
+ f:RegisterForDrag("LeftButton", "RightButton")
+ f:EnableMouseWheel(true)
+ f:SetMovable(true)
+ f:SetWidth(width)
+ f:SetHeight(height)
+ E:SetTemplate(f, "Transparent", nil, nil, true)
+ f:Hide()
+ f.parent = parent
+ f.name = name
+ f.textString = text
+ f.postdrag = postdrag
+ f.overlay = overlay
+ f.snapOffset = snapOffset or -2
+ f.shouldDisable = shouldDisable
+
+ f:SetFrameLevel(parent:GetFrameLevel() + 1)
+ if(overlay == true) then
+ f:SetFrameStrata("DIALOG")
+ else
+ f:SetFrameStrata("BACKGROUND")
+ end
+
+ E.CreatedMovers[name].mover = f
+ E["snapBars"][getn(E["snapBars"]) + 1] = f
+
+ local fs = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(fs)
+ fs:SetJustifyH("CENTER")
+ fs:SetPoint("CENTER", f)
+ fs:SetText(text or name)
+ fs:SetTextColor(unpack(E["media"].rgbvaluecolor))
+ f:SetFontString(fs)
+ f.text = fs
+
+ if E.db["movers"] and E.db["movers"][name] then
+ if type(E.db["movers"][name]) == "table" then
+ f:SetPoint(E.db["movers"][name]["p"], E.UIParent, E.db["movers"][name]["p2"], E.db["movers"][name]["p3"], E.db["movers"][name]["p4"])
+ E.db["movers"][name] = GetPoint(f)
+ f:ClearAllPoints()
+ end
+
+ local delim
+ local anchorString = E.db["movers"][name]
+ if find(anchorString, "\031") then
+ delim = "\031"
+ elseif find(anchorString, ",") then
+ delim = ","
+ end
+ local point, anchor, secondaryPoint, x, y = split(delim, anchorString)
+ f:SetPoint(point, anchor, secondaryPoint, x, y)
+ else
+
+ f:SetPoint(point, anchor, secondaryPoint, x, y)
+ end
+
+ local function OnDragStart(self)
+ if E.db["general"].stickyFrames then
+ Sticky:StartMoving(self, E["snapBars"], f.snapOffset, f.snapOffset, f.snapOffset, f.snapOffset)
+ else
+ self:StartMoving()
+ end
+ coordFrame.child = self
+ coordFrame:Show()
+ isDragging = true
+ end
+
+ local function OnDragStop(self)
+ isDragging = false
+ if E.db["general"].stickyFrames then
+ Sticky:StopMoving(self)
+ else
+ self:StopMovingOrSizing()
+ end
+
+ local x, y, point = E:CalculateMoverPoints(self)
+ self:ClearAllPoints()
+ local overridePoint
+ if(self.positionOverride) then
+ if(self.positionOverride == "BOTTOM" or self.positionOverride == "TOP") then
+ overridePoint = "BOTTOM"
+ else
+ overridePoint = "BOTTOMLEFT"
+ end
+ end
+
+ self:SetPoint(self.positionOverride or point, E.UIParent, overridePoint and overridePoint or point, x, y)
+ if(self.positionOverride) then
+ self.parent:ClearAllPoints()
+ self.parent:SetPoint(self.positionOverride, self, self.positionOverride)
+ end
+
+ E:SaveMoverPosition(name)
+
+ if ElvUIMoverNudgeWindow then
+ E:UpdateNudgeFrame(self, x, y)
+ end
+
+ coordFrame.child = nil
+ coordFrame:Hide()
+
+ if postdrag ~= nil and type(postdrag) == "function" then
+ postdrag(self, E:GetScreenQuadrant(self))
+ end
+
+ self:SetUserPlaced(false)
+ end
+
+ local function OnEnter()
+ if isDragging then return end
+ this.text:SetTextColor(1, 1, 1)
+ ElvUIMoverNudgeWindow:Show()
+ E.AssignFrameToNudge(this)
+ coordFrame.child = this
+ UpdateCoords(coordFrame)
+ --coordFrame:GetScript("OnUpdate")(coordFrame)
+ end
+
+ local function OnMouseDown(button)
+ if button == "RightButton" then
+ isDragging = false
+ if E.db["general"].stickyFrames then
+ Sticky:StopMoving(this)
+ else
+ this:StopMovingOrSizing()
+ end
+ if IsControlKeyDown() and this.textString then
+ E:ResetMovers(this.textString)
+ elseif IsShiftKeyDown() then
+ this:Hide()
+ end
+ end
+ end
+
+ local function OnLeave(self)
+ if isDragging then return end
+ this.text:SetTextColor(unpack(E["media"].rgbvaluecolor))
+ end
+
+ local function OnShow(self)
+ this:SetBackdropBorderColor(unpack(E["media"].rgbvaluecolor))
+ end
+
+ local function OnMouseWheel(_, delta)
+ if(IsShiftKeyDown()) then
+ E:NudgeMover(delta)
+ else
+ E:NudgeMover(nil, delta)
+ end
+ end
+
+ f:SetScript("OnDragStart", function() OnDragStart(f) end)
+ f:SetScript("OnMouseUp", E.AssignFrameToNudge)
+ f:SetScript("OnDragStop", function() OnDragStop(f) end)
+ f:SetScript("OnEnter", OnEnter)
+ f:SetScript("OnMouseDown", OnMouseDown)
+ f:SetScript("OnLeave", OnLeave)
+ f:SetScript("OnShow", OnShow)
+ f:SetScript("OnMouseWheel", OnMouseWheel)
+
+ parent:SetScript("OnSizeChanged", function() SizeChanged(parent) end)
+ parent.mover = f
+
+ parent:ClearAllPoints()
+ parent:SetPoint(point, f, 0, 0)
+
+ if postdrag ~= nil and type(postdrag) == "function" then
+ f:RegisterEvent("PLAYER_ENTERING_WORLD")
+ f:SetScript("OnEvent", function()
+ postdrag(f, E:GetScreenQuadrant(f))
+ this:UnregisterAllEvents()
+ end)
+ end
+
+ E.CreatedMovers[name].Created = true
+end
+
+function E:CalculateMoverPoints(mover, nudgeX, nudgeY)
+ local screenWidth, screenHeight, screenCenter = E.UIParent:GetRight(), E.UIParent:GetTop(), E.UIParent:GetCenter()
+ local x, y = mover:GetCenter()
+
+ local LEFT = screenWidth / 3
+ local RIGHT = screenWidth * 2 / 3
+ local TOP = screenHeight / 2
+ local point, nudgePoint, nudgeInversePoint
+
+ if(y >= TOP) then
+ point = "TOP"
+ nudgePoint = "TOP"
+ nudgeInversePoint = "BOTTOM"
+ y = -(screenHeight - mover:GetTop())
+ else
+ point = "BOTTOM"
+ nudgePoint = "BOTTOM"
+ nudgeInversePoint = "TOP"
+ y = mover:GetBottom()
+ end
+
+ if(x >= RIGHT) then
+ point = point .. "RIGHT"
+ nudgePoint = "RIGHT"
+ nudgeInversePoint = "LEFT"
+ x = mover:GetRight() - screenWidth
+ elseif(x <= LEFT) then
+ point = point .. "LEFT"
+ nudgePoint = "LEFT"
+ nudgeInversePoint = "RIGHT"
+ x = mover:GetLeft()
+ else
+ x = x - screenCenter
+ end
+
+ if(mover.positionOverride) then
+ if(mover.positionOverride == "TOPLEFT") then
+ x = mover:GetLeft() - E.diffGetLeft
+ y = mover:GetTop() - E.diffGetTop
+ elseif(mover.positionOverride == "TOPRIGHT") then
+ x = mover:GetRight() - E.diffGetRight
+ y = mover:GetTop() - E.diffGetTop
+ elseif(mover.positionOverride == "BOTTOMLEFT") then
+ x = mover:GetLeft() - E.diffGetLeft
+ y = mover:GetBottom() - E.diffGetBottom
+ elseif(mover.positionOverride == "BOTTOMRIGHT") then
+ x = mover:GetRight() - E.diffGetRight
+ y = mover:GetBottom() - E.diffGetBottom
+ elseif(mover.positionOverride == "BOTTOM") then
+ x = mover:GetCenter() - screenCenter
+ y = mover:GetBottom() - E.diffGetBottom
+ elseif(mover.positionOverride == "TOP") then
+ x = mover:GetCenter() - screenCenter
+ y = mover:GetTop() - E.diffGetTop
+ end
+ end
+
+ x = x + (nudgeX or 0)
+ y = y + (nudgeY or 0)
+
+ return x, y, point, nudgePoint, nudgeInversePoint
+end
+
+function E:UpdatePositionOverride(name)
+ if _G[name] and _G[name]:GetScript("OnDragStop") then
+ _G[name]:GetScript("OnDragStop")(_G[name])
+ end
+end
+
+function E:HasMoverBeenMoved(name)
+ if E.db["movers"] and E.db["movers"][name] then
+ return true
+ else
+ return false
+ end
+end
+
+function E:SaveMoverPosition(name)
+ if not _G[name] then return end
+ if not E.db.movers then E.db.movers = {} end
+
+ E.db.movers[name] = GetPoint(_G[name])
+end
+
+function E:SetMoverSnapOffset(name, offset)
+ if not _G[name] or not E.CreatedMovers[name] then return end
+ E.CreatedMovers[name].mover.snapOffset = offset or -2
+ E.CreatedMovers[name]["snapoffset"] = offset or -2
+end
+
+function E:SaveMoverDefaultPosition(name)
+ if not _G[name] then return end
+
+ E.CreatedMovers[name]["point"] = GetPoint(_G[name])
+ E.CreatedMovers[name]["postdrag"](_G[name], E:GetScreenQuadrant(_G[name]))
+end
+
+function E:CreateMover(parent, name, text, overlay, snapoffset, postdrag, moverTypes, shouldDisable)
+ if not moverTypes then moverTypes = "ALL,GENERAL" end
+
+ if E.CreatedMovers[name] == nil then
+ E.CreatedMovers[name] = {}
+ E.CreatedMovers[name]["parent"] = parent
+ E.CreatedMovers[name]["text"] = text
+ E.CreatedMovers[name]["overlay"] = overlay
+ E.CreatedMovers[name]["postdrag"] = postdrag
+ E.CreatedMovers[name]["snapoffset"] = snapoffset
+ E.CreatedMovers[name]["point"] = GetPoint(parent)
+ E.CreatedMovers[name]["shouldDisable"] = shouldDisable
+
+ E.CreatedMovers[name]["type"] = {}
+ local types = {split(",", moverTypes)}
+ for i = 1, getn(types) do
+ local moverType = types[i]
+ E.CreatedMovers[name]["type"][moverType] = true
+ end
+ end
+
+ CreateMover(parent, name, text, overlay, snapoffset, postdrag, shouldDisable)
+end
+
+function E:ToggleMovers(show, moverType)
+ self.configMode = show
+
+ for name, _ in pairs(E.CreatedMovers) do
+ if not show then
+ _G[name]:Hide()
+ else
+ if E.CreatedMovers[name]["type"][moverType] then
+ _G[name]:Show()
+ else
+ _G[name]:Hide()
+ end
+ end
+ end
+end
+
+function E:DisableMover(name)
+ if(self.DisabledMovers[name]) then return end
+ if(not self.CreatedMovers[name]) then
+ error("mover doesn't exist")
+ end
+
+ self.DisabledMovers[name] = {}
+ for x, y in pairs(self.CreatedMovers[name]) do
+ self.DisabledMovers[name][x] = y
+ end
+
+ if(self.configMode) then
+ _G[name]:Hide()
+ end
+
+ self.CreatedMovers[name] = nil
+end
+
+function E:EnableMover(name)
+ if(self.CreatedMovers[name]) then return end
+ if(not self.DisabledMovers[name]) then
+ error("mover doesn't exist")
+ end
+
+ self.CreatedMovers[name] = {}
+ for x, y in pairs(self.DisabledMovers[name]) do
+ self.CreatedMovers[name][x] = y
+ end
+
+ --Commented out, as it created an issue with trying to reset a mover after having used EnableMover on it. Not sure if this code is even needed anymore.
+--[[
+ if(E.db["movers"] and E.db["movers"][name] and type(E.db["movers"][name]) == "string") then
+ self.CreatedMovers[name]["point"] = E.db["movers"][name]
+ end
+]]
+
+ if(self.configMode) then
+ _G[name]:Show()
+ end
+
+ self.DisabledMovers[name] = nil
+end
+
+function E:ResetMovers(arg)
+ if arg == "" or arg == nil then
+ for name, _ in pairs(E.CreatedMovers) do
+ local f = _G[name]
+ local point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name]["point"])
+ f:ClearAllPoints()
+ f:SetPoint(point, anchor, secondaryPoint, x, y)
+
+ for key, value in pairs(E.CreatedMovers[name]) do
+ if key == "postdrag" and type(value) == "function" then
+ value(f, E:GetScreenQuadrant(f))
+ end
+ end
+ end
+ self.db.movers = nil
+ else
+ for name, _ in pairs(E.CreatedMovers) do
+ for key, value in pairs(E.CreatedMovers[name]) do
+ if key == "text" then
+ if arg == value then
+ local f = _G[name]
+ local point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name]["point"])
+ f:ClearAllPoints()
+ f:SetPoint(point, anchor, secondaryPoint, x, y)
+
+ if self.db.movers then
+ self.db.movers[name] = nil
+ end
+
+ if E.CreatedMovers[name]["postdrag"] ~= nil and type(E.CreatedMovers[name]["postdrag"]) == "function" then
+ E.CreatedMovers[name]["postdrag"](f, E:GetScreenQuadrant(f))
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+--Profile Change
+function E:SetMoversPositions()
+ for name in pairs(E.DisabledMovers) do
+ local shouldDisable = ((E.DisabledMovers[name].shouldDisable and E.DisabledMovers[name]["shouldDisable"]()) or false)
+ if not shouldDisable then
+ E:EnableMover(name)
+ end
+ end
+
+ for name, _ in pairs(E.CreatedMovers) do
+ local f = _G[name]
+ local point, anchor, secondaryPoint, x, y
+ if E.db["movers"] and E.db["movers"][name] and type(E.db["movers"][name]) == "string" then
+ local delim
+ local anchorString = E.db["movers"][name]
+ if(find(anchorString, "\031")) then
+ delim = "\031"
+ elseif(find(anchorString, ",")) then
+ delim = ","
+ end
+ point, anchor, secondaryPoint, x, y = split(delim, anchorString)
+ f:ClearAllPoints()
+ f:SetPoint(point, anchor, secondaryPoint, x, y)
+ elseif f then
+ point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name]["point"])
+ f:ClearAllPoints()
+ f:SetPoint(point, anchor, secondaryPoint, x, y)
+ end
+ end
+end
+
+--Called from core.lua
+function E:LoadMovers()
+ for n, _ in pairs(E.CreatedMovers) do
+ local p, t, o, so, pd
+ for key, value in pairs(E.CreatedMovers[n]) do
+ if key == "parent" then
+ p = value
+ elseif key == "text" then
+ t = value
+ elseif key == "overlay" then
+ o = value
+ elseif key == "snapoffset" then
+ so = value
+ elseif key == "postdrag" then
+ pd = value
+ end
+ end
+ CreateMover(p, n, t, o, so, pd)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Core/StaticPopups.lua b/ElvUI/Core/StaticPopups.lua
new file mode 100644
index 0000000..6a7167e
--- /dev/null
+++ b/ElvUI/Core/StaticPopups.lua
@@ -0,0 +1,932 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs, type, unpack, assert = pairs, type, unpack, assert
+local getn, tremove, tContains, tinsert, wipe = table.getn, tremove, tContains, tinsert, table.wipe
+local lower = string.lower
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local UnitIsDeadOrGhost, InCinematic = UnitIsDeadOrGhost, InCinematic
+local GetBindingFromClick, RunBinding = GetBindingFromClick, RunBinding
+local PurchaseSlot, GetBankSlotCost = PurchaseSlot, GetBankSlotCost
+local MoneyFrame_Update = MoneyFrame_Update
+local SetCVar, DisableAddOn = SetCVar, DisableAddOn
+local ReloadUI, PlaySound, StopMusic = ReloadUI, PlaySound, StopMusic
+local StaticPopup_Resize = StaticPopup_Resize
+
+E.PopupDialogs = {}
+E.StaticPopup_DisplayedFrames = {}
+
+E.PopupDialogs["ELVUI_UPDATE_AVAILABLE"] = {
+ text = L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"],
+ hasEditBox = 1,
+ OnShow = function()
+ this.editBox:SetAutoFocus(false)
+ this.editBox.width = this.editBox:GetWidth()
+ this.editBox:SetWidth(220)
+ this.editBox:SetText("https://github.com/ElvUI-Vanilla/ElvUI")
+ this.editBox:HighlightText()
+ -- ChatEdit_FocusActiveWindow()
+ end,
+ OnHide = function()
+ this.editBox:SetWidth(this.editBox.width or 50)
+ this.editBox.width = nil
+ end,
+ hideOnEscape = 1,
+ button1 = OKAY,
+ button2 = CLOSE, -- Temporary until further fix
+ OnAccept = E.noop,
+ EditBoxOnEnterPressed = function()
+ -- ChatEdit_FocusActiveWindow()
+ this:GetParent():Hide()
+ end,
+ EditBoxOnEscapePressed = function()
+ -- ChatEdit_FocusActiveWindow()
+ this:GetParent():Hide()
+ end,
+ EditBoxOnTextChanged = function()
+ if this:GetText() ~= "https://github.com/ElvUI-Vanilla/ElvUI" then
+ this:SetText("https://github.com/ElvUI-Vanilla/ElvUI")
+ end
+ this:HighlightText()
+ this:ClearFocus()
+ -- ChatEdit_FocusActiveWindow()
+ end,
+ OnEditFocusGained = function()
+ this:HighlightText()
+ end,
+ showAlert = 1
+}
+
+E.PopupDialogs["CLIQUE_ADVERT"] = {
+ text = L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."],
+ button1 = YES,
+ button2 = CLOSE, -- Temporary until further fix
+ OnAccept = E.noop,
+ showAlert = 1
+}
+
+E.PopupDialogs["CONFIRM_LOSE_BINDING_CHANGES"] = {
+ text = CONFIRM_LOSE_BINDING_CHANGES,
+ button1 = OKAY,
+ button2 = CANCEL,
+ OnAccept = function()
+ E:GetModule("ActionBars"):ChangeBindingProfile()
+ E:GetModule("ActionBars").bindingsChanged = nil
+ end,
+ OnCancel = function()
+ if ElvUIBindPopupWindowCheckButton:GetChecked() then
+ ElvUIBindPopupWindowCheckButton:SetChecked()
+ else
+ ElvUIBindPopupWindowCheckButton:SetChecked(1)
+ end
+ end,
+ timeout = 0,
+ whileDead = 1,
+ showAlert = 1
+}
+
+E.PopupDialogs["TUKUI_ELVUI_INCOMPATIBLE"] = {
+ text = L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."],
+ OnAccept = function() DisableAddOn("ElvUI") ReloadUI() end,
+ OnCancel = function() DisableAddOn("Tukui") ReloadUI() end,
+ button1 = "ElvUI",
+ button2 = "Tukui",
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["DISABLE_INCOMPATIBLE_ADDON"] = {
+ text = L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"],
+ OnAccept = function() E.global.ignoreIncompatible = true end,
+ OnCancel = function() E:StaticPopup_Hide("DISABLE_INCOMPATIBLE_ADDON") E:StaticPopup_Show("INCOMPATIBLE_ADDON", E.PopupDialogs["INCOMPATIBLE_ADDON"].addon, E.PopupDialogs["INCOMPATIBLE_ADDON"].module) end,
+ button1 = L["I Swear"],
+ button2 = DECLINE,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["INCOMPATIBLE_ADDON"] = {
+ text = L["INCOMPATIBLE_ADDON"],
+ OnAccept = function() DisableAddOn(E.PopupDialogs["INCOMPATIBLE_ADDON"].addon) ReloadUI() end,
+ OnCancel = function() E.private[lower(E.PopupDialogs["INCOMPATIBLE_ADDON"].module)].enable = false ReloadUI() end,
+ button3 = L["Disable Warning"],
+ OnAlt = function ()
+ E:StaticPopup_Hide("INCOMPATIBLE_ADDON")
+ E:StaticPopup_Show("DISABLE_INCOMPATIBLE_ADDON")
+ end,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["PIXELPERFECT_CHANGED"] = {
+ text = L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."],
+ button1 = ACCEPT,
+ button2 = CLOSE, -- Temporary until further fix
+ OnAccept = E.noop,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["CONFIGAURA_SET"] = {
+ text = L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."],
+ button1 = ACCEPT,
+ button2 = CLOSE, -- Temporary until further fix
+ OnAccept = E.noop,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["QUEUE_TAINT"] = {
+ text = L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = ReloadUI,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["FAILED_UISCALE"] = {
+ text = L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = function() E.global.general.autoScale = false ReloadUI() end,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["CONFIG_RL"] = {
+ text = L["One or more of the changes you have made require a ReloadUI."],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = ReloadUI,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["GLOBAL_RL"] = {
+ text = L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = ReloadUI,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["PRIVATE_RL"] = {
+ text = L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = ReloadUI,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["KEYBIND_MODE"] = {
+ text = L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."],
+ button1 = L["Save"],
+ button2 = L["Discard"],
+ OnAccept = function() E:GetModule("ActionBars"):DeactivateBindMode(true) end,
+ OnCancel = function() E:GetModule("ActionBars"):DeactivateBindMode(false) end,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+E.PopupDialogs["DELETE_GRAYS"] = {
+ text = L["Are you sure you want to delete all your gray items?"],
+ button1 = YES,
+ button2 = NO,
+ OnAccept = function() E:GetModule("Bags"):VendorGrays(true) end,
+ OnShow = function()
+ MoneyFrame_Update(this:GetName().."MoneyFrame", E.PopupDialogs["DELETE_GRAYS"].Money)
+ end,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false,
+ hasMoneyFrame = 1
+}
+
+E.PopupDialogs["BUY_BANK_SLOT"] = {
+ text = CONFIRM_BUY_BANK_SLOT,
+ button1 = YES,
+ button2 = NO,
+ OnAccept = PurchaseSlot,
+ OnShow = function()
+ MoneyFrame_Update(this:GetName().."MoneyFrame", GetBankSlotCost())
+ end,
+ hasMoneyFrame = 1,
+ timeout = 0,
+ hideOnEscape = 1
+}
+
+E.PopupDialogs["CANNOT_BUY_BANK_SLOT"] = {
+ text = L["Can't buy anymore slots!"],
+ button1 = ACCEPT,
+ button2 = CLOSE, -- Temporary until further fix
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["NO_BANK_BAGS"] = {
+ text = L["You must purchase a bank slot first!"],
+ button1 = ACCEPT,
+ button2 = CLOSE, -- Temporary until further fix
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["RESETUI_CHECK"] = {
+ text = L["Are you sure you want to reset every mover back to it's default position?"],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = function()
+ E:ResetAllUI()
+ end,
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["HARLEM_SHAKE"] = {
+ text = L["ElvUI needs to perform database optimizations please be patient."],
+ button1 = OKAY,
+ button2 = CLOSE, -- Temporary until further fix
+ OnAccept = function()
+ if E.isMassiveShaking then
+ E:StopHarlemShake()
+ else
+ E:BeginHarlemShake()
+ return true
+ end
+ end,
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["HELLO_KITTY"] = {
+ text = L["ElvUI needs to perform database optimizations please be patient."],
+ button1 = OKAY,
+ button2 = CLOSE, -- Temporary until further fix
+ OnAccept = function()
+ E:SetupHelloKitty()
+ end,
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["HELLO_KITTY_END"] = {
+ text = L["Do you enjoy the new ElvUI?"],
+ button1 = L["Yes, Keep Changes!"],
+ button2 = L["No, Revert Changes!"],
+ OnAccept = function()
+ E:Print(L["Type /hellokitty to revert to old settings."])
+ StopMusic()
+ SetCVar("Sound_EnableAllSound", E.oldEnableAllSound)
+ SetCVar("Sound_EnableMusic", E.oldEnableMusic)
+ end,
+ OnCancel = function()
+ E:RestoreHelloKitty()
+ StopMusic()
+ SetCVar("Sound_EnableAllSound", E.oldEnableAllSound)
+ SetCVar("Sound_EnableMusic", E.oldEnableMusic)
+ end,
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["DISBAND_RAID"] = {
+ text = L["Are you sure you want to disband the group?"],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = function() E:GetModule("Misc"):DisbandRaidGroup() end,
+ timeout = 0,
+ whileDead = 1
+}
+
+E.PopupDialogs["CONFIRM_LOOT_DISTRIBUTION"] = {
+ text = CONFIRM_LOOT_DISTRIBUTION,
+ button1 = YES,
+ button2 = NO,
+ timeout = 0,
+ hideOnEscape = 1
+}
+
+E.PopupDialogs["RESET_PROFILE_PROMPT"] = {
+ text = L["Are you sure you want to reset all the settings on this profile?"],
+ button1 = YES,
+ button2 = NO,
+ timeout = 0,
+ hideOnEscape = 1,
+ OnAccept = function() E:ResetProfile() end
+}
+
+E.PopupDialogs["APPLY_FONT_WARNING"] = {
+ text = L["Are you sure you want to apply this font to all ElvUI elements?"],
+ OnAccept = function()
+ local font = E.db.general.font
+ local fontSize = E.db.general.fontSize
+
+ E.db.bags.itemLevelFont = font
+ E.db.bags.itemLevelFontSize = fontSize
+ E.db.bags.countFont = font
+ E.db.bags.countFontSize = fontSize
+ E.db.nameplates.font = font
+ E.db.nameplates.fontSize = fontSize
+ E.db.actionbar.font = font
+ E.db.actionbar.fontSize = fontSize
+ E.db.auras.font = font
+ E.db.auras.fontSize = fontSize
+ E.db.chat.font = font
+ E.db.chat.fontSize = fontSize
+ E.db.chat.tabFont = font
+ E.db.chat.tapFontSize = fontSize
+ E.db.datatexts.font = font
+ E.db.datatexts.fontSize = fontSize
+ E.db.tooltip.font = font
+ E.db.tooltip.fontSize = fontSize
+ E.db.tooltip.headerFontSize = fontSize
+ E.db.tooltip.textFontSize = fontSize
+ E.db.tooltip.smallTextFontSize = fontSize
+ E.db.tooltip.healthBar.font = font
+ E.db.tooltip.healthBar.fontSize = fontSize
+ E.db.unitframe.font = font
+ E.db.unitframe.fontSize = fontSize
+ E.db.unitframe.units.party.rdebuffs.font = font
+ E.db.unitframe.units.raid.rdebuffs.font = font
+ E.db.unitframe.units.raid40.rdebuffs.font = font
+
+ E:UpdateAll(true)
+ end,
+ OnCancel = function() E:StaticPopup_Hide("APPLY_FONT_WARNING") end,
+ button1 = YES,
+ button2 = CANCEL,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false
+}
+
+local MAX_STATIC_POPUPS = 4
+
+function E:StaticPopup_OnShow()
+ PlaySound("igMainMenuOpen")
+
+ local dialog = E.PopupDialogs[this.which]
+ local OnShow = dialog.OnShow
+ if OnShow then
+ OnShow(this.data)
+ end
+ if dialog.enterClicksFirstButton then
+ this:SetScript("OnKeyDown", E.StaticPopup_OnKeyDown)
+ end
+end
+
+function E:StaticPopup_EscapePressed()
+ local closed = nil
+ for _, frame in pairs(E.StaticPopup_DisplayedFrames) do
+ if frame:IsShown() and frame.hideOnEscape then
+ local standardDialog = E.PopupDialogs[frame.which]
+ if standardDialog then
+ local OnCancel = standardDialog.OnCancel
+ local noCancelOnEscape = standardDialog.noCancelOnEscape
+ if OnCancel and not noCancelOnEscape then
+ OnCancel(frame, frame.data, "clicked")
+ end
+ frame:Hide()
+ else
+ E:StaticPopupSpecial_Hide(frame)
+ end
+ closed = 1
+ end
+ end
+ return closed
+end
+
+function E:StaticPopupSpecial_Hide(frame)
+ frame:Hide()
+ E:StaticPopup_CollapseTable()
+end
+
+function E:StaticPopup_CollapseTable()
+ local displayedFrames = E.StaticPopup_DisplayedFrames
+ local index = getn(displayedFrames)
+ while((index >= 1) and (not displayedFrames[index]:IsShown())) do
+ tremove(displayedFrames, index)
+ index = index - 1
+ end
+end
+
+function E:StaticPopup_SetUpPosition(dialog)
+ if not tContains(E.StaticPopup_DisplayedFrames, dialog) then
+ local lastFrame = E.StaticPopup_DisplayedFrames[getn(E.StaticPopup_DisplayedFrames)]
+ if lastFrame then
+ dialog:SetPoint("TOP", lastFrame, "BOTTOM", 0, -4)
+ else
+ dialog:SetPoint("TOP", E.UIParent, "TOP", 0, -100)
+ end
+ tinsert(E.StaticPopup_DisplayedFrames, dialog)
+ end
+end
+
+function E:StaticPopupSpecial_Show(frame)
+ if frame.exclusive then
+ E:StaticPopup_HideExclusive()
+ end
+ E:StaticPopup_SetUpPosition(frame)
+ frame:Show()
+end
+
+function E:StaticPopupSpecial_Hide(frame)
+ frame:Hide()
+ E:StaticPopup_CollapseTable()
+end
+
+function E:StaticPopup_IsLastDisplayedFrame(frame)
+ for i = getn(E.StaticPopup_DisplayedFrames), 1, -1 do
+ local popup = E.StaticPopup_DisplayedFrames[i]
+ if popup:IsShown() then
+ return frame == popup
+ end
+ end
+ return false
+end
+
+function E:StaticPopup_OnKeyDown(key)
+ if GetBindingFromClick(key) == "TOGGLEGAMEMENU" then
+ return E:StaticPopup_EscapePressed()
+ elseif GetBindingFromClick(key) == "SCREENSHOT" then
+ RunBinding("SCREENSHOT")
+ return
+ end
+
+ local dialog = E.PopupDialogs[this.which]
+ if dialog then
+ if arg1 == "ENTER" and dialog.enterClicksFirstButton then
+ local frameName = this:GetName()
+ local button
+ local i = 1
+ while true do
+ button = _G[frameName.."Button"..i]
+ if button then
+ if button:IsShown() then
+ E:StaticPopup_OnClick(this, i)
+ return
+ end
+ i = i + 1
+ else
+ break
+ end
+ end
+ end
+ end
+end
+
+function E:StaticPopup_OnHide()
+ PlaySound("igMainMenuClose")
+
+ E:StaticPopup_CollapseTable()
+
+ local dialog = E.PopupDialogs[this.which]
+ local OnHide = dialog.OnHide
+ if OnHide then
+ OnHide(this.data)
+ end
+ if dialog.enterClicksFirstButton then
+ this:SetScript("OnKeyDown", nil)
+ end
+end
+
+function E:StaticPopup_OnUpdate()
+ if this.timeleft and this.timeleft > 0 then
+ local which = this.which
+ local timeleft = this.timeleft - arg1
+ if timeleft <= 0 then
+ if not E.PopupDialogs[which].timeoutInformationalOnly then
+ this.timeleft = 0
+ local OnCancel = E.PopupDialogs[which].OnCancel
+ if OnCancel then
+ OnCancel(this.data, "timeout")
+ end
+ this:Hide()
+ end
+ return
+ end
+ this.timeleft = timeleft
+ end
+
+ if this.startDelay then
+ local which = this.which
+ local timeleft = this.startDelay - arg1
+ if timeleft <= 0 then
+ this.startDelay = nil
+ local text = _G[this:GetName().."Text"]
+ text:SetText(format(E.PopupDialogs[which].text, text.text_arg1, text.text_arg2))
+ local button1 = _G[this:GetName().."Button1"]
+ button1:Enable()
+ StaticPopup_Resize(this, which)
+ return
+ end
+ this.startDelay = timeleft
+ end
+
+ local onUpdate = E.PopupDialogs[this.which].OnUpdate
+ if onUpdate then
+ onUpdate(arg1, this)
+ end
+end
+
+function E:StaticPopup_OnClick(index)
+ if not self:IsShown() then
+ return
+ end
+ local which = self.which
+ local info = E.PopupDialogs[which]
+ if not info then
+ return nil
+ end
+ local hide = true
+ if index == 1 then
+ local OnAccept = info.OnAccept
+ if OnAccept then
+ hide = not OnAccept(self, self.data, self.data2)
+ end
+ elseif index == 3 then
+ local OnAlt = info.OnAlt
+ if OnAlt then
+ OnAlt(self, self.data, "clicked")
+ end
+ else
+ local OnCancel = info.OnCancel
+ if OnCancel then
+ hide = not OnCancel(self, self.data, "clicked")
+ end
+ end
+
+ if hide and (which == self.which) and (index ~= 3 or not info.noCloseOnAlt) then
+ self:Hide()
+ end
+end
+
+function E:StaticPopup_EditBoxOnEnterPressed()
+ local EditBoxOnEnterPressed, which, dialog
+ local parent = this:GetParent()
+ if parent.which then
+ which = parent.which
+ dialog = parent
+ elseif parent:GetParent().which then
+ which = parent:GetParent().which
+ dialog = parent:GetParent()
+ end
+ EditBoxOnEnterPressed = E.PopupDialogs[which].EditBoxOnEnterPressed
+ if EditBoxOnEnterPressed then
+ EditBoxOnEnterPressed(this, dialog.data)
+ end
+end
+
+function E:StaticPopup_EditBoxOnEscapePressed()
+ local EditBoxOnEscapePressed = E.PopupDialogs[this:GetParent().which].EditBoxOnEscapePressed
+ if EditBoxOnEscapePressed then
+ EditBoxOnEscapePressed(this, this:GetParent().data)
+ end
+end
+
+function E:StaticPopup_EditBoxOnTextChanged(userInput)
+ local EditBoxOnTextChanged = E.PopupDialogs[this:GetParent().which].EditBoxOnTextChanged
+ if EditBoxOnTextChanged then
+ EditBoxOnTextChanged(this, this:GetParent().data)
+ end
+end
+
+function E:StaticPopup_FindVisible(which, data)
+ local info = E.PopupDialogs[which]
+ if not info then
+ return nil
+ end
+ for index = 1, MAX_STATIC_POPUPS, 1 do
+ local frame = _G["ElvUI_StaticPopup"..index]
+ if (frame:IsShown() and (frame.which == which) and (not info.multiple or (frame.data == data))) then
+ return frame
+ end
+ end
+ return nil
+end
+
+function E:StaticPopup_Resize(dialog, which)
+ local info = E.PopupDialogs[which]
+ if not info then
+ return nil
+ end
+
+ local name = dialog:GetName()
+ local text = _G[name.."Text"]
+ local editBox = _G[name.."EditBox"]
+ local button1 = _G[name.."Button1"]
+
+ local maxHeightSoFar, maxWidthSoFar = (dialog.maxHeightSoFar or 0), (dialog.maxWidthSoFar or 0)
+ local width = 320
+
+ if dialog.numButtons == 3 then
+ width = 440
+ elseif info.showAlert or info.showAlertGear or info.closeButton then
+ width = 420
+ elseif info.editBoxWidth and info.editBoxWidth > 260 then
+ width = width + (info.editBoxWidth - 260)
+ end
+
+ if width > maxWidthSoFar then
+ dialog:SetWidth(width)
+ dialog.maxWidthSoFar = width
+ end
+
+ local height = 32 + text:GetHeight() + 8 + button1:GetHeight()
+ if info.hasEditBox then
+ height = height + 8 + editBox:GetHeight()
+ elseif info.hasMoneyFrame then
+ height = height + 16
+ end
+
+ if height > maxHeightSoFar then
+ dialog:SetHeight(height)
+ dialog.maxHeightSoFar = height
+ end
+end
+
+function E:StaticPopup_OnEvent()
+ self.maxHeightSoFar = 0
+ E:StaticPopup_Resize(self, self.which)
+end
+
+local tempButtonLocs = {}
+function E:StaticPopup_Show(which, text_arg1, text_arg2, data)
+ local info = E.PopupDialogs[which]
+ if not info then
+ return nil
+ end
+
+ if UnitIsDeadOrGhost("player") and not info.whileDead then
+ if info.OnCancel then
+ info.OnCancel()
+ end
+ return nil
+ end
+
+ if InCinematic() and not info.interruptCinematic then
+ if info.OnCancel then
+ info.OnCancel()
+ end
+ return nil
+ end
+
+ if info.cancels then
+ for index = 1, MAX_STATIC_POPUPS, 1 do
+ local frame = _G["ElvUI_StaticPopup"..index]
+ if (frame:IsShown() and (frame.which == info.cancels)) then
+ frame:Hide()
+ local OnCancel = E.PopupDialogs[frame.which].OnCancel
+ if OnCancel then
+ OnCancel(frame, frame.data, "override")
+ end
+ end
+ end
+ end
+
+ local dialog = nil
+ dialog = E:StaticPopup_FindVisible(which, data)
+ if dialog then
+ if not info.noCancelOnReuse then
+ local OnCancel = info.OnCancel
+ if OnCancel then
+ OnCancel(dialog, dialog.data, "override")
+ end
+ end
+ dialog:Hide()
+ end
+ if not dialog then
+ local index = 1
+ if info.preferredIndex then
+ index = info.preferredIndex
+ end
+ for i = index, MAX_STATIC_POPUPS do
+ local frame = _G["ElvUI_StaticPopup"..i]
+ if not frame:IsShown() then
+ dialog = frame
+ break
+ end
+ end
+ if not dialog and info.preferredIndex then
+ for i = 1, info.preferredIndex do
+ local frame = _G["ElvUI_StaticPopup"..i]
+ if not frame:IsShown() then
+ dialog = frame
+ break
+ end
+ end
+ end
+ end
+ if not dialog then
+ if info.OnCancel then
+ info.OnCancel()
+ end
+ return nil
+ end
+
+ dialog.maxHeightSoFar, dialog.maxWidthSoFar = 0, 0
+
+ local name = dialog:GetName()
+ local text = _G[name.."Text"]
+ text:SetText(format(info.text, text_arg1, text_arg2))
+
+ if info.closeButton then
+ local closeButton = _G[name.."CloseButton"]
+ if info.closeButtonIsHide then
+ closeButton:SetNormalTexture("Interface\\Buttons\\UI-Panel-HideButton-Up")
+ closeButton:SetPushedTexture("Interface\\Buttons\\UI-Panel-HideButton-Down")
+ else
+ closeButton:SetNormalTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up")
+ closeButton:SetPushedTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Down")
+ end
+ closeButton:Show()
+ else
+ _G[name.."CloseButton"]:Hide()
+ end
+
+ local editBox = _G[name.."EditBox"]
+ if info.hasEditBox then
+ editBox:Show()
+
+ if info.maxLetters then
+ editBox:SetMaxLetters(info.maxLetters)
+ end
+ if info.maxBytes then
+ editBox:SetMaxBytes(info.maxBytes)
+ end
+ editBox:SetText("")
+ if info.editBoxWidth then
+ editBox:SetWidth(info.editBoxWidth)
+ else
+ editBox:SetWidth(130)
+ end
+ else
+ editBox:Hide()
+ end
+
+ if info.hasMoneyFrame then
+ _G[name.."MoneyFrame"]:Show()
+ else
+ _G[name.."MoneyFrame"]:Hide()
+ end
+
+ dialog.which = which
+ dialog.timeleft = info.timeout
+ dialog.hideOnEscape = info.hideOnEscape
+ dialog.exclusive = info.exclusive
+ dialog.enterClicksFirstButton = info.enterClicksFirstButton
+ dialog.data = data
+
+ local button1 = _G[name.."Button1"]
+ local button2 = _G[name.."Button2"]
+
+ do
+ assert(getn(tempButtonLocs) == 0)
+
+ tinsert(tempButtonLocs, button1)
+ tinsert(tempButtonLocs, button2)
+
+ for i = getn(tempButtonLocs), 1, -1 do
+ tempButtonLocs[i]:SetText(info["button"..i])
+ tempButtonLocs[i]:Hide()
+ tempButtonLocs[i]:ClearAllPoints()
+ if not (info["button"..i] and (not info["DisplayButton"..i] or info["DisplayButton"..i](dialog))) then
+ tremove(tempButtonLocs, i)
+ end
+ end
+
+ local numButtons = getn(tempButtonLocs)
+ dialog.numButtons = numButtons
+ if numButtons == 2 then
+ tempButtonLocs[1]:SetPoint("BOTTOMRIGHT", dialog, "BOTTOM", -6, 16)
+ elseif numButtons == 1 then
+ tempButtonLocs[1]:SetPoint("BOTTOM", dialog, "BOTTOM", 0, 16)
+ end
+
+ for i = 1, numButtons do
+ if i > 1 then
+ tempButtonLocs[i]:SetPoint("LEFT", tempButtonLocs[i-1], "RIGHT", 13, 0)
+ end
+
+ local width = tempButtonLocs[i]:GetTextWidth()
+ if width > 110 then
+ tempButtonLocs[i]:SetWidth(width + 20)
+ else
+ tempButtonLocs[i]:SetWidth(120)
+ end
+ tempButtonLocs[i]:Enable()
+ tempButtonLocs[i]:Show()
+ end
+
+ wipe(tempButtonLocs)
+ table.setn(tempButtonLocs, 0)
+ end
+
+ local alertIcon = _G[name.."AlertIcon"]
+ if info.showAlert then
+ alertIcon:SetTexture("Interface\\DialogFrame\\DialogAlertIcon")
+ alertIcon:SetPoint("LEFT", 24, 0)
+ alertIcon:Show()
+ elseif info.showAlertGear then
+ alertIcon:SetTexture("Interface\\DialogFrame\\DialogAlertIcon")
+ alertIcon:SetPoint("LEFT", 24, 0)
+ alertIcon:Show()
+ else
+ alertIcon:SetTexture()
+ alertIcon:Hide()
+ end
+
+ if info.StartDelay then
+ dialog.startDelay = info.StartDelay()
+ button1:Disable()
+ else
+ dialog.startDelay = nil
+ button1:Enable()
+ end
+
+ E:StaticPopup_SetUpPosition(dialog)
+ dialog:Show()
+
+ E:StaticPopup_Resize(dialog, which)
+
+ if info.sound then
+ PlaySound(info.sound)
+ end
+
+ return dialog
+end
+
+function E:StaticPopup_Hide(which, data)
+ for index = 1, MAX_STATIC_POPUPS, 1 do
+ local dialog = _G["ElvUI_StaticPopup"..index]
+ if ((dialog.which == which) and (not data or (data == dialog.data))) then
+ dialog:Hide()
+ end
+ end
+end
+
+function E:Contruct_StaticPopups()
+ E.StaticPopupFrames = {}
+
+ local S = self:GetModule("Skins")
+ for index = 1, MAX_STATIC_POPUPS do
+ E.StaticPopupFrames[index] = CreateFrame("Frame", "ElvUI_StaticPopup"..index, E.UIParent, "StaticPopupTemplate")
+ E.StaticPopupFrames[index]:SetID(index)
+
+ E.StaticPopupFrames[index]:SetScript("OnShow", E.StaticPopup_OnShow)
+ E.StaticPopupFrames[index]:SetScript("OnHide", E.StaticPopup_OnHide)
+ E.StaticPopupFrames[index]:SetScript("OnUpdate", E.StaticPopup_OnUpdate)
+ E.StaticPopupFrames[index]:SetScript("OnEvent", E.StaticPopup_OnEvent)
+
+ local name = E.StaticPopupFrames[index]:GetName()
+ for i = 1, 2 do
+ local button = _G[name.."Button"..i]
+ S:HandleButton(button)
+
+ button:SetScript("OnClick", function()
+ E.StaticPopup_OnClick(this:GetParent(), this:GetID())
+ end)
+
+ E.StaticPopupFrames[index]["button"..i] = button
+ end
+
+ _G[name.."EditBox"]:SetScript("OnEnterPressed", E.StaticPopup_EditBoxOnEnterPressed)
+ _G[name.."EditBox"]:SetScript("OnEscapePressed", E.StaticPopup_EditBoxOnEscapePressed)
+ _G[name.."EditBox"]:SetScript("OnTextChanged", E.StaticPopup_EditBoxOnTextChanged)
+
+ E:SetTemplate(E.StaticPopupFrames[index], "Transparent")
+
+ E.StaticPopupFrames[index].text = _G[name.."Text"]
+ E.StaticPopupFrames[index].editBox = _G[name.."EditBox"]
+
+ _G[name.."EditBox"]:DisableDrawLayer("BACKGROUND")
+
+ S:HandleEditBox(_G[name.."EditBox"])
+
+ S:HandleEditBox(_G[name.."MoneyInputFrameGold"])
+ S:HandleEditBox(_G[name.."MoneyInputFrameSilver"])
+ S:HandleEditBox(_G[name.."MoneyInputFrameCopper"])
+ _G[name.."EditBox"].backdrop:SetPoint("TOPLEFT", -2, -4)
+ _G[name.."EditBox"].backdrop:SetPoint("BOTTOMRIGHT", 2, 4)
+ end
+
+ E:SecureHook("StaticPopup_Resize", "StaticPopup_SetUpPosition")
+ E:SecureHook("StaticPopup_OnHide", "StaticPopup_CollapseTable")
+end
\ No newline at end of file
diff --git a/ElvUI/Core/core.lua b/ElvUI/Core/core.lua
new file mode 100644
index 0000000..2485555
--- /dev/null
+++ b/ElvUI/Core/core.lua
@@ -0,0 +1,1146 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local tonumber, pairs, ipairs, error, unpack, select, tostring = tonumber, pairs, ipairs, error, unpack, select, tostring
+local assert, print, type, collectgarbage, pcall, date = assert, print, type, collectgarbage, pcall, date
+local twipe, tinsert, tremove, next = table.wipe, tinsert, tremove, next
+local floor = floor
+local format, find, match, strrep, len, sub, gsub = string.format, string.find, string.match, strrep, string.len, string.sub, string.gsub
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local GetActiveTalentGroup = GetActiveTalentGroup
+local GetCVar = GetCVar
+local GetFunctionCPUUsage = GetFunctionCPUUsage
+local GetTalentTabInfo = GetTalentTabInfo
+local InCombatLockdown = InCombatLockdown
+local IsAddOnLoaded = IsAddOnLoaded
+local IsInInstance, GetNumPartyMembers, GetNumRaidMembers = IsInInstance, GetNumPartyMembers, GetNumRaidMembers
+local RequestBattlefieldScoreData = RequestBattlefieldScoreData
+local SendAddonMessage = SendAddonMessage
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local ERR_NOT_IN_COMBAT = ERR_NOT_IN_COMBAT
+local MAX_TALENT_TABS = MAX_TALENT_TABS
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+
+_, E.myclass = UnitClass("player") -- Constants
+_, E.myrace = UnitRace("player")
+_, E.myfaction = UnitFactionGroup("player")
+E.myname = UnitName("player")
+E.version = GetAddOnMetadata("ElvUI", "Version")
+E.myrealm = GetRealmName()
+_, E.wowbuild = GetBuildInfo() E.wowbuild = tonumber(E.wowbuild)
+E.resolution = GetCVar("gxResolution")
+E.screenheight = tonumber(match(E.resolution, "%d+x(%d+)"));
+E.screenwidth = tonumber(match(E.resolution, "(%d+)x+%d"));
+E.isMacClient = IsMacClient()
+E.LSM = LSM
+
+E["media"] = {}
+E["frames"] = {}
+E["unitFrameElements"] = {}
+E["statusBars"] = {}
+E["texts"] = {}
+E["snapBars"] = {}
+E["RegisteredModules"] = {}
+E["RegisteredInitialModules"] = {}
+E["ModuleCallbacks"] = {["CallPriority"] = {}}
+E["InitialModuleCallbacks"] = {["CallPriority"] = {}}
+E["valueColorUpdateFuncs"] = {}
+E.TexCoords = {.08, .92, .08, .92}
+E.VehicleLocks = {}
+E.CreditsList = {}
+E.PixelMode = false
+
+E.InversePoints = {
+ TOP = "BOTTOM",
+ BOTTOM = "TOP",
+ TOPLEFT = "BOTTOMLEFT",
+ TOPRIGHT = "BOTTOMRIGHT",
+ LEFT = "RIGHT",
+ RIGHT = "LEFT",
+ BOTTOMLEFT = "TOPLEFT",
+ BOTTOMRIGHT = "TOPRIGHT",
+ CENTER = "CENTER"
+}
+
+E.DispelClasses = {
+ ["PRIEST"] = {
+ ["Magic"] = true,
+ ["Disease"] = true
+ },
+ ["SHAMAN"] = {
+ ["Poison"] = true,
+ ["Disease"] = true,
+ ["Curse"] = false
+ },
+ ["PALADIN"] = {
+ ["Poison"] = true,
+ ["Magic"] = true,
+ ["Disease"] = true
+ },
+ ["MAGE"] = {
+ ["Curse"] = true
+ },
+ ["DRUID"] = {
+ ["Curse"] = true,
+ ["Poison"] = true
+ },
+}
+
+E.HealingClasses = {
+ PALADIN = 1,
+ SHAMAN = 3,
+ DRUID = 3,
+ PRIEST = {1, 2}
+}
+
+E.ClassRole = {
+ PALADIN = {
+ [1] = "Caster",
+ [2] = "Tank",
+ [3] = "Melee"
+ },
+ PRIEST = "Caster",
+ WARLOCK = "Caster",
+ WARRIOR = {
+ [1] = "Melee",
+ [2] = "Melee",
+ [3] = "Tank"
+ },
+ HUNTER = "Melee",
+ SHAMAN = {
+ [1] = "Caster",
+ [2] = "Melee",
+ [3] = "Caster"
+ },
+ ROGUE = "Melee",
+ MAGE = "Caster",
+ DRUID = {
+ [1] = "Caster",
+ [2] = "Melee",
+ [3] = "Caster"
+ }
+}
+
+E.DEFAULT_FILTER = {
+ ["CCDebuffs"] = "Whitelist",
+ ["TurtleBuffs"] = "Whitelist",
+ ["PlayerBuffs"] = "Whitelist",
+ ["Blacklist"] = "Blacklist",
+ ["Whitelist"] = "Whitelist",
+ ["RaidDebuffs"] = "Whitelist",
+}
+
+E.noop = function() end
+
+local colorizedName
+function E:ColorizedName(name, colon)
+ local length = len(name)
+ for i = 1, length do
+ local letter = sub(name, i, i)
+ if i == 1 then
+ colorizedName = format("|cffA11313%s", letter)
+ elseif i == 2 then
+ colorizedName = format("%s|r|cffC4C4C4%s", colorizedName, letter)
+ elseif i == length and colon then
+ colorizedName = format("%s%s|r|cffA11313:|r", colorizedName, letter)
+ else
+ colorizedName = colorizedName..letter
+ end
+ end
+ return colorizedName
+end
+
+function E:Print(msg)
+ print(self:ColorizedName("ElvUI", true), msg)
+end
+
+E.PriestColors = {
+ r = 0.99,
+ g = 0.99,
+ b = 0.99
+}
+
+function E:GetPlayerRole()
+ local assignedRole = UnitGroupRolesAssigned("player")
+ if assignedRole == "NONE" or not assignedRole then
+ if self.HealingClasses[self.myclass] ~= nil and self:CheckTalentTree(self.HealingClasses[E.myclass]) then
+ return "HEALER"
+ elseif E.Role == "Tank" then
+ return "TANK"
+ else
+ return "DAMAGER"
+ end
+ else
+ return assignedRole
+ end
+end
+
+function E:CheckClassColor(r, g, b)
+ r, g, b = floor(r*100+.5)/100, floor(g*100+.5)/100, floor(b*100+.5)/100
+ local matchFound = false
+ for class, _ in pairs(RAID_CLASS_COLORS) do
+ if(class ~= E.myclass) then
+ local colorTable = class == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class])
+ if(colorTable.r == r and colorTable.g == g and colorTable.b == b) then
+ matchFound = true
+ end
+ end
+ end
+
+ return matchFound
+end
+
+function E:GetColorTable(data)
+ if (not data.r or not data.g or not data.b) then
+ error("Could not unpack color values.")
+ end
+
+ if data.a then
+ return {data.r, data.g, data.b, data.a}
+ else
+ return {data.r, data.g, data.b}
+ end
+end
+
+function E:UpdateMedia()
+ if (not self.db["general"] or not self.private["general"]) then return end
+
+ -- Fonts
+ self["media"].normFont = LSM:Fetch("font", self.db["general"].font)
+ self["media"].combatFont = LSM:Fetch("font", self.db["general"].dmgfont)
+
+ -- Textures
+ self["media"].blankTex = LSM:Fetch("background", "ElvUI Blank")
+ self["media"].normTex = LSM:Fetch("statusbar", self.private["general"].normTex)
+ self["media"].glossTex = LSM:Fetch("statusbar", self.private["general"].glossTex)
+
+ -- Border Color
+ local border = E.db["general"].bordercolor
+ if self:CheckClassColor(border.r, border.g, border.b) then
+ local classColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
+ E.db["general"].bordercolor.r = classColor.r
+ E.db["general"].bordercolor.g = classColor.g
+ E.db["general"].bordercolor.b = classColor.b
+ end
+
+ self["media"].bordercolor = {border.r, border.g, border.b}
+
+ -- UnitFrame Border Color
+ border = E.db["unitframe"].colors.borderColor
+ if self:CheckClassColor(border.r, border.g, border.b) then
+ local classColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
+ E.db["unitframe"].colors.borderColor.r = classColor.r
+ E.db["unitframe"].colors.borderColor.g = classColor.g
+ E.db["unitframe"].colors.borderColor.b = classColor.b
+ end
+ self["media"].unitframeBorderColor = {border.r, border.g, border.b}
+
+ -- Backdrop Color
+ self["media"].backdropcolor = E:GetColorTable(self.db["general"].backdropcolor)
+
+ -- Backdrop Fade Color
+ self["media"].backdropfadecolor = E:GetColorTable(self.db["general"].backdropfadecolor)
+
+ -- Value Color
+ local value = self.db["general"].valuecolor
+ if self:CheckClassColor(value.r, value.g, value.b) then
+ value = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
+ self.db["general"].valuecolor.r = value.r
+ self.db["general"].valuecolor.g = value.g
+ self.db["general"].valuecolor.b = value.b
+ end
+
+ self["media"].hexvaluecolor = self:RGBToHex(value.r, value.g, value.b)
+ self["media"].rgbvaluecolor = {value.r, value.g, value.b}
+
+ if LeftChatPanel and LeftChatPanel.tex and RightChatPanel and RightChatPanel.tex then
+ LeftChatPanel.tex:SetTexture(E.db.chat.panelBackdropNameLeft)
+ local a = E.db.general.backdropfadecolor.a or 0.5
+ LeftChatPanel.tex:SetAlpha(a)
+
+ RightChatPanel.tex:SetTexture(E.db.chat.panelBackdropNameRight)
+ RightChatPanel.tex:SetAlpha(a)
+ end
+
+ self:ValueFuncCall()
+ self:UpdateBlizzardFonts()
+end
+
+local function LSMCallback()
+ E:UpdateMedia()
+end
+E.LSM.RegisterCallback(E, "LibSharedMedia_Registered", LSMCallback)
+
+local LBF = LibStub("LibButtonFacade", true)
+
+local LBFGroupToTableElement = {
+ ["ActionBars"] = "actionbar",
+ ["Auras"] = "auras"
+}
+
+function E:LBFCallback(SkinID, _, _, Group)
+ if not E.private then return end
+ local element = LBFGroupToTableElement[Group]
+ if element then
+ if E.private[element].lbf.enable then
+ E.private[element].lbf.skin = SkinID
+ end
+ end
+end
+
+if LBF then
+ LBF:RegisterSkinCallback("ElvUI", E.LBFCallback, E)
+end
+
+function E:RequestBGInfo()
+ RequestBattlefieldScoreData()
+end
+
+function E:PLAYER_ENTERING_WORLD()
+ if not self.MediaUpdated then
+ self:UpdateMedia()
+ self.MediaUpdated = true
+ -- else
+ -- self:ScheduleTimer("CheckRole", 0.01)
+ end
+
+ local _, instanceType = IsInInstance()
+ if instanceType == "pvp" then
+ self.BGTimer = self:ScheduleRepeatingTimer("RequestBGInfo", 5)
+ self:RequestBGInfo()
+ elseif self.BGTimer then
+ self:CancelTimer(self.BGTimer)
+ self.BGTimer = nil
+ end
+end
+
+function E:ValueFuncCall()
+ for func, _ in pairs(self["valueColorUpdateFuncs"]) do
+ func(self["media"].hexvaluecolor, unpack(self["media"].rgbvaluecolor))
+ end
+end
+
+function E:UpdateFrameTemplates()
+ for frame in pairs(self["frames"]) do
+ if(frame and frame.template) then
+ E:SetTemplate(frame, frame.template, frame.glossTex)
+ else
+ self["frames"][frame] = nil
+ end
+ end
+
+ for frame in pairs(self["unitFrameElements"]) do
+ if frame and frame.template and not frame.ignoreUpdates then
+ E:SetTemplate(frame, frame.template, frame.glossTex)
+ else
+ self["unitFrameElements"][frame] = nil
+ end
+ end
+end
+
+function E:UpdateBorderColors()
+ for frame in pairs(self["frames"]) do
+ if(frame) then
+ if(frame.template == "Default" or frame.template == "Transparent" or frame.template == nil) then
+ frame:SetBackdropBorderColor(unpack(self["media"].bordercolor))
+ end
+ else
+ self["frames"][frame] = nil
+ end
+ end
+
+ for frame in pairs(self["unitFrameElements"]) do
+ if frame and not frame.ignoreUpdates then
+ if frame.template == "Default" or frame.template == "Transparent" or frame.template == nil then
+ frame:SetBackdropBorderColor(unpack(self["media"].unitframeBorderColor))
+ end
+ else
+ self["unitFrameElements"][frame] = nil
+ end
+ end
+end
+
+function E:UpdateBackdropColors()
+ for frame, _ in pairs(self["frames"]) do
+ if(frame) then
+ if(frame.template == "Default" or frame.template == nil) then
+ if(frame.backdropTexture) then
+ frame.backdropTexture:SetVertexColor(unpack(self["media"].backdropcolor))
+ else
+ frame:SetBackdropColor(unpack(self["media"].backdropcolor))
+ end
+ elseif(frame.template == "Transparent") then
+ frame:SetBackdropColor(unpack(self["media"].backdropfadecolor))
+ end
+ else
+ self["frames"][frame] = nil
+ end
+ end
+
+ for frame, _ in pairs(self["unitFrameElements"]) do
+ if frame then
+ if frame.template == "Default" or frame.template == nil then
+ if frame.backdropTexture then
+ frame.backdropTexture:SetVertexColor(unpack(self["media"].backdropcolor))
+ else
+ frame:SetBackdropColor(unpack(self["media"].backdropcolor))
+ end
+ elseif frame.template == "Transparent" then
+ frame:SetBackdropColor(unpack(self["media"].backdropfadecolor))
+ end
+ else
+ self["unitFrameElements"][frame] = nil
+ end
+ end
+end
+
+function E:UpdateFontTemplates()
+ for text, _ in pairs(self["texts"]) do
+ if text then
+ E:FontTemplate(text, text.font, text.fontSize, text.fontStyle)
+ else
+ self["texts"][text] = nil
+ end
+ end
+end
+
+function E:RegisterStatusBar(statusBar)
+ tinsert(self.statusBars, statusBar)
+end
+
+function E:UpdateStatusBars()
+ for _, statusBar in pairs(self.statusBars) do
+ if(statusBar and statusBar:GetObjectType() == "StatusBar") then
+ statusBar:SetStatusBarTexture(self.media.normTex)
+ elseif(statusBar and statusBar:GetObjectType() == "Texture") then
+ statusBar:SetTexture(self.media.normTex)
+ end
+ end
+end
+
+--This frame everything in ElvUI should be anchored to for Eyefinity support.
+E.UIParent = CreateFrame("Frame", "ElvUIParent", UIParent)
+E.UIParent:SetFrameLevel(UIParent:GetFrameLevel())
+E.UIParent:SetPoint("CENTER", UIParent, "CENTER")
+E.UIParent:SetHeight(UIParent:GetHeight())
+E.UIParent:SetWidth(UIParent:GetWidth())
+E["snapBars"][table.getn(E["snapBars"]) + 1] = E.UIParent
+
+E.HiddenFrame = CreateFrame("Frame")
+E.HiddenFrame:Hide()
+
+function E:IsDispellableByMe(debuffType)
+ if not self.DispelClasses[self.myclass] then return end
+
+ if self.DispelClasses[self.myclass][debuffType] then
+ return true
+ end
+end
+
+function E:GetTalentSpecInfo(isInspect)
+ local talantGroup = GetActiveTalentGroup(isInspect)
+ local maxPoints, specIdx, specName, specIcon = 0, 0
+
+ for i = 1, MAX_TALENT_TABS do
+ local name, icon, pointsSpent = GetTalentTabInfo(i, isInspect, nil, talantGroup)
+ if maxPoints < pointsSpent then
+ maxPoints = pointsSpent
+ specIdx = i
+ specName = name
+ specIcon = icon
+ end
+ end
+
+ if not specName then
+ specName = "None"
+ end
+ if not specIcon then
+ specIcon = "Interface\\Icons\\INV_Misc_QuestionMark"
+ end
+
+ return specIdx, specName, specIcon
+end
+
+function E:CheckTalentTree(tree)
+ local talentTree = self.TalentTree
+ if not talentTree then return false end
+
+ if type(tree) == "number" then
+ return tree == talentTree
+ elseif type(tree) == "table" then
+ for _, index in pairs(tree) do
+ return index == talentTree
+ end
+ end
+end
+
+function E:CheckRole()
+ local talentTree = self:GetTalentSpecInfo()
+ local role
+
+ if type(self.ClassRole[self.myclass]) == "string" then
+ role = self.ClassRole[self.myclass]
+ elseif(talentTree) then
+ if self.myclass == "DRUID" and talentTree == 2 then
+ role = select(5, GetTalentInfo(talentTree, 22)) > 0 and "Tank" or "Melee"
+ else
+ role = self.ClassRole[self.myclass][talentTree]
+ end
+ end
+
+ if not role then role = "Melee" end
+
+ if self.Role ~= role then
+ self.Role = role
+ self.TalentTree = talentTree
+ self.callbacks:Fire("RoleChanged")
+ end
+
+ if E.myclass == "SHAMAN" then
+ if talentTree == 3 then
+ self.DispelClasses[self.myclass].Curse = true
+ else
+ self.DispelClasses[self.myclass].Curse = false
+ end
+ end
+end
+
+function E:IncompatibleAddOn(addon, module)
+ E.PopupDialogs["INCOMPATIBLE_ADDON"].button1 = addon
+ E.PopupDialogs["INCOMPATIBLE_ADDON"].button2 = "ElvUI "..module
+ E.PopupDialogs["INCOMPATIBLE_ADDON"].addon = addon
+ E.PopupDialogs["INCOMPATIBLE_ADDON"].module = module
+ E:StaticPopup_Show("INCOMPATIBLE_ADDON", addon, module)
+end
+
+function E:CheckIncompatible()
+ if E.global.ignoreIncompatible then return end
+
+ if IsAddOnLoaded("Prat-3.0") and E.private.chat.enable then
+ E:IncompatibleAddOn("Prat-3.0", "Chat")
+ end
+
+ if IsAddOnLoaded("Chatter") and E.private.chat.enable then
+ E:IncompatibleAddOn("Chatter", "Chat")
+ end
+
+ if IsAddOnLoaded("SnowfallKeyPress") and E.private.actionbar.enable then
+ E.private.actionbar.keyDown = true
+ E:IncompatibleAddOn("SnowfallKeyPress", "ActionBar")
+ end
+
+ if IsAddOnLoaded("TidyPlates") and E.private.nameplates.enable then
+ E:IncompatibleAddOn("TidyPlates", "NamePlates")
+ end
+end
+
+function E:IsFoolsDay()
+ if find(date(), "04/01/") and not E.global.aprilFools then
+ return true
+ else
+ return false
+ end
+end
+
+function E:CopyTable(currentTable, defaultTable)
+ if type(currentTable) ~= "table" then currentTable = {} end
+
+ if type(defaultTable) == "table" then
+ for option, value in pairs(defaultTable) do
+ if type(value) == "table" then
+ value = self:CopyTable(currentTable[option], value)
+ end
+
+ currentTable[option] = value
+ end
+ end
+
+ return currentTable
+end
+
+function E:RemoveEmptySubTables(tbl)
+ if type(tbl) ~= "table" then
+ E:Print("Bad argument #1 to 'RemoveEmptySubTables' (table expected)")
+ return
+ end
+
+ for k, v in pairs(tbl) do
+ if type(v) == "table" then
+ if next(v) == nil then
+ tbl[k] = nil
+ else
+ self:RemoveEmptySubTables(v)
+ end
+ end
+ end
+end
+
+function E:RemoveTableDuplicates(cleanTable, checkTable)
+ if type(cleanTable) ~= "table" then
+ E:Print("Bad argument #1 to 'RemoveTableDuplicates' (table expected)")
+ return
+ end
+ if type(checkTable) ~= "table" then
+ E:Print("Bad argument #2 to 'RemoveTableDuplicates' (table expected)")
+ return
+ end
+
+ local cleaned = {}
+ for option, value in pairs(cleanTable) do
+ if type(value) == "table" and checkTable[option] and type(checkTable[option]) == "table" then
+ cleaned[option] = self:RemoveTableDuplicates(value, checkTable[option])
+ else
+ if cleanTable[option] ~= checkTable[option] then
+ cleaned[option] = value
+ end
+ end
+ end
+
+ self:RemoveEmptySubTables(cleaned)
+
+ return cleaned
+end
+
+function E:TableToLuaString(inTable)
+ if type(inTable) ~= "table" then
+ E:Print("Invalid argument #1 to E:TableToLuaString (table expected)")
+ return
+ end
+
+ local ret = "{\n"
+ local function recurse(table, level)
+ for i, v in pairs(table) do
+ ret = ret .. strrep(" ", level).."["
+ if type(i) == "string" then
+ ret = ret .. "\"" .. i .. "\""
+ else
+ ret = ret .. i
+ end
+ ret = ret .. "] = "
+
+ if type(v) == "number" then
+ ret = ret .. v .. ",\n"
+ elseif type(v) == "string" then
+ ret = ret .. "\"" .. gsub(gsub(gsub(v, "\\", "\\\\"), "\n", "\\n"), "\"", "\\\"") .. "\",\n"
+ elseif type(v) == "boolean" then
+ if v then
+ ret = ret .. "true,\n"
+ else
+ ret = ret .. "false,\n"
+ end
+ elseif type(v) == "table" then
+ ret = ret .. "{\n"
+ recurse(v, level + 1)
+ ret = ret .. strrep(" ", level) .. "},\n"
+ else
+ ret = ret .. "\""..tostring(v) .. "\",\n"
+ end
+ end
+ end
+
+ if inTable then
+ recurse(inTable, 1)
+ end
+ ret = ret.."}"
+
+ return ret
+end
+
+local profileFormat = {
+ ["profile"] = "E.db",
+ ["private"] = "E.private",
+ ["global"] = "E.global",
+ ["filtersNP"] = "E.global",
+ ["filtersUF"] = "E.global",
+ ["filtersAll"] = "E.global"
+}
+
+local lineStructureTable = {}
+
+function E:ProfileTableToPluginFormat(inTable, profileType)
+ local profileText = profileFormat[profileType]
+ if not profileText then
+ return
+ end
+
+ twipe(lineStructureTable)
+ local returnString = ""
+ local lineStructure = ""
+ local sameLine = false
+
+ local function buildLineStructure()
+ local str = profileText
+ for _, v in ipairs(lineStructureTable) do
+ if(type(v) == "string") then
+ str = str .. "[\"" .. v .. "\"]"
+ else
+ str = str .. "[" .. v .. "]"
+ end
+ end
+
+ return str
+ end
+
+ local function recurse(tbl)
+ lineStructure = buildLineStructure()
+ for k, v in pairs(tbl) do
+ if not sameLine then
+ returnString = returnString .. lineStructure
+ end
+
+ returnString = returnString .. "["
+
+ if type(k) == "string" then
+ returnString = returnString.."\"" .. k .. "\""
+ else
+ returnString = returnString .. k
+ end
+
+ if type(v) == "table" then
+ tinsert(lineStructureTable, k)
+ sameLine = true
+ returnString = returnString .. "]"
+ recurse(v)
+ else
+ sameLine = false
+ returnString = returnString .. "] = "
+
+ if type(v) == "number" then
+ returnString = returnString .. v .. "\n"
+ elseif type(v) == "string" then
+ returnString = returnString .. "\"" .. gsub(gsub(gsub(v, "\\", "\\\\"), "\n", "\\n"), "\"", "\\\"") .. "\"\n"
+ elseif type(v) == "boolean" then
+ if v then
+ returnString = returnString .. "true\n"
+ else
+ returnString = returnString .. "false\n"
+ end
+ else
+ returnString = returnString .. "\"" .. tostring(v) .. "\"\n"
+ end
+ end
+ end
+
+ tremove(lineStructureTable)
+ lineStructure = buildLineStructure()
+ end
+
+ if inTable and profileType then
+ recurse(inTable)
+ end
+
+ return returnString
+end
+
+function E:StringSplitMultiDelim(s, delim)
+ assert(type (delim) == "string" and len(delim) > 0, "bad delimiter")
+
+ local start = 1
+ local t = {}
+
+ while true do
+ local pos = find(s, delim, start, true)
+ if not pos then
+ break
+ end
+
+ tinsert(t, sub(s, start, pos - 1))
+ start = pos + len(delim)
+ end
+
+ tinsert(t, sub(s, start))
+
+ return unpack(t)
+end
+
+function E:SendMessage()
+ local numParty, numRaid = GetNumPartyMembers(), GetNumRaidMembers()
+ local inInstance, instanceType = IsInInstance()
+ if inInstance and (instanceType == "pvp" or instanceType == "arena") then
+ SendAddonMessage("ELVUI_VERSIONCHK", E.version, "BATTLEGROUND")
+ else
+ if numRaid > 0 then
+ SendAddonMessage("ELVUI_VERSIONCHK", E.version, "RAID")
+ elseif numParty > 0 then
+ SendAddonMessage("ELVUI_VERSIONCHK", E.version, "PARTY")
+ end
+ end
+
+ if E.SendMSGTimer then
+ self:CancelTimer(E.SendMSGTimer)
+ E.SendMSGTimer = nil
+ end
+end
+
+local SendRecieveGroupSize
+local function SendRecieve()
+ if not E.global.general.versionCheck then return end
+
+ if event == "CHAT_MSG_ADDON" then
+ if arg1 ~= "ELVUI_VERSIONCHK" then return end
+ if not arg4 or arg4 == E.myname or E.recievedOutOfDateMessage then return end
+
+ arg2 = tonumber(arg2)
+
+ if arg2 and arg2 > tonumber(E.version) then
+ E:Print(L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"])
+
+ if (arg2 - tonumber(E.version)) >= 0.05 then
+ E:StaticPopup_Show("ELVUI_UPDATE_AVAILABLE")
+ end
+
+ E.recievedOutOfDateMessage = true
+ end
+ else
+ local numRaid, numParty = GetNumRaidMembers(), GetNumPartyMembers() + 1
+ local num = numRaid > 0 and numRaid or numParty
+ if num ~= SendRecieveGroupSize then
+ if num > 1 and SendRecieveGroupSize and num > SendRecieveGroupSize then
+ E.SendMSGTimer = E:ScheduleTimer("SendMessage", 12)
+ end
+ SendRecieveGroupSize = num
+ end
+ end
+end
+
+local f = CreateFrame("Frame")
+f:RegisterEvent("RAID_ROSTER_UPDATE")
+f:RegisterEvent("PARTY_MEMBERS_CHANGED")
+f:RegisterEvent("CHAT_MSG_ADDON")
+f:SetScript("OnEvent", SendRecieve)
+
+function E:UpdateAll(ignoreInstall)
+ self.private = self.charSettings.profile
+ self.db = self.data.profile
+ self.global = self.data.global
+ self.db.theme = nil
+ self.db.install_complete = nil
+
+ self:SetMoversPositions()
+ self:UpdateMedia()
+ self:UpdateCooldownSettings()
+
+ local UF = self:GetModule("UnitFrames")
+ UF.db = self.db.unitframe
+ UF:Update_AllFrames()
+
+ local CH = self:GetModule("Chat")
+ CH.db = self.db.chat
+ CH:PositionChat(true)
+ CH:SetupChat()
+ CH:UpdateAnchors()
+
+ local AB = self:GetModule("ActionBars")
+ AB.db = self.db.actionbar
+ AB:UpdateButtonSettings()
+ AB:UpdateMicroPositionDimensions()
+
+ local bags = E:GetModule("Bags")
+ bags.db = self.db.bags
+ bags:Layout()
+ bags:Layout(true)
+ bags:SizeAndPositionBagBar()
+ bags:UpdateItemLevelDisplay()
+ bags:UpdateCountDisplay()
+
+ self:GetModule("Layout"):ToggleChatPanels()
+
+ local DT = self:GetModule("DataTexts")
+ DT.db = self.db.datatexts
+ DT:LoadDataTexts()
+
+ local NP = self:GetModule("NamePlates")
+ NP.db = self.db.nameplates
+ NP:ConfigureAll()
+
+ local DataBars = self:GetModule("DataBars")
+ DataBars.db = E.db.databars
+ DataBars:UpdateDataBarDimensions()
+ DataBars:EnableDisable_ExperienceBar()
+ DataBars:EnableDisable_ReputationBar()
+
+ self:GetModule("Auras").db = self.db.auras
+ self:GetModule("Tooltip").db = self.db.tooltip
+
+ if(ElvUIPlayerBuffs) then
+ E:GetModule("Auras"):UpdateHeader(ElvUIPlayerBuffs)
+ end
+
+ if(ElvUIPlayerDebuffs) then
+ E:GetModule("Auras"):UpdateHeader(ElvUIPlayerDebuffs)
+ end
+
+ if not (self.private.install_complete or ignoreInstall) then
+ self:Install()
+ end
+
+ self:GetModule("Minimap"):UpdateSettings()
+ self:GetModule("AFK"):Toggle()
+
+ self:UpdateBorderColors()
+ self:UpdateBackdropColors()
+
+ self:UpdateFrameTemplates()
+ self:UpdateStatusBars()
+
+ local LO = E:GetModule("Layout")
+ LO:ToggleChatPanels()
+ LO:BottomPanelVisibility()
+ LO:TopPanelVisibility()
+ LO:SetDataPanelStyle()
+
+ self:GetModule("Blizzard"):SetWatchFrameHeight()
+end
+
+function E:ResetAllUI()
+ self:ResetMovers()
+
+ if(E.db.lowresolutionset) then
+ E:SetupResolution(true)
+ end
+
+ if(E.db.layoutSet) then
+ E:SetupLayout(E.db.layoutSet, true)
+ end
+end
+
+function E:ResetUI(name)
+ if(name == "" or name == " " or name == nil) then
+ E:StaticPopup_Show("RESETUI_CHECK")
+ return
+ end
+
+ self:ResetMovers(name)
+end
+
+function E:RegisterModule(name, loadFunc)
+ --New method using callbacks
+ if (loadFunc and type(loadFunc) == "function") then
+ if self.initialized then
+ loadFunc()
+ else
+ if self.ModuleCallbacks[name] then
+ --Don't allow a registered module name to be overwritten
+ E:Print("Invalid argument #1 to E:RegisterModule (module name:", name, "is already registered, please use a unique name)")
+ return
+ end
+
+ --Add module name to registry
+ self.ModuleCallbacks[name] = true
+ self.ModuleCallbacks["CallPriority"][getn(self.ModuleCallbacks["CallPriority"]) + 1] = name
+
+ --Register loadFunc to be called when event is fired
+ E:RegisterCallback(name, loadFunc, E:GetModule(name))
+ end
+ --Old deprecated initialize method
+ else
+ if self.initialized then
+ self:GetModule(name):Initialize()
+ else
+ self["RegisteredModules"][getn(self["RegisteredModules"]) + 1] = name
+ end
+ end
+end
+
+function E:RegisterInitialModule(name, loadFunc)
+ --New method using callbacks
+ if loadFunc and type(loadFunc) == "function" then
+ if self.InitialModuleCallbacks[name] then
+ --Don't allow a registered module name to be overwritten
+ E:Print("Invalid argument #1 to E:RegisterInitialModule (module name:", name, "is already registered, please use a unique name)")
+ return
+ end
+
+ --Add module name to registry
+ self.InitialModuleCallbacks[name] = true
+ self.InitialModuleCallbacks["CallPriority"][getn(self.InitialModuleCallbacks["CallPriority"]) + 1] = name
+
+ --Register loadFunc to be called when event is fired
+ E:RegisterCallback(name, loadFunc, E:GetModule(name))
+ --Old deprecated initialize method
+ else
+ self["RegisteredInitialModules"][getn(self["RegisteredInitialModules"]) + 1] = name
+ end
+end
+
+function E:InitializeInitialModules()
+ --Fire callbacks for any module using the new system
+ for index, moduleName in ipairs(self.InitialModuleCallbacks["CallPriority"]) do
+ self.InitialModuleCallbacks[moduleName] = nil
+ self.InitialModuleCallbacks["CallPriority"][index] = nil
+ E.callbacks:Fire(moduleName)
+ end
+
+ --Old deprecated initialize method, we keep it for any plugins that may need it
+ for _, module in pairs(E["RegisteredInitialModules"]) do
+ module = self:GetModule(module, true)
+ if module and module.Initialize then
+ local _, catch = pcall(module.Initialize, module)
+ if catch and GetCVar("ShowErrors") == "1" then
+ ScriptErrorsFrame_OnError(catch, false)
+ end
+ end
+ end
+end
+
+function E:RefreshModulesDB()
+ local UF = self:GetModule("UnitFrames")
+ twipe(UF.db)
+ UF.db = self.db.unitframe
+end
+
+function E:InitializeModules()
+ --Fire callbacks for any module using the new system
+ for index, moduleName in ipairs(self.ModuleCallbacks["CallPriority"]) do
+ self.ModuleCallbacks[moduleName] = nil
+ self.ModuleCallbacks["CallPriority"][index] = nil
+ E.callbacks:Fire(moduleName)
+ end
+
+ --Old deprecated initialize method, we keep it for any plugins that may need it
+ for _, module in pairs(E["RegisteredModules"]) do
+ module = self:GetModule(module)
+ if module.Initialize then
+ local _, catch = pcall(module.Initialize, module)
+ if catch and GetCVar("ShowErrors") == "1" then
+ ScriptErrorsFrame_OnError(catch, false)
+ end
+ end
+ end
+end
+
+--DATABASE CONVERSIONS
+function E:DBConversions()
+ -- Add conversions here
+end
+
+local CPU_USAGE = {}
+local function CompareCPUDiff(showall, module, minCalls)
+ local greatestUsage, greatestCalls, greatestName, newName, newFunc
+ local greatestDiff, lastModule, mod, newUsage, calls, differance = 0
+
+ for name, oldUsage in pairs(CPU_USAGE) do
+ newName, newFunc = match(name, "^([^:]+):(.+)$")
+ if not newFunc then
+ E:Print("CPU_USAGE:", name, newFunc)
+ else
+ if newName ~= lastModule then
+ mod = E:GetModule(newName, true) or E
+ lastModule = newName
+ end
+ newUsage, calls = GetFunctionCPUUsage(mod[newFunc], true)
+ differance = newUsage - oldUsage
+ if showall and calls > minCalls then
+ E:Print(calls, name, differance)
+ end
+ if (differance > greatestDiff) and calls > minCalls then
+ greatestName, greatestUsage, greatestCalls, greatestDiff = name, newUsage, calls, differance
+ end
+ end
+ end
+
+ if greatestName then
+ E:Print(greatestName .. " had the CPU usage difference of: " .. greatestUsage .. "ms. And has been called " .. greatestCalls .. " times.")
+ else
+ E:Print("CPU Usage: No CPU Usage differences found.")
+ end
+end
+
+function E:GetTopCPUFunc(msg)
+ local module, showall, delay, minCalls = match(msg, "^([^%s]+)%s*([^%s]*)%s*([^%s]*)%s*(.*)$")
+ local mod
+
+ module = (module == "nil" and nil) or module
+ if not module then
+ E:Print("cpuusage: module (arg1) is required! This can be set as 'all' too.")
+ return
+ end
+ showall = (showall == "true" and true) or false
+ delay = (delay == "nil" and nil) or tonumber(delay) or 5
+ minCalls = (minCalls == "nil" and nil) or tonumber(minCalls) or 15
+
+ twipe(CPU_USAGE)
+ if module == "all" then
+ for _, registeredModule in pairs(self["RegisteredModules"]) do
+ mod = self:GetModule(registeredModule, true) or self
+ for name in pairs(mod) do
+ if type(mod[name]) == "function" and name ~= "GetModule" then
+ CPU_USAGE[registeredModule .. ":" .. name] = GetFunctionCPUUsage(mod[name], true)
+ end
+ end
+ end
+ else
+ mod = self:GetModule(module, true) or self
+ for name in pairs(mod) do
+ if type(mod[name]) == "function" and name ~= "GetModule" then
+ CPU_USAGE[module .. ":" .. name] = GetFunctionCPUUsage(mod[name], true)
+ end
+ end
+ end
+
+ self:Delay(delay, CompareCPUDiff, showall, module, minCalls)
+ self:Print("Calculating CPU Usage differences (module: " .. (module or "?") .. ", showall: " .. tostring(showall) .. ", minCalls: " .. tostring(minCalls) .. ", delay: " .. tostring(delay) .. ")")
+end
+
+function E:Initialize()
+ twipe(self.db)
+ twipe(self.global)
+ twipe(self.private)
+
+ self.data = LibStub("AceDB-3.0"):New("ElvDB", self.DF)
+ self.data.RegisterCallback(self, "OnProfileChanged", "UpdateAll")
+ self.data.RegisterCallback(self, "OnProfileCopied", "UpdateAll")
+ self.data.RegisterCallback(self, "OnProfileReset", "OnProfileReset")
+ self.charSettings = LibStub("AceDB-3.0"):New("ElvPrivateDB", self.privateVars)
+ self.private = self.charSettings.profile
+ self.db = self.data.profile
+ self.global = self.data.global
+ self:CheckIncompatible()
+ self:DBConversions()
+
+ -- self:ScheduleTimer("CheckRole", 0.01)
+ self:UIScale("PLAYER_LOGIN")
+
+ self:LoadCommands()
+ self:InitializeModules()
+ self:LoadMovers()
+ self:UpdateCooldownSettings()
+ self.initialized = true
+
+ if self.private.install_complete == nil then
+ self:Install()
+ end
+
+ if not find(date(), "04/01/") then
+ E.global.aprilFools = nil
+ end
+
+ --if(self:HelloKittyFixCheck()) then
+ -- self:HelloKittyFix()
+ --end
+
+ self:UpdateMedia()
+ self:UpdateFrameTemplates()
+ --self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", "CheckRole")
+ -- self:RegisterEvent("CHARACTER_POINTS_CHANGED", "CheckRole")
+ self:RegisterEvent("UPDATE_FLOATING_CHAT_WINDOWS", "UIScale")
+ self:RegisterEvent("PLAYER_ENTERING_WORLD")
+
+ if self.db.general.kittys then
+ self:CreateKittys()
+ self:Delay(5, self.Print, self, L["Type /hellokitty to revert to old settings."])
+ end
+
+ self:Tutorials()
+ self:GetModule("Minimap"):UpdateSettings()
+ self:RefreshModulesDB()
+ collectgarbage()
+
+ if self.db.general.loginmessage then
+ print(select(2, E:GetModule("Chat").FindURL(format(L["LOGIN_MSG"], self["media"].hexvaluecolor, self["media"].hexvaluecolor, self.version)))..".")
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Core/distributor.lua b/ElvUI/Core/distributor.lua
new file mode 100644
index 0000000..4d8ca89
--- /dev/null
+++ b/ElvUI/Core/distributor.lua
@@ -0,0 +1,549 @@
+local E, L, V, P, G = unpack(ElvUI) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local D = E:NewModule("Distributor", "AceEvent-3.0","AceTimer-3.0","AceComm-3.0","AceSerializer-3.0");
+local LibCompress = LibStub:GetLibrary("LibCompress");
+local LibBase64 = LibStub("LibBase64-1.0");
+
+--Cache global variables
+--Lua functions
+local tonumber, type, pcall, loadstring = tonumber, type, pcall, loadstring
+local len, format, split, find = string.len, string.format, string.split, string.find
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local GetNumRaidMembers, UnitInRaid = GetNumRaidMembers, UnitInRaid
+local GetNumPartyMembers, UnitInParty = GetNumPartyMembers, UnitInParty
+local ACCEPT, CANCEL, YES, NO = ACCEPT, CANCEL, YES, NO
+
+----------------------------------
+-- CONSTANTS
+----------------------------------
+
+local REQUEST_PREFIX = "ELVUI_REQUEST"
+local REPLY_PREFIX = "ELVUI_REPLY"
+local TRANSFER_PREFIX = "ELVUI_TRANSFER"
+local TRANSFER_COMPLETE_PREFIX = "ELVUI_COMPLETE"
+
+-- The active downloads
+local Downloads = {}
+local Uploads = {}
+
+function D:Initialize()
+ self:RegisterComm(REQUEST_PREFIX)
+ self:RegisterEvent("CHAT_MSG_ADDON")
+
+ self.statusBar = CreateFrame("StatusBar", "ElvUI_Download", UIParent)
+ E:RegisterStatusBar(self.statusBar)
+ E:CreateBackdrop(self.statusBar, "Default")
+ self.statusBar:SetStatusBarTexture(E.media.normTex)
+ self.statusBar:SetStatusBarColor(0.95, 0.15, 0.15)
+ self.statusBar:SetWidth(250)
+ self.statusBar:SetWidth(18)
+ self.statusBar.text = self.statusBar:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(self.statusBar.text)
+ self.statusBar.text:SetPoint("CENTER", 0, 0)
+ self.statusBar:Hide()
+end
+
+-- Used to start uploads
+function D:Distribute(target, otherServer, isGlobal)
+ local profileKey, data
+ if not isGlobal then
+ if ElvDB.profileKeys then
+ profileKey = ElvDB.profileKeys[E.myname.." - "..E.myrealm]
+ end
+
+ data = ElvDB.profiles[profileKey]
+ else
+ profileKey = "global"
+ data = ElvDB.global
+ end
+
+ if not data or not profileKey then return end
+
+ local serialData = self:Serialize(data)
+ local length = len(serialData)
+ local message = format("%s:%d:%s", profileKey, length, target)
+
+ Uploads[profileKey] = {
+ serialData = serialData,
+ target = target,
+ }
+
+ if otherServer then
+ local numParty, numRaid = GetNumPartyMembers(), GetNumRaidMembers()
+ if numRaid > 0 and UnitInRaid("target") then
+ self:SendCommMessage(REQUEST_PREFIX, message, "RAID")
+ elseif numParty > 0 and UnitInParty("target") then
+ self:SendCommMessage(REQUEST_PREFIX, message, "PARTY")
+ else
+ E:Print(L["Must be in group with the player if he isn't on the same server as you."])
+ return
+ end
+ else
+ self:SendCommMessage(REQUEST_PREFIX, message, "WHISPER", target)
+ end
+ self:RegisterComm(REPLY_PREFIX)
+ E:StaticPopup_Show("DISTRIBUTOR_WAITING")
+end
+
+function D:CHAT_MSG_ADDON(_, _, message, _, sender)
+ if not Downloads[sender] then return end
+ local cur = len(message)
+ local max = Downloads[sender].length
+ Downloads[sender].current = Downloads[sender].current + cur
+
+ if Downloads[sender].current > max then
+ Downloads[sender].current = max
+ end
+
+ self.statusBar:SetValue(Downloads[sender].current)
+end
+
+function D:OnCommReceived(prefix, msg, dist, sender)
+ if prefix == REQUEST_PREFIX then
+ local profile, length, sendTo = split(":", msg)
+
+ if dist ~= "WHISPER" and sendTo ~= E.myname then
+ return
+ end
+
+ if self.statusBar:IsShown() then
+ self:SendCommMessage(REPLY_PREFIX, profile..":NO", dist, sender)
+ return
+ end
+
+ local textString = format(L["%s is attempting to share the profile %s with you. Would you like to accept the request?"], sender, profile)
+ if profile == "global" then
+ textString = format(L["%s is attempting to share his filters with you. Would you like to accept the request?"], sender)
+ end
+
+ E.PopupDialogs["DISTRIBUTOR_RESPONSE"] = {
+ text = textString,
+ OnAccept = function()
+ self.statusBar:SetMinMaxValues(0, length)
+ self.statusBar:SetValue(0)
+ self.statusBar.text:SetFormattedText(L["Data From: %s"], sender)
+ E:StaticPopupSpecial_Show(self.statusBar)
+ self:SendCommMessage(REPLY_PREFIX, profile..":YES", dist, sender)
+ end,
+ OnCancel = function()
+ self:SendCommMessage(REPLY_PREFIX, profile..":NO", dist, sender)
+ end,
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ timeout = 32,
+ whileDead = 1,
+ hideOnEscape = 1,
+ }
+ E:StaticPopup_Show("DISTRIBUTOR_RESPONSE")
+
+ Downloads[sender] = {
+ current = 0,
+ length = tonumber(length),
+ profile = profile,
+ }
+
+ self:RegisterComm(TRANSFER_PREFIX)
+ elseif prefix == REPLY_PREFIX then
+ self:UnregisterComm(REPLY_PREFIX)
+ E:StaticPopup_Hide("DISTRIBUTOR_WAITING")
+
+ local profileKey, response = split(":", msg)
+ if response == "YES" then
+ self:RegisterComm(TRANSFER_COMPLETE_PREFIX)
+ self:SendCommMessage(TRANSFER_PREFIX, Uploads[profileKey].serialData, dist, Uploads[profileKey].target)
+ Uploads[profileKey] = nil
+ else
+ E:StaticPopup_Show("DISTRIBUTOR_REQUEST_DENIED")
+ Uploads[profileKey] = nil
+ end
+ elseif prefix == TRANSFER_PREFIX then
+ self:UnregisterComm(TRANSFER_PREFIX)
+ E:StaticPopupSpecial_Hide(self.statusBar)
+
+ local profileKey = Downloads[sender].profile
+ local success, data = self:Deserialize(msg)
+
+ if success then
+ local textString = format(L["Profile download complete from %s, would you like to load the profile %s now?"], sender, profileKey)
+
+ if profileKey == "global" then
+ textString = format(L["Filter download complete from %s, would you like to apply changes now?"], sender)
+ else
+ if not ElvDB.profiles[profileKey] then
+ ElvDB.profiles[profileKey] = data
+ else
+ textString = format(L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."], sender, profileKey)
+ E.PopupDialogs["DISTRIBUTOR_CONFIRM"] = {
+ text = textString,
+ button1 = ACCEPT,
+ hasEditBox = 1,
+ editBoxWidth = 350,
+ maxLetters = 127,
+ OnAccept = function(self)
+ ElvDB.profiles[self.editBox:GetText()] = data
+ LibStub("AceAddon-3.0"):GetAddon("ElvUI").data:SetProfile(self.editBox:GetText())
+ E:UpdateAll(true)
+ Downloads[sender] = nil
+ end,
+ OnShow = function(self) self.editBox:SetText(profileKey) self.editBox:SetFocus() end,
+ timeout = 0,
+ exclusive = 1,
+ whileDead = 1,
+ hideOnEscape = 1,
+ preferredIndex = 3
+ }
+
+ E:StaticPopup_Show("DISTRIBUTOR_CONFIRM")
+ self:SendCommMessage(TRANSFER_COMPLETE_PREFIX, "COMPLETE", dist, sender)
+ return
+ end
+ end
+
+ E.PopupDialogs["DISTRIBUTOR_CONFIRM"] = {
+ text = textString,
+ OnAccept = function()
+ if profileKey == "global" then
+ E:CopyTable(ElvDB.global, data)
+ E:UpdateAll(true)
+ else
+ LibStub("AceAddon-3.0"):GetAddon("ElvUI").data:SetProfile(profileKey)
+ end
+ Downloads[sender] = nil
+ end,
+ OnCancel = function()
+ Downloads[sender] = nil
+ end,
+ button1 = YES,
+ button2 = NO,
+ whileDead = 1,
+ hideOnEscape = 1,
+ }
+
+ E:StaticPopup_Show("DISTRIBUTOR_CONFIRM")
+ self:SendCommMessage(TRANSFER_COMPLETE_PREFIX, "COMPLETE", dist, sender)
+ else
+ E:StaticPopup_Show("DISTRIBUTOR_FAILED")
+ self:SendCommMessage(TRANSFER_COMPLETE_PREFIX, "FAILED", dist, sender)
+ end
+ elseif prefix == TRANSFER_COMPLETE_PREFIX then
+ self:UnregisterComm(TRANSFER_COMPLETE_PREFIX)
+ if msg == "COMPLETE" then
+ E:StaticPopup_Show("DISTRIBUTOR_SUCCESS")
+ else
+ E:StaticPopup_Show("DISTRIBUTOR_FAILED")
+ end
+ end
+end
+
+local function GetProfileData(profileType)
+ if not profileType or type(profileType) ~= "string" then
+ E:Print("Bad argument #1 to 'GetProfileData' (string expected)")
+ return
+ end
+
+ local profileKey
+ local profileData = {}
+
+ if profileType == "profile" then
+ if ElvDB.profileKeys then
+ profileKey = ElvDB.profileKeys[E.myname.." - "..E.myrealm]
+ end
+
+ profileData = E:CopyTable(profileData , ElvDB.profiles[profileKey])
+ profileData = E:RemoveTableDuplicates(profileData, P)
+ elseif profileType == "private" then
+ local privateProfileKey = E.myname.." - "..E.myrealm
+ profileKey = "private"
+
+ profileData = E:CopyTable(profileData, ElvPrivateDB.profiles[privateProfileKey])
+ profileData = E:RemoveTableDuplicates(profileData, V)
+ elseif profileType == "global" then
+ profileKey = "global"
+
+ profileData = E:CopyTable(profileData, ElvDB.global)
+ profileData = E:RemoveTableDuplicates(profileData, G)
+ elseif profileType == "filtersNP" then
+ profileKey = "filtersNP"
+
+ profileData["nameplates"] = {}
+ profileData["nameplates"]["filter"] = {}
+ profileData["nameplates"]["filter"] = E:CopyTable(profileData["nameplates"]["filter"], ElvDB.global.nameplates.filter)
+ profileData = E:RemoveTableDuplicates(profileData, G)
+ elseif profileType == "filtersUF" then
+ profileKey = "filtersUF"
+
+ profileData["unitframe"] = {}
+ profileData["unitframe"]["aurafilters"] = {}
+ profileData["unitframe"]["aurafilters"] = E:CopyTable(profileData["unitframe"]["aurafilters"], ElvDB.global.unitframe.aurafilters)
+ profileData["unitframe"]["buffwatch"] = {}
+ profileData["unitframe"]["buffwatch"] = E:CopyTable(profileData["unitframe"]["buffwatch"], ElvDB.global.unitframe.buffwatch)
+ profileData = E:RemoveTableDuplicates(profileData, G)
+ elseif profileType == "filtersAll" then
+ profileKey = "filtersAll"
+
+ profileData["nameplates"] = {}
+ profileData["nameplates"]["filter"] = {}
+ profileData["nameplates"]["filter"] = E:CopyTable(profileData["nameplates"]["filter"], ElvDB.global.nameplates.filter)
+ profileData["unitframe"] = {}
+ profileData["unitframe"]["aurafilters"] = {}
+ profileData["unitframe"]["aurafilters"] = E:CopyTable(profileData["unitframe"]["aurafilters"], ElvDB.global.unitframe.aurafilters)
+ profileData["unitframe"]["buffwatch"] = {}
+ profileData["unitframe"]["buffwatch"] = E:CopyTable(profileData["unitframe"]["buffwatch"], ElvDB.global.unitframe.buffwatch)
+ profileData = E:RemoveTableDuplicates(profileData, G)
+ end
+
+ return profileKey, profileData
+end
+
+local function GetProfileExport(profileType, exportFormat)
+ local profileExport, exportString
+ local profileKey, profileData = GetProfileData(profileType)
+
+ if not profileKey or not profileData or (profileData and type(profileData) ~= "table") then
+ E:Print("Error getting data from 'GetProfileData'")
+ return
+ end
+
+ if exportFormat == "text" then
+ local serialData = D:Serialize(profileData)
+
+ exportString = D:CreateProfileExport(serialData, profileType, profileKey)
+
+ local compressedData = LibCompress:Compress(exportString)
+ local encodedData = LibBase64:Encode(compressedData)
+ profileExport = encodedData
+ elseif exportFormat == "luaTable" then
+ exportString = E:TableToLuaString(profileData)
+ profileExport = D:CreateProfileExport(exportString, profileType, profileKey)
+ elseif exportFormat == "luaPlugin" then
+ profileExport = E:ProfileTableToPluginFormat(profileData, profileType)
+ end
+
+ return profileKey, profileExport
+end
+
+function D:CreateProfileExport(dataString, profileType, profileKey)
+ local returnString
+
+ if profileType == "profile" then
+ returnString = format("%s::%s::%s", dataString, profileType, profileKey)
+ else
+ returnString = format("%s::%s", dataString, profileType)
+ end
+
+ return returnString
+end
+
+function D:GetImportStringType(dataString)
+ local stringType = ""
+
+ if LibBase64:IsBase64(dataString) then
+ stringType = "Base64"
+ elseif find(dataString, "{") then
+ stringType = "Table"
+ end
+
+ return stringType
+end
+
+function D:Decode(dataString)
+ local profileInfo, profileType, profileKey, profileData, message
+ local stringType = self:GetImportStringType(dataString)
+
+ if stringType == "Base64" then
+ local decodedData = LibBase64:Decode(dataString)
+ local decompressedData, message = LibCompress:Decompress(decodedData)
+
+ if not decompressedData then
+ E:Print("Error decompressing data:", message)
+ return
+ end
+
+ local serializedData, success
+ serializedData, profileInfo = E:StringSplitMultiDelim(decompressedData, "^^::")
+
+ if not profileInfo then
+ E:Print("Error importing profile. String is invalid or corrupted!")
+ return
+ end
+
+ serializedData = format("%s%s", serializedData, "^^")
+ profileType, profileKey = E:StringSplitMultiDelim(profileInfo, "::")
+ success, profileData = D:Deserialize(serializedData)
+
+ if not success then
+ E:Print("Error deserializing:", profileData)
+ return
+ end
+ elseif stringType == "Table" then
+ local profileDataAsString
+ profileDataAsString, profileInfo = E:StringSplitMultiDelim(dataString, "}::")
+
+ if not profileInfo then
+ E:Print("Error extracting profile info. Invalid import string!")
+ return
+ end
+
+ if not profileDataAsString then
+ E:Print("Error extracting profile data. Invalid import string!")
+ return
+ end
+
+ profileDataAsString = format("%s%s", profileDataAsString, "}")
+ profileType, profileKey = E:StringSplitMultiDelim(profileInfo, "::")
+
+ local profileToTable = loadstring(format("%s %s", "return", profileDataAsString))
+ if profileToTable then
+ message, profileData = pcall(profileToTable)
+ end
+
+ if not profileData or type(profileData) ~= "table" then
+ E:Print("Error converting lua string to table:", message)
+ return
+ end
+ end
+
+ return profileType, profileKey, profileData
+end
+
+local function SetImportedProfile(profileType, profileKey, profileData, force)
+ D.profileType = nil
+ D.profileKey = nil
+ D.profileData = nil
+
+ if profileType == "profile" then
+ if not ElvDB.profiles[profileKey] or force then
+ if force and E.data.keys.profile == profileKey then
+ local tempKey = profileKey.."_Temp"
+ E.data.keys.profile = tempKey
+ end
+ ElvDB.profiles[profileKey] = profileData
+ E.data:SetProfile(profileKey)
+ else
+ D.profileType = profileType
+ D.profileKey = profileKey
+ D.profileData = profileData
+ E:StaticPopup_Show("IMPORT_PROFILE_EXISTS")
+
+ return
+ end
+ elseif profileType == "private" then
+ local profileKey = ElvPrivateDB.profileKeys[E.myname.." - "..E.myrealm]
+ ElvPrivateDB.profiles[profileKey] = profileData
+ E:StaticPopup_Show("IMPORT_RL")
+
+ elseif profileType == "global" then
+ E:CopyTable(ElvDB.global, profileData)
+ E:StaticPopup_Show("IMPORT_RL")
+ elseif profileType == "filtersNP" then
+ E:CopyTable(ElvDB.global.nameplates, profileData.nameplates)
+ elseif profileType == "filtersUF" then
+ E:CopyTable(ElvDB.global.unitframe, profileData.unitframe)
+ elseif profileType == "filtersAll" then
+ E:CopyTable(ElvDB.global.nameplates, profileData.nameplates)
+ E:CopyTable(ElvDB.global.unitframe, profileData.unitframe)
+ end
+
+ E:UpdateAll(true)
+end
+
+function D:ExportProfile(profileType, exportFormat)
+ if not profileType or not exportFormat then
+ E:Print("Bad argument to 'ExportProfile' (string expected)")
+ return
+ end
+
+ local profileKey, profileExport = GetProfileExport(profileType, exportFormat)
+ return profileKey, profileExport
+end
+
+function D:ImportProfile(dataString)
+ print(self)
+ local profileType, profileKey, profileData = self:Decode(dataString)
+
+ if not profileData or type(profileData) ~= "table" then
+ E:Print("Error: something went wrong when converting string to table!")
+ return
+ end
+
+ if profileType and ((profileType == "profile" and profileKey) or profileType ~= "profile") then
+ SetImportedProfile(profileType, profileKey, profileData)
+ end
+
+ return true
+end
+
+E.PopupDialogs["DISTRIBUTOR_SUCCESS"] = {
+ text = L["Your profile was successfully recieved by the player."],
+ whileDead = 1,
+ hideOnEscape = 1,
+ button1 = OKAY,
+}
+
+E.PopupDialogs["DISTRIBUTOR_WAITING"] = {
+ text = L["Profile request sent. Waiting for response from player."],
+ whileDead = 1,
+ hideOnEscape = 1,
+ timeout = 35,
+}
+
+E.PopupDialogs["DISTRIBUTOR_REQUEST_DENIED"] = {
+ text = L["Request was denied by user."],
+ whileDead = 1,
+ hideOnEscape = 1,
+ button1 = OKAY,
+}
+
+E.PopupDialogs["DISTRIBUTOR_FAILED"] = {
+ text = L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"],
+ whileDead = 1,
+ hideOnEscape = 1,
+ button1 = OKAY,
+}
+
+E.PopupDialogs["DISTRIBUTOR_RESPONSE"] = {}
+E.PopupDialogs["DISTRIBUTOR_CONFIRM"] = {}
+
+E.PopupDialogs["IMPORT_PROFILE_EXISTS"] = {
+ text = L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ hasEditBox = 1,
+ editBoxWidth = 350,
+ maxLetters = 127,
+ OnAccept = function(self)
+ local profileType = D.profileType
+ local profileKey = self.editBox:GetText()
+ local profileData = D.profileData
+ SetImportedProfile(profileType, profileKey, profileData, true)
+ end,
+ EditBoxOnTextChanged = function(self)
+ if self:GetText() == "" then
+ self:GetParent().button1:Disable()
+ else
+ self:GetParent().button1:Enable()
+ end
+ end,
+ OnShow = function() this.editBox:SetText(D.profileKey) this.editBox:SetFocus() end,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = true,
+ preferredIndex = 3
+}
+
+E.PopupDialogs["IMPORT_RL"] = {
+ text = L["You have imported settings which may require a UI reload to take effect. Reload now?"],
+ button1 = ACCEPT,
+ button2 = CANCEL,
+ OnAccept = ReloadUI,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = false,
+ preferredIndex = 3
+}
+
+local function InitializeCallback()
+ D:Initialize()
+end
+
+E:RegisterModule(D:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Core/dropdown.lua b/ElvUI/Core/dropdown.lua
new file mode 100644
index 0000000..062b1ad
--- /dev/null
+++ b/ElvUI/Core/dropdown.lua
@@ -0,0 +1,89 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local tinsert = tinsert
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local ToggleFrame = ToggleFrame
+local GetCursorPosition = GetCursorPosition
+
+local PADDING = 10
+local BUTTON_HEIGHT = 16
+local BUTTON_WIDTH = 135
+
+local function OnClick(btn)
+ btn.func()
+
+ btn:GetParent():Hide()
+end
+
+local function OnEnter(btn)
+ btn.hoverTex:Show()
+end
+
+local function OnLeave(btn)
+ btn.hoverTex:Hide()
+end
+
+function E:DropDown(list, frame, xOffset, yOffset)
+ if not frame.buttons then
+ frame.buttons = {}
+ frame:SetFrameStrata("DIALOG")
+ frame:SetClampedToScreen(true)
+ tinsert(UISpecialFrames, frame:GetName())
+ frame:Hide()
+ end
+
+ xOffset = xOffset or 0
+ yOffset = yOffset or 0
+
+ for i = 1, getn(frame.buttons) do
+ frame.buttons[i]:Hide()
+ end
+
+ for i = 1, getn(list) do
+ if not frame.buttons[i] then
+ frame.buttons[i] = CreateFrame("Button", nil, frame)
+
+ frame.buttons[i].hoverTex = frame.buttons[i]:CreateTexture(nil, "OVERLAY")
+ frame.buttons[i].hoverTex:SetAllPoints()
+ frame.buttons[i].hoverTex:SetTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]])
+ frame.buttons[i].hoverTex:SetBlendMode("ADD")
+ frame.buttons[i].hoverTex:Hide()
+
+ frame.buttons[i].text = frame.buttons[i]:CreateFontString(nil, "BORDER")
+ frame.buttons[i].text:SetAllPoints()
+ frame.buttons[i].text:FontTemplate()
+ frame.buttons[i].text:SetJustifyH("LEFT")
+
+ frame.buttons[i]:SetScript("OnEnter", OnEnter)
+ frame.buttons[i]:SetScript("OnLeave", OnLeave)
+ end
+
+ frame.buttons[i]:Show()
+ frame.buttons[i]:SetHeight(BUTTON_HEIGHT)
+ frame.buttons[i]:SetWidth(BUTTON_WIDTH)
+ frame.buttons[i].text:SetText(list[i].text)
+ frame.buttons[i].func = list[i].func
+ frame.buttons[i]:SetScript("OnClick", OnClick)
+
+ if i == 1 then
+ frame.buttons[i]:SetPoint("TOPLEFT", frame, "TOPLEFT", PADDING, -PADDING)
+ else
+ frame.buttons[i]:SetPoint("TOPLEFT", frame.buttons[i-1], "BOTTOMLEFT")
+ end
+ end
+
+ frame:SetHeight((getn(list) * BUTTON_HEIGHT) + PADDING * 2)
+ frame:SetWidth(BUTTON_WIDTH + PADDING * 2)
+
+ local UIScale = UIParent:GetScale()
+ local x, y = GetCursorPosition()
+ x = x/UIScale
+ y = y/UIScale
+ frame:ClearAllPoints()
+ frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x + xOffset, y + yOffset)
+
+ ToggleFrame(frame)
+end
\ No newline at end of file
diff --git a/ElvUI/Core/fonts.lua b/ElvUI/Core/fonts.lua
new file mode 100644
index 0000000..fb9dbde
--- /dev/null
+++ b/ElvUI/Core/fonts.lua
@@ -0,0 +1,90 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+
+--WoW API / Variables
+local SetCVar = SetCVar
+
+local function SetFont(obj, font, size, style, r, g, b, sr, sg, sb, sox, soy)
+ if(not obj) then return end
+
+ obj:SetFont(font, size, style)
+ if sr and sg and sb then obj:SetShadowColor(sr, sg, sb) end
+ if sox and soy then obj:SetShadowOffset(sox, soy) end
+ if r and g and b then obj:SetTextColor(r, g, b)
+ elseif r then obj:SetAlpha(r) end
+end
+
+function E:UpdateBlizzardFonts()
+ local NORMAL = self["media"].normFont
+ local COMBAT = LSM:Fetch("font", self.private.general.dmgfont)
+ local NUMBER = self["media"].normFont
+ local NAMEFONT = LSM:Fetch("font", self.private.general.namefont)
+ local MONOCHROME = ""
+
+ UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = 12
+ CHAT_FONT_HEIGHTS = {10, 12, 13, 14, 15, 16, 17, 18, 19, 20}
+
+ UNIT_NAME_FONT = NAMEFONT
+ NAMEPLATE_FONT = NAMEFONT
+ DAMAGE_TEXT_FONT = COMBAT
+ STANDARD_TEXT_FONT = NORMAL
+
+ if self.db.general.font == "Homespun" then
+ MONOCHROME = "MONOCHROME"
+ end
+
+ if self.eyefinity then
+ -- damage are huge on eyefinity, so we disable it
+ InterfaceOptionsCombatTextPanelTargetDamage:Hide()
+ InterfaceOptionsCombatTextPanelPeriodicDamage:Hide()
+ InterfaceOptionsCombatTextPanelPetDamage:Hide()
+ InterfaceOptionsCombatTextPanelHealing:Hide()
+ SetCVar("CombatLogPeriodicSpells",0)
+ SetCVar("PetMeleeDamage",0)
+ SetCVar("CombatDamage",0)
+ SetCVar("CombatHealing",0)
+
+ -- set an invisible font for xp, honor kill, etc
+ local INVISIBLE = "Interface\\Addons\\ElvUI\\Media\\Fonts\\Invisible.ttf"
+ COMBAT = INVISIBLE
+ end
+
+ if(self.private.general.replaceBlizzFonts) then
+ SetFont(SystemFont, NORMAL, self.db.general.fontSize);
+ SetFont(GameFontNormal, NORMAL, self.db.general.fontSize);
+ SetFont(GameFontNormalSmall, NORMAL, self.db.general.fontSize);
+ SetFont(GameFontNormalLarge, NORMAL, self.db.general.fontSize);
+ SetFont(GameFontNormalHuge, NORMAL, 25, MONOCHROME .. "OUTLINE");
+ SetFont(BossEmoteNormalHuge, NORMAL, 25, MONOCHROME .. "OUTLINE");
+ SetFont(GameFontBlack, NORMAL, self.db.general.fontSize);
+ SetFont(NumberFontNormal, NUMBER, self.db.general.fontSize, MONOCHROME .. "OUTLINE");
+ SetFont(NumberFontNormalSmall, NUMBER, self.db.general.fontSize);
+ SetFont(NumberFontNormalLarge, NUMBER, self.db.general.fontSize);
+ SetFont(NumberFontNormalHuge, NUMBER, self.db.general.fontSize);
+ SetFont(ChatFontNormal, NORMAL, self.db.general.fontSize);
+ SetFont(ChatFontSmall, NORMAL, self.db.general.fontSize);
+ SetFont(QuestTitleFont, NORMAL, self.db.general.fontSize + 8);
+ SetFont(QuestFont, NORMAL, self.db.general.fontSize);
+ SetFont(QuestFontHighlight, NORMAL, self.db.general.fontSize);
+ SetFont(ItemTextFontNormal, NORMAL, self.db.general.fontSize);
+ SetFont(ItemTextFontNormal, NORMAL, self.db.general.fontSize);
+ SetFont(MailTextFontNormal, NORMAL, self.db.general.fontSize);
+ SetFont(SubSpellFont, NORMAL, self.db.general.fontSize);
+ SetFont(DialogButtonNormalText, NORMAL, self.db.general.fontSize);
+ SetFont(ZoneTextFont, NORMAL, 32, MONOCHROME .. "OUTLINE");
+ SetFont(SubZoneTextFont, NORMAL, 25, MONOCHROME .. "OUTLINE");
+ SetFont(PVPInfoTextFont, NORMAL, 22, MONOCHROME .. "OUTLINE");
+ SetFont(TextStatusBarText, NORMAL, self.db.general.fontSize);
+ SetFont(TextStatusBarTextSmall, NORMAL, self.db.general.fontSize);
+ -- SetFont(GameTooltipText, NORMAL, self.db.general.fontSize);
+ -- SetFont(GameTooltipTextSmall, NORMAL, self.db.general.fontSize);
+ -- SetFont(GameTooltipHeaderText, NORMAL, self.db.general.fontSize);
+ SetFont(WorldMapTextFont, NORMAL, 32, MONOCHROME .. "OUTLINE");
+ SetFont(InvoiceTextFontNormal, NORMAL, self.db.general.fontSize);
+ SetFont(InvoiceTextFontSmall, NORMAL, self.db.general.fontSize);
+ SetFont(CombatTextFont, COMBAT, 25, MONOCHROME .. "OUTLINE");
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Core/install.lua b/ElvUI/Core/install.lua
new file mode 100644
index 0000000..500c4c7
--- /dev/null
+++ b/ElvUI/Core/install.lua
@@ -0,0 +1,1036 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local format = format
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local IsAddOnLoaded = IsAddOnLoaded
+local GetScreenWidth = GetScreenWidth
+local SetCVar = SetCVar
+local PlaySoundFile = PlaySoundFile
+local ReloadUI = ReloadUI
+local UIFrameFadeOut = UIFrameFadeOut
+local ChatFrame_AddMessageGroup = ChatFrame_AddMessageGroup
+local ChatFrame_RemoveAllMessageGroups = ChatFrame_RemoveAllMessageGroups
+local ChatFrame_AddChannel = ChatFrame_AddChannel
+local ChatFrame_RemoveChannel = ChatFrame_RemoveChannel
+local ChangeChatColor = ChangeChatColor
+local FCF_SetLocked = FCF_SetLocked
+local FCF_DockFrame, FCF_UnDockFrame = FCF_DockFrame, FCF_UnDockFrame
+local FCF_OpenNewWindow = FCF_OpenNewWindow
+local FCF_SetWindowName = FCF_SetWindowName
+local FCF_SetChatWindowFontSize = FCF_SetChatWindowFontSize
+local CLASS, CONTINUE, PREV = CLASS, CONTINUE, PREV
+local NUM_CHAT_WINDOWS = NUM_CHAT_WINDOWS
+local LOOT, GENERAL, TRADE = LOOT, GENERAL, TRADE
+local GUILD_EVENT_LOG = GUILD_EVENT_LOG
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+
+local CURRENT_PAGE = 0
+local MAX_PAGE = 8
+
+local function FCF_ResetChatWindows()
+ ChatFrame1:ClearAllPoints()
+ ChatFrame1:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 32, 95)
+ ChatFrame1:SetWidth(430)
+ ChatFrame1:SetHeight(120)
+ ChatFrame1.isInitialized = 0
+ FCF_SetButtonSide(ChatFrame1, "left")
+ FCF_SetChatWindowFontSize(ChatFrame1, 14)
+ FCF_SetWindowName(ChatFrame1, GENERAL)
+ FCF_SetWindowColor(ChatFrame1, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b)
+ FCF_SetWindowAlpha(ChatFrame1, DEFAULT_CHATFRAME_ALPHA)
+ FCF_UnDockFrame(ChatFrame1)
+ FCF_ValidateChatFramePosition(ChatFrame1)
+ ChatFrame_RemoveAllChannels(ChatFrame1)
+ ChatFrame_RemoveAllMessageGroups(ChatFrame1)
+ DEFAULT_CHAT_FRAME = ChatFrame1
+ SELECTED_CHAT_FRAME = ChatFrame1
+ ChatFrameEditBox.chatFrame = DEFAULT_CHAT_FRAME
+ DEFAULT_CHAT_FRAME.editBox = ChatFrameEditBox
+ DEFAULT_CHAT_FRAME.chatframe = DEFAULT_CHAT_FRAME
+
+ FCF_SetChatWindowFontSize(ChatFrame2, 14)
+ FCF_SetWindowName(ChatFrame2, COMBAT_LOG)
+ FCF_SetWindowColor(ChatFrame2, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b)
+ FCF_SetWindowAlpha(ChatFrame2, DEFAULT_CHATFRAME_ALPHA)
+ ChatFrame_RemoveAllChannels(ChatFrame2)
+ ChatFrame_RemoveAllMessageGroups(ChatFrame2)
+ FCF_UnDockFrame(ChatFrame2)
+ ChatFrame2.isInitialized = 0
+
+ for i = 2, NUM_CHAT_WINDOWS do
+ local chatFrame = _G["ChatFrame"..i]
+ chatFrame.isInitialized = 0
+ FCF_SetTabPosition(chatFrame, 0)
+ FCF_Close(chatFrame)
+ FCF_UnDockFrame(chatFrame)
+ FCF_SetChatWindowFontSize(chatFrame, 14)
+ FCF_SetWindowName(chatFrame, "")
+ FCF_SetWindowColor(chatFrame, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b)
+ FCF_SetWindowAlpha(chatFrame, DEFAULT_CHATFRAME_ALPHA)
+ ChatFrame_RemoveAllChannels(chatFrame)
+ ChatFrame_RemoveAllMessageGroups(chatFrame)
+ end
+
+ ChatFrame1.init = 0
+ FCF_DockFrame(ChatFrame1, 1)
+ FCF_DockFrame(ChatFrame2, 2)
+end
+
+local function FCF_StopDragging(chatFrame)
+ if not chatFrame then
+ return
+ end
+
+ chatFrame:StopMovingOrSizing()
+
+ local activeDockRegion = FCF_GetActiveDockRegion()
+ if activeDockRegion then
+ FCF_DockFrame(chatFrame, activeDockRegion, true)
+ else
+ FCF_SetTabPosition(chatFrame, 0)
+ FCF_ValidateChatFramePosition(chatFrame)
+ FCF_SelectDockFrame(DOCKED_CHAT_FRAMES[1])
+ end
+
+ MOVING_CHATFRAME = nil
+end
+
+local function SetupChat()
+ InstallStepComplete.message = L["Chat Set"]
+ InstallStepComplete:Show()
+ FCF_ResetChatWindows()
+ FCF_SetLocked(ChatFrame1, 1)
+ FCF_DockFrame(ChatFrame2)
+ FCF_SetLocked(ChatFrame2, 1)
+
+ FCF_OpenNewWindow(LOOT)
+ FCF_UnDockFrame(ChatFrame3)
+ FCF_SetLocked(ChatFrame3, 1)
+ ChatFrame3:Show()
+
+ for i = 1, NUM_CHAT_WINDOWS do
+ local frame = _G[format("ChatFrame%s", i)]
+
+ -- move general bottom left
+ if i == 1 then
+ frame:ClearAllPoints()
+ frame:SetPoint("BOTTOMLEFT", LeftChatToggleButton, "TOPLEFT", 1, 3)
+ elseif i == 3 then
+ frame:ClearAllPoints()
+ frame:SetPoint("BOTTOMLEFT", RightChatDataPanel, "TOPLEFT", 1, 3)
+ end
+
+ FCF_StopDragging(frame)
+
+ -- set default Elvui font size
+ FCF_SetChatWindowFontSize(frame, 12)
+
+ -- rename windows general because moved to chat #3
+ if i == 1 then
+ FCF_SetWindowName(frame, GENERAL)
+ elseif i == 2 then
+ FCF_SetWindowName(frame, GUILD_EVENT_LOG)
+ elseif i == 3 then
+ FCF_SetWindowName(frame, LOOT.." / "..TRADE)
+ end
+ end
+
+ ChatFrame_RemoveAllMessageGroups(ChatFrame1)
+ ChatFrame_AddMessageGroup(ChatFrame1, "SAY")
+ ChatFrame_AddMessageGroup(ChatFrame1, "EMOTE")
+ ChatFrame_AddMessageGroup(ChatFrame1, "YELL")
+ ChatFrame_AddMessageGroup(ChatFrame1, "GUILD")
+ ChatFrame_AddMessageGroup(ChatFrame1, "OFFICER")
+ ChatFrame_AddMessageGroup(ChatFrame1, "WHISPER")
+ ChatFrame_AddMessageGroup(ChatFrame1, "MONSTER_SAY")
+ ChatFrame_AddMessageGroup(ChatFrame1, "MONSTER_EMOTE")
+ ChatFrame_AddMessageGroup(ChatFrame1, "MONSTER_YELL")
+ ChatFrame_AddMessageGroup(ChatFrame1, "MONSTER_BOSS_EMOTE")
+ ChatFrame_AddMessageGroup(ChatFrame1, "PARTY")
+ ChatFrame_AddMessageGroup(ChatFrame1, "PARTY_LEADER")
+ ChatFrame_AddMessageGroup(ChatFrame1, "RAID")
+ ChatFrame_AddMessageGroup(ChatFrame1, "RAID_LEADER")
+ ChatFrame_AddMessageGroup(ChatFrame1, "RAID_WARNING")
+ ChatFrame_AddMessageGroup(ChatFrame1, "BATTLEGROUND")
+ ChatFrame_AddMessageGroup(ChatFrame1, "BATTLEGROUND_LEADER")
+ ChatFrame_AddMessageGroup(ChatFrame1, "BG_HORDE")
+ ChatFrame_AddMessageGroup(ChatFrame1, "BG_ALLIANCE")
+ ChatFrame_AddMessageGroup(ChatFrame1, "BG_NEUTRAL")
+ ChatFrame_AddMessageGroup(ChatFrame1, "SYSTEM")
+ ChatFrame_AddMessageGroup(ChatFrame1, "ERRORS")
+ ChatFrame_AddMessageGroup(ChatFrame1, "AFK")
+ ChatFrame_AddMessageGroup(ChatFrame1, "DND")
+ ChatFrame_AddMessageGroup(ChatFrame1, "IGNORED")
+ ChatFrame_AddMessageGroup(ChatFrame1, "CHANNEL")
+
+ ChatFrame_RemoveAllMessageGroups(ChatFrame3)
+ ChatFrame_AddMessageGroup(ChatFrame3, "COMBAT_FACTION_CHANGE")
+ ChatFrame_AddMessageGroup(ChatFrame3, "SKILL")
+ ChatFrame_AddMessageGroup(ChatFrame3, "LOOT")
+ ChatFrame_AddMessageGroup(ChatFrame3, "MONEY")
+ ChatFrame_AddMessageGroup(ChatFrame3, "COMBAT_XP_GAIN")
+ ChatFrame_AddMessageGroup(ChatFrame3, "COMBAT_HONOR_GAIN")
+ ChatFrame_AddMessageGroup(ChatFrame3, "COMBAT_GUILD_XP_GAIN")
+ ChatFrame_AddChannel(ChatFrame1, GENERAL)
+ ChatFrame_RemoveChannel(ChatFrame1, L["Trade"])
+ ChatFrame_AddChannel(ChatFrame3, L["Trade"])
+
+ --Adjust Chat Colors
+ --General
+ ChangeChatColor("CHANNEL1", 195/255, 230/255, 232/255)
+ --Trade
+ ChangeChatColor("CHANNEL2", 232/255, 158/255, 121/255)
+ --Local Defense
+ ChangeChatColor("CHANNEL3", 232/255, 228/255, 121/255)
+
+ if E.Chat then
+ E.Chat:PositionChat(true)
+ if E.db["RightChatPanelFaded"] then
+ RightChatToggleButton:Click()
+ end
+
+ if E.db["LeftChatPanelFaded"] then
+ LeftChatToggleButton:Click()
+ end
+ end
+end
+
+local function SetupCVars()
+ -- SetCVar("screenshotQuality", 10)
+ -- SetCVar("showNewbieTips", 0)
+ SetCVar("showLootSpam", 1)
+ SetCVar("UberTooltips", 1)
+ -- SetCVar("alwaysShowActionBars", 1)
+ -- SetCVar("lockActionBars", 1)
+
+ SetActionBarToggles(1, 0, 1, 1)
+ TutorialFrame_HideAllAlerts()
+ ClearTutorials()
+
+ InstallStepComplete.message = L["CVars Set"]
+ InstallStepComplete:Show()
+end
+
+function E:GetColor(r, b, g, a)
+ return { r = r, b = b, g = g, a = a }
+end
+
+function E:SetupTheme(theme, noDisplayMsg)
+ local classColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
+ E.private.theme = theme
+
+ --Set colors
+ if theme == "classic" then
+ E.db.general.bordercolor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(.31, .31, .31))
+ E.db.general.backdropcolor = E:GetColor(.1, .1, .1)
+ E.db.general.backdropfadecolor = E:GetColor(.06, .06, .06, .8)
+
+ E.db.unitframe.colors.borderColor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(.31, .31, .31))
+ E.db.unitframe.colors.healthclass = false
+ E.db.unitframe.colors.health = E:GetColor(.31, .31, .31)
+ E.db.unitframe.colors.auraBarBuff = E:GetColor(.31, .31, .31)
+ E.db.unitframe.colors.castColor = E:GetColor(.31, .31, .31)
+ E.db.unitframe.colors.castClassColor = false
+ elseif theme == "class" then
+ E.db.general.bordercolor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(.31, .31, .31))
+ E.db.general.backdropcolor = E:GetColor(.1, .1, .1)
+ E.db.general.backdropfadecolor = E:GetColor(.06, .06, .06, .8)
+ E.db.unitframe.colors.borderColor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(.31, .31, .31))
+ E.db.unitframe.colors.auraBarBuff = E:GetColor(classColor.r, classColor.b, classColor.g)
+ E.db.unitframe.colors.healthclass = true
+ E.db.unitframe.colors.castClassColor = true
+ else
+ E.db.general.bordercolor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(.1, .1, .1))
+ E.db.general.backdropcolor = E:GetColor(.1, .1, .1)
+ E.db.general.backdropfadecolor = E:GetColor(.054, .054, .054, .8)
+ E.db.unitframe.colors.borderColor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(.1, .1, .1))
+ E.db.unitframe.colors.auraBarBuff = E:GetColor(.1, .1, .1)
+ E.db.unitframe.colors.healthclass = false
+ E.db.unitframe.colors.health = E:GetColor(.1, .1, .1)
+ E.db.unitframe.colors.castColor = E:GetColor(.1, .1, .1)
+ E.db.unitframe.colors.castClassColor = false
+ end
+
+ --Value Color
+ if theme == "class" then
+ E.db.general.valuecolor = E:GetColor(classColor.r, classColor.b, classColor.g)
+ else
+ E.db.general.valuecolor = E:GetColor(.09, .819, .513)
+ end
+
+ if not noDisplayMsg then
+ E:UpdateAll(true)
+ end
+
+ if InstallStatus then
+ if InstallStepComplete and not noDisplayMsg then
+ InstallStepComplete.message = L["Theme Set"]
+ InstallStepComplete:Show()
+ end
+ end
+end
+
+function E:SetupResolution(noDataReset)
+ if not noDataReset then
+ E:ResetMovers("")
+ end
+
+ if self == "low" then
+ if not E.db.movers then E.db.movers = {} end
+ if not noDataReset then
+ E.db.chat.panelWidth = 400
+ E.db.chat.panelHeight = 180
+
+ E.db.bags.bagWidth = 394
+ E.db.bags.bankWidth = 394
+
+ E:CopyTable(E.db.actionbar, P.actionbar)
+
+ E.db.actionbar.bar1.heightMult = 2
+ E.db.actionbar.bar2.enabled = true
+ E.db.actionbar.bar3.enabled = false
+ E.db.actionbar.bar5.enabled = false
+ end
+
+ if not noDataReset then
+ E.db.auras.wrapAfter = 10
+ end
+
+ E.db.movers.ElvAB_2 = "CENTER,ElvUIParent,BOTTOM,0,56.18"
+
+ if not noDataReset then
+ E:CopyTable(E.db.unitframe.units, P.unitframe.units)
+
+ E.db.unitframe.fontSize = 11
+
+ E.db.unitframe.units.player.width = 200
+ E.db.unitframe.units.player.castbar.width = 200
+ E.db.unitframe.units.player.classbar.fill = "fill"
+ E.db.unitframe.units.player.health.text_format = "[healthcolor][health:current]"
+
+ E.db.unitframe.units.target.width = 200
+ E.db.unitframe.units.target.castbar.width = 200
+ E.db.unitframe.units.target.health.text_format = "[healthcolor][health:current]"
+
+ E.db.unitframe.units.pet.power.enable = false
+ E.db.unitframe.units.pet.width = 200
+ E.db.unitframe.units.pet.height = 26
+
+ E.db.unitframe.units.targettarget.debuffs.enable = false
+ E.db.unitframe.units.targettarget.power.enable = false
+ E.db.unitframe.units.targettarget.width = 200
+ E.db.unitframe.units.targettarget.height = 26
+
+ E.db.unitframe.units.arena.width = 200
+ E.db.unitframe.units.arena.castbar.width = 200
+ end
+
+ local isPixel = E.private.general.pixelPerfect
+ local xOffset = isPixel and 103 or 106
+ local yOffset = isPixel and 125 or 135
+ local yOffsetSmall = isPixel and 76 or 80
+
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,"..-xOffset..","..yOffset
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,"..xOffset..","..yOffsetSmall
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,"..xOffset..","..yOffset
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,"..-xOffset..","..yOffsetSmall
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+
+ E.db.lowresolutionset = true
+ elseif not noDataReset then
+ E.db.chat.panelWidth = P.chat.panelWidth
+ E.db.chat.panelHeight = P.chat.panelHeight
+
+ E.db.bags.bagWidth = P.bags.bagWidth
+ E.db.bags.bankWidth = P.bags.bankWidth
+
+ E:CopyTable(E.db.actionbar, P.actionbar)
+ E:CopyTable(E.db.unitframe.units, P.unitframe.units)
+ E.db.auras.wrapAfter = P.auras.wrapAfter
+
+ E.db.lowresolutionset = nil
+ end
+
+ if not noDataReset and E.private.theme then
+ E:SetupTheme(E.private.theme, true)
+ end
+
+ E:UpdateAll(true)
+
+ if InstallStepComplete and not noDataReset then
+ InstallStepComplete.message = L["Resolution Style Set"]
+ InstallStepComplete:Show()
+ end
+end
+
+function E:SetupLayout(layout, noDataReset)
+ --Unitframes
+ if not noDataReset then
+ E:CopyTable(E.db.unitframe.units, P.unitframe.units)
+ end
+
+ if not noDataReset then
+ E:ResetMovers("")
+ if not E.db.movers then E.db.movers = {} end
+
+ E.db.actionbar.bar2.enabled = E.db.lowresolutionset
+ if E.PixelMode then
+ E.db.movers.ElvAB_2 = "BOTTOM,ElvUIParent,BOTTOM,0,38"
+ else
+ E.db.movers.ElvAB_2 = "BOTTOM,ElvUIParent,BOTTOM,0,40"
+ end
+ if not E.db.lowresolutionset then
+ E.db.actionbar.bar3.buttons = 6
+ E.db.actionbar.bar5.buttons = 6
+ E.db.actionbar.bar4.enabled = true
+ end
+ end
+
+ if layout == "healer" then
+ if not IsAddOnLoaded("Clique") then
+ E:StaticPopup_Show("CLIQUE_ADVERT")
+ end
+
+ if not noDataReset then
+ E.db.unitframe.units.raid.horizontalSpacing = 9
+ E.db.unitframe.units.raid.rdebuffs.enable = false
+ E.db.unitframe.units.raid.verticalSpacing = 9
+ E.db.unitframe.units.raid.debuffs.sizeOverride = 16
+ E.db.unitframe.units.raid.debuffs.enable = true
+ E.db.unitframe.units.raid.debuffs.anchorPoint = "TOPRIGHT"
+ E.db.unitframe.units.raid.debuffs.xOffset = -4
+ E.db.unitframe.units.raid.debuffs.yOffset = -7
+ E.db.unitframe.units.raid.height = 45
+ E.db.unitframe.units.raid.buffs.noConsolidated = false
+ E.db.unitframe.units.raid.buffs.xOffset = 50
+ E.db.unitframe.units.raid.buffs.yOffset = -6
+ E.db.unitframe.units.raid.buffs.clickThrough = true
+ E.db.unitframe.units.raid.buffs.noDuration = false
+ E.db.unitframe.units.raid.buffs.playerOnly = false
+ E.db.unitframe.units.raid.buffs.perrow = 1
+ E.db.unitframe.units.raid.buffs.useFilter = "TurtleBuffs"
+ E.db.unitframe.units.raid.buffs.sizeOverride = 22
+ E.db.unitframe.units.raid.buffs.useBlacklist = false
+ E.db.unitframe.units.raid.buffs.enable = true
+ E.db.unitframe.units.raid.growthDirection = "LEFT_UP"
+
+ E.db.unitframe.units.party.growthDirection = "LEFT_UP"
+ E.db.unitframe.units.party.horizontalSpacing = 9
+ E.db.unitframe.units.party.verticalSpacing = 9
+ E.db.unitframe.units.party.debuffs.sizeOverride = 16
+ E.db.unitframe.units.party.debuffs.enable = true
+ E.db.unitframe.units.party.debuffs.anchorPoint = "TOPRIGHT"
+ E.db.unitframe.units.party.debuffs.xOffset = -4
+ E.db.unitframe.units.party.debuffs.yOffset = -7
+ E.db.unitframe.units.party.height = 45
+ E.db.unitframe.units.party.buffs.noConsolidated = false
+ E.db.unitframe.units.party.buffs.xOffset = 50
+ E.db.unitframe.units.party.buffs.yOffset = -6
+ E.db.unitframe.units.party.buffs.clickThrough = true
+ E.db.unitframe.units.party.buffs.noDuration = false
+ E.db.unitframe.units.party.buffs.playerOnly = false
+ E.db.unitframe.units.party.buffs.perrow = 1
+ E.db.unitframe.units.party.buffs.useFilter = "TurtleBuffs"
+ E.db.unitframe.units.party.buffs.sizeOverride = 22
+ E.db.unitframe.units.party.buffs.useBlacklist = false
+ E.db.unitframe.units.party.buffs.enable = true
+ E.db.unitframe.units.party.roleIcon.position = "BOTTOMRIGHT"
+ E.db.unitframe.units.party.health.text_format = "[healthcolor][health:deficit]"
+ E.db.unitframe.units.party.health.position = "BOTTOM"
+ E.db.unitframe.units.party.GPSArrow.size = 40
+ E.db.unitframe.units.party.width = 80
+ E.db.unitframe.units.party.height = 45
+ E.db.unitframe.units.party.name.text_format = "[namecolor][name:short]"
+ E.db.unitframe.units.party.name.position = "TOP"
+ E.db.unitframe.units.party.power.text_format = ""
+
+ E.db.unitframe.units.raid40.height = 30
+ E.db.unitframe.units.raid40.growthDirection = "LEFT_UP"
+
+ E.db.unitframe.units.party.health.frequentUpdates = true
+ E.db.unitframe.units.raid.health.frequentUpdates = true
+ E.db.unitframe.units.raid40.health.frequentUpdates = true
+
+ E.db.unitframe.units.party.healPrediction = true
+ E.db.unitframe.units.raid.healPrediction = true
+ E.db.unitframe.units.raid40.healPrediction = true
+
+ E.db.unitframe.units.player.castbar.insideInfoPanel = false
+ E.db.actionbar.bar2.enabled = true
+ if not E.db.lowresolutionset then
+ E.db.actionbar.bar3.buttons = 12
+ E.db.actionbar.bar5.buttons = 12
+ E.db.actionbar.bar4.enabled = false
+ if not E.PixelMode then
+ E.db.actionbar.bar1.heightMult = 2
+ end
+ end
+ end
+
+ if not E.db.movers then E.db.movers = {} end
+ local xOffset = ((GetScreenWidth() - E.diffGetLeft - E.diffGetRight) * 0.34375)
+
+ if E.PixelMode then
+ E.db.movers.ElvAB_3 = "BOTTOM,ElvUIParent,BOTTOM,312,4"
+ E.db.movers.ElvAB_5 = "BOTTOM,ElvUIParent,BOTTOM,-312,4"
+ E.db.movers.ElvUF_PartyMover = "BOTTOMRIGHT,ElvUIParent,BOTTOMLEFT,"..xOffset..",450"
+ E.db.movers.ElvUF_RaidMover = "BOTTOMRIGHT,ElvUIParent,BOTTOMLEFT,"..xOffset..",450"
+
+ E.db.movers.ElvUF_Raid40Mover = "BOTTOMRIGHT,ElvUIParent,BOTTOMLEFT,"..xOffset..",450"
+
+ if not E.db.lowresolutionset then
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,278,132"
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-278,132"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,0,176"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,0,132"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,432"
+ else
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-102,182"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,102,182"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,102,120"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-102,120"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+ end
+ else
+ E.db.movers.ElvAB_3 = "BOTTOM,ElvUIParent,BOTTOM,332,4"
+ E.db.movers.ElvAB_5 = "BOTTOM,ElvUIParent,BOTTOM,-332,4"
+ E.db.movers.ElvUF_PartyMover = "BOTTOMRIGHT,ElvUIParent,BOTTOMLEFT,"..xOffset..",450"
+ E.db.movers.ElvUF_RaidMover = "BOTTOMRIGHT,ElvUIParent,BOTTOMLEFT,"..xOffset..",450"
+ E.db.movers.ElvUF_Raid40Mover = "BOTTOMRIGHT,ElvUIParent,BOTTOMLEFT,"..xOffset..",450"
+
+ if not E.db.lowresolutionset then
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,307,145"
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-307,145"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,0,186"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,0,145"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,432"
+ else
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-118,182"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,118,182"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,118,120"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-118,120"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+ end
+ end
+ elseif E.db.lowresolutionset then
+ if not E.db.movers then E.db.movers = {} end
+ if E.PixelMode then
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-102,135"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,102,135"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,102,80"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-102,80"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+ else
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-118,142"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,118,142"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,118,84"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-118,84"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+ end
+ end
+
+ if layout ~= "healer" and not E.db.lowresolutionset then
+ E.db.actionbar.bar1.heightMult = 1
+ end
+
+ if E.db.lowresolutionset and not noDataReset then
+ E.db.unitframe.units.player.width = 200
+ if layout ~= "healer" then
+ E.db.unitframe.units.player.castbar.width = 200
+ end
+ E.db.unitframe.units.player.classbar.fill = "fill"
+
+ E.db.unitframe.units.target.width = 200
+ E.db.unitframe.units.target.castbar.width = 200
+
+ E.db.unitframe.units.pet.power.enable = false
+ E.db.unitframe.units.pet.width = 200
+ E.db.unitframe.units.pet.height = 26
+
+ E.db.unitframe.units.targettarget.debuffs.enable = false
+ E.db.unitframe.units.targettarget.power.enable = false
+ E.db.unitframe.units.targettarget.width = 200
+ E.db.unitframe.units.targettarget.height = 26
+
+ E.db.unitframe.units.arena.width = 200
+ E.db.unitframe.units.arena.castbar.width = 200
+ end
+
+ if(layout == "dpsCaster" or layout == "healer" or (layout == "dpsMelee" and E.myclass == "HUNTER")) then
+ if not E.db.movers then E.db.movers = {} end
+ E.db.unitframe.units.player.castbar.width = E.PixelMode and 406 or 436
+ E.db.unitframe.units.player.castbar.height = 28
+ E.db.unitframe.units.player.castbar.insideInfoPanel = false
+ local yOffset = 80
+ if not E.db.lowresolutionset then
+ if layout ~= "healer" then
+ yOffset = 42
+
+ if E.PixelMode then
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-278,110"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,278,110"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,0,110"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,0,150"
+ else
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-307,110"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,307,110"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,0,110"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,0,150"
+ end
+ else
+ yOffset = 76
+ end
+ elseif E.db.lowresolutionset then
+ if E.PixelMode then
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-102,182"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,102,182"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,102,120"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-102,120"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+ else
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-118,182"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,118,182"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,118,120"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-118,120"
+ E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,310,332"
+ end
+ end
+
+ if E.PixelMode then
+ E.db.movers.ElvUF_PlayerCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,"..yOffset
+ else
+ E.db.movers.ElvUF_PlayerCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,-2,"..(yOffset + 5)
+ end
+ elseif (layout == "dpsMelee" or layout == "tank") and not E.db.lowresolutionset and not E.PixelMode then
+ E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-307,76"
+ E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,307,76"
+ E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,0,76"
+ E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,0,115"
+ end
+
+ if not noDataReset then
+ E:CopyTable(E.db.datatexts.panels, P.datatexts.panels)
+ if layout == "tank" then
+ E.db.datatexts.panels.LeftChatDataPanel.left = "Armor"
+ E.db.datatexts.panels.LeftChatDataPanel.right = "Avoidance"
+ elseif layout == "healer" or layout == "dpsCaster" then
+ E.db.datatexts.panels.LeftChatDataPanel.left = "Spell/Heal Power"
+ E.db.datatexts.panels.LeftChatDataPanel.right = "Haste"
+ else
+ E.db.datatexts.panels.LeftChatDataPanel.left = "Attack Power"
+ E.db.datatexts.panels.LeftChatDataPanel.right = "Haste"
+ end
+
+ if InstallStepComplete then
+ InstallStepComplete.message = L["Layout Set"]
+ InstallStepComplete:Show()
+ end
+ end
+
+ E.db.layoutSet = layout
+
+ if not noDataReset and E.private.theme then
+ E:SetupTheme(E.private.theme, true)
+ end
+
+ E:UpdateAll(true)
+end
+
+local function SetupAuras(style)
+ local UF = E:GetModule("UnitFrames")
+
+ local frame = UF["player"]
+ E:CopyTable(E.db.unitframe.units.player.buffs, P.unitframe.units.player.buffs)
+ E:CopyTable(E.db.unitframe.units.player.debuffs, P.unitframe.units.player.debuffs)
+ E:CopyTable(E.db.unitframe.units.player.aurabar, P.unitframe.units.player.aurabar)
+
+ if frame then
+ UF:Configure_Auras(frame, "Buffs")
+ UF:Configure_Auras(frame, "Debuffs")
+ UF:Configure_AuraBars(frame)
+ end
+
+ frame = UF["target"]
+ E:CopyTable(E.db.unitframe.units.target.buffs, P.unitframe.units.target.buffs)
+ E:CopyTable(E.db.unitframe.units.target.debuffs, P.unitframe.units.target.debuffs)
+ E:CopyTable(E.db.unitframe.units.target.aurabar, P.unitframe.units.target.aurabar)
+ E.db.unitframe.units.target.smartAuraDisplay = P.unitframe.units.target.smartAuraDisplay
+
+ if frame then
+ UF:Configure_Auras(frame, "Buffs")
+ UF:Configure_Auras(frame, "Debuffs")
+ UF:Configure_AuraBars(frame)
+ end
+
+ frame = UF["focus"]
+ E:CopyTable(E.db.unitframe.units.focus.buffs, P.unitframe.units.focus.buffs)
+ E:CopyTable(E.db.unitframe.units.focus.debuffs, P.unitframe.units.focus.debuffs)
+ E:CopyTable(E.db.unitframe.units.focus.aurabar, P.unitframe.units.focus.aurabar)
+ E.db.unitframe.units.focus.smartAuraDisplay = P.unitframe.units.focus.smartAuraDisplay
+
+ if frame then
+ UF:Configure_Auras(frame, "Buffs")
+ UF:Configure_Auras(frame, "Debuffs")
+ UF:Configure_AuraBars(frame)
+ end
+
+ if not style then
+ E.db.unitframe.units.player.buffs.enable = true
+ E.db.unitframe.units.player.buffs.attachTo = "FRAME"
+ E.db.unitframe.units.player.buffs.noDuration = false
+ E.db.unitframe.units.player.debuffs.attachTo = "BUFFS"
+ E.db.unitframe.units.player.aurabar.enable = false
+ E:GetModule("UnitFrames"):CreateAndUpdateUF("player")
+
+ E.db.unitframe.units.target.smartAuraDisplay = "DISABLED"
+ E.db.unitframe.units.target.debuffs.enable = true
+ E.db.unitframe.units.target.aurabar.enable = false
+ E:GetModule("UnitFrames"):CreateAndUpdateUF("target")
+ end
+
+ if(InstallStepComplete) then
+ InstallStepComplete.message = L["Auras Set"]
+ InstallStepComplete:Show()
+ end
+end
+
+local function InstallComplete()
+ E.private.install_complete = E.version
+
+ ReloadUI()
+end
+
+local function ResetAll()
+ InstallNextButton:Disable()
+ InstallPrevButton:Disable()
+ InstallOption1Button:Hide()
+ InstallOption1Button:SetScript("OnClick", nil)
+ InstallOption1Button:SetText("")
+ InstallOption2Button:Hide()
+ InstallOption2Button:SetScript("OnClick", nil)
+ InstallOption2Button:SetText("")
+ InstallOption3Button:Hide()
+ InstallOption3Button:SetScript("OnClick", nil)
+ InstallOption3Button:SetText("")
+ InstallOption4Button:Hide()
+ InstallOption4Button:SetScript("OnClick", nil)
+ InstallOption4Button:SetText("")
+ ElvUIInstallFrame.SubTitle:SetText("")
+ ElvUIInstallFrame.Desc1:SetText("")
+ ElvUIInstallFrame.Desc2:SetText("")
+ ElvUIInstallFrame.Desc3:SetText("")
+ ElvUIInstallFrame:SetWidth(550)
+ ElvUIInstallFrame:SetHeight(400)
+end
+
+local function SetPage(PageNum)
+ CURRENT_PAGE = PageNum
+ ResetAll()
+ InstallStatus.anim.progress:SetChange(PageNum)
+ InstallStatus.anim.progress:Play()
+ InstallStatus.text:SetText(format("%d / %d", CURRENT_PAGE, MAX_PAGE))
+
+ local r, g, b = E:ColorGradient(CURRENT_PAGE / MAX_PAGE, 1, 0, 0, 1, 1, 0, 0, 1, 0)
+ ElvUIInstallFrame.Status:SetStatusBarColor(r, g, b)
+
+ local f = ElvUIInstallFrame
+
+ if PageNum == MAX_PAGE then
+ InstallNextButton:Disable()
+ else
+ InstallNextButton:Enable()
+ end
+
+ if PageNum == 1 then
+ InstallPrevButton:Disable()
+ else
+ InstallPrevButton:Enable()
+ end
+
+ if PageNum == 1 then
+ f.SubTitle:SetText(format(L["Welcome to ElvUI version %s!"], E.version))
+ f.Desc1:SetText(L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."])
+ f.Desc2:SetText(L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."])
+ f.Desc3:SetText(L["Please press the continue button to go onto the next step."])
+
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", InstallComplete)
+ InstallOption1Button:SetText(L["Skip Process"])
+ elseif PageNum == 2 then
+ f.SubTitle:SetText(L["CVars"])
+ f.Desc1:SetText(L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."])
+ f.Desc2:SetText(L["Please click the button below to setup your CVars."])
+ f.Desc3:SetText(L["Importance: |cff07D400High|r"])
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", SetupCVars)
+ InstallOption1Button:SetText(L["Setup CVars"])
+ elseif PageNum == 3 then
+ f.SubTitle:SetText(L["Chat"])
+ f.Desc1:SetText(L["This part of the installation process sets up your chat windows names, positions and colors."])
+ f.Desc2:SetText(L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."])
+ f.Desc3:SetText(L["Importance: |cffD3CF00Medium|r"])
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", SetupChat)
+ InstallOption1Button:SetText(L["Setup Chat"])
+ elseif PageNum == 4 then
+ f.SubTitle:SetText(L["Theme Setup"])
+ f.Desc1:SetText(L["Choose a theme layout you wish to use for your initial setup."])
+ f.Desc2:SetText(L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."])
+ f.Desc3:SetText(L["Importance: |cffFF0000Low|r"])
+
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", function() E:SetupTheme("classic") end)
+ InstallOption1Button:SetText(L["Classic"])
+ InstallOption2Button:Show()
+ InstallOption2Button:SetScript("OnClick", function() E:SetupTheme("default") end)
+ InstallOption2Button:SetText(L["Dark"])
+ InstallOption3Button:Show()
+ InstallOption3Button:SetScript("OnClick", function() E:SetupTheme("class") end)
+ InstallOption3Button:SetText(CLASS)
+ elseif PageNum == 5 then
+ f.SubTitle:SetText(L["Resolution"])
+ f.Desc1:SetText(format(L["Your current resolution is %s, this is considered a %s resolution."], E.resolution, E.lowversion == true and L["low"] or L["high"]))
+ if E.lowversion then
+ f.Desc2:SetText(L["This resolution requires that you change some settings to get everything to fit on your screen."].." "..L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."].." "..L["You may need to further alter these settings depending how low you resolution is."])
+ f.Desc3:SetText(L["Importance: |cff07D400High|r"])
+ else
+ f.Desc2:SetText(L["This resolution doesn't require that you change settings for the UI to fit on your screen."].." "..L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."].." "..L["This is completely optional."])
+ f.Desc3:SetText(L["Importance: |cffFF0000Low|r"])
+ end
+
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", function() E.SetupResolution("high") end)
+ InstallOption1Button:SetText(L["High Resolution"])
+ InstallOption2Button:Show()
+ InstallOption2Button:SetScript("OnClick", function() E.SetupResolution("low") end)
+ InstallOption2Button:SetText(L["Low Resolution"])
+ elseif PageNum == 6 then
+ f.SubTitle:SetText(L["Layout"])
+ f.Desc1:SetText(L["You can now choose what layout you wish to use based on your combat role."])
+ f.Desc2:SetText(L["This will change the layout of your unitframes and actionbars."])
+ f.Desc3:SetText(L["Importance: |cffD3CF00Medium|r"])
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", function() E.db.layoutSet = nil E:SetupLayout("tank") end)
+ InstallOption1Button:SetText(L["Tank"])
+ InstallOption2Button:Show()
+ InstallOption2Button:SetScript("OnClick", function() E.db.layoutSet = nil E:SetupLayout("healer") end)
+ InstallOption2Button:SetText(L["Healer"])
+ InstallOption3Button:Show()
+ InstallOption3Button:SetScript("OnClick", function() E.db.layoutSet = nil E:SetupLayout("dpsMelee") end)
+ InstallOption3Button:SetText(L["Physical DPS"])
+ InstallOption4Button:Show()
+ InstallOption4Button:SetScript("OnClick", function() E.db.layoutSet = nil E:SetupLayout("dpsCaster") end)
+ InstallOption4Button:SetText(L["Caster DPS"])
+ elseif PageNum == 7 then
+ f.SubTitle:SetText(L["Auras"])
+ f.Desc1:SetText(L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."])
+ f.Desc2:SetText(L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."])
+ f.Desc3:SetText(L["Importance: |cffD3CF00Medium|r"])
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", function() SetupAuras(true) end)
+ InstallOption1Button:SetText(L["Aura Bars & Icons"])
+ InstallOption2Button:Show()
+ InstallOption2Button:SetScript("OnClick", function() SetupAuras() end)
+ InstallOption2Button:SetText(L["Icons Only"])
+ elseif PageNum == 8 then
+ f.SubTitle:SetText(L["Installation Complete"])
+ f.Desc1:SetText(L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"])
+ f.Desc2:SetText(L["Please click the button below so you can setup variables and ReloadUI."])
+ InstallOption1Button:Show()
+ InstallOption1Button:SetScript("OnClick", InstallComplete)
+ InstallOption1Button:SetText(L["Finished"])
+ ElvUIInstallFrame:SetWidth(550)
+ ElvUIInstallFrame:SetHeight(350)
+ end
+end
+
+local function NextPage()
+ if CURRENT_PAGE ~= MAX_PAGE then
+ CURRENT_PAGE = CURRENT_PAGE + 1
+ SetPage(CURRENT_PAGE)
+ end
+end
+
+local function PreviousPage()
+ if CURRENT_PAGE ~= 1 then
+ CURRENT_PAGE = CURRENT_PAGE - 1
+ SetPage(CURRENT_PAGE)
+ end
+end
+
+--Install UI
+function E:Install()
+ if not InstallStepComplete then
+ local imsg = CreateFrame("Frame", "InstallStepComplete", E.UIParent)
+ imsg:SetWidth(418)
+ imsg:SetHeight(72)
+ imsg:SetPoint("TOP", 0, -190)
+ imsg:Hide()
+ imsg:SetScript("OnShow", function()
+ if this.message then
+ PlaySoundFile([[Sound\Interface\LevelUp.wav]])
+ this.text:SetText(this.message)
+ UIFrameFadeOut(this, 3.5, 1, 0)
+ E:Delay(4, function() this:Hide() end)
+ this.message = nil
+ else
+ this:Hide()
+ end
+ end)
+
+ imsg.firstShow = false
+
+ imsg.text = imsg:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(imsg.text, E["media"].normFont, 32, "OUTLINE")
+ imsg.text:SetPoint("BOTTOM", 0, 16)
+ imsg.text:SetTextColor(1, 0.82, 0)
+ imsg.text:SetJustifyH("CENTER")
+ end
+
+ if not ElvUIInstallFrame then
+ local f = CreateFrame("Button", "ElvUIInstallFrame", E.UIParent)
+ f.SetPage = SetPage
+ f:SetWidth(550)
+ f:SetHeight(400)
+ E:SetTemplate(f, "Transparent")
+ f:SetPoint("CENTER", 0, 0)
+ f:SetFrameStrata("TOOLTIP")
+
+ f.Title = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Title, nil, 17, nil)
+ f.Title:SetPoint("TOP", 0, -5)
+ f.Title:SetText(L["ElvUI Installation"])
+
+ f.Next = CreateFrame("Button", "InstallNextButton", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Next)
+ E:SetTemplate(f.Next, "Default", true)
+ f.Next:SetWidth(110)
+ f.Next:SetHeight(25)
+ f.Next:SetPoint("BOTTOMRIGHT", -5, 5)
+ f.Next:SetText(CONTINUE)
+ f.Next:Disable()
+ f.Next:SetScript("OnClick", NextPage)
+ E.Skins:HandleButton(f.Next, true)
+
+ f.Prev = CreateFrame("Button", "InstallPrevButton", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Prev)
+ E:SetTemplate(f.Prev, "Default", true)
+ f.Prev:SetWidth(110)
+ f.Prev:SetHeight(25)
+ f.Prev:SetPoint("BOTTOMLEFT", 5, 5)
+ f.Prev:SetText(PREV)
+ f.Prev:Disable()
+ f.Prev:SetScript("OnClick", PreviousPage)
+ E.Skins:HandleButton(f.Prev, true)
+
+ f.Status = CreateFrame("StatusBar", "InstallStatus", f)
+ f.Status:SetFrameLevel(f.Status:GetFrameLevel() + 2)
+ E:CreateBackdrop(f.Status, "Default")
+ f.Status:SetStatusBarTexture(E["media"].normTex)
+ E:RegisterStatusBar(f.Status)
+ f.Status:SetMinMaxValues(0, MAX_PAGE)
+ f.Status:SetPoint("TOPLEFT", f.Prev, "TOPRIGHT", 6, -2)
+ f.Status:SetPoint("BOTTOMRIGHT", f.Next, "BOTTOMLEFT", -6, 2)
+
+ f.Status.anim = CreateAnimationGroup(f.Status)
+ f.Status.anim.progress = f.Status.anim:CreateAnimation("Progress")
+ f.Status.anim.progress:SetSmoothing("Out")
+ f.Status.anim.progress:SetDuration(.3)
+
+ f.Status.text = f.Status:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Status.text)
+ f.Status.text:SetPoint("CENTER", 0, 0)
+ f.Status.text:SetText(format("%d / %d", CURRENT_PAGE, MAX_PAGE))
+
+ f.Option1 = CreateFrame("Button", "InstallOption1Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option1)
+ f.Option1:SetWidth(160)
+ f.Option1:SetHeight(30)
+ f.Option1:SetPoint("BOTTOM", 0, 45)
+ f.Option1:SetText("")
+ f.Option1:Hide()
+ E.Skins:HandleButton(f.Option1, true)
+
+ f.Option2 = CreateFrame("Button", "InstallOption2Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option2)
+ f.Option2:SetWidth(110)
+ f.Option2:SetHeight(30)
+ f.Option2:SetPoint("BOTTOMLEFT", f, "BOTTOM", 4, 45)
+ f.Option2:SetText("")
+ f.Option2:Hide()
+ f.Option2:SetScript("OnShow", function() f.Option1:SetWidth(110) f.Option1:ClearAllPoints() f.Option1:SetPoint("BOTTOMRIGHT", f, "BOTTOM", -4, 45) end)
+ f.Option2:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:SetPoint("BOTTOM", 0, 45) end)
+ E.Skins:HandleButton(f.Option2, true)
+
+ f.Option3 = CreateFrame("Button", "InstallOption3Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option3)
+ f.Option3:SetWidth(110)
+ f.Option3:SetHeight(30)
+ f.Option3:SetPoint("LEFT", f.Option2, "RIGHT", 4, 0)
+ f.Option3:SetText("")
+ f.Option3:Hide()
+ f.Option3:SetScript("OnShow", function() f.Option1:SetWidth(100) f.Option1:ClearAllPoints() f.Option1:SetPoint("RIGHT", f.Option2, "LEFT", -4, 0) f.Option2:SetWidth(100) f.Option2:ClearAllPoints() f.Option2:SetPoint("BOTTOM", f, "BOTTOM", 0, 45) end)
+ f.Option3:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:SetPoint("BOTTOM", 0, 45) f.Option2:SetWidth(110) f.Option2:ClearAllPoints() f.Option2:SetPoint("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
+ E.Skins:HandleButton(f.Option3, true)
+
+ f.Option4 = CreateFrame("Button", "InstallOption4Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option4)
+ f.Option4:SetWidth(110)
+ f.Option4:SetHeight(30)
+ f.Option4:SetPoint("LEFT", f.Option3, "RIGHT", 4, 0)
+ f.Option4:SetText("")
+ f.Option4:Hide()
+ f.Option4:SetScript("OnShow", function()
+ f.Option1:SetWidth(100)
+ f.Option2:SetWidth(100)
+
+ f.Option1:ClearAllPoints()
+ f.Option1:SetPoint("RIGHT", f.Option2, "LEFT", -4, 0)
+ f.Option2:ClearAllPoints()
+ f.Option2:SetPoint("BOTTOMRIGHT", f, "BOTTOM", -4, 45)
+ end)
+ f.Option4:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:SetPoint("BOTTOM", 0, 45) f.Option2:SetWidth(110) f.Option2:ClearAllPoints() f.Option2:SetPoint("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
+ E.Skins:HandleButton(f.Option4, true)
+
+ f.SubTitle = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.SubTitle, nil, 15, nil)
+ f.SubTitle:SetPoint("TOP", 0, -40)
+
+ f.Desc1 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc1)
+ f.Desc1:SetPoint("TOPLEFT", 20, -75)
+ f.Desc1:SetWidth(f:GetWidth() - 40)
+
+ f.Desc2 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc2)
+ f.Desc2:SetPoint("TOPLEFT", 20, -125)
+ f.Desc2:SetWidth(f:GetWidth() - 40)
+
+ f.Desc3 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc3)
+ f.Desc3:SetPoint("TOPLEFT", 20, -175)
+ f.Desc3:SetWidth(f:GetWidth() - 40)
+
+ local close = CreateFrame("Button", "InstallCloseButton", f, "UIPanelCloseButton")
+ close:SetPoint("TOPRIGHT", f, "TOPRIGHT")
+ close:SetScript("OnClick", function()
+ f:Hide()
+ end)
+ E.Skins:HandleCloseButton(close)
+
+ f.tutorialImage = f:CreateTexture("InstallTutorialImage", "OVERLAY")
+ f.tutorialImage:SetWidth(256)
+ f.tutorialImage:SetHeight(128)
+ f.tutorialImage:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\logo.tga")
+ f.tutorialImage:SetPoint("BOTTOM", 0, 70)
+
+ end
+
+ ElvUIInstallFrame:Show()
+ NextPage()
+end
\ No newline at end of file
diff --git a/ElvUI/Core/pixelperfect.lua b/ElvUI/Core/pixelperfect.lua
new file mode 100644
index 0000000..3ba9519
--- /dev/null
+++ b/ElvUI/Core/pixelperfect.lua
@@ -0,0 +1,133 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local abs, floor, min, max = math.abs, math.floor, math.min, math.max;
+local match = string.match;
+--WoW API / Variables
+local IsMacClient = IsMacClient;
+local GetCVar, SetCVar = GetCVar, SetCVar;
+local GetScreenHeight, GetScreenWidth = GetScreenHeight, GetScreenWidth;
+
+local scale
+
+function E:UIScale(event)
+ if IsMacClient() and self.global.screenheight and self.global.screenwidth and (self.screenheight ~= self.global.screenheight or self.screenwidth ~= self.global.screenwidth) then
+ self.screenheight = self.global.screenheight
+ self.screenwidth = self.global.screenwidth
+ end
+
+ if(GetCVar("UIScale")) then
+ self.global.uiScale = GetCVar("UIScale");
+ end
+
+ local minScale = self.global.general.minUiScale or 0.64;
+ if(self.global.general.autoScale) then
+ scale = max(minScale, min(1.00, 768/self.screenheight));
+ else
+ scale = max(minScale, min(1.00, self.global.uiScale or UIParent:GetScale() or 768/self.screenheight));
+ end
+
+ if self.screenwidth < 1600 then
+ self.lowversion = true;
+ elseif self.screenwidth >= 3840 and self.global.general.eyefinity then
+ local width = self.screenwidth;
+ local height = self.screenheight;
+
+ -- because some user enable bezel compensation, we need to find the real width of a single monitor.
+ -- I don't know how it really work, but i'm assuming they add pixel to width to compensate the bezel. :P
+
+ -- HQ resolution
+ if width >= 9840 then width = 3280; end -- WQSXGA
+ if width >= 7680 and width < 9840 then width = 2560; end -- WQXGA
+ if width >= 5760 and width < 7680 then width = 1920; end -- WUXGA & HDTV
+ if width >= 5040 and width < 5760 then width = 1680; end -- WSXGA+
+
+ -- adding height condition here to be sure it work with bezel compensation because WSXGA+ and UXGA/HD+ got approx same width
+ if width >= 4800 and width < 5760 and height == 900 then width = 1600; end -- UXGA & HD+
+
+ -- low resolution screen
+ if width >= 4320 and width < 4800 then width = 1440; end -- WSXGA
+ if width >= 4080 and width < 4320 then width = 1360; end -- WXGA
+ if width >= 3840 and width < 4080 then width = 1224; end -- SXGA & SXGA (UVGA) & WXGA & HDTV
+
+ -- yep, now set ElvUI to lower resolution if screen #1 width < 1600
+ if width < 1600 then
+ self.lowversion = true;
+ end
+
+ -- register a constant, we will need it later for launch.lua
+ self.eyefinity = width;
+ end
+
+ self.mult = 768/match(GetCVar("gxResolution"), "%d+x(%d+)")/scale;
+ self.Spacing = self.PixelMode and 0 or self.mult;
+ self.Border = (self.PixelMode and self.mult or self.mult*2);
+ --Set UIScale, NOTE: SetCVar for UIScale can cause taints so only do this when we need to..
+ if E.Round and E:Round(UIParent:GetScale(), 5) ~= E:Round(scale, 5) and (event == "PLAYER_LOGIN") then
+ SetCVar("UseUIScale", 1);
+ SetCVar("UIScale", scale);
+ WorldMapFrame.hasTaint = true;
+ end
+
+ if (event == "PLAYER_LOGIN" or event == "UPDATE_FLOATING_CHAT_WINDOWS") then
+ if IsMacClient() then
+ self.global.screenheight = floor(GetScreenHeight()*100+.5)/100
+ self.global.screenwidth = floor(GetScreenWidth()*100+.5)/100
+ end
+
+ --Resize self.UIParent if Eyefinity is on.
+ if self.eyefinity then
+ local width = self.eyefinity;
+ local height = self.screenheight;
+
+ -- if autoscale is off, find a new width value of self.UIParent for screen #1.
+ if not self.global.general.autoScale or height > 1200 then
+ local h = UIParent:GetHeight();
+ local ratio = self.screenheight / h;
+ local w = self.eyefinity / ratio;
+
+ width = w;
+ height = h;
+ end
+
+ self.UIParent:SetWidth(width);
+ self.UIParent:SetHeight(height);
+ else
+ --[[Eyefinity Test mode
+ Resize the E.UIParent to be smaller than it should be, all objects inside should relocate.
+ Dragging moveable frames outside the box and reloading the UI ensures that they are saving position correctly.
+ ]]
+ --self.UIParent:SetSize(UIParent:GetWidth() - 250, UIParent:GetHeight() - 250);
+
+ self.UIParent:SetWidth(GetScreenWidth());
+ self.UIParent:SetHeight(GetScreenHeight());
+ end
+
+ self.UIParent:ClearAllPoints();
+ self.UIParent:SetPoint("CENTER", UIParent);
+
+ self.diffGetLeft = E:Round(abs(UIParent:GetLeft() - self.UIParent:GetLeft()));
+ self.diffGetRight = E:Round(abs(UIParent:GetRight() - self.UIParent:GetRight()));
+ self.diffGetTop = E:Round(abs(UIParent:GetTop() - self.UIParent:GetTop()));
+ self.diffGetBottom = E:Round(abs(UIParent:GetBottom() - self.UIParent:GetBottom()));
+
+ local change
+ if E.Round then
+ change = abs((E:Round(UIParent:GetScale(), 5) * 100) - (E:Round(scale, 5) * 100))
+ end
+
+ if event == "UPDATE_FLOATING_CHAT_WINDOWS" and change and change > 1 and self.global.general.autoScale then
+ E:StaticPopup_Show("FAILED_UISCALE")
+ elseif event == "UPDATE_FLOATING_CHAT_WINDOWS" and change and change > 1 then
+ E:StaticPopup_Show("CONFIG_RL")
+ end
+
+ self:UnregisterEvent("PLAYER_LOGIN")
+ end
+end
+
+-- pixel perfect script of custom ui scale.
+function E:Scale(x)
+ return self.mult*floor(x/self.mult+.5);
+end
\ No newline at end of file
diff --git a/ElvUI/Core/pluginInstaller.lua b/ElvUI/Core/pluginInstaller.lua
new file mode 100644
index 0000000..0318585
--- /dev/null
+++ b/ElvUI/Core/pluginInstaller.lua
@@ -0,0 +1,480 @@
+--Plugins pass their info using the table like:
+--[[
+ addon = {
+ Title = "Your Own Title",
+ Name = "AddOnName",
+ tutorialImage = "TexturePath",
+ Pages = {
+ [1] = function1,
+ [2] = function2,
+ [3] = function3,
+ },
+ StepTitles = {
+ [1] = "Title 1",
+ [2] = "Title 2",
+ [3] = "Title 3",
+ },
+ StepTitlesColor = {r,g,b},
+ StepTitlesColorSelected = {r,g,b},
+ StepTitleWidth = 140,
+ StepTitleButtonWidth = 130,
+ StepTitleTextJustification = "CENTER",
+ }
+ E:GetModule("PluginInstaller"):Queue(addon)
+
+ Title is wat displayed on top of the window. By default it's ""ElvUI Plugin Installation""
+ Name is how your installation will be showin in "pending list", Default is "Unknown"
+ tutorialImage is a path to your own texture to use in frame. if not specified, then it will use ElvUI's one
+ Pages is a table to set up pages of your install where numbers are representing actual pages' order and function is what previously was used to set layout. For example
+ function function1()
+ PluginInstallFrame.SubTitle:SetText("Title Text")
+ PluginInstallFrame.Desc1:SetText("Desc 1 Tet")
+ PluginInstallFrame.Desc2:SetText("Desc 2 Tet")
+ PluginInstallFrame.Desc3:SetText("Desc 3 Tet")
+
+ PluginInstallFrame.Option1:Show()
+ PluginInstallFrame.Option1:SetScript("OnClick", function() end)
+ PluginInstallFrame.Option1:SetText("Text 1")
+
+ PluginInstallFrame.Option2:Show()
+ PluginInstallFrame.Option2:SetScript("OnClick", function() end)
+ PluginInstallFrame.Option2:SetText("Text 2")
+ end
+ StepTitles - a table to specify "titles" for your install steps. If specified and number of lines here = number of pages then you'll get an additional frame to the right of main frame
+ with a list of steps (current one being highlighted), clicking on those will open respective step. BenikUI style of doing stuff.
+ StepTitlesColor - a table with color values to color "titles" when they are not active
+ StepTitlesColorSelected - a table with color values to color "titles" when they are active
+ StepTitleWidth - Width of the steps frame on the right side
+ StepTitleButtonWidth - Width of each step button in the steps frame
+ StepTitleTextJustification - The justification of the text on each step button ("LEFT", "RIGHT", "CENTER"). Default: "CENTER"
+]]
+
+local E, L, V, P, G, _ = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local PI = E:NewModule("PluginInstaller");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs, unpack = pairs, unpack
+local tinsert, tremove = tinsert, tremove
+local format = string.format
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local PlaySoundFile = PlaySoundFile
+local UIFrameFadeOut = UIFrameFadeOut
+local CreateAnimationGroup = CreateAnimationGroup
+local CONTINUE, PREV, UNKNOWN = CONTINUE, PREV, UNKNOWN
+
+--Global variables that we don't cache, list them here for the mikk's Find Globals script
+-- GLOBALS: PluginInstallFrame
+
+--Installation Functions
+PI.Installs = {}
+local f
+local BUTTON_HEIGHT = 20
+
+local function ResetAll()
+ f.Next:Disable()
+ f.Prev:Disable()
+ f.Option1:Hide()
+ f.Option1:SetScript("OnClick", nil)
+ f.Option1:SetText("")
+ f.Option2:Hide()
+ f.Option2:SetScript("OnClick", nil)
+ f.Option2:SetText("")
+ f.Option3:Hide()
+ f.Option3:SetScript("OnClick", nil)
+ f.Option3:SetText("")
+ f.Option4:Hide()
+ f.Option4:SetScript("OnClick", nil)
+ f.Option4:SetText("")
+ f.SubTitle:SetText("")
+ f.Desc1:SetText("")
+ f.Desc2:SetText("")
+ f.Desc3:SetText("")
+ f.Desc4:SetText("")
+ f:SetWidth(550)
+ f:SetHeight(400)
+ if f.StepTitles then
+ for i = 1, getn(f.side.Lines) do f.side.Lines[i].text:SetText("") end
+ end
+end
+
+local function SetPage(PageNum, PrevPage)
+ f.CurrentPage = PageNum
+ f.PrevPage = PrevPage
+ ResetAll()
+ f.Status.anim.progress:SetChange(PageNum)
+ f.Status.anim.progress:Play()
+
+ local r, g, b = E:ColorGradient(f.CurrentPage / f.MaxPage, 1, 0, 0, 1, 1, 0, 0, 1, 0)
+ f.Status:SetStatusBarColor(r, g, b)
+
+ if PageNum == f.MaxPage then
+ f.Next:Disable()
+ else
+ f.Next:Enable()
+ end
+
+ if PageNum == 1 then
+ f.Prev:Disable()
+ else
+ f.Prev:Enable()
+ end
+
+ f.Pages[f.CurrentPage]()
+ f.Status.text:SetFormattedText("%d / %d", f.CurrentPage, f.MaxPage)
+ if f.StepTitles then
+ for i = 1, getn(f.side.Lines) do
+ local b = f.side.Lines[i]
+ local color
+ b.text:SetText(f.StepTitles[i])
+ if i == f.CurrentPage then
+ color = f.StepTitlesColorSelected or {.09,.52,.82}
+ else
+ color = f.StepTitlesColor or {1,1,1}
+ end
+ b.text:SetTextColor(color[1] or color.r, color[2] or color.g, color[3] or color.b)
+ end
+ end
+end
+
+local function NextPage()
+ if f.CurrentPage ~= f.MaxPage then
+ f.CurrentPage = f.CurrentPage + 1
+ SetPage(f.CurrentPage, f.CurrentPage - 1)
+ end
+end
+
+local function PreviousPage()
+ if f.CurrentPage ~= 1 then
+ f.CurrentPage = f.CurrentPage - 1
+ SetPage(f.CurrentPage, f.CurrentPage + 1)
+ end
+end
+
+function PI:CreateStepComplete()
+ local imsg = CreateFrame("Frame", "PluginInstallStepComplete", E.UIParent)
+ imsg:SetWidth(418)
+ imsg:SetHeight(72)
+ imsg:SetPoint("TOP", 0, -190)
+ imsg:Hide()
+ imsg:SetScript("OnShow", function(self)
+ if self.message then
+ PlaySoundFile([[Sound\Interface\LevelUp.wav]])
+ self.text:SetText(self.message)
+ UIFrameFadeOut(self, 3.5, 1, 0)
+ E:Delay(4, function() self:Hide() end)
+ self.message = nil
+ else
+ self:Hide()
+ end
+ end)
+
+ imsg.firstShow = false
+
+ imsg.bg = imsg:CreateTexture(nil, "BACKGROUND")
+ imsg.bg:SetTexture([[Interface\LevelUp\LevelUpTex]])
+ imsg.bg:SetPoint("BOTTOM", 0, 0)
+ imsg.bg:SetWidth(326)
+ imsg.bg:SetHeight(103)
+ imsg.bg:SetTexCoord(0.00195313, 0.63867188, 0.03710938, 0.23828125)
+ imsg.bg:SetVertexColor(1, 1, 1, 0.6)
+
+ imsg.lineTop = imsg:CreateTexture(nil, "BACKGROUND")
+ imsg.lineTop:SetDrawLayer("BACKGROUND", 2)
+ imsg.lineTop:SetTexture([[Interface\LevelUp\LevelUpTex]])
+ imsg.lineTop:SetPoint("TOP", 0, 0)
+ imsg.lineTop:SetWidth(418)
+ imsg.lineTop:SetHeight(7)
+ imsg.lineTop:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)
+
+ imsg.lineBottom = imsg:CreateTexture(nil, "BACKGROUND")
+ imsg.lineBottom:SetDrawLayer("BACKGROUND", 2)
+ imsg.lineBottom:SetTexture([[Interface\LevelUp\LevelUpTex]])
+ imsg.lineBottom:SetPoint("BOTTOM", 0, 0)
+ imsg.lineBottom:SetWidth(418)
+ imsg.lineBottom:SetHeight(7)
+ imsg.lineBottom:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)
+
+ imsg.text = imsg:CreateFontString(nil, "ARTWORK")
+ E:FontTemplate(imsg.text, E["media"].normFont, 32, "OUTLINE")
+ imsg.text:SetPoint("BOTTOM", 0, 12)
+ imsg.text:SetTextColor(1, 0.82, 0)
+ imsg.text:SetJustifyH("CENTER")
+end
+
+function PI:CreateFrame()
+ f = CreateFrame("Button", "PluginInstallFrame", E.UIParent)
+ f.SetPage = SetPage
+ f:SetWidth(550)
+ f:SetHeight(400)
+ E:SetTemplate(f, "Transparent")
+ f:SetPoint("CENTER", 0, 0)
+ f:SetFrameStrata("TOOLTIP")
+
+ f.Title = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Title, nil, 17, nil)
+ f.Title:SetPoint("TOP", 0, -5)
+
+ f.Next = CreateFrame("Button", "PluginInstallNextButton", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Next)
+ E:SetTemplate(f.Next, "Default", true)
+ f.Next:SetWidth(110)
+ f.Next:SetHeight(25)
+ f.Next:SetPoint("BOTTOMRIGHT", -5, 5)
+ f.Next:SetText(CONTINUE)
+ f.Next:Disable()
+ f.Next:SetScript("OnClick", NextPage)
+ E.Skins:HandleButton(f.Next, true)
+
+ f.Prev = CreateFrame("Button", "PluginInstallPrevButton", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Prev)
+ E:SetTemplate(f.Prev, "Default", true)
+ f.Prev:SetWidth(110)
+ f.Prev:SetHeight(25)
+ f.Prev:SetPoint("BOTTOMLEFT", 5, 5)
+ f.Prev:SetText(PREV)
+ f.Prev:Disable()
+ f.Prev:SetScript("OnClick", PreviousPage)
+ E.Skins:HandleButton(f.Prev, true)
+
+ f.Status = CreateFrame("StatusBar", "PluginInstallStatus", f)
+ f.Status:SetFrameLevel(f.Status:GetFrameLevel() + 2)
+ E:CreateBackdrop(f.Status, "Default", true)
+ f.Status:SetStatusBarTexture(E["media"].normTex)
+ f.Status:SetStatusBarColor(unpack(E["media"].rgbvaluecolor))
+ f.Status:SetPoint("TOPLEFT", f.Prev, "TOPRIGHT", 6, -2)
+ f.Status:SetPoint("BOTTOMRIGHT", f.Next, "BOTTOMLEFT", -6, 2)
+ -- Setup StatusBar Animation
+ f.Status.anim = CreateAnimationGroup(f.Status)
+ f.Status.anim.progress = f.Status.anim:CreateAnimation("Progress")
+ f.Status.anim.progress:SetSmoothing("Out")
+ f.Status.anim.progress:SetDuration(.3)
+
+ f.Status.text = f.Status:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Status.text)
+ f.Status.text:SetPoint("CENTER", 0, 0)
+
+ f.Option1 = CreateFrame("Button", "PluginInstallOption1Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option1)
+ f.Option1:SetWidth(160)
+ f.Option1:SetHeight(30)
+ f.Option1:SetPoint("BOTTOM", 0, 45)
+ f.Option1:SetText("")
+ f.Option1:Hide()
+ E.Skins:HandleButton(f.Option1, true)
+
+ f.Option2 = CreateFrame("Button", "PluginInstallOption2Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option2)
+ f.Option2:SetWidth(160)
+ f.Option2:SetHeight(30)
+ f.Option2:SetPoint("BOTTOMLEFT", f, "BOTTOM", 4, 45)
+ f.Option2:SetText("")
+ f.Option2:Hide()
+ f.Option2:SetScript("OnShow", function() f.Option1:SetWidth(110); f.Option1:ClearAllPoints(); f.Option1:SetPoint("BOTTOMRIGHT", f, "BOTTOM", -4, 45) end)
+ f.Option2:SetScript("OnHide", function() f.Option1:SetWidth(160); f.Option1:ClearAllPoints(); f.Option1:SetPoint("BOTTOM", 0, 45) end)
+ E.Skins:HandleButton(f.Option2, true)
+
+ f.Option3 = CreateFrame("Button", "PluginInstallOption3Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option3)
+ f.Option3:SetWidth(100)
+ f.Option3:SetHeight(30)
+ f.Option3:SetPoint("LEFT", f.Option2, "RIGHT", 4, 0)
+ f.Option3:SetText("")
+ f.Option3:Hide()
+ f.Option3:SetScript("OnShow", function() f.Option1:SetWidth(100); f.Option1:ClearAllPoints(); f.Option1:SetPoint("RIGHT", f.Option2, "LEFT", -4, 0); f.Option2:SetWidth(100); f.Option2:ClearAllPoints(); f.Option2:SetPoint("BOTTOM", f, "BOTTOM", 0, 45) end)
+ f.Option3:SetScript("OnHide", function() f.Option1:SetWidth(160); f.Option1:ClearAllPoints(); f.Option1:SetPoint("BOTTOM", 0, 45); f.Option2:SetWidth(110); f.Option2:ClearAllPoints(); f.Option2:SetPoint("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
+ E.Skins:HandleButton(f.Option3, true)
+
+ f.Option4 = CreateFrame("Button", "PluginInstallOption4Button", f, "UIPanelButtonTemplate")
+ E:StripTextures(f.Option4)
+ f.Option4:SetWidth(100)
+ f.Option4:SetHeight(30)
+ f.Option4:SetPoint("LEFT", f.Option3, "RIGHT", 4, 0)
+ f.Option4:SetText("")
+ f.Option4:Hide()
+ f.Option4:SetScript("OnShow", function()
+ f.Option1:SetWidth(100)
+ f.Option2:SetWidth(100)
+
+ f.Option1:ClearAllPoints();
+ f.Option1:SetPoint("RIGHT", f.Option2, "LEFT", -4, 0);
+ f.Option2:ClearAllPoints();
+ f.Option2:SetPoint("BOTTOMRIGHT", f, "BOTTOM", -4, 45)
+ end)
+ f.Option4:SetScript("OnHide", function() f.Option1:SetWidth(160); f.Option1:ClearAllPoints(); f.Option1:SetPoint("BOTTOM", 0, 45); f.Option2:SetWidth(110); f.Option2:ClearAllPoints(); f.Option2:SetPoint("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
+ E.Skins:HandleButton(f.Option4, true)
+
+ f.SubTitle = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.SubTitle, nil, 15, nil)
+ f.SubTitle:SetPoint("TOP", 0, -40)
+
+ f.Desc1 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc1)
+ f.Desc1:SetPoint("TOPLEFT", 20, -75)
+ f.Desc1:SetWidth(f:GetWidth() - 40)
+
+ f.Desc2 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc2)
+ f.Desc2:SetPoint("TOP", f.Desc1, "BOTTOM", 0, -20)
+ f.Desc2:SetWidth(f:GetWidth() - 40)
+
+ f.Desc3 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc3)
+ f.Desc3:SetPoint("TOP", f.Desc2, "BOTTOM", 0, -20)
+ f.Desc3:SetWidth(f:GetWidth() - 40)
+
+ f.Desc4 = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Desc4)
+ f.Desc4:SetPoint("TOP", f.Desc3, "BOTTOM", 0, -20)
+ f.Desc4:SetWidth(f:GetWidth() - 40)
+
+ local close = CreateFrame("Button", "PluginInstallCloseButton", f, "UIPanelCloseButton")
+ close:SetPoint("TOPRIGHT", f, "TOPRIGHT")
+ close:SetScript("OnClick", function() f:Hide() end)
+ E.Skins:HandleCloseButton(close)
+
+ f.pending = CreateFrame("Frame", "PluginInstallPendingButton", f)
+ f.pending:SetWidth(20)
+ f.pending:SetHeight(20)
+ f.pending:SetPoint("TOPLEFT", f, "TOPLEFT", 8, -8)
+ f.pending.tex = f.pending:CreateTexture(nil, "OVERLAY")
+ f.pending.tex:SetPoint("TOPLEFT", f.pending, "TOPLEFT", 2, -2)
+ f.pending.tex:SetPoint("BOTTOMRIGHT", f.pending, "BOTTOMRIGHT", -2, 2)
+ f.pending.tex:SetTexture([[Interface\OptionsFrame\UI-OptionsFrame-NewFeatureIcon]])
+ E:CreateBackdrop(f.pending, "Transparent")
+ f.pending:SetScript("OnEnter", function(self)
+ _G["GameTooltip"]:SetOwner(self, "ANCHOR_BOTTOMLEFT", E.PixelMode and -7 or -9);
+ _G["GameTooltip"]:AddLine(L["List of installations in queue:"], 1, 1, 1)
+ _G["GameTooltip"]:AddLine(" ")
+ for i = 1, getn(PI.Installs) do
+ _G["GameTooltip"]:AddDoubleLine(format("%d. %s", i, (PI.Installs[i].Name or UNKNOWN)), i == 1 and format("|cff00FF00%s|r", L["In Progress"]) or format("|cffFF0000%s|r", L["Pending"]))
+ end
+ _G["GameTooltip"]:Show()
+ end)
+ f.pending:SetScript("OnLeave", function()
+ _G["GameTooltip"]:Hide()
+ end)
+
+ f.tutorialImage = f:CreateTexture("PluginInstallTutorialImage", "OVERLAY")
+ f.tutorialImage:SetWidth(256)
+ f.tutorialImage:SetHeight(128)
+ f.tutorialImage:SetPoint("BOTTOM", 0, 70)
+
+ f.side = CreateFrame("Frame", "PluginInstallTitleFrame", f)
+ E:SetTemplate(f.side, "Transparent")
+ f.side:SetPoint("TOPLEFT", f, "TOPRIGHT", E.PixelMode and 1 or 3, 0)
+ f.side:SetPoint("BOTTOMLEFT", f, "BOTTOMRIGHT", E.PixelMode and 1 or 3, 0)
+ f.side:SetWidth(140)
+ f.side.text = f.side:CreateFontString(nil, "OVERLAY")
+ f.side.text:SetPoint("TOP", f.side, "TOP", 0, -4)
+ f.side.text:SetFont(E["media"].normFont, 18, "OUTLINE")
+ f.side.text:SetText(L["Steps"])
+ f.side.Lines = {} --Table to keep shown lines
+ f.side:Hide()
+ for i = 1, 18 do
+ local button = CreateFrame("Button", nil, f)
+ if i == 1 then
+ button:SetPoint("TOP", f.side.text, "BOTTOM", 0, -6)
+ else
+ button:SetPoint("TOP", f.side.Lines[i - 1], "BOTTOM")
+ end
+ button:SetWidth(130)
+ button:SetHeight(BUTTON_HEIGHT)
+ button.text = button:CreateFontString(nil, "OVERLAY")
+ button.text:SetPoint("TOPLEFT", button, "TOPLEFT", 2, -2)
+ button.text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
+ button.text:SetFont(E["media"].normFont, 14, "OUTLINE")
+ button:SetScript("OnClick", function() if i <= f.MaxPage then SetPage(i, f.CurrentPage) end end)
+ button.text:SetText("")
+ f.side.Lines[i] = button
+ button:Hide()
+ end
+
+ f:Hide()
+
+ f:SetScript("OnHide", function() PI:CloseInstall() end)
+end
+
+function PI:Queue(addon)
+ local addonIsQueued = false
+ for _, v in pairs(self.Installs) do
+ if v.Name == addon.Name then
+ addonIsQueued = true
+ end
+ end
+
+ if not addonIsQueued then
+ tinsert(self.Installs, getn(self.Installs)+1, addon)
+ self:RunInstall()
+ end
+end
+
+function PI:CloseInstall()
+ tremove(self.Installs, 1)
+ f.side:Hide()
+ for i = 1, getn(f.side.Lines) do
+ f.side.Lines[i].text:SetText("")
+ f.side.Lines[i]:Hide()
+ end
+ if getn(self.Installs) > 0 then E:Delay(1, function() PI:RunInstall() end) end
+end
+
+function PI:RunInstall()
+ if not E.private.install_complete then return end
+ if self.Installs[1] and not PluginInstallFrame:IsShown() and not (_G["ElvUIInstallFrame"] and _G["ElvUIInstallFrame"]:IsShown()) then
+ f.StepTitles = nil
+ f.StepTitlesColor = nil
+ f.StepTitlesColorSelected = nil
+ local db = self.Installs[1]
+ f.CurrentPage = 0
+ f.MaxPage = getn(db.Pages)
+
+ f.Title:SetText(db.Title or L["ElvUI Plugin Installation"])
+ f.Status:SetMinMaxValues(0, f.MaxPage)
+ f.Status.text:SetText(f.CurrentPage.." / "..f.MaxPage)
+ f.tutorialImage:SetTexture(db.tutorialImage or [[Interface\AddOns\ElvUI\media\textures\logo.tga]])
+
+ f.Pages = db.Pages
+
+ PluginInstallFrame:Show()
+ f:SetPoint("CENTER")
+ if db.StepTitles and getn(db.StepTitles) == f.MaxPage then
+ f:SetPoint("CENTER", E.UIParent, "CENTER", -((db.StepTitleWidth or 140)/2), 0)
+ f.side:SetWidth(db.StepTitleWidth or 140)
+ f.side:Show()
+
+ for i = 1, getn(f.side.Lines) do
+ if db.StepTitles[i] then
+ f.side.Lines[i]:SetWidth(db.StepTitleButtonWidth or 130)
+ f.side.Lines[i].text:SetJustifyH(db.StepTitleTextJustification or "CENTER")
+ f.side.Lines[i]:Show()
+ end
+ end
+
+ f.StepTitles = db.StepTitles
+ f.StepTitlesColor = db.StepTitlesColor
+ f.StepTitlesColorSelected = db.StepTitlesColorSelected
+ end
+ NextPage()
+ end
+ if getn(self.Installs) > 1 then
+ f.pending:Show()
+-- E:Flash(f.pending, 0.53, true)
+ else
+ f.pending:Hide()
+-- E:StopFlash(f.pending)
+ end
+end
+
+function PI:Initialize()
+ PI:CreateStepComplete()
+ PI:CreateFrame()
+end
+
+local function InitializeCallback()
+ PI:Initialize()
+end
+
+E:RegisterModule(PI:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Core/toolkit.lua b/ElvUI/Core/toolkit.lua
new file mode 100644
index 0000000..5723447
--- /dev/null
+++ b/ElvUI/Core/toolkit.lua
@@ -0,0 +1,312 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack, type = unpack, type
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+
+--Preload shit..
+E.mult = 1
+local backdropr, backdropg, backdropb, backdropa, borderr, borderg, borderb = 0, 0, 0, 1, 0, 0, 0
+
+local function GetTemplate(t, isUnitFrameElement)
+ backdropa = 1
+ if t == "ClassColor" then
+ if(CUSTOM_CLASS_COLORS) then
+ borderr, borderg, borderb = CUSTOM_CLASS_COLORS[E.myclass].r, CUSTOM_CLASS_COLORS[E.myclass].g, CUSTOM_CLASS_COLORS[E.myclass].b
+ else
+ borderr, borderg, borderb = RAID_CLASS_COLORS[E.myclass].r, RAID_CLASS_COLORS[E.myclass].g, RAID_CLASS_COLORS[E.myclass].b
+ end
+
+ if t ~= "Transparent" then
+ backdropr, backdropg, backdropb = unpack(E["media"].backdropcolor)
+ else
+ backdropr, backdropg, backdropb, backdropa = unpack(E["media"].backdropfadecolor)
+ end
+ elseif t == "Transparent" then
+ if isUnitFrameElement then
+ borderr, borderg, borderb = unpack(E["media"].bordercolor)
+ else
+ borderr, borderg, borderb = unpack(E["media"].bordercolor)
+ end
+ backdropr, backdropg, backdropb, backdropa = unpack(E["media"].backdropfadecolor)
+ else
+ if isUnitFrameElement then
+ borderr, borderg, borderb = unpack(E["media"].bordercolor)
+ else
+ borderr, borderg, borderb = unpack(E["media"].bordercolor)
+ end
+ backdropr, backdropg, backdropb = unpack(E["media"].backdropcolor)
+ end
+end
+
+function E:Size(frame, width, height)
+ assert(width)
+ frame:SetSize(E:Scale(width), E:Scale(height or width))
+end
+
+function E:Width(frame, width)
+ frame:SetWidth(E:Scale(width))
+end
+
+function E:Height(frame, height)
+ assert(height)
+ frame:SetHeight(E:Scale(height))
+end
+
+function E:Point(obj, arg1, arg2, arg3, arg4, arg5)
+ if(arg2 == nil) then
+ arg2 = obj:GetParent()
+ end
+
+ if type(arg1)=="number" then arg1 = E:Scale(arg1) end
+ if type(arg2)=="number" then arg2 = E:Scale(arg2) end
+ if type(arg3)=="number" then arg3 = E:Scale(arg3) end
+ if type(arg4)=="number" then arg4 = E:Scale(arg4) end
+ if type(arg5)=="number" then arg5 = E:Scale(arg5) end
+
+ obj:SetPoint(arg1, arg2, arg3, arg4, arg5)
+end
+
+function E:SetOutside(obj, anchor, xOffset, yOffset, anchor2)
+ xOffset = xOffset or E.Border
+ yOffset = yOffset or E.Border
+ anchor = anchor or obj:GetParent()
+
+ assert(anchor)
+ if obj:GetPoint() then
+ obj:ClearAllPoints()
+ end
+
+ obj:SetPoint("TOPLEFT", anchor, "TOPLEFT", -xOffset, yOffset)
+ obj:SetPoint("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", xOffset, -yOffset)
+end
+
+function E:SetInside(obj, anchor, xOffset, yOffset, anchor2)
+ xOffset = xOffset or E.Border
+ yOffset = yOffset or E.Border
+ anchor = anchor or obj:GetParent()
+
+ assert(anchor)
+ if obj:GetPoint() then
+ obj:ClearAllPoints()
+ end
+
+ obj:SetPoint("TOPLEFT", anchor, "TOPLEFT", xOffset, -yOffset)
+ obj:SetPoint("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", -xOffset, yOffset)
+end
+
+function E:SetTemplate(f, t, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
+ GetTemplate(t, isUnitFrameElement)
+
+ if(t) then
+ f.template = t
+ end
+
+ if(glossTex) then
+ f.glossTex = glossTex
+ end
+
+ if(ignoreUpdates) then
+ f.ignoreUpdates = ignoreUpdates
+ end
+
+ if(forcePixelMode) then
+ f.forcePixelMode = forcePixelMode
+ end
+
+ local bgFile = E.media.blankTex
+ if(glossTex) then
+ bgFile = E.media.glossTex
+ end
+
+ if(isUnitFrameElement) then
+ f.isUnitFrameElement = isUnitFrameElement
+ end
+
+ if(t ~= "NoBackdrop") then
+ if(E.private.general.pixelPerfect or f.forcePixelMode) then
+ f:SetBackdrop({
+ bgFile = bgFile,
+ edgeFile = E["media"].blankTex,
+ tile = false, tileSize = 0, edgeSize = E.mult,
+ insets = {left = 0, right = 0, top = 0, bottom = 0}
+ })
+ else
+ f:SetBackdrop({
+ bgFile = bgFile,
+ edgeFile = E["media"].blankTex,
+ tile = false, tileSize = 0, edgeSize = E.mult,
+ insets = {left = -E.mult, right = -E.mult, top = -E.mult, bottom = -E.mult}
+ })
+ end
+
+ if not f.oborder and not f.iborder and not E.private.general.pixelPerfect and not f.forcePixelMode then
+ local border = CreateFrame("Frame", nil, f)
+ E:SetInside(border, f, E.mult, E.mult)
+ border:SetBackdrop({
+ edgeFile = E["media"].blankTex,
+ edgeSize = E.mult,
+ insets = {left = E.mult, right = E.mult, top = E.mult, bottom = E.mult}
+ })
+ border:SetBackdropBorderColor(0, 0, 0, 1)
+ f.iborder = border
+
+ if f.oborder then return end
+ border = CreateFrame("Frame", nil, f)
+ E:SetOutside(border, f, E.mult, E.mult)
+ border:SetFrameLevel(f:GetFrameLevel() + 1)
+ border:SetBackdrop({
+ edgeFile = E["media"].blankTex,
+ edgeSize = E.mult,
+ insets = {left = E.mult, right = E.mult, top = E.mult, bottom = E.mult}
+ })
+ border:SetBackdropBorderColor(0, 0, 0, 1)
+ f.oborder = border
+ end
+ else
+ f:SetBackdrop(nil)
+ end
+
+ f:SetBackdropColor(backdropr, backdropg, backdropb, backdropa)
+ f:SetBackdropBorderColor(borderr, borderg, borderb)
+
+ if(not f.ignoreUpdates) then
+ if f.isUnitFrameElement then
+ E["unitFrameElements"][f] = true
+ else
+ E["frames"][f] = true
+ end
+ end
+end
+
+function E:CreateBackdrop(f, t, tex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
+ if not f then return end
+ if(not t) then t = "Default" end
+
+ local b = CreateFrame("Frame", nil, f)
+ if(f.forcePixelMode or forcePixelMode) then
+ E:SetOutside(b, nil, E.mult, E.mult)
+ else
+ E:SetOutside(b)
+ end
+ E:SetTemplate(b, t, tex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
+
+ if(f:GetFrameLevel() - 1 >= 0) then
+ b:SetFrameLevel(f:GetFrameLevel() - 1)
+ else
+ b:SetFrameLevel(0)
+ end
+
+ f.backdrop = b
+end
+
+function E:CreateShadow(f)
+ if f.shadow then return end
+
+ borderr, borderg, borderb = 0, 0, 0
+ backdropr, backdropg, backdropb = 0, 0, 0
+
+ local shadow = CreateFrame("Frame", nil, f)
+ shadow:SetFrameLevel(1)
+ shadow:SetFrameStrata(f:GetFrameStrata())
+ E:SetOutside(shadow, f, 3, 3)
+ shadow:SetBackdrop({
+ edgeFile = LSM:Fetch("border", "ElvUI GlowBorder"), edgeSize = E:Scale(3),
+ insets = {left = E:Scale(5), right = E:Scale(5), top = E:Scale(5), bottom = E:Scale(5)}
+ })
+ shadow:SetBackdropColor(backdropr, backdropg, backdropb, 0)
+ shadow:SetBackdropBorderColor(borderr, borderg, borderb, 0.9)
+ f.shadow = shadow
+end
+
+function E:Kill(object)
+ if object.UnregisterAllEvents then
+ object:UnregisterAllEvents()
+ object:SetParent(E.HiddenFrame)
+ else
+ object.Show = object.Hide
+ end
+
+ object:Hide()
+end
+
+function E:StripTextures(object, kill)
+ for _, region in ipairs({object:GetRegions()}) do
+ if region and region:GetObjectType() == "Texture" then
+ if kill and type(kill) == "boolean" then
+ E:Kill(region)
+ elseif region:GetDrawLayer() == kill then
+ region:SetTexture(nil)
+ elseif kill and type(kill) == "string" and region:GetTexture() ~= kill then
+ region:SetTexture(nil)
+ else
+ region:SetTexture(nil)
+ end
+ end
+ end
+end
+
+function E:FontTemplate(fs, font, fontSize, fontStyle)
+ fs.font = font
+ fs.fontSize = fontSize
+ fs.fontStyle = fontStyle
+
+ font = font or LSM:Fetch("font", E.db["general"].font)
+ fontSize = fontSize or E.db.general.fontSize
+
+ if fontStyle == "OUTLINE" and (E.db.general.font == "Homespun") then
+ if (fontSize > 10 and not fs.fontSize) then
+ fontStyle = "MONOCHROMEOUTLINE"
+ fontSize = 10
+ end
+ end
+
+ fs:SetFont(font, fontSize, fontStyle)
+ if fontStyle and (fontStyle ~= "NONE") then
+ fs:SetShadowColor(0, 0, 0, 0.2)
+ else
+ fs:SetShadowColor(0, 0, 0, 1)
+ end
+ fs:SetShadowOffset((E.mult or 1), -(E.mult or 1))
+
+ E["texts"][fs] = true
+end
+
+function E:StyleButton(button, noHover, noPushed, noChecked)
+ if button.SetHighlightTexture and not button.hover and not noHover then
+ local hover = button:CreateTexture()
+ hover:SetTexture(1, 1, 1, 0.3)
+ E:SetInside(hover)
+ button.hover = hover
+ button:SetHighlightTexture(hover)
+ end
+
+ if button.SetPushedTexture and not button.pushed and not noPushed then
+ local pushed = button:CreateTexture()
+ pushed:SetTexture(0.9, 0.8, 0.1, 0.3)
+ E:SetInside(pushed)
+ button.pushed = pushed
+ button:SetPushedTexture(pushed)
+ end
+
+ if button.SetCheckedTexture and not button.checked and not noChecked then
+ local checked = button:CreateTexture()
+ checked:SetTexture(1, 1, 1)
+ E:SetInside(checked)
+ checked:SetAlpha(0.3)
+ button.checked = checked
+ button:SetCheckedTexture(checked)
+ end
+
+ local cooldown = button:GetName() and _G[button:GetName().."Cooldown"]
+ if cooldown then
+ cooldown:ClearAllPoints()
+ E:SetInside(cooldown)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Core/tutorials.lua b/ElvUI/Core/tutorials.lua
new file mode 100644
index 0000000..ef038fe
--- /dev/null
+++ b/ElvUI/Core/tutorials.lua
@@ -0,0 +1,121 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local DISABLE = DISABLE
+local HIDE = HIDE
+
+E.TutorialList = {
+ L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"],
+ L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."],
+ L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."],
+ L["You can set your keybinds quickly by typing /kb."],
+ L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."],
+ L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."],
+ L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."],
+ L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."],
+ L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."],
+ L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."],
+ L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"],
+ L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."],
+ L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."]
+}
+
+function E:SetNextTutorial()
+ self.db.currentTutorial = self.db.currentTutorial or 0
+ self.db.currentTutorial = self.db.currentTutorial + 1
+
+ if self.db.currentTutorial > getn(E.TutorialList) then
+ self.db.currentTutorial = 1
+ end
+
+ ElvUITutorialWindow.desc:SetText(E.TutorialList[self.db.currentTutorial])
+end
+
+function E:SetPrevTutorial()
+ self.db.currentTutorial = self.db.currentTutorial or 0
+ self.db.currentTutorial = self.db.currentTutorial - 1
+
+ if self.db.currentTutorial <= 0 then
+ self.db.currentTutorial = getn(E.TutorialList)
+ end
+
+ ElvUITutorialWindow.desc:SetText(E.TutorialList[self.db.currentTutorial])
+end
+
+function E:SpawnTutorialFrame()
+ local f = CreateFrame("Frame", "ElvUITutorialWindow", UIParent)
+ f:SetFrameStrata("DIALOG")
+ f:SetToplevel(true)
+ f:SetClampedToScreen(true)
+ f:SetWidth(360)
+ f:SetHeight(110)
+ E:SetTemplate(f, "Transparent")
+ f:Hide()
+
+ local S = E:GetModule("Skins")
+
+ local header = CreateFrame("Button", nil, f)
+ E:SetTemplate(header, "Default", true)
+ header:SetWidth(120); header:SetHeight(25)
+ header:SetPoint("CENTER", f, "TOP")
+ header:SetFrameLevel(header:GetFrameLevel() + 2)
+
+ local title = header:CreateFontString("OVERLAY")
+ E:FontTemplate(title)
+ title:SetPoint("CENTER", header, "CENTER")
+ title:SetText("ElvUI")
+
+ local desc = f:CreateFontString("ARTWORK")
+ desc:SetFontObject("GameFontHighlight")
+ desc:SetJustifyV("TOP")
+ desc:SetJustifyH("LEFT")
+ desc:SetPoint("TOPLEFT", 18, -32)
+ desc:SetPoint("BOTTOMRIGHT", -18, 30)
+ f.desc = desc
+
+ f.disableButton = CreateFrame("CheckButton", f:GetName().."DisableButton", f, "OptionsCheckButtonTemplate")
+ _G[f.disableButton:GetName() .. "Text"]:SetText(DISABLE)
+ f.disableButton:SetPoint("BOTTOMLEFT", 1, 1)
+ S:HandleCheckBox(f.disableButton)
+ f.disableButton:SetScript("OnShow", function() this:SetChecked(E.db.hideTutorial) end)
+
+ f.disableButton:SetScript("OnClick", function() E.db.hideTutorial = this:GetChecked() end)
+
+ f.hideButton = CreateFrame("Button", f:GetName().."HideButton", f, "OptionsButtonTemplate")
+ f.hideButton:SetPoint("BOTTOMRIGHT", -5, 5)
+ S:HandleButton(f.hideButton)
+ _G[f.hideButton:GetName() .. "Text"]:SetText(HIDE)
+ f.hideButton:SetScript("OnClick", function() E:StaticPopupSpecial_Hide(this:GetParent()) end)
+
+ f.nextButton = CreateFrame("Button", f:GetName().."NextButton", f, "OptionsButtonTemplate")
+ f.nextButton:SetPoint("RIGHT", f.hideButton, "LEFT", -4, 0)
+ f.nextButton:SetWidth(20)
+ S:HandleButton(f.nextButton)
+ _G[f.nextButton:GetName() .. "Text"]:SetText(">")
+ f.nextButton:SetScript("OnClick", function() E:SetNextTutorial() end)
+
+ f.prevButton = CreateFrame("Button", f:GetName().."PrevButton", f, "OptionsButtonTemplate")
+ f.prevButton:SetPoint("RIGHT", f.nextButton, "LEFT", -4, 0)
+ f.prevButton:SetWidth(20)
+ S:HandleButton(f.prevButton)
+ _G[f.prevButton:GetName() .. "Text"]:SetText("<")
+ f.prevButton:SetScript("OnClick", function() E:SetPrevTutorial() end)
+
+ return f
+end
+
+function E:Tutorials(forceShow)
+ if (not forceShow and self.db.hideTutorial) or (not forceShow and not self.private.install_complete) then return end
+ local f = ElvUITutorialWindow
+ if not f then
+ f = E:SpawnTutorialFrame()
+ end
+
+ E:StaticPopupSpecial_Show(f)
+
+ self:SetNextTutorial()
+end
\ No newline at end of file
diff --git a/ElvUI/Developer/Frame.lua b/ElvUI/Developer/Frame.lua
new file mode 100644
index 0000000..71ac1bc
--- /dev/null
+++ b/ElvUI/Developer/Frame.lua
@@ -0,0 +1,57 @@
+--Cache global variables
+--Lua functions
+local _G = _G
+local format = string.format
+--WoW API / Variables
+local GetMouseFocus = GetMouseFocus
+
+--[[
+ Command to grab frame information when mouseing over a frame
+
+ Frame Name
+ Width
+ Height
+ Strata
+ Level
+ X Offset
+ Y Offset
+ Point
+]]
+
+SLASH_FRAME1 = "/frame"
+SlashCmdList["FRAME"] = function(arg)
+ if arg ~= "" then
+ arg = _G[arg]
+ else
+ arg = GetMouseFocus()
+ end
+ if arg ~= nil then FRAME = arg end --Set the global variable FRAME to = whatever we are mousing over to simplify messing with frames that have no name.
+ if arg ~= nil and arg:GetName() ~= nil then
+ local point, relativeTo, relativePoint, xOfs, yOfs = arg:GetPoint()
+ ChatFrame1:AddMessage("|cffCC0000----------------------------")
+ ChatFrame1:AddMessage("Name: |cffFFD100"..arg:GetName())
+ if arg:GetParent() and arg:GetParent():GetName() then
+ ChatFrame1:AddMessage("Parent: |cffFFD100"..arg:GetParent():GetName())
+ end
+
+ ChatFrame1:AddMessage("Width: |cffFFD100"..format("%.2f",arg:GetWidth()))
+ ChatFrame1:AddMessage("Height: |cffFFD100"..format("%.2f",arg:GetHeight()))
+ ChatFrame1:AddMessage("Strata: |cffFFD100"..arg:GetFrameStrata())
+ ChatFrame1:AddMessage("Level: |cffFFD100"..arg:GetFrameLevel())
+
+ if xOfs then
+ ChatFrame1:AddMessage("X: |cffFFD100"..format("%.2f",xOfs))
+ end
+ if yOfs then
+ ChatFrame1:AddMessage("Y: |cffFFD100"..format("%.2f",yOfs))
+ end
+ if relativeTo and relativeTo:GetName() then
+ ChatFrame1:AddMessage("Point: |cffFFD100"..point.."|r anchored to "..relativeTo:GetName().."'s |cffFFD100"..relativePoint)
+ end
+ ChatFrame1:AddMessage("|cffCC0000----------------------------|r")
+ elseif arg == nil then
+ ChatFrame1:AddMessage("Invalid frame name")
+ else
+ ChatFrame1:AddMessage("Could not find frame info")
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Developer/Load_Developer.xml b/ElvUI/Developer/Load_Developer.xml
new file mode 100644
index 0000000..9399215
--- /dev/null
+++ b/ElvUI/Developer/Load_Developer.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Developer/ReloadUI.lua b/ElvUI/Developer/ReloadUI.lua
new file mode 100644
index 0000000..ce7623b
--- /dev/null
+++ b/ElvUI/Developer/ReloadUI.lua
@@ -0,0 +1,7 @@
+--[[
+ Shortcut to ReloadUI
+]]
+
+SLASH_RELOADUI1 = "/rl"
+SLASH_RELOADUI2 = "/reloadui"
+SlashCmdList.RELOADUI = ReloadUI
\ No newline at end of file
diff --git a/ElvUI/Developer/Table.lua b/ElvUI/Developer/Table.lua
new file mode 100644
index 0000000..e00a2e6
--- /dev/null
+++ b/ElvUI/Developer/Table.lua
@@ -0,0 +1,22 @@
+--Cache global variables
+local setmetatable, getmetatable = setmetatable, getmetatable
+local pairs, type = pairs, type
+local table = table
+
+function table.copy(t, deep, seen)
+ seen = seen or {}
+ if t == nil then return nil end
+ if seen[t] then return seen[t] end
+
+ local nt = {}
+ for k, v in pairs(t) do
+ if deep and type(v) == "table" then
+ nt[k] = table.copy(v, deep, seen)
+ else
+ nt[k] = v
+ end
+ end
+ setmetatable(nt, table.copy(getmetatable(t), deep, seen))
+ seen[t] = nt
+ return nt
+end
\ No newline at end of file
diff --git a/ElvUI/Developer/Test.lua b/ElvUI/Developer/Test.lua
new file mode 100644
index 0000000..1b12ce3
--- /dev/null
+++ b/ElvUI/Developer/Test.lua
@@ -0,0 +1,5 @@
+--[[
+ Going to leave this as my bullshit lua file.
+
+ So I can test stuff.
+]]
diff --git a/ElvUI/ElvUI.toc b/ElvUI/ElvUI.toc
new file mode 100644
index 0000000..847289e
--- /dev/null
+++ b/ElvUI/ElvUI.toc
@@ -0,0 +1,19 @@
+## Interface: 11200
+## Author: Elv, Bunny
+## Version: 0.01
+## Title: |cffA11313E|r|cffC4C4C4lvUI|r
+## Notes: User Interface replacement AddOn for World of Warcraft.
+## SavedVariables: ElvDB, ElvPrivateDB
+## SavedVariablesPerCharacter: ElvCharacterDB
+## Dependencies: !Compatibility
+## OptionalDeps: !DebugTools, SharedMedia, Tukui, ButtonFacade
+
+Developer\Load_Developer.xml
+Libraries\Load_Libraries.xml
+Locales\Load_Locales.xml
+Media\Load_Media.xml
+Init.lua
+Settings\Load_Config.xml
+Core\Load_Core.xml
+Layout\Load_Layout.xml
+Modules\Load_Modules.xml
\ No newline at end of file
diff --git a/ElvUI/Init.lua b/ElvUI/Init.lua
new file mode 100644
index 0000000..46a7471
--- /dev/null
+++ b/ElvUI/Init.lua
@@ -0,0 +1,152 @@
+local _G = _G
+
+BINDING_HEADER_ELVUI = GetAddOnMetadata("ElvUI", "Title")
+
+local AddOnName, Engine = "ElvUI", {}
+local AddOn = LibStub("AceAddon-3.0"):NewAddon(AddOnName, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceHook-3.0")
+AddOn.callbacks = AddOn.callbacks or
+ LibStub("CallbackHandler-1.0"):New(AddOn)
+AddOn.DF = {} AddOn.DF["profile"] = {} AddOn.DF["global"] = {} AddOn.privateVars = {} AddOn.privateVars["profile"] = {} -- Defaults
+AddOn.Options = {
+ type = "group",
+ name = AddOnName,
+ args = {},
+}
+
+local Locale = LibStub("AceLocale-3.0"):GetLocale(AddOnName, false)
+Engine[1] = AddOn
+Engine[2] = Locale
+Engine[3] = AddOn.privateVars["profile"]
+Engine[4] = AddOn.DF["profile"]
+Engine[5] = AddOn.DF["global"]
+
+_G[AddOnName] = Engine
+local tcopy = table.copy
+function AddOn:OnInitialize()
+ if not ElvCharacterDB then
+ ElvCharacterDB = {}
+ end
+
+ self.db = tcopy(self.DF.profile, true)
+ self.global = tcopy(self.DF.global, true)
+ if ElvDB then
+ if ElvDB.global then
+ self:CopyTable(self.global, ElvDB.global)
+ end
+
+ local profileKey
+ if ElvDB.profileKeys then
+ profileKey = ElvDB.profileKeys[self.myname.." - "..self.myrealm]
+ end
+
+ if profileKey and ElvDB.profiles and ElvDB.profiles[profileKey] then
+ self:CopyTable(self.db, ElvDB.profiles[profileKey])
+ end
+ end
+
+ self.private = tcopy(self.privateVars.profile, true)
+ if ElvPrivateDB then
+ local profileKey
+ if ElvPrivateDB.profileKeys then
+ profileKey = ElvPrivateDB.profileKeys[self.myname.." - "..self.myrealm]
+ end
+
+ if profileKey and ElvPrivateDB.profiles and ElvPrivateDB.profiles[profileKey] then
+ self:CopyTable(self.private, ElvPrivateDB.profiles[profileKey])
+ end
+ end
+
+ if self.private.general.pixelPerfect then
+ self.Border = self.mult
+ self.Spacing = 0
+ self.PixelMode = true
+ end
+
+ self:UIScale()
+ self:UpdateMedia()
+
+ self:RegisterEvent("PLAYER_LOGIN", "Initialize")
+ self:Contruct_StaticPopups()
+ self:InitializeInitialModules()
+
+ if IsAddOnLoaded("Tukui") then
+ self:StaticPopup_Show("TUKUI_ELVUI_INCOMPATIBLE")
+ end
+
+ local GameMenuButton = CreateFrame("Button", nil, GameMenuFrame, "GameMenuButtonTemplate")
+ GameMenuButton:SetWidth(GameMenuButtonLogout:GetWidth())
+ GameMenuButton:SetHeight(GameMenuButtonLogout:GetHeight())
+
+ GameMenuButton:SetText(self:ColorizedName(AddOnName))
+ GameMenuButton:SetScript("OnClick", function()
+ AddOn:ToggleConfig()
+ HideUIPanel(GameMenuFrame)
+ end)
+ GameMenuFrame[AddOnName] = GameMenuButton
+
+ HookScript(GameMenuFrame, "OnShow", function()
+ if not GameMenuFrame.isElvUI then
+ GameMenuFrame:SetHeight(GameMenuFrame:GetHeight() + GameMenuButtonLogout:GetHeight() + 1)
+ GameMenuFrame.isElvUI = true
+ end
+ local _, relTo = GameMenuButtonLogout:GetPoint()
+ if relTo ~= GameMenuFrame[AddOnName] then
+ GameMenuFrame[AddOnName]:ClearAllPoints()
+ GameMenuFrame[AddOnName]:SetPoint("TOPLEFT", relTo, "BOTTOMLEFT", 0, -1)
+ GameMenuButtonLogout:ClearAllPoints()
+ GameMenuButtonLogout:SetPoint("TOPLEFT", GameMenuFrame[AddOnName], "BOTTOMLEFT", 0, -16)
+ end
+ end)
+ local S = AddOn:GetModule("Skins")
+ S:HandleButton(GameMenuButton)
+end
+
+function AddOn:ResetProfile()
+ local profileKey
+ if ElvPrivateDB.profileKeys then
+ profileKey = ElvPrivateDB.profileKeys[self.myname.." - "..self.myrealm]
+ end
+
+ if profileKey and ElvPrivateDB.profiles and ElvPrivateDB.profiles[profileKey] then
+ ElvPrivateDB.profiles[profileKey] = nil
+ end
+
+ ElvCharacterDB = nil
+ ReloadUI()
+end
+
+function AddOn:OnProfileReset()
+ self:StaticPopup_Show("RESET_PROFILE_PROMPT")
+end
+
+function AddOn:ToggleConfig()
+ if not IsAddOnLoaded("ElvUI_Config") then
+ local _, _, _, _, _, reason = GetAddOnInfo("ElvUI_Config")
+ if reason ~= "MISSING" and reason ~= "DISABLED" then
+ LoadAddOn("ElvUI_Config")
+ if GetAddOnMetadata("ElvUI_Config", "Version") ~= "1.01" then
+ self:StaticPopup_Show("CLIENT_UPDATE_REQUEST")
+ end
+ else
+ self:Print("|cffff0000Error -- Addon 'ElvUI_Config' not found or is disabled.|r")
+ return
+ end
+ end
+
+ local ACD = LibStub("AceConfigDialog-3.0")
+
+ local mode = "Close"
+ if not ACD.OpenFrames[AddOnName] then
+ mode = "Open"
+ end
+
+ if mode == "Open" then
+ PlaySound("igMainMenuOpen")
+ else
+ PlaySound("igMainMenuClose")
+ end
+
+ ACD[mode](ACD, AddOnName)
+
+ GameTooltip:Hide() --Just in case you're mouseovered something and it closes.
+end
diff --git a/ElvUI/Layout/Layout.lua b/ElvUI/Layout/Layout.lua
new file mode 100644
index 0000000..151d58d
--- /dev/null
+++ b/ElvUI/Layout/Layout.lua
@@ -0,0 +1,415 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local LO = E:NewModule("Layout", "AceEvent-3.0");
+
+--Cache global variables
+--Lua functions
+
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local UIFrameFadeIn, UIFrameFadeOut = UIFrameFadeIn, UIFrameFadeOut
+
+local PANEL_HEIGHT = 22
+local SIDE_BUTTON_WIDTH = 16
+
+E.Layout = LO
+
+local function Panel_OnShow(self)
+ self:SetFrameLevel(0)
+ self:SetFrameStrata("BACKGROUND")
+end
+
+function LO:Initialize()
+ self:CreateChatPanels()
+ self:CreateMinimapPanels()
+
+ self:SetDataPanelStyle()
+
+ self.BottomPanel = CreateFrame("Frame", "ElvUI_BottomPanel", E.UIParent)
+ E:SetTemplate(self.BottomPanel, "Transparent")
+ self.BottomPanel:SetPoint("BOTTOMLEFT", E.UIParent, "BOTTOMLEFT", -1, -1)
+ self.BottomPanel:SetPoint("BOTTOMRIGHT", E.UIParent, "BOTTOMRIGHT", 1, -1)
+ self.BottomPanel:SetHeight(PANEL_HEIGHT)
+ self.BottomPanel:SetScript("OnShow", function() Panel_OnShow(this) end)
+ Panel_OnShow(self.BottomPanel)
+ self:BottomPanelVisibility()
+
+ self.TopPanel = CreateFrame("Frame", "ElvUI_TopPanel", E.UIParent)
+ E:SetTemplate(self.TopPanel, "Transparent")
+ self.TopPanel:SetPoint("TOPLEFT", E.UIParent, "TOPLEFT", -1, 1)
+ self.TopPanel:SetPoint("TOPRIGHT", E.UIParent, "TOPRIGHT", 1, 1)
+ self.TopPanel:SetHeight(PANEL_HEIGHT)
+ self.TopPanel:SetScript("OnShow", function() Panel_OnShow(this) end)
+ Panel_OnShow(self.TopPanel)
+ self:TopPanelVisibility()
+end
+
+function LO:BottomPanelVisibility()
+ if(E.db.general.bottomPanel) then
+ self.BottomPanel:Show()
+ else
+ self.BottomPanel:Hide()
+ end
+end
+
+function LO:TopPanelVisibility()
+ if E.db.general.topPanel then
+ self.TopPanel:Show()
+ else
+ self.TopPanel:Hide()
+ end
+end
+
+local function ChatPanelLeft_OnFade()
+ LeftChatPanel:Hide()
+end
+
+local function ChatPanelRight_OnFade()
+ RightChatPanel:Hide()
+end
+
+local function ChatButton_OnEnter()
+ if E.db[this.parent:GetName().."Faded"] then
+ this.parent:Show()
+ UIFrameFadeIn(this.parent, 0.2, this.parent:GetAlpha(), 1)
+ UIFrameFadeIn(this, 0.2, this:GetAlpha(), 1)
+ end
+
+ if this == LeftChatToggleButton then
+ GameTooltip:SetOwner(this, "ANCHOR_TOPLEFT", 0, (E.PixelMode and 1 or 3))
+ GameTooltip:ClearLines()
+ GameTooltip:AddDoubleLine(L["Left Click:"], L["Toggle Chat Frame"], 1, 1, 1)
+ else
+ GameTooltip:SetOwner(this, "ANCHOR_TOPRIGHT", 0, (E.PixelMode and 1 or 3))
+ GameTooltip:ClearLines()
+ GameTooltip:AddDoubleLine(L["Left Click:"], L["Toggle Chat Frame"], 1, 1, 1)
+ end
+
+ GameTooltip:Show()
+end
+
+local function ChatButton_OnLeave()
+ if E.db[this.parent:GetName().."Faded"] then
+ UIFrameFadeOut(this.parent, 0.2, this.parent:GetAlpha(), 0)
+ UIFrameFadeOut(this, 0.2, this:GetAlpha(), 0)
+ this.parent.fadeInfo.finishedFunc = this.parent.fadeFunc
+ end
+ GameTooltip:Hide()
+end
+
+local function ChatButton_OnClick()
+ GameTooltip:Hide()
+ if E.db[this.parent:GetName().."Faded"] then
+ E.db[this.parent:GetName().."Faded"] = nil
+ UIFrameFadeIn(this.parent, 0.2, this.parent:GetAlpha(), 1)
+ UIFrameFadeIn(this, 0.2, this:GetAlpha(), 1)
+ else
+ E.db[this.parent:GetName().."Faded"] = true
+ UIFrameFadeOut(this.parent, 0.2, this.parent:GetAlpha(), 0)
+ UIFrameFadeOut(this, 0.2, this:GetAlpha(), 0)
+ this.parent.fadeInfo.finishedFunc = this.parent.fadeFunc
+ end
+end
+
+function HideLeftChat()
+ ChatButton_OnClick(LeftChatToggleButton)
+end
+
+function HideRightChat()
+ ChatButton_OnClick(RightChatToggleButton)
+end
+
+function HideBothChat()
+ ChatButton_OnClick(LeftChatToggleButton)
+ ChatButton_OnClick(RightChatToggleButton)
+end
+
+function LO:ToggleChatTabPanels(rightOverride, leftOverride)
+ if leftOverride or not E.db.chat.panelTabBackdrop then
+ LeftChatTab:Hide()
+ else
+ LeftChatTab:Show()
+ end
+
+ if rightOverride or not E.db.chat.panelTabBackdrop then
+ RightChatTab:Hide()
+ else
+ RightChatTab:Show()
+ end
+end
+
+function LO:SetChatTabStyle()
+ if E.db.chat.panelTabTransparency then
+ E:SetTemplate(LeftChatTab, "Transparent")
+ E:SetTemplate(RightChatTab, "Transparent")
+ else
+ E:SetTemplate(LeftChatTab, "Default", true)
+ E:SetTemplate(RightChatTab, "Default", true)
+ end
+end
+
+function LO:SetDataPanelStyle()
+ if E.db.datatexts.panelTransparency then
+ if not E.db.datatexts.panelBackdrop then
+ E:SetTemplate(LeftChatDataPanel, "NoBackdrop")
+ E:SetTemplate(LeftChatToggleButton, "NoBackdrop")
+ E:SetTemplate(RightChatDataPanel, "NoBackdrop")
+ E:SetTemplate(RightChatToggleButton, "NoBackdrop")
+ else
+ E:SetTemplate(LeftChatDataPanel, "Transparent")
+ E:SetTemplate(LeftChatToggleButton, "Transparent")
+ E:SetTemplate(RightChatDataPanel, "Transparent")
+ E:SetTemplate(RightChatToggleButton, "Transparent")
+ end
+
+ E:SetTemplate(LeftMiniPanel, "Transparent")
+ E:SetTemplate(RightMiniPanel, "Transparent")
+ else
+ if not E.db.datatexts.panelBackdrop then
+ E:SetTemplate(LeftChatDataPanel, "NoBackdrop")
+ E:SetTemplate(LeftChatToggleButton, "NoBackdrop")
+ E:SetTemplate(RightChatDataPanel, "NoBackdrop")
+ E:SetTemplate(RightChatToggleButton, "NoBackdrop")
+ else
+ E:SetTemplate(LeftChatDataPanel, "Default", true)
+ E:SetTemplate(LeftChatToggleButton, "Default", true)
+ E:SetTemplate(RightChatDataPanel, "Default", true)
+ E:SetTemplate(RightChatToggleButton, "Default", true)
+ end
+
+ E:SetTemplate(RightMiniPanel, "Default", true)
+ E:SetTemplate(LeftMiniPanel, "Default", true)
+ end
+end
+
+function LO:ToggleChatPanels()
+ LeftChatDataPanel:ClearAllPoints()
+ RightChatDataPanel:ClearAllPoints()
+ local SPACING = E.Border*3 - E.Spacing
+
+ if E.db.datatexts.leftChatPanel then
+ LeftChatDataPanel:Show()
+ LeftChatToggleButton:Show()
+ else
+ LeftChatDataPanel:Hide()
+ LeftChatToggleButton:Hide()
+ end
+
+ if E.db.datatexts.rightChatPanel then
+ RightChatDataPanel:Show()
+ RightChatToggleButton:Show()
+ else
+ RightChatDataPanel:Hide()
+ RightChatToggleButton:Hide()
+ end
+
+ local panelBackdrop = E.db.chat.panelBackdrop
+ if(panelBackdrop == "SHOWBOTH") then
+ LeftChatPanel.backdrop:Show()
+ RightChatPanel.backdrop:Show()
+ LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING + SIDE_BUTTON_WIDTH, SPACING)
+ RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT", SPACING, SPACING)
+ LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING, SPACING)
+ RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", -SPACING, SPACING)
+ LO:ToggleChatTabPanels()
+ elseif(panelBackdrop == "HIDEBOTH") then
+ LeftChatPanel.backdrop:Hide()
+ RightChatPanel.backdrop:Hide()
+ LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SIDE_BUTTON_WIDTH, 0)
+ RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT")
+ LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT")
+ RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT")
+ LO:ToggleChatTabPanels(true, true)
+ elseif(panelBackdrop == "LEFT") then
+ LeftChatPanel.backdrop:Show()
+ RightChatPanel.backdrop:Hide()
+ LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING + SIDE_BUTTON_WIDTH, SPACING)
+ RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT")
+ LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING, SPACING)
+ RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT")
+ LO:ToggleChatTabPanels(true)
+ else
+ LeftChatPanel.backdrop:Hide()
+ RightChatPanel.backdrop:Show()
+ LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SIDE_BUTTON_WIDTH, 0)
+ RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT", SPACING, SPACING)
+ LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT")
+ RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", -SPACING, SPACING)
+ LO:ToggleChatTabPanels(nil, true)
+ end
+end
+
+function LO:CreateChatPanels()
+ local SPACING = E.Border*3 - E.Spacing
+ --Left Chat
+ local lchat = CreateFrame("Frame", "LeftChatPanel", E.UIParent)
+ lchat:SetFrameStrata("BACKGROUND")
+ lchat:SetWidth(E.db.chat.panelWidth)
+ lchat:SetHeight(E.db.chat.panelHeight)
+ lchat:SetPoint("BOTTOMLEFT", E.UIParent, 4, 4)
+ lchat:SetFrameLevel(lchat:GetFrameLevel() + 2)
+ E:CreateBackdrop(lchat, "Transparent")
+ lchat.backdrop:SetAllPoints()
+ E:CreateMover(lchat, "LeftChatMover", L["Left Chat"])
+
+ --Background Texture
+ lchat.tex = lchat:CreateTexture(nil, "OVERLAY")
+ E:SetInside(lchat.tex)
+ lchat.tex:SetTexture(E.db.chat.panelBackdropNameLeft)
+ lchat.tex:SetAlpha(E.db.general.backdropfadecolor.a - 0.7 > 0 and E.db.general.backdropfadecolor.a - 0.7 or 0.5)
+
+ --Left Chat Tab
+ local lchattab = CreateFrame("Frame", "LeftChatTab", LeftChatPanel)
+ lchattab:SetPoint("TOPLEFT", lchat, "TOPLEFT", SPACING, -SPACING)
+ lchattab:SetPoint("BOTTOMRIGHT", lchat, "TOPRIGHT", -SPACING, -(SPACING + PANEL_HEIGHT))
+ E:SetTemplate(lchattab, E.db.chat.panelTabTransparency == true and "Transparent" or "Default", true)
+
+ --Left Chat Data Panel
+ local lchatdp = CreateFrame("Frame", "LeftChatDataPanel", LeftChatPanel)
+ lchatdp:SetWidth(E.db.chat.panelWidth -((SPACING*2) + SIDE_BUTTON_WIDTH))
+ lchatdp:SetHeight(PANEL_HEIGHT)
+ lchatdp:SetPoint("BOTTOMLEFT", lchat, "BOTTOMLEFT", SPACING + SIDE_BUTTON_WIDTH, SPACING)
+ E:SetTemplate(lchatdp, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
+ E:GetModule("DataTexts"):RegisterPanel(lchatdp, 3, "ANCHOR_TOPLEFT", -16, (E.PixelMode and 1 or 3))
+
+ --Left Chat Toggle Button
+ local lchattb = CreateFrame("Button", "LeftChatToggleButton", E.UIParent)
+ lchattb.parent = LeftChatPanel
+ LeftChatPanel.fadeFunc = ChatPanelLeft_OnFade
+ lchattb:SetPoint("TOPRIGHT", lchatdp, "TOPLEFT", E.Border - E.Spacing*3, 0)
+ lchattb:SetPoint("BOTTOMLEFT", lchat, "BOTTOMLEFT", SPACING, SPACING)
+ E:SetTemplate(lchattb, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
+ lchattb:SetScript("OnEnter", ChatButton_OnEnter)
+ lchattb:SetScript("OnLeave", ChatButton_OnLeave)
+ lchattb:SetScript("OnClick", ChatButton_OnClick)
+ lchattb.text = lchattb:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(lchattb.text)
+ lchattb.text:SetPoint("CENTER", lchattb)
+ lchattb.text:SetJustifyH("CENTER")
+ lchattb.text:SetText("<")
+
+ --Right Chat
+ local rchat = CreateFrame("Frame", "RightChatPanel", E.UIParent)
+ rchat:SetFrameStrata("BACKGROUND")
+ rchat:SetWidth(E.db.chat.separateSizes and E.db.chat.panelWidthRight or E.db.chat.panelWidth)
+ rchat:SetHeight(E.db.chat.separateSizes and E.db.chat.panelHeightRight or E.db.chat.panelHeight)
+ rchat:SetPoint("BOTTOMRIGHT", E.UIParent, -4, 4)
+ rchat:SetFrameLevel(lchat:GetFrameLevel() + 2)
+ E:CreateBackdrop(rchat, "Transparent")
+ rchat.backdrop:SetAllPoints()
+ E:CreateMover(rchat, "RightChatMover", L["Right Chat"])
+
+ --Background Texture
+ rchat.tex = rchat:CreateTexture(nil, "OVERLAY")
+ E:SetInside(rchat.tex)
+ rchat.tex:SetTexture(E.db.chat.panelBackdropNameRight)
+ rchat.tex:SetAlpha(E.db.general.backdropfadecolor.a - 0.7 > 0 and E.db.general.backdropfadecolor.a - 0.7 or 0.5)
+
+ --Right Chat Tab
+ local rchattab = CreateFrame("Frame", "RightChatTab", RightChatPanel)
+ rchattab:SetPoint("TOPRIGHT", rchat, "TOPRIGHT", -SPACING, -SPACING)
+ rchattab:SetPoint("BOTTOMLEFT", rchat, "TOPLEFT", SPACING, -(SPACING + PANEL_HEIGHT))
+ E:SetTemplate(rchattab, E.db.chat.panelTabTransparency == true and "Transparent" or "Default", true)
+
+ --Right Chat Data Panel
+ local rchatdp = CreateFrame("Frame", "RightChatDataPanel", RightChatPanel)
+ rchatdp:SetWidth((E.db.chat.separateSizes and E.db.chat.panelWidthRight or E.db.chat.panelWidth) -((SPACING*2) + SIDE_BUTTON_WIDTH))
+ rchatdp:SetHeight(PANEL_HEIGHT)
+ rchatdp:SetPoint("BOTTOMLEFT", rchat, "BOTTOMLEFT", SPACING, SPACING)
+ E:SetTemplate(rchatdp, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
+ E:GetModule("DataTexts"):RegisterPanel(rchatdp, 3, "ANCHOR_TOPRIGHT", 16, (E.PixelMode and 1 or 3))
+
+ --Right Chat Toggle Button
+ local rchattb = CreateFrame("Button", "RightChatToggleButton", E.UIParent)
+ rchattb.parent = RightChatPanel
+ RightChatPanel.fadeFunc = ChatPanelRight_OnFade
+ rchattb:SetPoint("TOPLEFT", rchatdp, "TOPRIGHT", -E.Border + E.Spacing*3, 0)
+ rchattb:SetPoint("BOTTOMRIGHT", rchat, "BOTTOMRIGHT", -SPACING, SPACING)
+ E:SetTemplate(rchattb, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
+ rchattb:SetScript("OnEnter", ChatButton_OnEnter)
+ rchattb:SetScript("OnLeave", ChatButton_OnLeave)
+ rchattb:SetScript("OnClick", ChatButton_OnClick)
+ rchattb.text = rchattb:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(rchattb.text)
+ rchattb.text:SetPoint("CENTER", rchattb)
+ rchattb.text:SetJustifyH("CENTER")
+ rchattb.text:SetText(">")
+
+ --Load Settings
+ if E.db["LeftChatPanelFaded"] then
+ LeftChatToggleButton:SetAlpha(0)
+ LeftChatPanel:Hide()
+ end
+
+ if E.db["RightChatPanelFaded"] then
+ RightChatToggleButton:SetAlpha(0)
+ RightChatPanel:Hide()
+ end
+
+ self:ToggleChatPanels()
+end
+
+function LO:CreateMinimapPanels()
+ local lminipanel = CreateFrame("Frame", "LeftMiniPanel", Minimap.backdrop)
+ lminipanel:SetWidth(E.db.general.minimap.size/2 + (E.PixelMode and 1 or 3))
+ lminipanel:SetHeight(PANEL_HEIGHT)
+ lminipanel:SetPoint("TOPLEFT", Minimap, "BOTTOMLEFT", -E.Border, (E.PixelMode and 0 or -3))
+ E:SetTemplate(lminipanel, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
+ E:GetModule("DataTexts"):RegisterPanel(lminipanel, 1, "ANCHOR_BOTTOMLEFT", lminipanel:GetWidth() * 2, -(E.PixelMode and 1 or 3))
+
+ local rminipanel = CreateFrame("Frame", "RightMiniPanel", Minimap.backdrop)
+ rminipanel:SetWidth(E.db.general.minimap.size/2 + (E.PixelMode and 1 or 3))
+ rminipanel:SetHeight(PANEL_HEIGHT)
+ rminipanel:SetPoint("TOPRIGHT", Minimap, "BOTTOMRIGHT", E.Border, (E.PixelMode and 0 or -3))
+ E:SetTemplate(rminipanel, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
+ E:GetModule("DataTexts"):RegisterPanel(rminipanel, 1, "ANCHOR_BOTTOM", 0, -(E.PixelMode and 1 or 3))
+
+ if E.db.datatexts.minimapPanels then
+ LeftMiniPanel:Show()
+ RightMiniPanel:Show()
+ else
+ LeftMiniPanel:Hide()
+ RightMiniPanel:Hide()
+ end
+
+ local f = CreateFrame("Frame", "BottomMiniPanel", Minimap.backdrop)
+ f:SetPoint("BOTTOM", Minimap, "BOTTOM")
+ f:SetWidth(75)
+ f:SetHeight(20)
+ E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOM", 0, -10)
+
+ f = CreateFrame("Frame", "TopMiniPanel", Minimap.backdrop)
+ f:SetPoint("TOP", Minimap, "TOP")
+ f:SetWidth(75)
+ f:SetHeight(20)
+ E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOM", 0, -10)
+
+ f = CreateFrame("Frame", "TopLeftMiniPanel", Minimap.backdrop)
+ f:SetPoint("TOPLEFT", Minimap, "TOPLEFT")
+ f:SetWidth(75)
+ f:SetHeight(20)
+ E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMLEFT", 0, -10)
+
+ f = CreateFrame("Frame", "TopRightMiniPanel", Minimap.backdrop)
+ f:SetPoint("TOPRIGHT", Minimap, "TOPRIGHT")
+ f:SetWidth(75)
+ f:SetHeight(20)
+ E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMRIGHT", 0, -10)
+
+ f = CreateFrame("Frame", "BottomLeftMiniPanel", Minimap.backdrop)
+ f:SetPoint("BOTTOMLEFT", Minimap, "BOTTOMLEFT")
+ f:SetWidth(75)
+ f:SetHeight(20)
+ E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMLEFT", 0, -10)
+
+ f = CreateFrame("Frame", "BottomRightMiniPanel", Minimap.backdrop)
+ f:SetPoint("BOTTOMRIGHT", Minimap, "BOTTOMRIGHT")
+ f:SetWidth(75)
+ f:SetHeight(20)
+ E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMRIGHT", 0, -10)
+end
+
+local function InitializeCallback()
+ LO:Initialize()
+end
+
+E:RegisterModule(LO:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Layout/Load_Layout.xml b/ElvUI/Layout/Load_Layout.xml
new file mode 100644
index 0000000..5b02b2e
--- /dev/null
+++ b/ElvUI/Layout/Load_Layout.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceAddon-3.0/AceAddon-3.0.lua b/ElvUI/Libraries/AceAddon-3.0/AceAddon-3.0.lua
new file mode 100644
index 0000000..cc99899
--- /dev/null
+++ b/ElvUI/Libraries/AceAddon-3.0/AceAddon-3.0.lua
@@ -0,0 +1,681 @@
+--- **AceAddon-3.0** provides a template for creating addon objects.
+-- It'll provide you with a set of callback functions that allow you to simplify the loading
+-- process of your addon.\\
+-- Callbacks provided are:\\
+-- * **OnInitialize**, which is called directly after the addon is fully loaded.
+-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
+-- * **OnDisable**, which is only called when your addon is manually being disabled.
+-- @usage
+-- -- A small (but complete) addon, that doesn't do anything,
+-- -- but shows usage of the callbacks.
+-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+--
+-- function MyAddon:OnInitialize()
+-- -- do init tasks here, like loading the Saved Variables,
+-- -- or setting up slash commands.
+-- end
+--
+-- function MyAddon:OnEnable()
+-- -- Do more initialization here, that really enables the use of your addon.
+-- -- Register Events, Hook functions, Create Frames, Get information from
+-- -- the game that wasn't available in OnInitialize
+-- end
+--
+-- function MyAddon:OnDisable()
+-- -- Unhook, Unregister Events, Hide frames that you created.
+-- -- You would probably only use an OnDisable if you want to
+-- -- build a "standby" mode, or be able to toggle modules on/off.
+-- end
+-- @class file
+-- @name AceAddon-3.0.lua
+-- @release $Id: AceAddon-3.0.lua 1084 2013-04-27 20:14:11Z nevcairiel $
+
+local MAJOR, MINOR = "AceAddon-3.0", 12
+local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceAddon then return end -- No Upgrade needed.
+
+local AceCore = LibStub("AceCore-3.0")
+local new, del = AceCore.new, AceCore.del
+local wipe, truncate = AceCore.wipe, AceCore.truncate
+
+AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
+AceAddon.addons = AceAddon.addons or {} -- addons in general
+AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
+AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
+AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
+AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
+
+-- Lua APIs
+local tinsert, tconcat, tremove, tgetn = table.insert, table.concat, table.remove, table.getn
+local strfmt, tostring = string.format, tostring
+local pairs, next, type, unpack = pairs, next, type, unpack
+local loadstring, assert, error = loadstring, assert, error
+local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
+
+--[[
+ xpcall safecall implementation
+]]
+local safecall = AceCore.safecall
+
+-- local functions that will be implemented further down
+local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
+
+-- used in the addon metatable
+local function addontostring( self ) return self.name end
+
+-- Check if the addon is queued for initialization
+local function queuedForInitialization(addon)
+ for i = 1, tgetn(AceAddon.initializequeue) do
+ if AceAddon.initializequeue[i] == addon then
+ return true
+ end
+ end
+ return false
+end
+
+--- Create a new AceAddon-3.0 addon.
+-- Any libraries you specified will be embeded, and the addon will be scheduled for
+-- its OnInitialize and OnEnable callbacks.
+-- The final addon object, with all libraries embeded, will be returned.
+-- @paramsig [object ,]name[, lib, ...]
+-- @param object Table to use as a base for the addon (optional)
+-- @param name Name of the addon object to create
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create a simple addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
+--
+-- -- Create a Addon object based on the table of a frame
+-- local MyFrame = CreateFrame("Frame")
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
+function AceAddon:NewAddon(objectorname,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+
+ local object,name
+ if type(objectorname)=="table" then
+ object=objectorname
+ name=a0
+ else
+ name=objectorname
+ end
+ if type(name)~="string" then
+ error(strfmt("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'.", type(name)), 2)
+ end
+ if self.addons[name] then
+ error(strfmt("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists.", name), 2)
+ end
+
+ local args = new()
+ args[1] = a1
+ args[2] = a2
+ args[3] = a3
+ args[4] = a4
+ args[5] = a5
+ args[6] = a6
+ args[7] = a7
+ args[8] = a8
+ args[9] = a9
+ args[10] = a10
+
+ object = object or {}
+ object.name = name
+
+ local addonmeta = {}
+ local oldmeta = getmetatable(object)
+ if oldmeta then
+ for k, v in pairs(oldmeta) do addonmeta[k] = v end
+ end
+ addonmeta.__tostring = addontostring
+
+ setmetatable( object, addonmeta )
+ self.addons[name] = object
+ object.modules = {}
+ object.orderedModules = {}
+ object.defaultModuleLibraries = {}
+ Embed( object ) -- embed NewModule, GetModule methods
+ if type(objectorname)=="table" then
+ self:EmbedLibraries(object,nil,args)
+ elseif a0 then
+ self:EmbedLibraries(object,a0,args)
+ end
+ del(args)
+
+ -- add to queue of addons to be initialized upon ADDON_LOADED
+ tinsert(self.initializequeue, object)
+ return object
+end
+
+--- Get the addon object by its name from the internal AceAddon registry.
+-- Throws an error if the addon object cannot be found (except if silent is set).
+-- @param name unique name of the addon object
+-- @param silent if true, the addon is optional, silently return nil if its not found
+-- @usage
+-- -- Get the Addon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+function AceAddon:GetAddon(name, silent)
+ if not silent and not self.addons[name] then
+ error(strfmt("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'.", tostring(name)), 2)
+ end
+ return self.addons[name]
+end
+
+-- - Embed a list of libraries into the specified addon.
+-- This function will try to embed all of the listed libraries into the addon
+-- and error if a single one fails.
+--
+-- **Note:** This function is for internal use by :NewAddon/:NewModule
+-- @paramsig addon, [lib, ...]
+-- @param addon addon object to embed the libs in
+-- @param lib List of libraries to embed into the addon
+function AceAddon:EmbedLibraries(addon,a1,arg)
+ if a1 then self:EmbedLibrary(addon, a1, false, 4) end
+ -- 10 is the max number of variable arguments in the function NewAddon and NewModule
+ for i=1,10 do
+ if not arg[i] then return end
+ self:EmbedLibrary(addon, arg[i], false, 4)
+ end
+end
+
+-- - Embed a library into the addon object.
+-- This function will check if the specified library is registered with LibStub
+-- and if it has a :Embed function to call. It'll error if any of those conditions
+-- fails.
+--
+-- **Note:** This function is for internal use by :EmbedLibraries
+-- @paramsig addon, libname[, silent[, offset]]
+-- @param addon addon object to embed the library in
+-- @param libname name of the library to embed
+-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
+-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
+function AceAddon:EmbedLibrary(addon, libname, silent, offset)
+ local lib = LibStub:GetLibrary(libname, true)
+ if not lib and not silent then
+ error(strfmt("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q.", tostring(libname)), offset or 2)
+ elseif lib and type(lib.Embed) == "function" then
+ lib:Embed(addon)
+ tinsert(self.embeds[addon], libname)
+ return true
+ elseif lib then
+ error(strfmt("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable", libname), offset or 2)
+ end
+end
+
+--- Return the specified module from an addon object.
+-- Throws an error if the addon object cannot be found (except if silent is set)
+-- @name //addon//:GetModule
+-- @paramsig name[, silent]
+-- @param name unique name of the module
+-- @param silent if true, the module is optional, silently return nil if its not found (optional)
+-- @usage
+-- -- Get the Addon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- -- Get the Module
+-- MyModule = MyAddon:GetModule("MyModule")
+function GetModule(self, name, silent)
+ if not self.modules[name] and not silent then
+ error(strfmt("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'.", tostring(name)), 2)
+ end
+ return self.modules[name]
+end
+
+local function IsModuleTrue(self) return true end
+
+--- Create a new module for the addon.
+-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
+-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
+-- an addon object.
+-- @name //addon//:NewModule
+-- @paramsig name[, prototype|lib[, lib, ...]]
+-- @param name unique name of the module
+-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create a module with some embeded libraries
+-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
+--
+-- -- Create a module with a prototype
+-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
+-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
+function NewModule(self, name, prototype, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if type(name) ~= "string" then error(strfmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'.", type(name)), 2) end
+ if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(strfmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'.", type(prototype)), 2) end
+
+ if self.modules[name] then error(strfmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists.", name), 2) end
+
+ -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
+ -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
+ local module = AceAddon:NewAddon(strfmt("%s_%s", self.name or tostring(self), name))
+
+ module.IsModule = IsModuleTrue
+ module:SetEnabledState(self.defaultModuleState)
+ module.moduleName = name
+
+ local args = new()
+ args[1] = a1
+ args[2] = a2
+ args[3] = a3
+ args[4] = a4
+ args[5] = a5
+ args[6] = a6
+ args[7] = a7
+ args[8] = a8
+ args[9] = a9
+ args[10] = a10
+
+ if type(prototype) == "string" then
+ AceAddon:EmbedLibraries(module, prototype, args)
+ else
+ AceAddon:EmbedLibraries(module, nil, args)
+ end
+ del(args)
+ AceAddon:EmbedLibraries(module, nil, self.defaultModuleLibraries)
+
+ if not prototype or type(prototype) == "string" then
+ prototype = self.defaultModulePrototype or nil
+ end
+
+ if type(prototype) == "table" then
+ local mt = getmetatable(module)
+ mt.__index = prototype
+ setmetatable(module, mt) -- More of a Base class type feel.
+ end
+
+ safecall(self.OnModuleCreated, 2, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
+ self.modules[name] = module
+ tinsert(self.orderedModules, module)
+
+ return module
+end
+
+--- Returns the real name of the addon or module, without any prefix.
+-- @name //addon//:GetName
+-- @paramsig
+-- @usage
+-- print(MyAddon:GetName())
+-- -- prints "MyAddon"
+function GetName(self)
+ return self.moduleName or self.name
+end
+
+--- Enables the Addon, if possible, return true or false depending on success.
+-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
+-- and enabling all modules of the addon (unless explicitly disabled).\\
+-- :Enable() also sets the internal `enableState` variable to true
+-- @name //addon//:Enable
+-- @paramsig
+-- @usage
+-- -- Enable MyModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Enable()
+function Enable(self)
+ self:SetEnabledState(true)
+
+ -- nevcairiel 2013-04-27: don't enable an addon/module if its queued for init still
+ -- it'll be enabled after the init process
+ if not queuedForInitialization(self) then
+ return AceAddon:EnableAddon(self)
+ end
+end
+
+--- Disables the Addon, if possible, return true or false depending on success.
+-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
+-- and disabling all modules of the addon.\\
+-- :Disable() also sets the internal `enableState` variable to false
+-- @name //addon//:Disable
+-- @paramsig
+-- @usage
+-- -- Disable MyAddon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:Disable()
+function Disable(self)
+ self:SetEnabledState(false)
+ return AceAddon:DisableAddon(self)
+end
+
+--- Enables the Module, if possible, return true or false depending on success.
+-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
+-- @name //addon//:EnableModule
+-- @paramsig name
+-- @usage
+-- -- Enable MyModule using :GetModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Enable()
+--
+-- -- Enable MyModule using the short-hand
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:EnableModule("MyModule")
+function EnableModule(self, name)
+ local module = self:GetModule( name )
+ return module:Enable()
+end
+
+--- Disables the Module, if possible, return true or false depending on success.
+-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
+-- @name //addon//:DisableModule
+-- @paramsig name
+-- @usage
+-- -- Disable MyModule using :GetModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Disable()
+--
+-- -- Disable MyModule using the short-hand
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:DisableModule("MyModule")
+function DisableModule(self, name)
+ local module = self:GetModule( name )
+ return module:Disable()
+end
+
+--- Set the default libraries to be mixed into all modules created by this object.
+-- Note that you can only change the default module libraries before any module is created.
+-- @name //addon//:SetDefaultModuleLibraries
+-- @paramsig lib[, lib, ...]
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create the addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
+-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
+-- -- Create a module
+-- MyModule = MyAddon:NewModule("MyModule")
+function SetDefaultModuleLibraries(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if next(self.modules) then
+ error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
+ end
+ local args = self.defaultModuleLibraries or {}
+ args[1] = a1
+ args[2] = a2
+ args[3] = a3
+ args[4] = a4
+ args[5] = a5
+ args[6] = a6
+ args[7] = a7
+ args[8] = a8
+ args[9] = a9
+ args[10] = a10
+
+ self.defaultModuleLibraries = args
+end
+
+--- Set the default state in which new modules are being created.
+-- Note that you can only change the default state before any module is created.
+-- @name //addon//:SetDefaultModuleState
+-- @paramsig state
+-- @param state Default state for new modules, true for enabled, false for disabled
+-- @usage
+-- -- Create the addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+-- -- Set the default state to "disabled"
+-- MyAddon:SetDefaultModuleState(false)
+-- -- Create a module and explicilty enable it
+-- MyModule = MyAddon:NewModule("MyModule")
+-- MyModule:Enable()
+function SetDefaultModuleState(self, state)
+ if next(self.modules) then
+ error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
+ end
+ self.defaultModuleState = state
+end
+
+--- Set the default prototype to use for new modules on creation.
+-- Note that you can only change the default prototype before any module is created.
+-- @name //addon//:SetDefaultModulePrototype
+-- @paramsig prototype
+-- @param prototype Default prototype for the new modules (table)
+-- @usage
+-- -- Define a prototype
+-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
+-- -- Set the default prototype
+-- MyAddon:SetDefaultModulePrototype(prototype)
+-- -- Create a module and explicitly Enable it
+-- MyModule = MyAddon:NewModule("MyModule")
+-- MyModule:Enable()
+-- -- should print "OnEnable called!" now
+-- @see NewModule
+function SetDefaultModulePrototype(self, prototype)
+ if next(self.modules) then
+ error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
+ end
+ if type(prototype) ~= "table" then
+ error(strfmt("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'.", type(prototype)), 2)
+ end
+ self.defaultModulePrototype = prototype
+end
+
+--- Set the state of an addon or module
+-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
+-- @name //addon//:SetEnabledState
+-- @paramsig state
+-- @param state the state of an addon or module (enabled=true, disabled=false)
+function SetEnabledState(self, state)
+ self.enabledState = state
+end
+
+
+--- Return an iterator of all modules associated to the addon.
+-- @name //addon//:IterateModules
+-- @paramsig
+-- @usage
+-- -- Enable all modules
+-- for name, module in MyAddon:IterateModules() do
+-- module:Enable()
+-- end
+local function IterateModules(self) return pairs(self.modules) end
+
+-- Returns an iterator of all embeds in the addon
+-- @name //addon//:IterateEmbeds
+-- @paramsig
+local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
+
+--- Query the enabledState of an addon.
+-- @name //addon//:IsEnabled
+-- @paramsig
+-- @usage
+-- if MyAddon:IsEnabled() then
+-- MyAddon:Disable()
+-- end
+local function IsEnabled(self) return self.enabledState end
+local mixins = {
+ NewModule = NewModule,
+ GetModule = GetModule,
+ Enable = Enable,
+ Disable = Disable,
+ EnableModule = EnableModule,
+ DisableModule = DisableModule,
+ IsEnabled = IsEnabled,
+ SetDefaultModuleLibraries = SetDefaultModuleLibraries,
+ SetDefaultModuleState = SetDefaultModuleState,
+ SetDefaultModulePrototype = SetDefaultModulePrototype,
+ SetEnabledState = SetEnabledState,
+ IterateModules = IterateModules,
+ IterateEmbeds = IterateEmbeds,
+ GetName = GetName,
+}
+local function IsModule(self) return false end
+local pmixins = {
+ defaultModuleState = true,
+ enabledState = true,
+ IsModule = IsModule,
+}
+-- Embed( target )
+-- target (object) - target object to embed aceaddon in
+--
+-- this is a local function specifically since it's meant to be only called internally
+function Embed(target, skipPMixins)
+ for k, v in pairs(mixins) do
+ target[k] = v
+ end
+ if not skipPMixins then
+ for k, v in pairs(pmixins) do
+ target[k] = target[k] or v
+ end
+ end
+end
+
+
+-- - Initialize the addon after creation.
+-- This function is only used internally during the ADDON_LOADED event
+-- It will call the **OnInitialize** function on the addon object (if present),
+-- and the **OnEmbedInitialize** function on all embeded libraries.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- @param addon addon object to intialize
+function AceAddon:InitializeAddon(addon)
+ safecall(addon.OnInitialize, 1, addon)
+
+ local embeds = self.embeds[addon]
+ for i = 1, tgetn(embeds) do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedInitialize, 2, lib, addon) end
+ end
+
+ -- we don't call InitializeAddon on modules specifically, this is handled
+ -- from the event handler and only done _once_
+end
+
+-- - Enable the addon after creation.
+-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
+-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
+-- It will call the **OnEnable** function on the addon object (if present),
+-- and the **OnEmbedEnable** function on all embeded libraries.\\
+-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- Use :Enable on the addon itself instead.
+-- @param addon addon object to enable
+function AceAddon:EnableAddon(addon)
+ if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
+ if self.statuses[addon.name] or not addon.enabledState then return false end
+
+ -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
+ self.statuses[addon.name] = true
+
+ safecall(addon.OnEnable, 1, addon)
+
+ -- make sure we're still enabled before continueing
+ if self.statuses[addon.name] then
+ local embeds = self.embeds[addon]
+ for i = 1, tgetn(embeds) do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedEnable, 2, lib, addon) end
+ end
+
+ -- enable possible modules.
+ local modules = addon.orderedModules
+ for i = 1, tgetn(modules) do
+ self:EnableAddon(modules[i])
+ end
+ end
+ return self.statuses[addon.name] -- return true if we're disabled
+end
+
+-- - Disable the addon
+-- Note: This function is only used internally.
+-- It will call the **OnDisable** function on the addon object (if present),
+-- and the **OnEmbedDisable** function on all embeded libraries.\\
+-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- Use :Disable on the addon itself instead.
+-- @param addon addon object to enable
+function AceAddon:DisableAddon(addon)
+ if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
+ if not self.statuses[addon.name] then return false end
+
+ -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
+ self.statuses[addon.name] = false
+
+ safecall(addon.OnDisable, 1, addon)
+
+ -- make sure we're still disabling...
+ if not self.statuses[addon.name] then
+ local embeds = self.embeds[addon]
+ for i = 1, tgetn(embeds) do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedDisable, 2, lib, addon) end
+ end
+ -- disable possible modules.
+ local modules = addon.orderedModules
+ for i = 1, tgetn(modules) do
+ self:DisableAddon(modules[i])
+ end
+ end
+
+ return not self.statuses[addon.name] -- return true if we're disabled
+end
+
+--- Get an iterator over all registered addons.
+-- @usage
+-- -- Print a list of all installed AceAddon's
+-- for name, addon in AceAddon:IterateAddons() do
+-- print("Addon: " .. name)
+-- end
+function AceAddon:IterateAddons() return pairs(self.addons) end
+
+--- Get an iterator over the internal status registry.
+-- @usage
+-- -- Print a list of all enabled addons
+-- for name, status in AceAddon:IterateAddonStatus() do
+-- if status then
+-- print("EnabledAddon: " .. name)
+-- end
+-- end
+function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
+
+-- Following Iterators are deprecated, and their addon specific versions should be used
+-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
+function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
+function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
+
+
+local onEvent
+do
+local IsLoggedIn = false
+-- Event Handling
+function onEvent()
+ -- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up
+ -- Ace3v: When the ADDON_LOADED event is triggerd, global arg1 is the loaded addon name
+ -- so onEvent(event, arg1) won't work because it will cover the global variables
+ if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then
+ -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
+ -- Ace3v: When an Ace3 addons is loaded, then he initializeque should not be empty unless
+ -- the addon does not use the library. If an addon that does not use Ace3 library
+ -- is loaded, we will also receive the ADDON_LOADED event but in this case the
+ -- queue will be empty so we have nothing to do.
+ while(tgetn(AceAddon.initializequeue) > 0) do
+ local addon = tremove(AceAddon.initializequeue, 1)
+ -- this might be an issue with recursion - TODO: validate
+ if event == "ADDON_LOADED" then addon.baseName = arg1 end
+ AceAddon:InitializeAddon(addon)
+ tinsert(AceAddon.enablequeue, addon)
+ end
+
+ if event == "PLAYER_LOGIN" then
+ IsLoggedIn = true
+ end
+
+ if IsLoggedIn then
+ while(tgetn(AceAddon.enablequeue) > 0) do
+ local addon = tremove(AceAddon.enablequeue, 1)
+ AceAddon:EnableAddon(addon)
+ end
+ end
+ end
+end
+end -- onEvent
+
+AceAddon.frame:RegisterEvent("ADDON_LOADED")
+AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
+AceAddon.frame:SetScript("OnEvent", onEvent)
+
+-- upgrade embeded
+for name, addon in pairs(AceAddon.addons) do
+ Embed(addon, true)
+end
diff --git a/ElvUI/Libraries/AceAddon-3.0/AceAddon-3.0.xml b/ElvUI/Libraries/AceAddon-3.0/AceAddon-3.0.xml
new file mode 100644
index 0000000..0ae8501
--- /dev/null
+++ b/ElvUI/Libraries/AceAddon-3.0/AceAddon-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceComm-3.0/AceComm-3.0.lua b/ElvUI/Libraries/AceComm-3.0/AceComm-3.0.lua
new file mode 100644
index 0000000..fec536d
--- /dev/null
+++ b/ElvUI/Libraries/AceComm-3.0/AceComm-3.0.lua
@@ -0,0 +1,306 @@
+--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels.
+-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\
+-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server.
+--
+-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceComm itself.\\
+-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceComm.
+-- @class file
+-- @name AceComm-3.0
+-- @release $Id: AceComm-3.0.lua 1107 2014-02-19 16:40:32Z nevcairiel $
+
+--[[ AceComm-3.0
+
+TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited.
+
+]]
+
+local MAJOR, MINOR = "AceComm-3.0", 9
+
+local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceComm then return end
+
+local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
+local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
+
+-- Lua APIs
+local type, next, pairs, tostring = type, next, pairs, tostring
+local strlen, strsub, strfind = string.len, string.sub, string.find
+local tinsert, tconcat, tgetn, tremove = table.insert, table.concat, table.getn, table.remove
+local error, assert = error, assert
+
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix
+
+AceComm.embeds = AceComm.embeds or {}
+
+-- for my sanity and yours, let's give the message type bytes some names
+local MSG_MULTI_FIRST = "\001"
+local MSG_MULTI_NEXT = "\002"
+local MSG_MULTI_LAST = "\003"
+local MSG_ESCAPE = "\004"
+
+-- remove old structures (pre WoW 4.0)
+AceComm.multipart_origprefixes = nil
+AceComm.multipart_reassemblers = nil
+
+-- the multipart message spool: indexed by a combination of sender+distribution+
+AceComm.multipart_spool = AceComm.multipart_spool or {}
+
+--- Register for Addon Traffic on a specified prefix
+-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters
+-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
+function AceComm:RegisterComm(prefix, method)
+ if method == nil then
+ method = "OnCommReceived"
+ end
+
+ if strlen(prefix) > 16 then -- TODO: 15?
+ error("AceComm:RegisterComm(prefix,method): prefix length is limited to 16 characters")
+ end
+
+ return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
+end
+
+local warnedPrefix=false
+
+--- Send a message over the Addon Channel
+-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
+-- @param text Data to send, nils (\000) not allowed. Any length.
+-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
+-- @param target Destination for some distributions; see SendAddonMessage API
+-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
+-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send.
+-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified.
+function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg)
+ prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery!
+ if not( type(prefix)=="string" and
+ type(text)=="string" and
+ type(distribution)=="string" and
+ (target==nil or type(target)=="string") and
+ (prio=="BULK" or prio=="NORMAL" or prio=="ALERT")
+ ) then
+ error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2)
+ end
+
+ local textlen = strlen(text)
+ -- Yes, the max is 255 even if the dev post said 256. I tested. Char 256+ get silently truncated. /Mikk, 20110327
+ -- Ace3v: substract the prefix length
+ local maxtextlen = 254 - strlen(prefix)
+ local queueName = prefix..distribution..(target or "")
+
+ local ctlCallback = nil
+ if callbackFn then
+ ctlCallback = function(sent)
+ return callbackFn(callbackArg, sent, textlen)
+ end
+ end
+
+ local forceMultipart
+ if strfind(text, "^[\001-\009]") then -- 4.1+: see if the first character is a control character
+ -- we need to escape the first character with a \004
+ if textlen+1 > maxtextlen then -- would we go over the size limit?
+ forceMultipart = true -- just make it multipart, no escape problems then
+ else
+ text = "\004" .. text
+ end
+ end
+
+ if not forceMultipart and textlen <= maxtextlen then
+ -- fits all in one message
+ CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen)
+ else
+ maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix(4.0)/start of message(4.1)
+
+ -- first part
+ local chunk = strsub(text, 1, maxtextlen)
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen)
+
+ -- continuation
+ local pos = 1+maxtextlen
+
+ while pos+maxtextlen <= textlen do
+ chunk = strsub(text, pos, pos+maxtextlen-1)
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
+ pos = pos + maxtextlen
+ end
+
+ -- final part
+ chunk = strsub(text, pos)
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen)
+ end
+end
+
+
+----------------------------------------
+-- Message receiving
+----------------------------------------
+
+do
+ local compost = setmetatable({}, {__mode = "k"})
+ local function new()
+ local t = next(compost)
+ if t then
+ compost[t]=nil
+ for i=tgetn(t),3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
+ tremove(t) -- Ace3v: t[i] = nil wont affect the tgetn return value
+ end
+ return t
+ end
+
+ return {}
+ end
+
+ local function lostdatawarning(prefix,sender,where)
+ DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
+ end
+
+ function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+
+ --[[
+ if spool[key] then
+ lostdatawarning(prefix,sender,"First")
+ -- continue and overwrite
+ end
+ --]]
+
+ spool[key] = message -- plain string for now
+ end
+
+ function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+ local olddata = spool[key]
+
+ if not olddata then
+ --lostdatawarning(prefix,sender,"Next")
+ return
+ end
+
+ if type(olddata)~="table" then
+ -- ... but what we have is not a table. So make it one. (Pull a composted one if available)
+ local t = new()
+ t[1] = olddata -- add old data as first string
+ t[2] = message -- and new message as second string
+ spool[key] = t -- and put the table in the spool instead of the old string
+ else
+ tinsert(olddata, message)
+ end
+ end
+
+ function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+ local olddata = spool[key]
+
+ if not olddata then
+ --lostdatawarning(prefix,sender,"End")
+ return
+ end
+
+ spool[key] = nil
+
+ if type(olddata) == "table" then
+ -- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
+ tinsert(olddata, message)
+ AceComm.callbacks:Fire(prefix, 3, tconcat(olddata, ""), distribution, sender)
+ compost[olddata] = true
+ else
+ -- if we've only received a "first", the spooled data will still only be a string
+ AceComm.callbacks:Fire(prefix, 3, olddata..message, distribution, sender)
+ end
+ end
+end
+
+
+
+
+
+
+----------------------------------------
+-- Embed CallbackHandler
+----------------------------------------
+
+if not AceComm.callbacks then
+ AceComm.callbacks = CallbackHandler:New(AceComm,
+ "_RegisterComm",
+ "UnregisterComm",
+ "UnregisterAllComm")
+end
+
+AceComm.callbacks.OnUsed = nil
+AceComm.callbacks.OnUnused = nil
+
+-- Ace3v: in vanilla, global vars:
+-- event -> event type
+-- arg1 -> prefix
+-- arg2 -> message
+-- arg3 -> channel
+-- arg4 -> sender
+local function OnEvent()
+ local prefix, message, distribution, sender = arg1, arg2, arg3, arg4
+ if event == "CHAT_MSG_ADDON" then
+ local _, _, control, rest = strfind(message, "^([\001-\009])(.*)")
+ if control then
+ if control==MSG_MULTI_FIRST then
+ AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender)
+ elseif control==MSG_MULTI_NEXT then
+ AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender)
+ elseif control==MSG_MULTI_LAST then
+ AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender)
+ elseif control==MSG_ESCAPE then
+ AceComm.callbacks:Fire(prefix, 3, rest, distribution, sender)
+ else
+ -- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!)
+ end
+ else
+ -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
+ AceComm.callbacks:Fire(prefix, 3, message, distribution, sender)
+ end
+ else
+ assert(false, "Received "..tostring(event).." event?!")
+ end
+end
+
+AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
+AceComm.frame:SetScript("OnEvent", OnEvent)
+AceComm.frame:UnregisterAllEvents()
+AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
+
+
+----------------------------------------
+-- Base library stuff
+----------------------------------------
+
+local mixins = {
+ "RegisterComm",
+ "UnregisterComm",
+ "UnregisterAllComm",
+ "SendCommMessage",
+}
+
+-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceComm-3.0 in
+function AceComm:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+function AceComm:OnEmbedDisable(target)
+ target:UnregisterAllComm()
+end
+
+-- Update embeds
+for target, v in pairs(AceComm.embeds) do
+ AceComm:Embed(target)
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceComm-3.0/AceComm-3.0.xml b/ElvUI/Libraries/AceComm-3.0/AceComm-3.0.xml
new file mode 100644
index 0000000..2c2a26d
--- /dev/null
+++ b/ElvUI/Libraries/AceComm-3.0/AceComm-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceComm-3.0/ChatThrottleLib.lua b/ElvUI/Libraries/AceComm-3.0/ChatThrottleLib.lua
new file mode 100644
index 0000000..8cf7e47
--- /dev/null
+++ b/ElvUI/Libraries/AceComm-3.0/ChatThrottleLib.lua
@@ -0,0 +1,527 @@
+--
+-- ChatThrottleLib by Mikk
+--
+-- Manages AddOn chat output to keep player from getting kicked off.
+--
+-- ChatThrottleLib:SendChatMessage/:SendAddonMessage functions that accept
+-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
+--
+-- Priorities get an equal share of available bandwidth when fully loaded.
+-- Communication channels are separated on extension+chattype+destination and
+-- get round-robinned. (Destination only matters for whispers and channels,
+-- obviously)
+--
+-- Will install hooks for SendChatMessage and SendAddonMessage to measure
+-- bandwidth bypassing the library and use less bandwidth itself.
+--
+--
+-- Fully embeddable library. Just copy this file into your addon directory,
+-- add it to the .toc, and it's done.
+--
+-- Can run as a standalone addon also, but, really, just embed it! :-)
+--
+-- LICENSE: ChatThrottleLib is released into the Public Domain
+--
+
+local CTL_VERSION = 23
+
+local AceCore = LibStub("AceCore-3.0")
+local _G = AceCore._G
+local hooksecurefunc = AceCore.hooksecurefunc
+local wipe = AceCore.wipe
+
+if _G.ChatThrottleLib then
+ if _G.ChatThrottleLib.version >= CTL_VERSION then
+ -- There's already a newer (or same) version loaded. Buh-bye.
+ return
+ elseif not _G.ChatThrottleLib.securelyHooked then
+ print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, =v16) in it!")
+ -- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
+ -- ... and if someone has securehooked, they can kiss that goodbye too... >.<
+ _G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage
+ if _G.ChatThrottleLib.ORIG_SendAddonMessage then
+ _G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage
+ end
+ end
+ _G.ChatThrottleLib.ORIG_SendChatMessage = nil
+ _G.ChatThrottleLib.ORIG_SendAddonMessage = nil
+end
+
+if not _G.ChatThrottleLib then
+ _G.ChatThrottleLib = {}
+end
+
+ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
+local ChatThrottleLib = _G.ChatThrottleLib
+
+ChatThrottleLib.version = CTL_VERSION
+
+
+
+------------------ TWEAKABLES -----------------
+
+ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
+ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
+
+ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
+
+ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
+
+
+local setmetatable = setmetatable
+local table_remove = table.remove
+local tinsert = table.insert
+local tostring = tostring
+local GetTime = GetTime
+local math_min = math.min
+local math_max = math.max
+local next = next
+local strlen = string.len
+local GetFramerate = GetFramerate
+local strlower = string.lower
+local unpack,type,pairs,wipe = unpack,type,pairs,wipe
+local UnitInRaid,UnitInParty = UnitInRaid,UnitInParty
+
+
+-----------------------------------------------------------------------
+-- Double-linked ring implementation
+
+local Ring = {}
+local RingMeta = { __index = Ring }
+
+function Ring:New()
+ local ret = {}
+ setmetatable(ret, RingMeta)
+ return ret
+end
+
+function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
+ if self.pos then
+ obj.prev = self.pos.prev
+ obj.prev.next = obj
+ obj.next = self.pos
+ obj.next.prev = obj
+ else
+ obj.next = obj
+ obj.prev = obj
+ self.pos = obj
+ end
+end
+
+function Ring:Remove(obj)
+ obj.next.prev = obj.prev
+ obj.prev.next = obj.next
+ if self.pos == obj then
+ self.pos = obj.next
+ if self.pos == obj then
+ self.pos = nil
+ end
+ end
+end
+
+
+
+-----------------------------------------------------------------------
+-- Recycling bin for pipes
+-- A pipe is a plain integer-indexed queue of messages
+-- Pipes normally live in Rings of pipes (3 rings total, one per priority)
+
+ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
+local PipeBin = setmetatable({}, {__mode="k"})
+
+local function DelPipe(pipe)
+ PipeBin[pipe] = true
+end
+
+local function NewPipe()
+ local pipe = next(PipeBin)
+ if pipe then
+ wipe(pipe)
+ PipeBin[pipe] = nil
+ return pipe
+ end
+ return {}
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Recycling bin for messages
+
+ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
+local MsgBin = setmetatable({}, {__mode="k"})
+
+local function DelMsg(msg)
+ msg[1] = nil
+ -- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
+ MsgBin[msg] = true
+end
+
+local function NewMsg()
+ local msg = next(MsgBin)
+ if msg then
+ MsgBin[msg] = nil
+ return msg
+ end
+ return {}
+end
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib:Init
+-- Initialize queues, set up frame for OnUpdate, etc
+
+
+function ChatThrottleLib:Init()
+
+ -- Set up queues
+ if not self.Prio then
+ self.Prio = {}
+ self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ end
+
+ -- v4: total send counters per priority
+ for _, Prio in pairs(self.Prio) do
+ Prio.nTotalSent = Prio.nTotalSent or 0
+ end
+
+ if not self.avail then
+ self.avail = 0 -- v5
+ end
+ if not self.nTotalSent then
+ self.nTotalSent = 0 -- v5
+ end
+
+
+ -- Set up a frame to get OnUpdate events
+ if not self.Frame then
+ self.Frame = CreateFrame("Frame")
+ self.Frame:Hide()
+ end
+ self.Frame:SetScript("OnUpdate", self.OnUpdate)
+ self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
+ self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
+ self.OnUpdateDelay = 0
+ self.LastAvailUpdate = GetTime()
+ self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
+
+ -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
+ if not self.securelyHooked then
+ -- Use secure hooks as of v16. Old regular hook support yanked out in v21.
+ self.securelyHooked = true
+ --SendChatMessage
+ hooksecurefunc("SendChatMessage", function(text, chattype, language, destination)
+ return ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination)
+ end)
+ --SendAddonMessage
+ hooksecurefunc("SendAddonMessage", function(prefix, text, chattype, destination)
+ return ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination)
+ end)
+ end
+ self.nBypass = 0
+end
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
+
+local bMyTraffic = false
+
+function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination)
+ if bMyTraffic then
+ return
+ end
+ local self = ChatThrottleLib
+ local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
+ self.avail = self.avail - size
+ self.nBypass = self.nBypass + size -- just a statistic
+end
+function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination)
+ if bMyTraffic then
+ return
+ end
+ local self = ChatThrottleLib
+ local size = strlen(tostring(text or "")) + strlen(tostring(prefix or ""));
+ size = size + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
+ self.avail = self.avail - size
+ self.nBypass = self.nBypass + size -- just a statistic
+end
+
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib:UpdateAvail
+-- Update self.avail with how much bandwidth is currently available
+
+function ChatThrottleLib:UpdateAvail()
+ local now = GetTime()
+ local MAX_CPS = self.MAX_CPS;
+ local newavail = MAX_CPS * (now - self.LastAvailUpdate)
+ local avail = self.avail
+
+ if now - self.HardThrottlingBeginTime < 5 then
+ -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
+ avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
+ self.bChoking = true
+ elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
+ avail = math_min(MAX_CPS, avail + newavail*0.5)
+ self.bChoking = true -- just a statistic
+ else
+ avail = math_min(self.BURST, avail + newavail)
+ self.bChoking = false
+ end
+
+ avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
+
+ self.avail = avail
+ self.LastAvailUpdate = now
+
+ return avail
+end
+
+
+-----------------------------------------------------------------------
+-- Despooling logic
+-- Reminder:
+-- - We have 3 Priorities, each containing a "Ring" construct ...
+-- - ... made up of N "Pipe"s (1 for each destination/pipename)
+-- - and each pipe contains messages
+
+function ChatThrottleLib:Despool(Prio)
+ local ring = Prio.Ring
+ while ring.pos and Prio.avail > ring.pos[1].nSize do
+ local msg = table_remove(ring.pos, 1)
+ if not ring.pos[1] then -- did we remove last msg in this pipe?
+ local pipe = Prio.Ring.pos
+ Prio.Ring:Remove(pipe)
+ Prio.ByName[pipe.name] = nil
+ DelPipe(pipe)
+ else
+ Prio.Ring.pos = Prio.Ring.pos.next
+ end
+ local didSend=false
+ local lowerDest = strlower(msg[3] or "")
+ if lowerDest == "raid" and not UnitInRaid("player") then
+ -- do nothing
+ elseif lowerDest == "party" and not UnitInParty("player") then
+ -- do nothing
+ else
+ Prio.avail = Prio.avail - msg.nSize
+ bMyTraffic = true
+ msg.f(unpack(msg, 1, msg.n))
+ bMyTraffic = false
+ Prio.nTotalSent = Prio.nTotalSent + msg.nSize
+ DelMsg(msg)
+ didSend = true
+ end
+ -- notify caller of delivery (even if we didn't send it)
+ if msg.callbackFn then
+ msg.callbackFn (msg.callbackArg, didSend)
+ end
+ -- USER CALLBACK MAY ERROR
+ end
+end
+
+
+function ChatThrottleLib.OnEvent()
+ -- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
+ local self = ChatThrottleLib
+ if event == "PLAYER_ENTERING_WORLD" then
+ self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
+ self.avail = 0
+ end
+end
+
+
+function ChatThrottleLib.OnUpdate()
+ local self = ChatThrottleLib
+
+ self.OnUpdateDelay = self.OnUpdateDelay + arg1
+ if self.OnUpdateDelay < 0.08 then
+ return
+ end
+ self.OnUpdateDelay = 0
+
+ self:UpdateAvail()
+
+ if self.avail < 0 then
+ return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
+ end
+
+ -- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
+ local n = 0
+ for prioname,Prio in pairs(self.Prio) do
+ if Prio.Ring.pos or Prio.avail < 0 then
+ n = n + 1
+ end
+ end
+
+ -- Anything queued still?
+ if n<1 then
+ -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
+ for prioname, Prio in pairs(self.Prio) do
+ self.avail = self.avail + Prio.avail
+ Prio.avail = 0
+ end
+ self.bQueueing = false
+ self.Frame:Hide()
+ return
+ end
+
+ -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
+ local avail = self.avail/n
+ self.avail = 0
+
+ for prioname, Prio in pairs(self.Prio) do
+ if Prio.Ring.pos or Prio.avail < 0 then
+ Prio.avail = Prio.avail + avail
+ if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
+ self:Despool(Prio)
+ -- Note: We might not get here if the user-supplied callback function errors out! Take care!
+ end
+ end
+ end
+
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Spooling logic
+
+function ChatThrottleLib:Enqueue(prioname, pipename, msg)
+ local Prio = self.Prio[prioname]
+ local pipe = Prio.ByName[pipename]
+ if not pipe then
+ self.Frame:Show()
+ pipe = NewPipe()
+ pipe.name = pipename
+ Prio.ByName[pipename] = pipe
+ Prio.Ring:Add(pipe)
+ end
+
+ tinsert(pipe,msg)
+
+ self.bQueueing = true
+end
+
+function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
+ if not self or not prio or not prefix or not text or not self.Prio[prio] then
+ error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
+ end
+ if callbackFn and type(callbackFn)~="function" then
+ error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
+ end
+
+ local nSize = strlen(text)
+
+ if nSize>255 then
+ error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
+ end
+
+ nSize = nSize + self.MSG_OVERHEAD
+
+ -- Check if there's room in the global available bandwidth gauge to send directly
+ if not self.bQueueing and nSize < self:UpdateAvail() then
+ self.avail = self.avail - nSize
+ bMyTraffic = true
+ _G.SendChatMessage(text, chattype, language, destination)
+ bMyTraffic = false
+ self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
+ if callbackFn then
+ callbackFn (callbackArg, true)
+ end
+ -- USER CALLBACK MAY ERROR
+ return
+ end
+
+ -- Message needs to be queued
+ local msg = NewMsg()
+ msg.f = _G.SendChatMessage
+ msg[1] = text
+ msg[2] = chattype or "SAY"
+ msg[3] = language
+ msg[4] = destination
+ msg.n = 4
+ msg.nSize = nSize
+ msg.callbackFn = callbackFn
+ msg.callbackArg = callbackArg
+
+ self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
+end
+
+
+function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
+ if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
+ error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
+ end
+ if callbackFn and type(callbackFn)~="function" then
+ error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
+ end
+
+ local nSize = strlen(text);
+
+ if RegisterAddonMessagePrefix then
+ if nSize>255 then
+ error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
+ end
+ else
+ nSize = nSize + strlen(prefix) + 1
+ if nSize>255 then
+ error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
+ end
+ end
+
+ nSize = nSize + self.MSG_OVERHEAD;
+
+ -- Check if there's room in the global available bandwidth gauge to send directly
+ if not self.bQueueing and nSize < self:UpdateAvail() then
+ self.avail = self.avail - nSize
+ bMyTraffic = true
+ _G.SendAddonMessage(prefix, text, chattype, target)
+ bMyTraffic = false
+ self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
+ if callbackFn then
+ callbackFn (callbackArg, true)
+ end
+ -- USER CALLBACK MAY ERROR
+ return
+ end
+
+ -- Message needs to be queued
+ local msg = NewMsg()
+ msg.f = _G.SendAddonMessage
+ msg[1] = prefix
+ msg[2] = text
+ msg[3] = chattype
+ msg[4] = target
+ msg.n = (target~=nil) and 4 or 3;
+ msg.nSize = nSize
+ msg.callbackFn = callbackFn
+ msg.callbackArg = callbackArg
+
+ self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Get the ball rolling!
+
+ChatThrottleLib:Init()
+
+--[[ WoWBench debugging snippet
+if(WOWB_VER) then
+ local function SayTimer()
+ print("SAY: "..GetTime().." "..arg1)
+ end
+ ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
+ ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
+end
+]]
+
diff --git a/ElvUI/Libraries/AceConsole-3.0/AceConsole-3.0.lua b/ElvUI/Libraries/AceConsole-3.0/AceConsole-3.0.lua
new file mode 100644
index 0000000..e38bc8b
--- /dev/null
+++ b/ElvUI/Libraries/AceConsole-3.0/AceConsole-3.0.lua
@@ -0,0 +1,270 @@
+--- **AceConsole-3.0** provides registration facilities for slash commands.
+-- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
+-- to your addons individual needs.
+--
+-- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceConsole itself.\\
+-- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceConsole.
+-- @class file
+-- @name AceConsole-3.0
+-- @release $Id: AceConsole-3.0.lua 1143 2016-07-11 08:52:03Z nevcairiel $
+local MAJOR,MINOR = "AceConsole-3.0", 7
+
+local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceConsole then return end -- No upgrade needed
+
+local AceCore = LibStub("AceCore-3.0")
+
+AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
+AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
+AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
+
+-- Lua APIs
+local tinsert, tconcat, tgetn, tsetn = table.insert, table.concat, table.getn, table.setn
+local tostring = tostring
+local type, pairs, error = type, pairs, error
+local format, strfind, strsub = string.format, string.find, string.sub
+local max = math.max
+local strupper, strlower = string.upper, string.lower
+
+-- WoW APIs
+local _G = AceCore._G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
+local Print
+do
+local tmp = {}
+function Print(self, frame, arg)
+ if self ~= AceConsole then
+ tmp[1] = "|cff33ff99"..tostring(self).."|r:"
+ else
+ tmp[1] = ''
+ end
+ if type(arg) == "string" then
+ frame:AddMessage(tmp[1]..arg)
+ else -- arg is table and may contain frame as first element if argument frame is nil
+ local b, e = frame and 1 or 2, tgetn(arg)
+ if e >= b then
+ frame = frame or arg[1]
+ for i=0,e-b do
+ tmp[2+i] = tostring(arg[b+i])
+ end
+ frame:AddMessage(tconcat(tmp," ",1,e-b+2)) -- explicitly, because the length is not affected by assignment
+ end
+ end
+end
+end -- Print
+
+--- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
+-- @paramsig [chatframe ,] ...
+-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
+-- @param ... List of any values to be printed
+function AceConsole:Print(...)
+ local frame = arg[1]
+ if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
+ return Print(self, nil, arg)
+ else
+ return Print(self, DEFAULT_CHAT_FRAME, arg)
+ end
+end
+
+--- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
+-- @paramsig [chatframe ,] "format"[, ...]
+-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
+-- @param format Format string - same syntax as standard Lua format()
+-- @param ... Arguments to the format string
+function AceConsole:Printf(a1, ...)
+ local frame, succ, s
+ if type(a1) == "table" and a1.AddMessage then -- Is first argument something with an .AddMessage member?
+ frame, succ, s = a1, pcall(format, unpack(arg))
+ else
+ frame, succ, s = DEFAULT_CHAT_FRAME, pcall(format, a1, unpack(arg))
+ end
+ if not succ then error(s,2) end
+ return Print(self, frame, s)
+end
+
+
+
+
+
+--- Register a simple chat command
+-- @param command Chat command to be registered WITHOUT leading "/"
+-- @param func Function to call when the slash command is being used (funcref or methodname)
+-- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
+function AceConsole:RegisterChatCommand( command, func, persist )
+ if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand(command, func[, persist ]): 'command' - expected a string]], 2) end
+
+ if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
+
+ local name = "ACECONSOLE_"..strupper(command)
+
+ local t = type(func)
+
+ if t == "string" then
+ -- Ace3v: prevent user from using AceConSole as self
+ if self == AceConsole then
+ error([[Usage: RegisterChatCommand(command, func[, persist]): 'self' - use your own 'self']], 2)
+ end
+ SlashCmdList[name] = function(input, editBox)
+ self[func](self, input, editBox)
+ end
+ elseif t == "function" then
+ SlashCmdList[name] = func
+ else
+ error([[Usage: AceConsole:RegisterChatCommand(command, func[, persist ]): 'func' - expected a string or a function]], 2)
+ end
+ _G["SLASH_"..name.."1"] = "/"..strlower(command)
+ AceConsole.commands[command] = name
+ -- non-persisting commands are registered for enabling disabling
+ if not persist then
+ if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
+ AceConsole.weakcommands[self][command] = func
+ end
+ return true
+end
+
+--- Unregister a chatcommand
+-- @param command Chat command to be unregistered WITHOUT leading "/"
+function AceConsole:UnregisterChatCommand( command )
+ local name = AceConsole.commands[command]
+ if name then
+ SlashCmdList[name] = nil
+ _G["SLASH_" .. name .. "1"] = nil
+ AceConsole.commands[command] = nil
+ end
+end
+
+--- Get an iterator over all Chat Commands registered with AceConsole
+-- @return Iterator (pairs) over all commands
+function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
+
+local function nils(n,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if n >= 1 then
+ return nil, nils(n-1,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ elseif not argc or argc == 0 then
+ return
+ else
+ return a1, nils(0,argc-1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+end
+
+--- Retreive one or more space-separated arguments from a string.
+-- Treats quoted strings and itemlinks as non-spaced.
+-- @param str The raw argument string
+-- @param numargs How many arguments to get (default 1)
+-- @param startpos Where in the string to start scanning (default 1)
+-- @return Returns arg1, arg2, ..., nextposition\\
+-- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
+function AceConsole:GetArgs(str, numargs, startpos)
+ numargs = numargs or 1
+ startpos = max(startpos or 1, 1)
+
+ local pos=startpos
+
+ -- find start of new arg
+ pos = strfind(str, "[^ ]", pos)
+ if not pos then -- whoops, end of string
+ return nils(numargs, 1, 1e9)
+ end
+
+ if numargs<1 then
+ return pos
+ end
+
+ -- quoted or space separated? find out which pattern to use
+ local delim_or_pipe
+ local ch = strsub(str, pos, pos)
+ if ch=='"' then
+ pos = pos + 1
+ delim_or_pipe='([|"])'
+ elseif ch=="'" then
+ pos = pos + 1
+ delim_or_pipe="([|'])"
+ else
+ delim_or_pipe="([| ])"
+ end
+
+ startpos = pos
+
+ while true do
+ -- find delimiter or hyperlink
+ local ch,_
+ pos,_,ch = strfind(str, delim_or_pipe, pos)
+
+ if not pos then break end
+
+ if ch=="|" then
+ -- some kind of escape
+
+ if strsub(str,pos,pos+1)=="|H" then
+ -- It's a |H....|hhyper link!|h
+ pos=strfind(str, "|h", pos+2) -- first |h
+ if not pos then break end
+
+ pos=strfind(str, "|h", pos+2) -- second |h
+ if not pos then break end
+ elseif strsub(str,pos, pos+1) == "|T" then
+ -- It's a |T....|t texture
+ pos=strfind(str, "|t", pos+2)
+ if not pos then break end
+ end
+
+ pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
+
+ else
+ -- found delimiter, done with this arg
+ return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
+ end
+
+ end
+
+ -- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
+ return strsub(str, startpos), nils(numargs-1, 1, 1e9)
+end
+
+
+--- embedding and embed handling
+
+local mixins = {
+ "Print",
+ "Printf",
+ "RegisterChatCommand",
+ "UnregisterChatCommand",
+ "GetArgs",
+}
+
+-- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceBucket in
+function AceConsole:Embed( target )
+ for k, v in pairs( mixins ) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+function AceConsole:OnEmbedEnable( target )
+ if AceConsole.weakcommands[target] then
+ for command, func in pairs( AceConsole.weakcommands[target] ) do
+ target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
+ end
+ end
+end
+
+function AceConsole:OnEmbedDisable( target )
+ if AceConsole.weakcommands[target] then
+ for command, func in pairs( AceConsole.weakcommands[target] ) do
+ target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
+ end
+ end
+end
+
+for addon in pairs(AceConsole.embeds) do
+ AceConsole:Embed(addon)
+end
diff --git a/ElvUI/Libraries/AceConsole-3.0/AceConsole-3.0.xml b/ElvUI/Libraries/AceConsole-3.0/AceConsole-3.0.xml
new file mode 100644
index 0000000..11c6ee3
--- /dev/null
+++ b/ElvUI/Libraries/AceConsole-3.0/AceConsole-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceCore-3.0/AceCore-3.0.lua b/ElvUI/Libraries/AceCore-3.0/AceCore-3.0.lua
new file mode 100644
index 0000000..3ddb49b
--- /dev/null
+++ b/ElvUI/Libraries/AceCore-3.0/AceCore-3.0.lua
@@ -0,0 +1,204 @@
+local ACECORE_MAJOR, ACECORE_MINOR = "AceCore-3.0", 1
+local AceCore, oldminor = LibStub:NewLibrary(ACECORE_MAJOR, ACECORE_MINOR)
+
+if not AceCore then return end -- No upgrade needed
+
+AceCore._G = AceCore._G or _G
+local _G = AceCore._G
+local strsub, strgsub, strfind = string.sub, string.gsub, string.find
+local tremove, tconcat = table.remove, table.concat
+local tgetn, tsetn = table.getn, table.setn
+
+local new, del
+do
+local list = setmetatable({}, {__mode = "k"})
+function new()
+ local t = next(list)
+ if not t then
+ return {}
+ end
+ list[t] = nil
+ return t
+end
+
+function del(t)
+ setmetatable(t, nil)
+ for k in pairs(t) do
+ t[k] = nil
+ end
+ tsetn(t,0)
+ list[t] = true
+end
+
+-- debug
+function AceCore.listcount()
+ local count = 0
+ for k in list do
+ count = count + 1
+ end
+ return count
+end
+end -- AceCore.new, AceCore.del
+AceCore.new, AceCore.del = new, del
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+AceCore.errorhandler = errorhandler
+
+local function CreateSafeDispatcher(argCount)
+ local code = [[
+ local errorhandler = LibStub("AceCore-3.0").errorhandler
+ local method, UP_ARGS
+ local function call()
+ local func, ARGS = method, UP_ARGS
+ method, UP_ARGS = nil, NILS
+ return func(ARGS)
+ end
+ return function(func, ARGS)
+ method, UP_ARGS = func, ARGS
+ return xpcall(call, errorhandler)
+ end
+ ]]
+ local c = 4*argCount-1
+ local s = "b01,b02,b03,b04,b05,b06,b07,b08,b09,b10,b11,b12,b13,b14,b15,b16,b17,b18,b19,b20"
+ code = strgsub(code, "UP_ARGS", string.sub(s,1,c))
+ s = "a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20"
+ code = strgsub(code, "ARGS", string.sub(s,1,c))
+ s = "nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil"
+ code = strgsub(code, "NILS", string.sub(s,1,c))
+ return assert(loadstring(code, "safecall SafeDispatcher["..tostring(argCount).."]"))()
+end
+
+local SafeDispatchers = setmetatable({}, {__index=function(self, argCount)
+ local dispatcher
+ if argCount > 0 then
+ dispatcher = CreateSafeDispatcher(argCount)
+ else
+ dispatcher = function(func) return xpcall(func,errorhandler) end
+ end
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+end})
+
+local function safecall(func,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
+ -- we check to see if the func is passed is actually a function here and don't error when it isn't
+ -- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
+ -- present execution should continue without hinderance
+ if type(func) == "function" then
+ return SafeDispatchers[argc](func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
+ end
+end
+AceCore.safecall = safecall
+
+local function CreateDispatcher(argCount)
+ local code = [[
+ return function(func,ARGS)
+ return func(ARGS)
+ end
+ ]]
+ local s = "a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20"
+ code = strgsub(code, "ARGS", string.sub(s,1,4*argCount-1))
+ return assert(loadstring(code, "call Dispatcher["..tostring(argCount).."]"))()
+end
+
+AceCore.Dispatchers = setmetatable({}, {__index=function(self, argCount)
+ local dispatcher
+ if argCount > 0 then
+ dispatcher = CreateDispatcher(argCount)
+ else
+ dispatcher = function(func) return func() end
+ end
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+end})
+
+-- some string functions
+-- vanilla available string operations:
+-- sub, gfind, rep, gsub, char, dump, find, upper, len, format, byte, lower
+-- we will just replace every string.match with string.find in the code
+function AceCore.strtrim(s)
+ return strgsub(s, "^%s*(.-)%s*$", "%1")
+end
+
+local function strsplit(delim, s, n)
+ if n and n < 2 then return s end
+ beg = beg or 1
+ local i,j = string.find(s,delim,beg)
+ if not i then
+ return s, nil
+ end
+ return string.sub(s,1,j-1), strsplit(delim, string.sub(s,j+1), n and n-1 or nil)
+end
+AceCore.strsplit = strsplit
+
+-- Ace3v: fonctions copied from AceHook-2.1
+local protFuncs = {
+ CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true,
+ TurnOrActionStart = true, TurnOrActionStop = true,
+ PitchUpStart = true, PitchUpStop = true,
+ PitchDownStart = true, PitchDownStop = true,
+ MoveBackwardStart = true, MoveBackwardStop = true,
+ MoveForwardStart = true, MoveForwardStop = true,
+ Jump = true, StrafeLeftStart = true,
+ StrafeLeftStop = true, StrafeRightStart = true,
+ StrafeRightStop = true, ToggleMouseMove = true,
+ ToggleRun = true, TurnLeftStart = true,
+ TurnLeftStop = true, TurnRightStart = true,
+ TurnRightStop = true,
+}
+
+local function issecurevariable(x)
+ return protFuncs[x] and 1 or nil
+end
+AceCore.issecurevariable = issecurevariable
+
+local function hooksecurefunc(arg1, arg2, arg3)
+ if type(arg1) == "string" then
+ arg1, arg2, arg3 = _G, arg1, arg2
+ end
+ local orig = arg1[arg2]
+ if type(orig) ~= "function" then
+ error("The function "..arg2.." does not exist", 2)
+ end
+ arg1[arg2] = function(...)
+ local tmp = {orig(unpack(arg))}
+ arg3(unpack(arg))
+ return unpack(tmp)
+ end
+end
+AceCore.hooksecurefunc = hooksecurefunc
+
+-- pickfirstset() - picks the first non-nil value and returns it
+local function pickfirstset(argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if (argc <= 1) or (a1 ~= nil) then
+ return a1
+ else
+ return pickfirstset(argc-1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+end
+AceCore.pickfirstset = pickfirstset
+
+local function countargs(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if (a1 == nil) then return 0 end
+ return 1 + countargs(a2,a3,a4,a5,a6,a7,a8,a9,a10)
+end
+AceCore.countargs = countargs
+
+-- wipe preserves metatable
+function AceCore.wipe(t)
+ for k,v in pairs(t) do t[k] = nil end
+ tsetn(t,0)
+ return t
+end
+
+function AceCore.truncate(t,e)
+ e = e or tgetn(t)
+ for i=1,e do
+ if t[i] == nil then
+ tsetn(t,i-1)
+ return
+ end
+ end
+ tsetn(t,e)
+end
diff --git a/ElvUI/Libraries/AceCore-3.0/AceCore-3.0.xml b/ElvUI/Libraries/AceCore-3.0/AceCore-3.0.xml
new file mode 100644
index 0000000..c16a6eb
--- /dev/null
+++ b/ElvUI/Libraries/AceCore-3.0/AceCore-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceDB-3.0/AceDB-3.0.lua b/ElvUI/Libraries/AceDB-3.0/AceDB-3.0.lua
new file mode 100644
index 0000000..9e10914
--- /dev/null
+++ b/ElvUI/Libraries/AceDB-3.0/AceDB-3.0.lua
@@ -0,0 +1,755 @@
+--- **AceDB-3.0** manages the SavedVariables of your addon.
+-- It offers profile management, smart defaults and namespaces for modules.\\
+-- Data can be saved in different data-types, depending on its intended usage.
+-- The most common data-type is the `profile` type, which allows the user to choose
+-- the active profile, and manage the profiles of all of his characters.\\
+-- The following data types are available:
+-- * **char** Character-specific data. Every character has its own database.
+-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
+-- * **class** Class-specific data. All of the players characters of the same class share this database.
+-- * **race** Race-specific data. All of the players characters of the same race share this database.
+-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
+-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
+-- * **locale** Locale specific data, based on the locale of the players game client.
+-- * **global** Global Data. All characters on the same account share this database.
+-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
+--
+-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
+-- of the DBObjectLib listed here. \\
+-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
+-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
+-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
+--
+-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
+--
+-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
+--
+-- @usage
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
+--
+-- -- declare defaults to be used in the DB
+-- local defaults = {
+-- profile = {
+-- setting = true,
+-- }
+-- }
+--
+-- function MyAddon:OnInitialize()
+-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
+-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
+-- end
+-- @class file
+-- @name AceDB-3.0.lua
+-- @release $Id: AceDB-3.0.lua 1142 2016-07-11 08:36:19Z nevcairiel $
+local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 26
+local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
+
+if not AceDB then return end -- No upgrade needed
+
+local AceCore = LibStub("AceCore-3.0")
+local new, del = AceCore.new, AceCore.del
+
+-- Lua APIs
+local type, pairs, next, error = type, pairs, next, error
+local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
+
+-- WoW APIs
+local _G = AceCore._G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub
+
+AceDB.db_registry = AceDB.db_registry or {}
+AceDB.frame = AceDB.frame or CreateFrame("Frame")
+
+local CallbackHandler
+local CallbackDummy = { Fire = function() end }
+
+local DBObjectLib = {}
+
+-- Ace3v: for all recursive functions we must declare the iterator as local again, this step is necessary in vanilla
+-- Example:
+-- for k,v in pairs(table) do
+-- local v = v
+-- ...
+
+
+--[[-------------------------------------------------------------------------
+ AceDB Utility Functions
+---------------------------------------------------------------------------]]
+
+-- Simple shallow copy for copying defaults
+local function copyTable(src, dest)
+ if type(dest) ~= "table" then dest = {} end
+ if type(src) == "table" then
+ for k,v in pairs(src) do
+ local v = v
+ if type(v) == "table" then
+ -- try to index the key first so that the metatable creates the defaults, if set, and use that table
+ v = copyTable(v, dest[k])
+ end
+ dest[k] = v
+ end
+ end
+ return dest
+end
+
+-- Called to add defaults to a section of the database
+--
+-- When a ["*"] default section is indexed with a new key, a table is returned
+-- and set in the host table. These tables must be cleaned up by removeDefaults
+-- in order to ensure we don't write empty default tables.
+local function copyDefaults(dest, src)
+ -- this happens if some value in the SV overwrites our default value with a non-table
+ --if type(dest) ~= "table" then return end
+ for k, v in pairs(src) do
+ local v = v
+ if k == "*" or k == "**" then
+ if type(v) == "table" then
+ -- This is a metatable used for table defaults
+ local mt = {
+ -- This handles the lookup and creation of new subtables
+ __index = function(t,k)
+ if k == nil then return nil end
+ local tbl = {}
+ copyDefaults(tbl, v)
+ rawset(t, k, tbl)
+ return tbl
+ end,
+ }
+ setmetatable(dest, mt)
+ -- handle already existing tables in the SV
+ for dk, dv in pairs(dest) do
+ if not rawget(src, dk) and type(dv) == "table" then
+ copyDefaults(dv, v)
+ end
+ end
+ else
+ -- Values are not tables, so this is just a simple return
+ local mt = {__index = function(t,k) return k~=nil and v or nil end}
+ setmetatable(dest, mt)
+ end
+ elseif type(v) == "table" then
+ if not rawget(dest, k) then rawset(dest, k, {}) end
+ if type(dest[k]) == "table" then
+ copyDefaults(dest[k], v)
+ if src['**'] then
+ copyDefaults(dest[k], src['**'])
+ end
+ end
+ else
+ if rawget(dest, k) == nil then
+ rawset(dest, k, v)
+ end
+ end
+ end
+end
+
+-- Called to remove all defaults in the default table from the database
+local function removeDefaults(db, defaults, blocker)
+ -- remove all metatables from the db, so we don't accidentally create new sub-tables through them
+ setmetatable(db, nil)
+ -- loop through the defaults and remove their content
+ for k,v in pairs(defaults) do
+ local v = v
+ if k == "*" or k == "**" then
+ if type(v) == "table" then
+ -- Loop through all the actual k,v pairs and remove
+ for key, value in pairs(db) do
+ local value = value
+ if type(value) == "table" then
+ -- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
+ if defaults[key] == nil and (not blocker or blocker[key] == nil) then
+ removeDefaults(value, v)
+ -- if the table is empty afterwards, remove it
+ if next(value) == nil then
+ db[key] = nil
+ end
+ -- if it was specified, only strip ** content, but block values which were set in the key table
+ elseif k == "**" then
+ removeDefaults(value, v, defaults[key])
+ end
+ end
+ end
+ elseif k == "*" then
+ -- check for non-table default
+ for key, value in pairs(db) do
+ if defaults[key] == nil and v == value then
+ db[key] = nil
+ end
+ end
+ end
+ elseif type(v) == "table" and type(db[k]) == "table" then
+ -- if a blocker was set, dive into it, to allow multi-level defaults
+ removeDefaults(db[k], v, blocker and blocker[k])
+ if next(db[k]) == nil then
+ db[k] = nil
+ end
+ else
+ -- check if the current value matches the default, and that its not blocked by another defaults table
+ if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
+ db[k] = nil
+ end
+ end
+ end
+end
+
+-- This is called when a table section is first accessed, to set up the defaults
+local function initSection(db, section, svstore, key, defaults)
+ local sv = rawget(db, "sv")
+
+ local tableCreated
+ if not sv[svstore] then sv[svstore] = {} end
+ if not sv[svstore][key] then
+ sv[svstore][key] = {}
+ tableCreated = true
+ end
+
+ local tbl = sv[svstore][key]
+
+ if defaults then
+ copyDefaults(tbl, defaults)
+ end
+ rawset(db, section, tbl)
+
+ return tableCreated, tbl
+end
+
+-- Metatable to handle the dynamic creation of sections and copying of sections.
+local dbmt = {
+ __index = function(t, section)
+ local keys = rawget(t, "keys")
+ local key = keys[section]
+ if key then
+ local defaultTbl = rawget(t, "defaults")
+ local defaults = defaultTbl and defaultTbl[section]
+
+ if section == "profile" then
+ if initSection(t, section, "profiles", key, defaults) then
+ -- Callback: OnNewProfile, database, newProfileKey
+ t.callbacks:Fire("OnNewProfile", 2, t, key)
+ end
+ elseif section == "profiles" then
+ local sv = rawget(t, "sv")
+ if not sv.profiles then sv.profiles = {} end
+ rawset(t, "profiles", sv.profiles)
+ elseif section == "global" then
+ local sv = rawget(t, "sv")
+ if not sv.global then sv.global = {} end
+ if defaults then
+ copyDefaults(sv.global, defaults)
+ end
+ rawset(t, section, sv.global)
+ else
+ initSection(t, section, section, key, defaults)
+ end
+ end
+
+ return rawget(t, section)
+ end
+}
+
+local function validateDefaults(defaults, keyTbl, offset)
+ if not defaults then return end
+ offset = offset or 0
+ for k in pairs(defaults) do
+ if not keyTbl[k] or k == "profiles" then
+ error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
+ end
+ end
+end
+
+local preserve_keys = {
+ ["callbacks"] = true,
+ ["RegisterCallback"] = true,
+ ["UnregisterCallback"] = true,
+ ["UnregisterAllCallbacks"] = true,
+ ["children"] = true,
+}
+
+local realmKey = GetRealmName()
+local charKey = UnitName("player") .. " - " .. realmKey
+local _, classKey = UnitClass("player")
+local _, raceKey = UnitRace("player")
+local _, factionKey = UnitFactionGroup("player")
+-- Ace3v: the faction key may error when in GM mode
+factionKey = factionKey or "Others"
+local localeKey = string.lower(GetLocale())
+
+-- Actual database initialization function
+local function initdb(sv, defaults, defaultProfile, olddb, parent)
+ -- Generate the database keys for each section
+
+ -- map "true" to our "Default" profile
+ if defaultProfile == true then defaultProfile = "Default" end
+
+ local profileKey
+ if not parent then
+ -- Make a container for profile keys
+ if not sv.profileKeys then sv.profileKeys = {} end
+
+ -- Try to get the profile selected from the char db
+ profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
+
+ -- save the selected profile for later
+ sv.profileKeys[charKey] = profileKey
+ else
+ -- Use the profile of the parents DB
+ profileKey = parent.keys.profile or defaultProfile or charKey
+
+ -- clear the profileKeys in the DB, namespaces don't need to store them
+ sv.profileKeys = nil
+ end
+
+ -- This table contains keys that enable the dynamic creation
+ -- of each section of the table. The 'global' and 'profiles'
+ -- have a key of true, since they are handled in a special case
+ local keyTbl= {
+ ["char"] = charKey,
+ ["realm"] = realmKey,
+ ["class"] = classKey,
+ ["race"] = raceKey,
+ ["faction"] = factionKey,
+ ["factionrealm"] = factionKey .. " - " .. realmKey,
+ ["profile"] = profileKey,
+ ["locale"] = localeKey,
+ ["global"] = true,
+ ["profiles"] = true,
+ }
+
+ validateDefaults(defaults, keyTbl, 1)
+
+ -- This allows us to use this function to reset an entire database
+ -- Clear out the old database
+ if olddb then
+ for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
+ end
+
+ -- Give this database the metatable so it initializes dynamically
+ local db = setmetatable(olddb or {}, dbmt)
+
+ if not rawget(db, "callbacks") then
+ -- try to load CallbackHandler-1.0 if it loaded after our library
+ if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
+ db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
+ end
+
+ -- Copy methods locally into the database object, to avoid hitting
+ -- the metatable when calling methods
+
+ if not parent then
+ for name, func in pairs(DBObjectLib) do
+ db[name] = func
+ end
+ else
+ -- hack this one in
+ db.RegisterDefaults = DBObjectLib.RegisterDefaults
+ db.ResetProfile = DBObjectLib.ResetProfile
+ end
+
+ -- Set some properties in the database object
+ db.profiles = sv.profiles
+ db.keys = keyTbl
+ db.sv = sv
+ --db.sv_name = name
+ db.defaults = defaults
+ db.parent = parent
+
+ -- store the DB in the registry
+ AceDB.db_registry[db] = true
+
+ return db
+end
+
+-- handle PLAYER_LOGOUT
+-- strip all defaults from all databases
+-- and cleans up empty sections
+local function logoutHandler()
+ if event == "PLAYER_LOGOUT" then
+ for db in pairs(AceDB.db_registry) do
+ db.callbacks:Fire("OnDatabaseShutdown", 1, db)
+ db:RegisterDefaults(nil)
+
+ -- cleanup sections that are empty without defaults
+ local sv = rawget(db, "sv")
+ for section in pairs(db.keys) do
+ if rawget(sv, section) then
+ -- global is special, all other sections have sub-entrys
+ -- also don't delete empty profiles on main dbs, only on namespaces
+ if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
+ for key in pairs(sv[section]) do
+ if not next(sv[section][key]) then
+ sv[section][key] = nil
+ end
+ end
+ end
+ if not next(sv[section]) then
+ sv[section] = nil
+ end
+ end
+ end
+ end
+ end
+end
+
+AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
+AceDB.frame:SetScript("OnEvent", logoutHandler)
+
+
+--[[-------------------------------------------------------------------------
+ AceDB Object Method Definitions
+---------------------------------------------------------------------------]]
+
+--- Sets the defaults table for the given database object by clearing any
+-- that are currently set, and then setting the new defaults.
+-- @param defaults A table of defaults for this database
+function DBObjectLib:RegisterDefaults(defaults)
+ if defaults and type(defaults) ~= "table" then
+ error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
+ end
+
+ validateDefaults(defaults, self.keys)
+
+ -- Remove any currently set defaults
+ if self.defaults then
+ for section,key in pairs(self.keys) do
+ if self.defaults[section] and rawget(self, section) then
+ removeDefaults(self[section], self.defaults[section])
+ end
+ end
+ end
+
+ -- Set the DBObject.defaults table
+ self.defaults = defaults
+
+ -- Copy in any defaults, only touching those sections already created
+ if defaults then
+ for section,key in pairs(self.keys) do
+ if defaults[section] and rawget(self, section) then
+ copyDefaults(self[section], defaults[section])
+ end
+ end
+ end
+end
+
+--- Changes the profile of the database and all of it's namespaces to the
+-- supplied named profile
+-- @param name The name of the profile to set as the current profile
+function DBObjectLib:SetProfile(name)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
+ end
+
+ -- changing to the same profile, dont do anything
+ if name == self.keys.profile then return end
+
+ local oldProfile = self.profile
+ local defaults = self.defaults and self.defaults.profile
+
+ -- Callback: OnProfileShutdown, database
+ self.callbacks:Fire("OnProfileShutdown", 1, self)
+
+ if oldProfile and defaults then
+ -- Remove the defaults from the old profile
+ removeDefaults(oldProfile, defaults)
+ end
+
+ self.profile = nil
+ self.keys["profile"] = name
+
+ -- if the storage exists, save the new profile
+ -- this won't exist on namespaces.
+ if self.sv.profileKeys then
+ self.sv.profileKeys[charKey] = name
+ end
+
+ -- populate to child namespaces
+ if self.children then
+ for _, db in pairs(self.children) do
+ DBObjectLib.SetProfile(db, name)
+ end
+ end
+
+ -- Callback: OnProfileChanged, database, newProfileKey
+ self.callbacks:Fire("OnProfileChanged", 2, self, name)
+end
+
+--- Returns a table with the names of the existing profiles in the database.
+-- You can optionally supply a table to re-use for this purpose.
+-- @param tbl A table to store the profile names in (optional)
+function DBObjectLib:GetProfiles(tbl)
+ if tbl and type(tbl) ~= "table" then
+ error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
+ end
+
+ -- Clear the container table
+ if tbl then
+ for k,v in pairs(tbl) do tbl[k] = nil end
+ else
+ tbl = {}
+ end
+
+ local curProfile = self.keys.profile
+
+ local i = 0
+ for profileKey in pairs(self.profiles) do
+ i = i + 1
+ tbl[i] = profileKey
+ if curProfile and profileKey == curProfile then curProfile = nil end
+ end
+
+ -- Add the current profile, if it hasn't been created yet
+ if curProfile then
+ i = i + 1
+ tbl[i] = curProfile
+ end
+
+ return tbl, i
+end
+
+--- Returns the current profile name used by the database
+function DBObjectLib:GetCurrentProfile()
+ return self.keys.profile
+end
+
+--- Deletes a named profile. This profile must not be the active profile.
+-- @param name The name of the profile to be deleted
+-- @param silent If true, do not raise an error when the profile does not exist
+function DBObjectLib:DeleteProfile(name, silent)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
+ end
+
+ if self.keys.profile == name then
+ error("Cannot delete the active profile in an AceDBObject.", 2)
+ end
+
+ if not rawget(self.profiles, name) and not silent then
+ error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
+ end
+
+ self.profiles[name] = nil
+
+ -- populate to child namespaces
+ if self.children then
+ for _, db in pairs(self.children) do
+ DBObjectLib.DeleteProfile(db, name, true)
+ end
+ end
+
+ -- switch all characters that use this profile back to the default
+ if self.sv.profileKeys then
+ for key, profile in pairs(self.sv.profileKeys) do
+ if profile == name then
+ self.sv.profileKeys[key] = nil
+ end
+ end
+ end
+
+ -- Callback: OnProfileDeleted, database, profileKey
+ self.callbacks:Fire("OnProfileDeleted", 2, self, name)
+end
+
+--- Copies a named profile into the current profile, overwriting any conflicting
+-- settings.
+-- @param name The name of the profile to be copied into the current profile
+-- @param silent If true, do not raise an error when the profile does not exist
+function DBObjectLib:CopyProfile(name, silent)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
+ end
+
+ if name == self.keys.profile then
+ error("Cannot have the same source and destination profiles.", 2)
+ end
+
+ if not rawget(self.profiles, name) and not silent then
+ error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
+ end
+
+ -- Reset the profile before copying
+ DBObjectLib.ResetProfile(self, nil, true)
+
+ local profile = self.profile
+ local source = self.profiles[name]
+
+ copyTable(source, profile)
+
+ -- populate to child namespaces
+ if self.children then
+ for _, db in pairs(self.children) do
+ DBObjectLib.CopyProfile(db, name, true)
+ end
+ end
+
+ -- Callback: OnProfileCopied, database, sourceProfileKey
+ self.callbacks:Fire("OnProfileCopied", 2, self, name)
+end
+
+--- Resets the current profile to the default values (if specified).
+-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
+-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
+function DBObjectLib:ResetProfile(noChildren, noCallbacks)
+ local profile = self.profile
+
+ for k,v in pairs(profile) do
+ profile[k] = nil
+ end
+
+ local defaults = self.defaults and self.defaults.profile
+ if defaults then
+ copyDefaults(profile, defaults)
+ end
+
+ -- populate to child namespaces
+ if self.children and not noChildren then
+ for _, db in pairs(self.children) do
+ DBObjectLib.ResetProfile(db, nil, noCallbacks)
+ end
+ end
+
+ -- Callback: OnProfileReset, database
+ if not noCallbacks then
+ self.callbacks:Fire("OnProfileReset", 2, self, self.keys["profile"])
+ end
+end
+
+--- Resets the entire database, using the string defaultProfile as the new default
+-- profile.
+-- @param defaultProfile The profile name to use as the default
+function DBObjectLib:ResetDB(defaultProfile)
+ if defaultProfile and type(defaultProfile) ~= "string" then
+ error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
+ end
+
+ local sv = self.sv
+ for k,v in pairs(sv) do
+ sv[k] = nil
+ end
+
+ local parent = self.parent
+
+ initdb(sv, self.defaults, defaultProfile, self)
+
+ -- fix the child namespaces
+ if self.children then
+ if not sv.namespaces then sv.namespaces = {} end
+ for name, db in pairs(self.children) do
+ if not sv.namespaces[name] then sv.namespaces[name] = {} end
+ initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
+ end
+ end
+
+ -- Callback: OnDatabaseReset, database
+ self.callbacks:Fire("OnDatabaseReset", 1, self)
+ -- Callback: OnProfileChanged, database, profileKey
+ self.callbacks:Fire("OnProfileChanged", 2, self, self.keys["profile"])
+
+ return self
+end
+
+--- Creates a new database namespace, directly tied to the database. This
+-- is a full scale database in it's own rights other than the fact that
+-- it cannot control its profile individually
+-- @param name The name of the new namespace
+-- @param defaults A table of values to use as defaults
+function DBObjectLib:RegisterNamespace(name, defaults)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
+ end
+ if defaults and type(defaults) ~= "table" then
+ error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
+ end
+ if self.children and self.children[name] then
+ error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
+ end
+
+ local sv = self.sv
+ if not sv.namespaces then sv.namespaces = {} end
+ if not sv.namespaces[name] then
+ sv.namespaces[name] = {}
+ end
+
+ local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
+
+ if not self.children then self.children = {} end
+ self.children[name] = newDB
+ return newDB
+end
+
+--- Returns an already existing namespace from the database object.
+-- @param name The name of the new namespace
+-- @param silent if true, the addon is optional, silently return nil if its not found
+-- @usage
+-- local namespace = self.db:GetNamespace('namespace')
+-- @return the namespace object if found
+function DBObjectLib:GetNamespace(name, silent)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
+ end
+ if not silent and not (self.children and self.children[name]) then
+ error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
+ end
+ if not self.children then self.children = {} end
+ return self.children[name]
+end
+
+--[[-------------------------------------------------------------------------
+ AceDB Exposed Methods
+---------------------------------------------------------------------------]]
+
+--- Creates a new database object that can be used to handle database settings and profiles.
+-- By default, an empty DB is created, using a character specific profile.
+--
+-- You can override the default profile used by passing any profile name as the third argument,
+-- or by passing //true// as the third argument to use a globally shared profile called "Default".
+--
+-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
+-- will use a profile named "char", and not a character-specific profile.
+-- @param tbl The name of variable, or table to use for the database
+-- @param defaults A table of database defaults
+-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
+-- You can also pass //true// to use a shared global profile called "Default".
+-- @usage
+-- -- Create an empty DB using a character-specific default profile.
+-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
+-- @usage
+-- -- Create a DB using defaults and using a shared default profile
+-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
+function AceDB:New(tbl, defaults, defaultProfile)
+ if type(tbl) == "string" then
+ local name = tbl
+ tbl = _G[name]
+ if not tbl then
+ tbl = {}
+ _G[name] = tbl
+ end
+ end
+
+ if type(tbl) ~= "table" then
+ error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
+ end
+
+ if defaults and type(defaults) ~= "table" then
+ error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
+ end
+
+ if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
+ error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
+ end
+
+ return initdb(tbl, defaults, defaultProfile)
+end
+
+-- upgrade existing databases
+for db in pairs(AceDB.db_registry) do
+ if not db.parent then
+ for name,func in pairs(DBObjectLib) do
+ db[name] = func
+ end
+ else
+ db.RegisterDefaults = DBObjectLib.RegisterDefaults
+ db.ResetProfile = DBObjectLib.ResetProfile
+ end
+end
diff --git a/ElvUI/Libraries/AceDB-3.0/AceDB-3.0.xml b/ElvUI/Libraries/AceDB-3.0/AceDB-3.0.xml
new file mode 100644
index 0000000..789d9f2
--- /dev/null
+++ b/ElvUI/Libraries/AceDB-3.0/AceDB-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceEvent-3.0/AceEvent-3.0.lua b/ElvUI/Libraries/AceEvent-3.0/AceEvent-3.0.lua
new file mode 100644
index 0000000..9eb0e36
--- /dev/null
+++ b/ElvUI/Libraries/AceEvent-3.0/AceEvent-3.0.lua
@@ -0,0 +1,129 @@
+--- AceEvent-3.0 provides event registration and secure dispatching.
+-- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
+-- CallbackHandler, and dispatches all game events or addon message to the registrees.
+--
+-- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceEvent itself.\\
+-- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceEvent.
+-- @class file
+-- @name AceEvent-3.0
+-- @release $Id: AceEvent-3.0.lua 975 2010-10-23 11:26:18Z nevcairiel $
+local MAJOR, MINOR = "AceEvent-3.0", 3
+local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceEvent then return end
+
+-- Lua APIs
+local pairs = pairs
+
+local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
+
+AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
+AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
+
+-- APIs and registry for blizzard events, using CallbackHandler lib
+if not AceEvent.events then
+ AceEvent.events = CallbackHandler:New(AceEvent,
+ "RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
+end
+
+function AceEvent.events:OnUsed(target, eventname)
+ AceEvent.frame:RegisterEvent(eventname)
+end
+
+function AceEvent.events:OnUnused(target, eventname)
+ AceEvent.frame:UnregisterEvent(eventname)
+end
+
+
+-- APIs and registry for IPC messages, using CallbackHandler lib
+if not AceEvent.messages then
+ AceEvent.messages = CallbackHandler:New(AceEvent,
+ "RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
+ )
+ AceEvent.SendMessage = AceEvent.messages.Fire
+end
+
+--- embedding and embed handling
+local mixins = {
+ "RegisterEvent", "UnregisterEvent",
+ "RegisterMessage", "UnregisterMessage",
+ "SendMessage",
+ "UnregisterAllEvents", "UnregisterAllMessages",
+}
+
+--- Register for a Blizzard Event.
+-- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
+-- Any arguments to the event will be passed on after that.
+-- @name AceEvent:RegisterEvent
+-- @class function
+-- @paramsig event[, callback [, arg]]
+-- @param event The event to register for
+-- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
+-- @param arg An optional argument to pass to the callback function
+
+--- Unregister an event.
+-- @name AceEvent:UnregisterEvent
+-- @class function
+-- @paramsig event
+-- @param event The event to unregister
+
+--- Register for a custom AceEvent-internal message.
+-- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
+-- Any arguments to the event will be passed on after that.
+-- @name AceEvent:RegisterMessage
+-- @class function
+-- @paramsig message[, callback [, arg]]
+-- @param message The message to register for
+-- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
+-- @param arg An optional argument to pass to the callback function
+
+--- Unregister a message
+-- @name AceEvent:UnregisterMessage
+-- @class function
+-- @paramsig message
+-- @param message The message to unregister
+
+--- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
+-- @name AceEvent:SendMessage
+-- @class function
+-- @paramsig message, ...
+-- @param message The message to send
+-- @param ... Any arguments to the message
+
+
+-- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceEvent in
+function AceEvent:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+-- AceEvent:OnEmbedDisable( target )
+-- target (object) - target object that is being disabled
+--
+-- Unregister all events messages etc when the target disables.
+-- this method should be called by the target manually or by an addon framework
+function AceEvent:OnEmbedDisable(target)
+ target:UnregisterAllEvents()
+ target:UnregisterAllMessages()
+end
+
+-- Script to fire blizzard events into the event listeners
+-- Ace3v: in vanilla the arguments are set to global:
+-- event, arg1, arg2, arg3 ...
+-- the user have always access to them, so we save the table cost here
+local events = AceEvent.events
+AceEvent.frame:SetScript("OnEvent", function()
+ events:Fire(event)
+end)
+
+--- Finally: upgrade our old embeds
+for target, v in pairs(AceEvent.embeds) do
+ AceEvent:Embed(target)
+end
diff --git a/ElvUI/Libraries/AceEvent-3.0/AceEvent-3.0.xml b/ElvUI/Libraries/AceEvent-3.0/AceEvent-3.0.xml
new file mode 100644
index 0000000..6be93ee
--- /dev/null
+++ b/ElvUI/Libraries/AceEvent-3.0/AceEvent-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceHook-3.0/AceHook-3.0.lua b/ElvUI/Libraries/AceHook-3.0/AceHook-3.0.lua
new file mode 100644
index 0000000..7714848
--- /dev/null
+++ b/ElvUI/Libraries/AceHook-3.0/AceHook-3.0.lua
@@ -0,0 +1,540 @@
+--- **AceHook-3.0** offers safe Hooking/Unhooking of functions, methods and frame scripts.
+-- Using AceHook-3.0 is recommended when you need to unhook your hooks again, so the hook chain isn't broken
+-- when you manually restore the original function.
+--
+-- **AceHook-3.0** can be embeded into your addon, either explicitly by calling AceHook:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceHook itself.\\
+-- It is recommended to embed AceHook, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceHook.
+-- @class file
+-- @name AceHook-3.0
+-- @release $Id: AceHook-3.0.lua 1118 2014-10-12 08:21:54Z nevcairiel $
+local ACEHOOK_MAJOR, ACEHOOK_MINOR = "AceHook-3.0", 8
+local AceHook, oldminor = LibStub:NewLibrary(ACEHOOK_MAJOR, ACEHOOK_MINOR)
+
+if not AceHook then return end -- No upgrade needed
+
+local AceCore = LibStub("AceCore-3.0")
+local new, del = AceCore.new, AceCore.del
+
+AceHook.embeded = AceHook.embeded or {}
+AceHook.registry = AceHook.registry or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end })
+AceHook.handlers = AceHook.handlers or {}
+AceHook.actives = AceHook.actives or {}
+AceHook.scripts = AceHook.scripts or {}
+AceHook.onceSecure = AceHook.onceSecure or {}
+AceHook.hooks = AceHook.hooks or {}
+
+-- local upvalues
+local registry = AceHook.registry
+local handlers = AceHook.handlers
+local actives = AceHook.actives
+local scripts = AceHook.scripts
+local onceSecure = AceHook.onceSecure
+
+-- Lua APIs
+local pairs, next, type = pairs, next, type
+local format = string.format
+local assert, error = assert, error
+
+-- WoW APIs
+local hooksecurefunc, issecurevariable = AceCore.hooksecurefunc, AceCore.issecurevariable
+
+local _G = AceCore._G
+
+local protectedScripts = {
+ OnClick = true,
+}
+
+-- upgrading of embeded is done at the bottom of the file
+
+local mixins = {
+ "Hook", "SecureHook",
+ "HookScript", "SecureHookScript",
+ "Unhook", "UnhookAll",
+ "IsHooked",
+ "RawHook", "RawHookScript"
+}
+
+-- AceHook:Embed( target )
+-- target (object) - target object to embed AceHook in
+--
+-- Embeds AceEevent into the target object making the functions from the mixins list available on target:..
+function AceHook:Embed( target )
+ for k, v in pairs( mixins ) do
+ target[v] = self[v]
+ end
+ self.embeded[target] = true
+ -- inject the hooks table safely
+ target.hooks = target.hooks or {}
+ return target
+end
+
+-- AceHook:OnEmbedDisable( target )
+-- target (object) - target object that is being disabled
+--
+-- Unhooks all hooks when the target disables.
+-- this method should be called by the target manually or by an addon framework
+function AceHook:OnEmbedDisable( target )
+ target:UnhookAll()
+end
+
+-- failsafe means even the hooking method fails, the original method will
+-- always be called
+local function createHook(self, handler, orig, secure, failsafe)
+ local uid
+ local method = type(handler) == "string"
+ -- Ace3v: when this function called in the "hook" function, we have
+ -- failsafe = not (raw or secure), so the first check condition
+ -- is same as "if failsafe" or "if not raw and not secure"
+ if failsafe and not secure then
+ -- failsafe hook creation
+ uid = function(...)
+ if actives[uid] then
+ if method then
+ self[handler](self,unpack(arg))
+ else
+ handler(unpack(arg))
+ end
+ end
+ return orig(unpack(arg))
+ end
+ -- /failsafe hook
+ else
+ -- all other hooks
+ uid = function(...)
+ if actives[uid] then
+ if method then
+ return self[handler](self,unpack(arg))
+ else
+ return handler(unpack(arg))
+ end
+ elseif not secure then -- backup on non secure
+ return orig(unpack(arg))
+ end
+ end
+ -- /hook
+ end
+ return uid
+end
+
+local function donothing() end
+
+-- @param self
+-- @param obj nil or a frame object, use with script = true
+-- @param method string, the name of a global function or the name of an object method
+-- @param handler function, or string when it's a method of 'self', if nil then will use the same value as method
+-- @param script boolean, must be true, if the hooked object is a frame
+-- @param secure boolean, if hooking a secure script, if true the original script will be called first, else later
+-- @param raw boolean, if raw hooking (replacing the original method)
+-- @param forceSecure boolean, if forcing to hook a secure method
+-- @param usage
+local function hook(self, obj, method, handler, script, secure, raw, forceSecure, usage)
+ if not handler then handler = method end
+
+ -- These asserts make sure AceHooks's devs play by the rules.
+ assert(not script or type(script) == "boolean")
+ assert(not secure or type(secure) == "boolean")
+ assert(not raw or type(raw) == "boolean")
+ assert(not forceSecure or type(forceSecure) == "boolean")
+ assert(usage)
+
+ -- Error checking Battery!
+ if obj and type(obj) ~= "table" then
+ error(format("%s: 'object' - nil or table expected got %s", usage, type(obj)), 3)
+ end
+ if type(method) ~= "string" then
+ error(format("%s: 'method' - string expected got %s", usage, type(method)), 3)
+ end
+ if type(handler) ~= "string" and type(handler) ~= "function" then
+ error(format("%s: 'handler' - nil, string, or function expected got %s", usage, type(handler)), 3)
+ end
+ if type(handler) == "string" and type(self[handler]) ~= "function" then
+ error(format("%s: 'handler' - Handler specified does not exist at self[handler]", usage), 3)
+ end
+ if script then
+ if not obj or not obj.GetScript or not obj:HasScript(method) then
+ error(format("%s: You can only hook a script on a frame object", usage), 3)
+ end
+ if not secure and obj.IsProtected and obj:IsProtected() and protectedScripts[method] then
+ error(format("Cannot hook secure script %q; Use SecureHookScript(obj, method, [handler]) instead.", method), 3)
+ end
+ else
+ local issecure
+ if obj then
+ issecure = onceSecure[obj] and onceSecure[obj][method] or issecurevariable(obj, method)
+ else
+ issecure = onceSecure[method] or issecurevariable(method)
+ end
+ if issecure then
+ if forceSecure then
+ if obj then
+ onceSecure[obj] = onceSecure[obj] or {}
+ onceSecure[obj][method] = true
+ else
+ onceSecure[method] = true
+ end
+ elseif not secure then
+ error(format("%s: Attempt to hook secure function %s. Use `SecureHook' or add `true' to the argument list to override.", usage, method), 3)
+ end
+ end
+ end
+
+ local uid
+ if obj then
+ uid = registry[self][obj] and registry[self][obj][method]
+ else
+ uid = registry[self][method]
+ end
+
+ if uid then
+ if actives[uid] then
+ -- Only two sane choices exist here. We either a) error 100% of the time or b) always unhook and then hook
+ -- choice b would likely lead to odd debuging conditions or other mysteries so we're going with a.
+ error(format("Attempting to rehook already active hook %s.", method))
+ end
+
+ if handlers[uid] == handler then -- turn on a decative hook, note enclosures break this ability, small memory leak
+ actives[uid] = true
+ return
+ elseif obj then -- is there any reason not to call unhook instead of doing the following several lines?
+ if self.hooks and self.hooks[obj] then
+ self.hooks[obj][method] = nil
+ end
+ registry[self][obj][method] = nil
+ else
+ if self.hooks then
+ self.hooks[method] = nil
+ end
+ registry[self][method] = nil
+ end
+ handlers[uid], actives[uid], scripts[uid] = nil, nil, nil
+ uid = nil
+ end
+
+ local orig
+ if script then
+ -- Sometimes there is not a original function for a script.
+ orig = obj:GetScript(method) or donothing
+ elseif obj then
+ orig = obj[method]
+ else
+ orig = _G[method]
+ end
+
+ if not orig then
+ error(format("%s: Attempting to hook a non existing target", usage), 3)
+ end
+
+ uid = createHook(self, handler, orig, secure, not (raw or secure))
+
+ if obj then
+ registry[self][obj] = registry[self][obj] or new()
+ registry[self][obj][method] = uid
+
+ if not secure then
+ self.hooks[obj] = self.hooks[obj] or new()
+ self.hooks[obj][method] = orig
+ end
+
+ if script then
+ if not secure then
+ obj:SetScript(method, uid)
+ else
+ obj:SetScript(method, function(...)
+ local tmp = {orig(unpack(arg))}
+ uid(unpack(arg))
+ return unpack(tmp)
+ end)
+ --obj:HookScript(method, uid) -- Ace3v: vanilla frame has no HookScript
+ end
+ else
+ if not secure then
+ obj[method] = uid
+ else
+ hooksecurefunc(obj, method, uid)
+ end
+ end
+ else
+ registry[self][method] = uid
+
+ if not secure then
+ _G[method] = uid
+ self.hooks[method] = orig
+ else
+ hooksecurefunc(method, uid)
+ end
+ end
+
+ actives[uid], handlers[uid], scripts[uid] = true, handler, script and true or nil
+end
+
+--- Hook a function or a method on an object.
+-- The hook created will be a "safe hook", that means that your handler will be called
+-- before the hooked function ("Pre-Hook"), and you don't have to call the original function yourself,
+-- however you cannot stop the execution of the function, or modify any of the arguments/return values.\\
+-- This type of hook is typically used if you need to know if some function got called, and don't want to modify it.
+-- @paramsig [object], method, [handler], [hookSecure]
+-- @param object The object to hook a method from
+-- @param method If object was specified, the name of the method, or the name of the function to hook.
+-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
+-- @param hookSecure If true, AceHook will allow hooking of secure functions.
+-- @usage
+-- -- create an addon with AceHook embeded
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
+--
+-- function MyAddon:OnEnable()
+-- -- Hook ActionButton_UpdateHotkeys, overwriting the secure status
+-- self:Hook("ActionButton_UpdateHotkeys", true)
+-- end
+--
+-- function MyAddon:ActionButton_UpdateHotkeys(button, type)
+-- print(button:GetName() .. " is updating its HotKey")
+-- end
+function AceHook:Hook(object, method, handler, hookSecure)
+ if type(object) == "string" then
+ method, handler, hookSecure, object = object, method, handler, nil
+ end
+
+ if handler == true then
+ handler, hookSecure = nil, true
+ end
+
+ hook(self, object, method, handler, false, false, false, hookSecure or false, "Usage: Hook([object], method, [handler], [hookSecure])")
+end
+
+--- RawHook a function or a method on an object.
+-- The hook created will be a "raw hook", that means that your handler will completly replace
+-- the original function, and your handler has to call the original function (or not, depending on your intentions).\\
+-- The original function will be stored in `self.hooks[object][method]` or `self.hooks[functionName]` respectively.\\
+-- This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments
+-- or want to control execution of the original function.
+-- @paramsig [object], method, [handler], [hookSecure]
+-- @param object The object to hook a method from
+-- @param method If object was specified, the name of the method, or the name of the function to hook.
+-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
+-- @param hookSecure If true, AceHook will allow hooking of secure functions.
+-- @usage
+-- -- create an addon with AceHook embeded
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
+--
+-- function MyAddon:OnEnable()
+-- -- Hook ActionButton_UpdateHotkeys, overwriting the secure status
+-- self:RawHook("ActionButton_UpdateHotkeys", true)
+-- end
+--
+-- function MyAddon:ActionButton_UpdateHotkeys(button, type)
+-- if button:GetName() == "MyButton" then
+-- -- do stuff here
+-- else
+-- self.hooks.ActionButton_UpdateHotkeys(button, type)
+-- end
+-- end
+function AceHook:RawHook(object, method, handler, hookSecure)
+ if type(object) == "string" then
+ method, handler, hookSecure, object = object, method, handler, nil
+ end
+
+ if handler == true then
+ handler, hookSecure = nil, true
+ end
+
+ hook(self, object, method, handler, false, false, true, hookSecure or false, "Usage: RawHook([object], method, [handler], [hookSecure])")
+end
+
+--- SecureHook a function or a method on an object.
+-- This function is a wrapper around the `hooksecurefunc` function in the WoW API. Using AceHook
+-- extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't
+-- required anymore, or the addon is being disabled.\\
+-- Secure Hooks should be used if the secure-status of the function is vital to its function,
+-- and taint would block execution. Secure Hooks are always called after the original function was called
+-- ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
+-- @paramsig [object], method, [handler]
+-- @param object The object to hook a method from
+-- @param method If object was specified, the name of the method, or the name of the function to hook.
+-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
+function AceHook:SecureHook(object, method, handler)
+ if type(object) == "string" then
+ method, handler, object = object, method, nil
+ end
+
+ hook(self, object, method, handler, false, true, false, false, "Usage: SecureHook([object], method, [handler])")
+end
+
+--- Hook a script handler on a frame.
+-- The hook created will be a "safe hook", that means that your handler will be called
+-- before the hooked script ("Pre-Hook"), and you don't have to call the original function yourself,
+-- however you cannot stop the execution of the function, or modify any of the arguments/return values.\\
+-- This is the frame script equivalent of the :Hook safe-hook. It would typically be used to be notified
+-- when a certain event happens to a frame.
+-- @paramsig frame, script, [handler]
+-- @param frame The Frame to hook the script on
+-- @param script The script to hook
+-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
+-- @usage
+-- -- create an addon with AceHook embeded
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
+--
+-- function MyAddon:OnEnable()
+-- -- Hook the OnShow of FriendsFrame
+-- self:HookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
+-- end
+--
+-- function MyAddon:FriendsFrameOnShow(frame)
+-- print("The FriendsFrame was shown!")
+-- end
+function AceHook:HookScript(frame, script, handler)
+ hook(self, frame, script, handler, true, false, false, false, "Usage: HookScript(object, method, [handler])")
+end
+
+--- RawHook a script handler on a frame.
+-- The hook created will be a "raw hook", that means that your handler will completly replace
+-- the original script, and your handler has to call the original script (or not, depending on your intentions).\\
+-- The original script will be stored in `self.hooks[frame][script]`.\\
+-- This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments
+-- or want to control execution of the original script.
+-- @paramsig frame, script, [handler]
+-- @param frame The Frame to hook the script on
+-- @param script The script to hook
+-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
+-- @usage
+-- -- create an addon with AceHook embeded
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
+--
+-- function MyAddon:OnEnable()
+-- -- Hook the OnShow of FriendsFrame
+-- self:RawHookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
+-- end
+--
+-- function MyAddon:FriendsFrameOnShow(frame)
+-- -- Call the original function
+-- self.hooks[frame].OnShow(frame)
+-- -- Do our processing
+-- -- .. stuff
+-- end
+function AceHook:RawHookScript(frame, script, handler)
+ hook(self, frame, script, handler, true, false, true, false, "Usage: RawHookScript(object, method, [handler])")
+end
+
+--- SecureHook a script handler on a frame.
+-- This function is a wrapper around the `frame:HookScript` function in the WoW API. Using AceHook
+-- extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't
+-- required anymore, or the addon is being disabled.\\
+-- Secure Hooks should be used if the secure-status of the function is vital to its function,
+-- and taint would block execution. Secure Hooks are always called after the original function was called
+-- ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
+-- @paramsig frame, script, [handler]
+-- @param frame The Frame to hook the script on
+-- @param script The script to hook
+-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
+function AceHook:SecureHookScript(frame, script, handler)
+ hook(self, frame, script, handler, true, true, false, false, "Usage: SecureHookScript(object, method, [handler])")
+end
+
+--- Unhook from the specified function, method or script.
+-- @paramsig [obj], method
+-- @param obj The object or frame to unhook from
+-- @param method The name of the method, function or script to unhook from.
+function AceHook:Unhook(obj, method)
+ local usage = "Usage: Unhook([obj], method)"
+ if type(obj) == "string" then
+ method, obj = obj, nil
+ end
+
+ if obj and type(obj) ~= "table" then
+ error(format("%s: 'obj' - expecting nil or table got %s", usage, type(obj)), 2)
+ end
+ if type(method) ~= "string" then
+ error(format("%s: 'method' - expeting string got %s", usage, type(method)), 2)
+ end
+
+ local uid
+ if obj then
+ uid = registry[self][obj] and registry[self][obj][method]
+ else
+ uid = registry[self][method]
+ end
+
+ if not uid or not actives[uid] then
+ -- Declining to error on an unneeded unhook since the end effect is the same and this would just be annoying.
+ return false
+ end
+
+ actives[uid], handlers[uid] = nil, nil
+
+ if obj then
+ local tmp = registry[self][obj]
+ tmp[method] = nil
+ if not next(tmp) then
+ del(tmp)
+ registry[self][obj] = nil
+ end
+
+ -- if the hook reference doesnt exist, then its a secure hook, just bail out and dont do any unhooking
+ if not self.hooks[obj] or not self.hooks[obj][method] then return true end
+
+ if scripts[uid] and obj:GetScript(method) == uid then -- unhooks scripts
+ obj:SetScript(method, self.hooks[obj][method] ~= donothing and self.hooks[obj][method] or nil)
+ scripts[uid] = nil
+ elseif obj and self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then -- unhooks methods
+ obj[method] = self.hooks[obj][method]
+ end
+
+ tmp = self.hooks[obj]
+ tmp[method] = nil
+ if not next(tmp) then
+ del(tmp)
+ self.hooks[obj] = nil
+ end
+ else
+ registry[self][method] = nil
+
+ -- if self.hooks[method] doesn't exist, then this is a SecureHook, just bail out
+ if not self.hooks[method] then return true end
+
+ if self.hooks[method] and _G[method] == uid then -- unhooks functions
+ _G[method] = self.hooks[method]
+ end
+
+ self.hooks[method] = nil
+ end
+ return true
+end
+
+--- Unhook all existing hooks for this addon.
+function AceHook:UnhookAll()
+ for key, value in pairs(registry[self]) do
+ if type(key) == "table" then
+ for method in pairs(value) do
+ self:Unhook(key, method)
+ end
+ else
+ self:Unhook(key)
+ end
+ end
+end
+
+--- Check if the specific function, method or script is already hooked.
+-- @paramsig [obj], method
+-- @param obj The object or frame to unhook from
+-- @param method The name of the method, function or script to unhook from.
+function AceHook:IsHooked(obj, method)
+ -- we don't check if registry[self] exists, this is done by evil magicks in the metatable
+ if type(obj) == "string" then
+ if registry[self][obj] and actives[registry[self][obj]] then
+ return true, handlers[registry[self][obj]]
+ end
+ else
+ if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
+ return true, handlers[registry[self][obj][method]]
+ end
+ end
+
+ return false, nil
+end
+
+--- Upgrade our old embeded
+for target, v in pairs( AceHook.embeded ) do
+ AceHook:Embed( target )
+end
diff --git a/ElvUI/Libraries/AceHook-3.0/AceHook-3.0.xml b/ElvUI/Libraries/AceHook-3.0/AceHook-3.0.xml
new file mode 100644
index 0000000..00a2ce8
--- /dev/null
+++ b/ElvUI/Libraries/AceHook-3.0/AceHook-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceLocale-3.0/AceLocale-3.0.lua b/ElvUI/Libraries/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 0000000..896f372
--- /dev/null
+++ b/ElvUI/Libraries/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return nil -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/ElvUI/Libraries/AceLocale-3.0/AceLocale-3.0.xml b/ElvUI/Libraries/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 0000000..b092e58
--- /dev/null
+++ b/ElvUI/Libraries/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceSerializer-3.0/AceSerializer-3.0.lua b/ElvUI/Libraries/AceSerializer-3.0/AceSerializer-3.0.lua
new file mode 100644
index 0000000..75430bb
--- /dev/null
+++ b/ElvUI/Libraries/AceSerializer-3.0/AceSerializer-3.0.lua
@@ -0,0 +1,286 @@
+--- **AceSerializer-3.0** can serialize any variable (except functions or userdata) into a string format,
+-- that can be send over the addon comm channel. AceSerializer was designed to keep all data intact, especially
+-- very large numbers or floating point numbers, and table structures. The only caveat currently is, that multiple
+-- references to the same table will be send individually.
+--
+-- **AceSerializer-3.0** can be embeded into your addon, either explicitly by calling AceSerializer:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceSerializer itself.\\
+-- It is recommended to embed AceSerializer, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceSerializer.
+-- @class file
+-- @name AceSerializer-3.0
+-- @release $Id: AceSerializer-3.0.lua 1135 2015-09-19 20:39:16Z nevcairiel $
+local MAJOR,MINOR = "AceSerializer-3.0", 5
+local AceSerializer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceSerializer then return end
+
+-- Lua APIs
+local strbyte, strchar, gsub, gfind, format = string.byte, string.char, string.gsub, string.gfind, string.format
+local assert, error, pcall = assert, error, pcall
+local type, tostring, tonumber = type, tostring, tonumber
+local pairs, select, frexp = pairs, select, math.frexp
+local tconcat, tgetn = table.concat, table.getn
+
+-- quick copies of string representations of wonky numbers
+local inf = 1/0
+
+local serNaN -- can't do this in 4.3, see ace3 ticket 268
+local serInf, serInfMac = "1.#INF", "inf"
+local serNegInf, serNegInfMac = "-1.#INF", "-inf"
+
+
+-- Serialization functions
+
+local function SerializeStringHelper(ch) -- Used by SerializeValue for strings
+ -- We use \126 ("~") as an escape character for all nonprints plus a few more
+ local n = strbyte(ch)
+ if n==30 then -- v3 / ticket 115: catch a nonprint that ends up being "~^" when encoded... DOH
+ return "\126\122"
+ elseif n<=32 then -- nonprint + space
+ return "\126"..strchar(n+64)
+ elseif n==94 then -- value separator
+ return "\126\125"
+ elseif n==126 then -- our own escape character
+ return "\126\124"
+ elseif n==127 then -- nonprint (DEL)
+ return "\126\123"
+ else
+ assert(false) -- can't be reached if caller uses a sane regex
+ end
+end
+
+local function SerializeValue(v, res, nres)
+ -- We use "^" as a value separator, followed by one byte for type indicator
+ local t=type(v)
+
+ if t=="string" then -- ^S = string (escaped to remove nonprints, "^"s, etc)
+ res[nres+1] = "^S"
+ res[nres+2] = gsub(v,"[%c \94\126\127]", SerializeStringHelper)
+ nres=nres+2
+
+ elseif t=="number" then -- ^N = number (just tostring()ed) or ^F (float components)
+ local str = tostring(v)
+ if tonumber(str)==v --[[not in 4.3 or str==serNaN]] then
+ -- translates just fine, transmit as-is
+ res[nres+1] = "^N"
+ res[nres+2] = str
+ nres=nres+2
+ elseif v == inf or v == -inf then
+ res[nres+1] = "^N"
+ res[nres+2] = v == inf and serInf or serNegInf
+ nres=nres+2
+ else
+ local m,e = frexp(v)
+ res[nres+1] = "^F"
+ res[nres+2] = format("%.0f",m*2^53) -- force mantissa to become integer (it's originally 0.5--0.9999)
+ res[nres+3] = "^f"
+ res[nres+4] = tostring(e-53) -- adjust exponent to counteract mantissa manipulation
+ nres=nres+4
+ end
+
+ elseif t=="table" then -- ^T...^t = table (list of key,value pairs)
+ nres=nres+1
+ res[nres] = "^T"
+ for k,v in pairs(v) do
+ nres = SerializeValue(k, res, nres)
+ nres = SerializeValue(v, res, nres)
+ end
+ nres=nres+1
+ res[nres] = "^t"
+
+ elseif t=="boolean" then -- ^B = true, ^b = false
+ nres=nres+1
+ if v then
+ res[nres] = "^B" -- true
+ else
+ res[nres] = "^b" -- false
+ end
+
+ elseif t=="nil" then -- ^Z = nil (zero, "N" was taken :P)
+ nres=nres+1
+ res[nres] = "^Z"
+
+ else
+ error(MAJOR..": Cannot serialize a value of type '"..t.."'") -- can't produce error on right level, this is wildly recursive
+ end
+
+ return nres
+end
+
+
+
+local serializeTbl = { "^1" } -- "^1" = Hi, I'm data serialized by AceSerializer protocol rev 1
+
+--- Serialize the data passed into the function.
+-- Takes a list of values (strings, numbers, booleans, nils, tables)
+-- and returns it in serialized form (a string).\\
+-- May throw errors on invalid data types.
+-- @param ... List of values to serialize
+-- @return The data in its serialized form (string)
+function AceSerializer:Serialize(...)
+ local nres = 1
+ for i = 1,tgetn(arg) do
+ local v = arg[i]
+ nres = SerializeValue(v, serializeTbl, nres)
+ end
+
+ serializeTbl[nres+1] = "^^" -- "^^" = End of serialized data
+
+ return tconcat(serializeTbl, "", 1, nres+1)
+end
+
+-- Deserialization functions
+local function DeserializeStringHelper(escape)
+ if escape<"~\122" then
+ return strchar(strbyte(escape,2,2)-64)
+ elseif escape=="~\122" then -- v3 / ticket 115: special case encode since 30+64=94 ("^") - OOPS.
+ return "\030"
+ elseif escape=="~\123" then
+ return "\127"
+ elseif escape=="~\124" then
+ return "\126"
+ elseif escape=="~\125" then
+ return "\94"
+ end
+ error("DeserializeStringHelper got called for '"..escape.."'?!?") -- can't be reached unless regex is screwed up
+end
+
+local function DeserializeNumberHelper(number)
+ --[[ not in 4.3 if number == serNaN then
+ return 0/0
+ else]]if number == serNegInf or number == serNegInfMac then
+ return -inf
+ elseif number == serInf or number == serInfMac then
+ return inf
+ else
+ return tonumber(number)
+ end
+end
+
+-- DeserializeValue: worker function for :Deserialize()
+-- It works in two modes:
+-- Main (top-level) mode: Deserialize a list of values and return them all
+-- Recursive (table) mode: Deserialize only a single value (_may_ of course be another table with lots of subvalues in it)
+--
+-- The function _always_ works recursively due to having to build a list of values to return
+--
+-- Callers are expected to pcall(DeserializeValue) to trap errors
+
+local function DeserializeValue(iter,single,ctl,data)
+
+ if not single then
+ ctl,data = iter()
+ end
+
+ if not ctl then
+ error("Supplied data misses AceSerializer terminator ('^^')")
+ end
+
+ if ctl=="^^" then
+ -- ignore extraneous data
+ return
+ end
+
+ local res
+
+ if ctl=="^S" then
+ res = gsub(data, "~.", DeserializeStringHelper)
+ elseif ctl=="^N" then
+ res = DeserializeNumberHelper(data)
+ if not res then
+ error("Invalid serialized number: '"..tostring(data).."'")
+ end
+ elseif ctl=="^F" then -- ^F^f
+ local ctl2,e = iter()
+ if ctl2~="^f" then
+ error("Invalid serialized floating-point number, expected '^f', not '"..tostring(ctl2).."'")
+ end
+ local m=tonumber(data)
+ e=tonumber(e)
+ if not (m and e) then
+ error("Invalid serialized floating-point number, expected mantissa and exponent, got '"..tostring(m).."' and '"..tostring(e).."'")
+ end
+ res = m*(2^e)
+ elseif ctl=="^B" then -- yeah yeah ignore data portion
+ res = true
+ elseif ctl=="^b" then -- yeah yeah ignore data portion
+ res = false
+ elseif ctl=="^Z" then -- yeah yeah ignore data portion
+ res = nil
+ elseif ctl=="^T" then
+ -- ignore ^T's data, future extensibility?
+ res = {}
+ local k,v
+ while true do
+ ctl,data = iter()
+ if ctl=="^t" then break end -- ignore ^t's data
+ k = DeserializeValue(iter,true,ctl,data)
+ if k==nil then
+ error("Invalid AceSerializer table format (no table end marker)")
+ end
+ ctl,data = iter()
+ v = DeserializeValue(iter,true,ctl,data)
+ if v==nil then
+ error("Invalid AceSerializer table format (no table end marker)")
+ end
+ res[k]=v
+ end
+ else
+ error("Invalid AceSerializer control code '"..ctl.."'")
+ end
+
+ if not single then
+ return res,DeserializeValue(iter)
+ else
+ return res
+ end
+end
+
+--- Deserializes the data into its original values.
+-- Accepts serialized data, ignoring all control characters and whitespace.
+-- @param str The serialized data (from :Serialize)
+-- @return true followed by a list of values, OR false followed by an error message
+function AceSerializer:Deserialize(str)
+ str = gsub(str, "[%c ]", "") -- ignore all control characters; nice for embedding in email and stuff
+
+ local iter = gfind(str, "(^.)([^^]*)") -- Any ^x followed by string of non-^
+ local ctl,data = iter()
+ if not ctl or ctl~="^1" then
+ -- we purposefully ignore the data portion of the start code, it can be used as an extension mechanism
+ return false, "Supplied data is not AceSerializer data (rev 1)"
+ end
+
+ return pcall(DeserializeValue, iter)
+end
+
+
+----------------------------------------
+-- Base library stuff
+----------------------------------------
+
+AceSerializer.internals = { -- for test scripts
+ SerializeValue = SerializeValue,
+ SerializeStringHelper = SerializeStringHelper,
+}
+
+local mixins = {
+ "Serialize",
+ "Deserialize",
+}
+
+AceSerializer.embeds = AceSerializer.embeds or {}
+
+function AceSerializer:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+-- Update embeds
+for target, v in pairs(AceSerializer.embeds) do
+ AceSerializer:Embed(target)
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceSerializer-3.0/AceSerializer-3.0.xml b/ElvUI/Libraries/AceSerializer-3.0/AceSerializer-3.0.xml
new file mode 100644
index 0000000..9d1b91f
--- /dev/null
+++ b/ElvUI/Libraries/AceSerializer-3.0/AceSerializer-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceTimer-3.0/AceTimer-3.0.lua b/ElvUI/Libraries/AceTimer-3.0/AceTimer-3.0.lua
new file mode 100644
index 0000000..0bd4b9f
--- /dev/null
+++ b/ElvUI/Libraries/AceTimer-3.0/AceTimer-3.0.lua
@@ -0,0 +1,379 @@
+--- **AceTimer-3.0** provides a central facility for registering timers.
+-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
+-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered
+-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
+-- AceTimer is currently limited to firing timers at a frequency of 0.01s as this is what the WoW timer API
+-- restricts us to.
+--
+-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
+-- need to cancel the timer you just registered.
+--
+-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceTimer itself.\\
+-- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceTimer.
+-- @class file
+-- @name AceTimer-3.0
+-- @release $Id: AceTimer-3.0.lua 1119 2014-10-14 17:23:29Z nevcairiel $
+
+local MAJOR, MINOR = "AceTimer-3.0", 17 -- Bump minor on changes
+local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceTimer then return end -- No upgrade needed
+
+local AceCore = LibStub("AceCore-3.0")
+local safecall = AceCore.safecall
+
+AceTimer.counter = AceTimer.counter or {}
+AceTimer.hash = AceTimer.hash or {} -- Array of [1..BUCKETS] = linked list of timers (using .next member)
+AceTimer.activeTimers = AceTimer.activeTimers or {} -- Active timer list
+AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame")
+
+local counter = AceTimer.counter
+local activeTimers = AceTimer.activeTimers -- Upvalue our private data
+local timerFrame = AceTimer.frame
+
+-- Lua APIs
+local type, unpack, next, error = type, unpack, next, error
+local floor, max, min, mod = math.floor, math.max, math.min, math.mod
+local tostring = tostring
+
+-- WoW APIs
+local GetTime = GetTime
+
+--[[
+ Timers will not be fired more often than HZ-1 times per second.
+ Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999)
+ If this is ever LOWERED, all existing timers need to be enforced to have a delay >= 1/HZ on lib upgrade.
+ If this number is ever changed, all entries need to be rehashed on lib upgrade.
+ ]]
+local HZ = 11
+local minDelay = 1/(HZ-1)
+
+--[[
+ Prime for good distribution
+ If this number is ever changed, all entries need to be rehashed on lib upgrade.
+]]
+local BUCKETS = 131
+
+local hash = AceTimer.hash
+for i=1,BUCKETS do
+ hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes
+end
+
+local new, del
+do
+local list = setmetatable({}, {__mode = "k"})
+function new(self, loop, func, delay, argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ local name = loop and "ScheduleRepeatingTimer" or "ScheduleTimer"
+ if self == AceTimer then
+ error(MAJOR..": " .. name .. "(callback, delay, argc, args...): use your own 'self'", 3)
+ end
+ if not func or not delay then
+ error(MAJOR..": " .. name .. "(callback, delay, argc, args...): 'callback' and 'delay' must have set values.", 3)
+ end
+ if argc and (type(argc) ~= "number" or floor(argc) ~= argc) then
+ error(MAJOR..": " .. name .. "(callback, delay, argc, args...): 'argc' must be an integer.", 3)
+ end
+ if type(func) == "string" then
+ if type(self) ~= "table" then
+ error(MAJOR..": " .. name .. "(callback, delay, argc, args...): 'self' - must be a table.", 3)
+ elseif type(self[func]) ~= "function" then
+ error(MAJOR..": " .. name .. "(callback, delay, argc, args...): Tried to register '"..func.."' as the callback, but it is not a method.", 3)
+ end
+ elseif type(func) ~= "function" then
+ error(MAJOR..": " .. name .. "(callback, delay, argc, args...): Tried to register '"..tostring(func).."' as the callback, but it is not a function.", 3)
+ end
+
+ if delay < minDelay then
+ delay = minDelay
+ end
+
+ -- Create and stuff timer in the correct hash bucket
+ local now = GetTime()
+
+ local timer = next(list) or {}
+ list[timer] = nil
+
+ timer.object = self
+ timer.func = func
+ timer.delay = delay
+ timer.status = loop and "loop" or "once"
+ timer.ends = now + delay
+ timer.argsCount = argc or 0
+ timer[1] = a1
+ timer[2] = a2
+ timer[3] = a3
+ timer[4] = a4
+ timer[5] = a5
+ timer[6] = a6
+ timer[7] = a7
+ timer[8] = a8
+ timer[9] = a9
+ timer[10] = a10
+
+ local bucket = floor(mod((now+delay)*HZ,BUCKETS)) + 1
+ timer.next = hash[bucket]
+ hash[bucket] = timer
+
+ local id = tostring(timer) -- user has only access to the id but not the table itself
+ activeTimers[id] = timer
+
+ counter[self] = (counter[self] or 0) + 1
+
+ timerFrame:Show()
+ return id
+end
+
+function del(t)
+ local id = tostring(t)
+ activeTimers[id] = nil
+ if not next(activeTimers) then
+ timerFrame:Hide()
+ end
+ local self = t.object
+ for k in pairs(t) do t[k] = nil end
+ list[t] = true
+ if counter[self] then
+ counter[self] = counter[self] - 1
+ else
+ counter[self] = nil
+ end
+end
+end -- new, del
+
+--- Schedule a new one-shot timer.
+-- The timer will fire once in `delay` seconds, unless canceled before.
+-- @param callback Callback function for the timer pulse (funcref or method name).
+-- @param delay Delay for the timer, in seconds.
+-- @param argc The numbers of arguments to be passed to the callback function
+-- @param a1,...,a10 The arguments
+-- @usage
+-- MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "AceTimer-3.0")
+--
+-- function MyAddOn:OnEnable()
+-- self:ScheduleTimer("TimerFeedback", 5)
+-- end
+--
+-- function MyAddOn:TimerFeedback()
+-- print("5 seconds passed")
+-- end
+function AceTimer:ScheduleTimer(func, delay, argc, ...)
+ return new(self, nil, func, delay, argc, unpack(arg))
+end
+
+--- Schedule a repeating timer.
+-- The timer will fire every `delay` seconds, until canceled.
+-- @param callback Callback function for the timer pulse (funcref or method name).
+-- @param delay Delay for the timer, in seconds.
+-- @param argc The numbers of arguments to be passed to the callback function
+-- @param a1,...,a10 The arguments
+-- @usage
+-- MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "AceTimer-3.0")
+--
+-- function MyAddOn:OnEnable()
+-- self.timerCount = 0
+-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
+-- end
+--
+-- function MyAddOn:TimerFeedback()
+-- self.timerCount = self.timerCount + 1
+-- print(("%d seconds passed"):format(5 * self.timerCount))
+-- -- run 30 seconds in total
+-- if self.timerCount == 6 then
+-- self:CancelTimer(self.testTimer)
+-- end
+-- end
+function AceTimer:ScheduleRepeatingTimer(func, delay, argc, ...)
+ return new(self, true, func, delay, argc, unpack(arg))
+end
+
+--- Cancels a timer with the given id, registered by the same addon object as used for `:ScheduleTimer`
+-- Both one-shot and repeating timers can be canceled with this function, as long as the `id` is valid
+-- and the timer has not fired yet or was canceled before.
+-- @param id The id of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
+function AceTimer:CancelTimer(id)
+ local timer = activeTimers[id]
+
+ if not timer then
+ return false
+ else
+ -- Ace3v: the timer will always be collected in the next update but not here
+ -- this is necessary for AceBucket to determinate if the bucket has been unregistered
+ -- in the callback
+ timer.status = nil
+ activeTimers[id] = nil
+ return true
+ end
+end
+
+--- Cancels all timers registered to the current addon object ('self')
+function AceTimer:CancelAllTimers()
+ if type(self) ~= "table" then
+ error(MAJOR..": CancelAllTimers(): 'self' - must be a table",2)
+ end
+ if self == AceTimer then
+ error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2)
+ end
+
+ for k,v in pairs(activeTimers) do
+ if v.object == self then
+ AceTimer.CancelTimer(self, k)
+ end
+ end
+end
+
+--- Returns the time left for a timer with the given id, registered by the current addon object ('self').
+-- This function will return 0 when the id is invalid.
+-- @param id The id of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
+-- @return The time left on the timer.
+function AceTimer:TimeLeft(id)
+ local timer = activeTimers[id]
+ if not timer then
+ return 0
+ else
+ return timer.ends - GetTime()
+ end
+end
+
+function AceTimer:TimerStatus(id)
+ local timer = activeTimers[id]
+ if not timer then
+ return nil
+ else
+ return timer.status
+ end
+end
+
+-- ---------------------------------------------------------------------
+-- Embed handling
+
+AceTimer.embeds = AceTimer.embeds or {}
+
+local mixins = {
+ "ScheduleTimer", "ScheduleRepeatingTimer",
+ "CancelTimer", "CancelAllTimers",
+ "TimeLeft"
+}
+
+function AceTimer:Embed(target)
+ AceTimer.embeds[target] = true
+ for _,v in pairs(mixins) do
+ target[v] = AceTimer[v]
+ end
+ return target
+end
+
+-- AceTimer:OnEmbedDisable(target)
+-- target (object) - target object that AceTimer is embedded in.
+--
+-- cancel all timers registered for the object
+function AceTimer:OnEmbedDisable(target)
+ target:CancelAllTimers()
+end
+
+for addon in pairs(AceTimer.embeds) do
+ AceTimer:Embed(addon)
+end
+
+-- --------------------------------------------------------------------
+-- OnUpdate handler
+--
+-- traverse buckets, always chasing "now", and fire timers that have expired
+local lastint = floor(GetTime() * HZ)
+local function OnUpdate()
+ local now = GetTime()
+ local nowint = floor(now * HZ)
+
+ -- Have we passed into a new hash bucket?
+ if nowint == lastint then return end
+
+ local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2
+
+ -- Pass through each bucket at most once
+ -- Happens on e.g. instance loads, but COULD happen on high local load situations also
+ for curint = (max(lastint, nowint-BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteratio
+ local curbucket = mod(curint,BUCKETS) + 1 -- Ace3v: both int so no floor here
+ -- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
+ local nexttimer = hash[curbucket]
+ hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
+
+ while nexttimer do
+ local timer = nexttimer
+ nexttimer = timer.next
+ local status = timer.status
+ if not status then
+ del(timer)
+ else
+ local ends = timer.ends
+ if (status == "loop" or status == "once") and ends < soon then
+ local object = timer.object
+ local callback = timer.func
+ if type(callback) == "string" then
+ callback = (type(object) == "table") and object[callback]
+ if type(callback) == "function" then
+ safecall(callback, timer.argsCount+1, object,
+ timer[1], timer[2], timer[3], timer[4], timer[5],
+ timer[6], timer[7], timer[8], timer[9], timer[10])
+ else
+ status = "once"
+ end
+ elseif type(callback) == "function" then
+ safecall(callback, timer.argsCount,
+ timer[1], timer[2], timer[3], timer[4], timer[5],
+ timer[6], timer[7], timer[8], timer[9], timer[10])
+ else
+ -- probably nilled out by CancelTimer
+ status = "once" -- don't reschedule it
+ end
+
+ if status == "once" then
+ del(timer)
+ else
+ local delay = timer.delay
+ local newends = ends + delay
+ if newends < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
+ newends = now + delay
+ end
+ timer.ends = newends
+ -- add next timer execution to the correct bucket
+ local bucket = floor(mod(newends*HZ,BUCKETS)) + 1
+ timer.next = hash[bucket]
+ hash[bucket] = timer
+ end
+ else
+ -- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
+ timer.next = hash[curbucket]
+ hash[curbucket] = timer
+ end
+ end
+ end
+ end
+
+ lastint = nowint
+end
+
+local lastchecked = nil
+local function OnEvent()
+ if event ~= "PLAYER_REGEN_ENABLED" then return end
+
+ local addon = next(counter, lastchecked)
+ if not addon then
+ addon = next(counter)
+ end
+ lastchecked = addon
+ if not addon then -- should only happen if counter is empty
+ return
+ end
+
+ local n = counter[addon]
+ if n > BUCKETS then
+ DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(addon).."' has "..tostring(n).." live timers. Surely that's not intended?")
+ end
+end
+
+timerFrame:SetScript("OnUpdate", OnUpdate)
+timerFrame:SetScript("OnEvent", OnEvent)
+timerFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
+timerFrame:Hide()
\ No newline at end of file
diff --git a/ElvUI/Libraries/AceTimer-3.0/AceTimer-3.0.xml b/ElvUI/Libraries/AceTimer-3.0/AceTimer-3.0.xml
new file mode 100644
index 0000000..e5d7037
--- /dev/null
+++ b/ElvUI/Libraries/AceTimer-3.0/AceTimer-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.lua b/ElvUI/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.lua
new file mode 100644
index 0000000..40b9510
--- /dev/null
+++ b/ElvUI/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.lua
@@ -0,0 +1,234 @@
+--[[ $Id: CallbackHandler-1.0.lua 18 2014-10-16 02:52:20Z mikk $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 6
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local tconcat = table.concat
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler
+
+local xpcall = xpcall
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+ local code = [[
+ local method, ARGS
+ local function call() method(ARGS) end
+
+ local function dispatch(handlers, ...)
+ local index
+ index, method = next(handlers)
+ if not method then return end
+ local OLD_ARGS = ARGS
+ ARGS = unpack(arg)
+ repeat
+ xpcall(call, function(err) return geterrorhandler()(err) end)
+ index, method = next(handlers, index)
+ until not method
+ ARGS = OLD_ARGS
+ end
+
+ return dispatch
+ ]]
+
+ local ARGS, OLD_ARGS = {}, {}
+ for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
+ code = gsub(gsub(code, "OLD_ARGS", tconcat(OLD_ARGS, ", ")), "ARGS", tconcat(ARGS, ", "))
+ return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+ local dispatcher = CreateDispatcher(argCount)
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+end})
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+-- target - target object to embed public APIs in
+-- RegisterName - name of the callback registration API, default "RegisterCallback"
+-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
+-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName)
+
+ RegisterName = RegisterName or "RegisterCallback"
+ UnregisterName = UnregisterName or "UnregisterCallback"
+ if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
+ UnregisterAllName = "UnregisterAllCallbacks"
+ end
+
+ -- we declare all objects and exported APIs inside this closure to quickly gain access
+ -- to e.g. function names, the "target" parameter, etc
+
+
+ -- Create the registry object
+ local events = setmetatable({}, meta)
+ local registry = { recurse=0, events=events }
+
+ -- registry:Fire() - fires the given event/message into the registry
+ function registry:Fire(eventname, ...)
+ if not rawget(events, eventname) or not next(events[eventname]) then return end
+ local oldrecurse = registry.recurse
+ registry.recurse = oldrecurse + 1
+
+ Dispatchers[getn(arg) + 1](events[eventname], eventname, unpack(arg))
+
+ registry.recurse = oldrecurse
+
+ if registry.insertQueue and oldrecurse==0 then
+ -- Something in one of our callbacks wanted to register more callbacks; they got queued
+ for eventname,callbacks in pairs(registry.insertQueue) do
+ local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
+ for self,func in pairs(callbacks) do
+ events[eventname][self] = func
+ -- fire OnUsed callback?
+ if first and registry.OnUsed then
+ registry.OnUsed(registry, target, eventname)
+ first = nil
+ end
+ end
+ end
+ registry.insertQueue = nil
+ end
+ end
+
+ -- Registration of a callback, handles:
+ -- self["method"], leads to self["method"](self, ...)
+ -- self with function ref, leads to functionref(...)
+ -- "addonId" (instead of self) with function ref, leads to functionref(...)
+ -- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+ target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+ if type(eventname) ~= "string" then
+ error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+ end
+
+ method = method or eventname
+
+ local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
+
+ if type(method) ~= "string" and type(method) ~= "function" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+ end
+
+ local regfunc
+
+ if type(method) == "string" then
+ -- self["method"] calling style
+ if type(self) ~= "table" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+ elseif self==target then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+ elseif type(self[method]) ~= "function" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+ end
+
+ if getn(arg)>=1 then -- this is not the same as testing for arg==nil!
+ regfunc = function(...) self[method](self,arg1,unpack(arg)) end
+ else
+ regfunc = function(...) self[method](self,unpack(arg)) end
+ end
+ else
+ -- function ref with self=object or self="addonId" or self=thread
+ if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+ error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+ end
+
+ if getn(arg)>=1 then -- this is not the same as testing for arg==nil!
+ regfunc = function(...) method(arg1,unpack(arg)) end
+ else
+ regfunc = method
+ end
+ end
+
+
+ if events[eventname][self] or registry.recurse<1 then
+ -- if registry.recurse<1 then
+ -- we're overwriting an existing entry, or not currently recursing. just set it.
+ events[eventname][self] = regfunc
+ -- fire OnUsed callback?
+ if registry.OnUsed and first then
+ registry.OnUsed(registry, target, eventname)
+ end
+ else
+ -- we're currently processing a callback in this registry, so delay the registration of this new entry!
+ -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+ registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+ registry.insertQueue[eventname][self] = regfunc
+ end
+ end
+
+ -- Unregister a callback
+ target[UnregisterName] = function(self, eventname)
+ if not self or self==target then
+ error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+ end
+ if type(eventname) ~= "string" then
+ error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+ end
+ if rawget(events, eventname) and events[eventname][self] then
+ events[eventname][self] = nil
+ -- Fire OnUnused callback?
+ if registry.OnUnused and not next(events[eventname]) then
+ registry.OnUnused(registry, target, eventname)
+ end
+ end
+ if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+ registry.insertQueue[eventname][self] = nil
+ end
+ end
+
+ -- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+ if UnregisterAllName then
+ target[UnregisterAllName] = function(...)
+ if getn(arg)<1 then
+ error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+ end
+ if getn(arg)==1 and arg1==target then
+ error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+ end
+
+
+ for i=1,getn(arg) do
+ local self = arg[i]
+ if registry.insertQueue then
+ for eventname, callbacks in pairs(registry.insertQueue) do
+ if callbacks[self] then
+ callbacks[self] = nil
+ end
+ end
+ end
+ for eventname, callbacks in pairs(events) do
+ if callbacks[self] then
+ callbacks[self] = nil
+ -- Fire OnUnused callback?
+ if registry.OnUnused and not next(callbacks) then
+ registry.OnUnused(registry, target, eventname)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/ElvUI/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.xml b/ElvUI/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.xml
new file mode 100644
index 0000000..8763444
--- /dev/null
+++ b/ElvUI/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibAnim/LibAnim.lua b/ElvUI/Libraries/LibAnim/LibAnim.lua
new file mode 100644
index 0000000..adab9e5
--- /dev/null
+++ b/ElvUI/Libraries/LibAnim/LibAnim.lua
@@ -0,0 +1,819 @@
+-- LibAnim by Hydra
+local Version = 2.01
+
+if (_LibAnim and _LibAnim >= Version) then
+ return
+end
+
+local _G = _G
+local cos = cos
+local sin = sin
+local pairs = pairs
+local floor = floor
+local getn = getn
+local tinsert = tinsert
+local tremove = tremove
+local strlower = strlower
+local Updater = CreateFrame("StatusBar")
+local Texture = Updater:CreateTexture()
+local Text = Updater:CreateFontString()
+local AnimTypes = {}
+local UpdateFuncs = {}
+local Callbacks = {["onplay"] = {}, ["onpause"] = {}, ["onresume"] = {}, ["onstop"] = {}, ["onreset"] = {}, ["onfinished"] = {}}
+
+-- Update all current animations
+local AnimationOnUpdate = function()
+ for i = 1, getn(this) do
+ if this[i] then -- Double check the the index still exists, due to pauses/stops removing them on the fly
+ this[i]:Update(arg1, i)
+ end
+ end
+
+ if (getn(this) == 0) then
+ this:SetScript("OnUpdate", nil)
+ end
+end
+
+local StartUpdating = function(anim)
+ tinsert(Updater, anim)
+
+ if (not Updater:GetScript("OnUpdate")) then
+ Updater:SetScript("OnUpdate", AnimationOnUpdate)
+ end
+end
+
+local GetColor = function(p, r1, g1, b1, r2, g2, b2)
+ return r1 + (r2 - r1) * p, g1 + (g2 - g1) * p, b1 + (b2 - b1) * p
+end
+
+local Set = {
+ ["backdrop"] = Updater.SetBackdropColor,
+ ["border"] = Updater.SetBackdropBorderColor,
+ ["statusbar"] = Updater.SetStatusBarColor,
+ ["text"] = Text.SetTextColor,
+ ["texture"] = Texture.SetTexture,
+ ["vertex"] = Texture.SetVertexColor,
+}
+
+local Get = {
+ ["backdrop"] = Updater.GetBackdropColor,
+ ["border"] = Updater.GetBackdropBorderColor,
+ ["statusbar"] = Updater.GetStatusBarColor,
+ ["text"] = Text.GetTextColor,
+ ["texture"] = Texture.GetVertexColor,
+ ["vertex"] = Texture.GetVertexColor,
+}
+
+local Smoothing = {
+ ["none"] = function(t, b, c, d)
+ return c * t / d + b
+ end,
+
+ ["in"] = function(t, b, c, d)
+ t = t / d
+
+ return c * t * t + b
+ end,
+
+ ["out"] = function(t, b, c, d)
+ t = t / d
+
+ return -c * t * (t - 2) + b
+ end,
+
+ ["inout"] = function(t, b, c, d)
+ t = t / (d / 2)
+
+ if (t < 1) then
+ return c / 2 * t * t + b
+ end
+
+ t = t - 1
+ return -c / 2 * (t * (t - 2) - 1) + b
+ end,
+
+ ["bounce"] = function(t, b, c, d)
+ t = t / d
+
+ if (t < (1 / 2.75)) then
+ return c * (7.5625 * t * t) + b
+ elseif (t < (2 / 2.75)) then
+ t = t - (1.5 / 2.75)
+
+ return c * (7.5625 * t * t + 0.75) + b
+ elseif (t < (2.5 / 2.75)) then
+ t = t - (2.25 / 2.75)
+
+ return c * (7.5625 * t * t + 0.9375) + b
+ else
+ t = t - (2.625 / 2.75)
+
+ return c * (7.5625 * (t) * t + 0.984375) + b
+ end
+ end,
+ ["elastic"] = function(t, b, c, d)
+ local s, p, a = 1.70158, d * .3, c;
+ if t == 0 then
+ return b
+ end
+ t = t / d
+
+ if t == 1 then
+ return b + c
+ end
+
+ if a < math.abs(c) then
+ a = c
+ s = p / 4
+ else
+ s = p / (2 * math.pi) * math.asin(c / a)
+ end
+
+ return a * math.pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b
+ end
+}
+
+local AnimMethods = {
+ All = {
+ Play = function(self)
+ if (not self.Paused) then
+ AnimTypes[self.Type](self)
+ self:Callback("OnPlay")
+ else
+ StartUpdating(self)
+ self:Callback("OnResume")
+ end
+
+ self.Playing = true
+ self.Paused = false
+ self.Stopped = false
+ end,
+
+ IsPlaying = function(self)
+ return self.Playing
+ end,
+
+ Pause = function(self)
+ for i = 1, getn(Updater) do
+ if (Updater[i] == self) then
+ tremove(Updater, i)
+
+ break
+ end
+ end
+
+ self.Playing = false
+ self.Paused = true
+ self.Stopped = false
+ self:Callback("OnPause")
+ end,
+
+ IsPaused = function(self)
+ return self.Paused
+ end,
+
+ Stop = function(self, reset)
+ for i = 1, getn(Updater) do
+ if (Updater[i] == self) then
+ tremove(Updater, i)
+
+ break
+ end
+ end
+
+ self.Playing = false
+ self.Paused = false
+ self.Stopped = true
+
+ if reset then
+ self:Reset()
+ self:Callback("OnReset")
+ else
+ self:Callback("OnStop")
+ end
+ end,
+
+ IsStopped = function(self)
+ return self.Stopped
+ end,
+
+ SetSmoothing = function(self, smoothType)
+ smoothType = strlower(smoothType)
+
+ self.Smoothing = Smoothing[smoothType] and smoothType or "none"
+ end,
+
+ GetSmoothing = function(self)
+ return self.Smoothing
+ end,
+
+ SetDuration = function(self, duration)
+ self.Duration = duration or 0
+ end,
+
+ GetDuration = function(self)
+ return self.Duration
+ end,
+
+ GetProgressByTimer = function(self)
+ return self.Timer
+ end,
+
+ SetOrder = function(self, order)
+ self.Order = order or 1
+
+ if (order > self.Group.MaxOrder) then
+ self.Group.MaxOrder = order
+ end
+ end,
+
+ GetOrder = function(self)
+ return self.Order
+ end,
+
+ GetParent = function(self)
+ return self.Parent
+ end,
+
+ SetScript = function(self, handler, func)
+ handler = strlower(handler)
+
+ if (not Callbacks[handler]) then
+ return
+ end
+
+ Callbacks[handler][self] = func
+ end,
+
+ GetScript = function(self, handler)
+ handler = strlower(handler)
+
+ if (Callbacks[handler] and Callbacks[handler][self]) then
+ return Callbacks[handler][self]
+ end
+ end,
+
+ Callback = function(self, handler)
+ handler = strlower(handler)
+
+ if Callbacks[handler][self] then
+ Callbacks[handler][self](self)
+ end
+ end,
+ },
+
+ move = {
+ SetOffset = function(self, x, y)
+ self.XSetting = x or 0
+ self.YSetting = y or 0
+ end,
+
+ GetOffset = function(self)
+ return self.XSetting, self.YSetting
+ end,
+
+ SetRounded = function(self, flag)
+ self.IsRounded = flag
+ end,
+
+ GetRounded = function(self)
+ return self.IsRounded
+ end,
+
+ GetProgress = function(self)
+ return self.XOffset, self.YOffset
+ end,
+
+ Reset = function(self)
+ self.Parent:ClearAllPoints()
+ self.Parent:SetPoint(self.A1, self.P, self.A2, self.StartX, self.StartY)
+ end,
+ },
+
+ fade = {
+ SetChange = function(self, alpha)
+ self.EndAlphaSetting = alpha or 0
+ end,
+
+ GetChange = function(self)
+ return self.EndAlphaSetting
+ end,
+
+ GetProgress = function(self)
+ return self.AlphaOffset
+ end,
+
+ Reset = function(self)
+ self.Parent:SetAlpha(self.StartAlpha)
+ end,
+ },
+
+ height = {
+ SetChange = function(self, height)
+ self.EndHeightSetting = height or 0
+ end,
+
+ GetChange = function(self)
+ return self.EndHeightSetting
+ end,
+
+ GetProgress = function(self)
+ return self.HeightOffset
+ end,
+
+ Reset = function(self)
+ self.Parent:SetHeight(self.StartHeight)
+ end,
+ },
+
+ width = {
+ SetChange = function(self, width)
+ self.EndWidthSetting = width or 0
+ end,
+
+ GetChange = function(self)
+ return self.EndWidthSetting
+ end,
+
+ GetProgress = function(self)
+ return self.WidthOffset
+ end,
+
+ Reset = function(self)
+ self.Parent:SetWidth(self.StartWidth)
+ end,
+ },
+
+ color = {
+ SetChange = function(self, r, g, b)
+ self.EndRSetting = r or 1
+ self.EndGSetting = g or 1
+ self.EndBSetting = b or 1
+ end,
+
+ GetChange = function(self)
+ return self.EndRSetting, self.EndGSetting, self.EndBSetting
+ end,
+
+ SetColorType = function(self, type)
+ type = strlower(type)
+
+ self.ColorType = Set[type] and type or "border"
+ end,
+
+ GetColorType = function(self)
+ return self.ColorType
+ end,
+
+ GetProgress = function(self)
+ return self.ColorOffset
+ end,
+
+ Reset = function(self)
+ Set[self.ColorType](self.Parent, self.StartR, self.StartG, self.StartB)
+ end,
+ },
+
+ progress = {
+ SetChange = function(self, value)
+ self.EndValueSetting = value or 0
+ end,
+
+ GetChange = function(self)
+ return self.EndValueSetting
+ end,
+
+ GetProgress = function(self)
+ return self.ValueOffset
+ end,
+
+ Reset = function(self)
+ self.Parent:SetValue(self.StartValue)
+ end,
+ },
+
+ number = {
+ SetChange = function(self, value)
+ self.EndNumberSetting = value or 0
+ end,
+
+ GetChange = function(self)
+ return self.EndNumberSetting
+ end,
+
+ SetPrefix = function(self, text)
+ self.Prefix = text or ""
+ end,
+
+ GetPrefix = function(self)
+ return self.Prefix
+ end,
+
+ SetPostfix = function(self, text)
+ self.Postfix = text or ""
+ end,
+
+ GetPostfix = function(self)
+ return self.Postfix
+ end,
+
+ GetProgress = function(self)
+ return self.NumberOffset
+ end,
+
+ Reset = function(self)
+ self.Parent:SetText(self.StartNumer)
+ end,
+ },
+}
+
+local GroupMethods = {
+ Play = function(self)
+ -- Play!
+ for i = 1, getn(self.Animations) do
+ if (self.Animations[i].Order == self.Order) then
+ self.Animations[i]:Play()
+ end
+ end
+
+ self.Playing = true
+ self.Paused = false
+ self.Stopped = false
+ end,
+
+ IsPlaying = function(self)
+ return self.Playing
+ end,
+
+ Pause = function(self)
+ -- Only pause current order
+ for i = 1, getn(self.Animations) do
+ if (self.Animations[i].Order == self.Order) then
+ self.Animations[i]:Pause()
+ end
+ end
+
+ self.Playing = false
+ self.Paused = true
+ self.Stopped = false
+ end,
+
+ IsPaused = function(self)
+ return self.Paused
+ end,
+
+ Stop = function(self)
+ for i = 1, getn(self.Animations) do
+ self.Animations[i]:Stop()
+ end
+
+ self.Playing = false
+ self.Paused = false
+ self.Stopped = true
+ end,
+
+ IsStopped = function(self)
+ return self.Stopped
+ end,
+
+ SetLooping = function(self, shouldLoop)
+ self.Looping = shouldLoop
+ end,
+
+ GetLooping = function(self)
+ return self.Looping
+ end,
+
+ GetParent = function(self)
+ return self.Parent
+ end,
+
+ CheckOrder = function(self)
+ -- Check if we're done all animations at the current order, then proceed to the next order.
+ local NumAtOrder = 0
+ local NumDoneAtOrder = 0
+
+ for i = 1, getn(self.Animations) do
+ if (self.Animations[i].Order == self.Order) then
+ NumAtOrder = NumAtOrder + 1
+
+ if (not self.Animations[i].Playing) then
+ NumDoneAtOrder = NumDoneAtOrder + 1
+ end
+ end
+ end
+
+ -- All the animations at x order finished, go to next order
+ if (NumAtOrder == NumDoneAtOrder) then
+ self.Order = self.Order + 1
+
+ -- We exceeded max order, reset to 1 and bail the function, or restart if we're looping
+ if (self.Order > self.MaxOrder) then
+ self.Order = 1
+
+ if (self.Stopped or not self.Looping) then
+ self.Playing = false
+
+ return
+ end
+ end
+
+ -- Play!
+ for i = 1, getn(self.Animations) do
+ if (self.Animations[i].Order == self.Order) then
+ self.Animations[i]:Play()
+ end
+ end
+ end
+ end,
+
+ CreateAnimation = function(self, type)
+ type = strlower(type)
+
+ if (not AnimTypes[type]) then
+ return
+ end
+
+ local Animation = {}
+
+ -- General methods
+ for key, func in pairs(AnimMethods.All) do
+ Animation[key] = func
+ end
+
+ -- Animation specific methods
+ if AnimMethods[type] then
+ for key, func in pairs(AnimMethods[type]) do
+ Animation[key] = func
+ end
+ end
+
+ -- Set some attributes and defaults
+ Animation.Paused = false
+ Animation.Playing = false
+ Animation.Stopped = false
+ Animation.Looping = false
+ Animation.Type = type
+ Animation.Group = self
+ Animation.Parent = self.Parent
+ Animation.Order = 1
+ Animation.Duration = 0.3
+ Animation.Smoothing = "none"
+ Animation.Update = UpdateFuncs[type]
+
+ tinsert(self.Animations, Animation)
+
+ return Animation
+ end,
+}
+
+CreateAnimationGroup = function(parent)
+ local Group = {Animations = {}}
+
+ -- Add methods to the group
+ for key, func in pairs(GroupMethods) do
+ Group[key] = func
+ end
+
+ Group.Parent = parent
+ Group.Playing = false
+ Group.Paused = false
+ Group.Stopped = false
+ Group.Order = 1
+ Group.MaxOrder = 1
+
+ return Group
+end
+
+-- Movement
+UpdateFuncs["move"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+
+ if self.IsRounded then
+ self.ModTimer = Smoothing[self.Smoothing](self.Timer, 0, self.Duration, self.Duration)
+ self.XOffset = self.StartX - (-1) * (self.XChange * (1 - cos(90 * self.ModTimer / self.Duration)))
+ self.YOffset = self.StartY + self.YChange * sin(90 * self.ModTimer / self.Duration)
+ else
+ self.XOffset = Smoothing[self.Smoothing](self.Timer, self.StartX, self.XChange, self.Duration)
+ self.YOffset = Smoothing[self.Smoothing](self.Timer, self.StartY, self.YChange, self.Duration)
+ end
+
+ self.Parent:SetPoint(self.A1, self.P, self.A2, (self.EndX ~= 0 and self.XOffset or self.StartX), (self.EndY ~= 0 and self.YOffset or self.StartY))
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Parent:SetPoint(self.A1, self.P, self.A2, self.EndX, self.EndY)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["move"] = function(self)
+ if self:IsPlaying() then
+ return
+ end
+
+ local A1, P, A2, X, Y = self.Parent:GetPoint()
+
+ self.Timer = 0
+ self.A1 = A1
+ self.P = P
+ self.A2 = A2
+ self.StartX = X
+ self.EndX = X + self.XSetting or 0
+ self.StartY = Y
+ self.EndY = Y + self.YSetting or 0
+ self.XChange = self.EndX - self.StartX
+ self.YChange = self.EndY - self.StartY
+
+ if self.IsRounded then
+ if (self.XChange == 0 or self.YChange == 0) then -- Double check if we're valid to be rounded
+ self.IsRounded = false
+ else
+ self.ModTimer = 0
+ end
+ end
+
+ StartUpdating(self)
+end
+
+-- Fade
+UpdateFuncs["fade"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+ self.AlphaOffset = Smoothing[self.Smoothing](self.Timer, self.StartAlpha, self.Change, self.Duration)
+ self.Parent:SetAlpha(self.AlphaOffset)
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Parent:SetAlpha(self.EndAlpha)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["fade"] = function(self)
+ if self:IsPlaying() then
+ return
+ end
+
+ self.Timer = 0
+ self.StartAlpha = self.Parent:GetAlpha() or 1
+ self.EndAlpha = self.EndAlphaSetting or 0
+ self.Change = self.EndAlpha - self.StartAlpha
+
+ StartUpdating(self)
+end
+
+-- Height
+UpdateFuncs["height"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+ self.HeightOffset = Smoothing[self.Smoothing](self.Timer, self.StartHeight, self.HeightChange, self.Duration)
+ self.Parent:SetHeight(self.HeightOffset)
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Parent:SetHeight(self.EndHeight)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["height"] = function(self)
+ if self:IsPlaying() then
+ return
+ end
+
+ self.Timer = 0
+ self.StartHeight = self.Parent:GetHeight() or 0
+ self.EndHeight = self.EndHeightSetting or 0
+ self.HeightChange = self.EndHeight - self.StartHeight
+
+ StartUpdating(self)
+end
+
+-- Width
+UpdateFuncs["width"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+ self.WidthOffset = Smoothing[self.Smoothing](self.Timer, self.StartWidth, self.WidthChange, self.Duration)
+ self.Parent:SetWidth(self.WidthOffset)
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Parent:SetWidth(self.EndWidth)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["width"] = function(self)
+ if self:IsPlaying() then
+ return
+ end
+
+ self.Timer = 0
+ self.StartWidth = self.Parent:GetWidth() or 0
+ self.EndWidth = self.EndWidthSetting or 0
+ self.WidthChange = self.EndWidth - self.StartWidth
+
+ StartUpdating(self)
+end
+
+-- Color
+UpdateFuncs["color"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+ self.ColorOffset = Smoothing[self.Smoothing](self.Timer, 0, self.Duration, self.Duration)
+ Set[self.ColorType](self.Parent, GetColor(self.Timer / self.Duration, self.StartR, self.StartG, self.StartB, self.EndR, self.EndG, self.EndB))
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ Set[self.ColorType](self.Parent, self.EndR, self.EndG, self.EndB)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["color"] = function(self)
+ self.Timer = 0
+ self.ColorType = self.ColorType or "backdrop"
+ self.StartR, self.StartG, self.StartB = Get[self.ColorType](self.Parent)
+ self.EndR = self.EndRSetting or 1
+ self.EndG = self.EndGSetting or 1
+ self.EndB = self.EndBSetting or 1
+
+ StartUpdating(self)
+end
+
+-- Progress
+UpdateFuncs["progress"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+ self.ValueOffset = Smoothing[self.Smoothing](self.Timer, self.StartValue, self.ProgressChange, self.Duration)
+ self.Parent:SetValue(self.ValueOffset)
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Parent:SetValue(self.EndValue)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["progress"] = function(self)
+ self.Timer = 0
+ self.StartValue = self.Parent:GetValue() or 0
+ self.EndValue = self.EndValueSetting or 0
+ self.ProgressChange = self.EndValue - self.StartValue
+
+ StartUpdating(self)
+end
+
+-- Sleep
+UpdateFuncs["sleep"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["sleep"] = function(self)
+ self.Timer = 0
+
+ StartUpdating(self)
+end
+
+-- Number
+UpdateFuncs["number"] = function(self, elapsed, i)
+ self.Timer = self.Timer + elapsed
+ self.NumberOffset = Smoothing[self.Smoothing](self.Timer, self.StartNumber, self.NumberChange, self.Duration)
+ self.Parent:SetText(self.Prefix..floor(self.NumberOffset)..self.Postfix)
+
+ if (self.Timer >= self.Duration) then
+ tremove(Updater, i)
+ self.Parent:SetText(self.Prefix..floor(self.EndNumber)..self.Postfix)
+ self.Playing = false
+ self:Callback("OnFinished")
+ self.Group:CheckOrder()
+ end
+end
+
+AnimTypes["number"] = function(self)
+ self.Timer = 0
+ self.StartNumber = tonumber(self.Parent:GetText()) or 0
+ self.EndNumber = self.EndNumberSetting or 0
+ self.NumberChange = self.EndNumberSetting - self.StartNumber
+ self.Prefix = self.Prefix or ""
+ self.Postfix = self.Postfix or ""
+
+ StartUpdating(self)
+end
+
+_G["_LibAnim"] = Version
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibAnim/LibAnim.xml b/ElvUI/Libraries/LibAnim/LibAnim.xml
new file mode 100644
index 0000000..72dc77e
--- /dev/null
+++ b/ElvUI/Libraries/LibAnim/LibAnim.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua b/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua
new file mode 100644
index 0000000..5d27683
--- /dev/null
+++ b/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua
@@ -0,0 +1,227 @@
+--[[
+Name: LibBase64-1.0
+Author(s): ckknight (ckknight@gmail.com)
+Website: http://www.wowace.com/projects/libbase64-1-0/
+Description: A library to encode and decode Base64 strings
+License: MIT
+]]
+
+local modf = math.modf
+local sub = string.sub
+local format = string.format
+local getn = table.getn
+local strlen = string.len
+local byte = string.byte
+
+local LibBase64 = LibStub:NewLibrary("LibBase64-1.0", 1)
+
+if not LibBase64 then
+ return
+end
+
+local _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+local charTable = {}
+local byteToNum = {}
+local numToChar = {}
+
+for i = 1, strlen(_chars) do
+ charTable[i] = sub(_chars, i, i)
+end
+
+for i = 1, getn(charTable) do
+ numToChar[i - 1] = sub(_chars, i, i)
+ byteToNum[byte(_chars, i)] = i - 1
+end
+
+_chars = nil
+
+local A_byte = byte("A")
+local Z_byte = byte("Z")
+local a_byte = byte("a")
+local z_byte = byte("z")
+local zero_byte = byte("0")
+local nine_byte = byte("9")
+local plus_byte = byte("+")
+local slash_byte = byte("/")
+local equals_byte = byte("=")
+local whitespace = {
+ [byte(" ")] = true,
+ [byte("\t")] = true,
+ [byte("\n")] = true,
+ [byte("\r")] = true,
+}
+
+local t = {}
+
+--- Encode a normal bytestring into a Base64-encoded string
+-- @param text a bytestring, can be binary data
+-- @param maxLineLength This should be a multiple of 4, greater than 0 or nil. If non-nil, it will break up the output into lines no longer than the given number of characters. 76 is recommended.
+-- @param lineEnding a string to end each line with. This is "\r\n" by default.
+-- @usage LibBase64.Encode("Hello, how are you doing today?") == "SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw=="
+-- @return a Base64-encoded string
+function LibBase64:Encode(text, maxLineLength, lineEnding)
+ if type(text) ~= "string" then
+ error(format("Bad argument #1 to `Encode'. Expected %q, got %q", "string", type(text)), 2)
+ end
+
+ if maxLineLength == nil then
+ -- do nothing
+ elseif type(maxLineLength) ~= "number" then
+ error(format("Bad argument #2 to `Encode'. Expected %q or %q, got %q", "number", "nil", type(maxLineLength)), 2)
+ elseif modf(maxLineLength, 4) ~= 0 then
+ error(format("Bad argument #2 to `Encode'. Expected a multiple of 4, got %s", maxLineLength), 2)
+ elseif maxLineLength <= 0 then
+ error(format("Bad argument #2 to `Encode'. Expected a number > 0, got %s", maxLineLength), 2)
+ end
+
+ if lineEnding == nil then
+ lineEnding = "\r\n"
+ elseif type(lineEnding) ~= "string" then
+ error(format("Bad argument #3 to `Encode'. Expected %q, got %q", "string", type(lineEnding)), 2)
+ end
+
+ local currentLength = 0
+
+ for i = 1, getn(text), 3 do
+ local a, b, c = byte(text, i, i+2)
+ local nilNum = 0
+ if not b then
+ nilNum = 2
+ b = 0
+ c = 0
+ elseif not c then
+ nilNum = 1
+ c = 0
+ end
+ local num = a * 2^16 + b * 2^8 + c
+
+ local d = modf(num, 2^6)
+ num = (num - d) / 2^6
+
+ local c = modf(num, 2^6)
+ num = (num - c) / 2^6
+
+ local b = modf(num, 2^6)
+ num = (num - b) / 2^6
+
+ local a = modf(num, 2^6)
+
+ t[getn(t)+1] = numToChar[a]
+
+ t[getn(t)+1] = numToChar[b]
+
+ t[getn(t)+1] = (nilNum >= 2) and "=" or numToChar[c]
+
+ t[getn(t)+1] = (nilNum >= 1) and "=" or numToChar[d]
+
+ currentLength = currentLength + 4
+ if maxLineLength and modf(currentLength, maxLineLength) == 0 then
+ t[getn(t)+1] = lineEnding
+ end
+ end
+
+ local s = table.concat(t)
+ for i = 1, getn(t) do
+ t[i] = nil
+ end
+ return s
+end
+
+local t2 = {}
+
+--- Decode a Base64-encoded string into a bytestring
+-- this will raise an error if the data passed in is not a Base64-encoded string
+-- this will ignore whitespace, but not invalid characters
+-- @param text a Base64-encoded string
+-- @usage LibBase64.Encode("SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw==") == "Hello, how are you doing today?"
+-- @return a bytestring
+function LibBase64:Decode(text)
+ if type(text) ~= "string" then
+ error(format("Bad argument #1 to `Decode'. Expected %q, got %q", "string", type(text)), 2)
+ end
+
+ for i = 1, getn(text) do
+ local byte = byte(text, i)
+ if whitespace[byte] or byte == equals_byte then
+ -- do nothing
+ else
+ local num = byteToNum[byte]
+ if not num then
+ for i = 1, getn(t2) do
+ t2[k] = nil
+ end
+
+ error(format("Bad argument #1 to `Decode'. Received an invalid char: %q", sub(text, i, i)), 2)
+ end
+ t2[getn(t2)+1] = num
+ end
+ end
+
+ for i = 1, getn(t2), 4 do
+ local a, b, c, d = t2[i], t2[i+1], t2[i+2], t2[i+3]
+
+ local nilNum = 0
+ if not c then
+ nilNum = 2
+ c = 0
+ d = 0
+ elseif not d then
+ nilNum = 1
+ d = 0
+ end
+
+ local num = a * 2^18 + b * 2^12 + c * 2^6 + d
+
+ local c = modf(num, 2^8)
+ num = (num - c) / 2^8
+
+ local b = modf(num, 2^8)
+ num = (num - b) / 2^8
+
+ local a = modf(num, 2^8)
+
+ t[getn(t)+1] = string.char(a)
+ if nilNum < 2 then
+ t[getn(t)+1] = string.char(b)
+ end
+ if nilNum < 1 then
+ t[getn(t)+1] = string.char(c)
+ end
+ end
+
+ for i = 1, getn(t2) do
+ t2[i] = nil
+ end
+
+ local s = table.concat(t)
+
+ for i = 1, getn(t) do
+ t[i] = nil
+ end
+
+ return s
+end
+
+function LibBase64:IsBase64(text)
+ if type(text) ~= "string" then
+ error(format("Bad argument #1 to `IsBase64'. Expected %q, got %q", "string", type(text)), 2)
+ end
+
+ if modf(strlen(text), 4) ~= 0 then
+ return false
+ end
+
+ for i = 1, getn(text) do
+ local byte = byte(text, i)
+ if whitespace[byte] or byte == equals_byte then
+ -- do nothing
+ else
+ local num = byteToNum[byte]
+ if not num then
+ return false
+ end
+ end
+ end
+
+ return true
+end
diff --git a/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.xml b/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.xml
new file mode 100644
index 0000000..358521f
--- /dev/null
+++ b/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibCompress/LibCompress.lua b/ElvUI/Libraries/LibCompress/LibCompress.lua
new file mode 100644
index 0000000..5f14835
--- /dev/null
+++ b/ElvUI/Libraries/LibCompress/LibCompress.lua
@@ -0,0 +1,807 @@
+----------------------------------------------------------------------------------
+--
+-- LibCompress.lua
+--
+-- Authors: jjsheets and Galmok of European Stormrage (Horde)
+-- Email : sheets.jeff@gmail.com and galmok@gmail.com
+-- Licence: GPL version 2 (General Public License)
+----------------------------------------------------------------------------------
+
+
+local MAJOR, MINOR = "LibCompress", 3
+
+local LibCompress,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not LibCompress then return end
+
+-- list of codecs in this file:
+-- \000 - Never used
+-- \001 - Uncompressed
+-- \002 - LZW
+-- \003 - Huffman
+
+
+-- local is faster than global
+local table_insert = table.insert
+local table_remove = table.remove
+local table_concat = table.concat
+local string_char = string.char
+local string_byte = string.byte
+local string_len = string.len
+local string_sub = string.sub
+local unpack = unpack
+local pairs = pairs
+local math_modf = math.modf
+local bit_band = bit.band
+local bit_bor = bit.bor
+local bit_lshift = bit.lshift
+local bit_rshift = bit.rshift
+local tostring = tostring
+local next = next
+local strlen = strlen
+local strsplit = string.split
+local strfind = string.find
+local strgfind = string.gfind
+local tonumber = tonumber
+
+--------------------------------------------------------------------------------
+-- Cleanup
+
+local tables = {} -- tables that may be cleaned have to be kept here
+local tables_to_clean = {} -- list of tables by name (string) that may be reset to {} after a timeout
+local timeout = -1
+
+-- tables that may be erased
+local function cleanup()
+ for k,v in pairs(tables_to_clean) do
+ tables[k]={}
+ tables_to_clean[k]=nil
+ end
+end
+
+local function onUpdate(frame, elapsed)
+ timeout = timeout - arg1
+ if timeout < 0 then
+ this:Hide()
+ cleanup()
+ end
+end
+
+LibCompress.frame = LibCompress.frame or CreateFrame("frame", nil, UIParent) -- reuse the old frame
+LibCompress.frame:SetScript("OnUpdate", onUpdate)
+LibCompress.frame:Hide()
+
+local function setCleanupTables(s1, s2)
+ timeout = 15 -- empty tables after 15 seconds
+ if not LibCompress.frame:IsShown() then
+ LibCompress.frame:Show()
+ end
+
+ if tables_to_clean[s1] then
+ tables_to_clean[s1] = true
+ end
+ if tables_to_clean[s2] then
+ tables_to_clean[s2] = true
+ end
+end
+
+
+--------------------------------------------------------------------------------
+-- LZW codec
+-- implemented by sheets.jeff@gmail.com
+
+-- encode is used to uniquely encode a number into a sequence of bytes that can be decoded using decode()
+-- the bytes returned by this do not contain "\000"
+local bytes = {}
+local function encode(x)
+ local math_modf = math.modf
+ for k = 1, getn(bytes) do bytes[k] = nil end
+ local xmod
+ x, xmod = math_modf(x/255.0)
+ xmod = xmod * 255
+ bytes[getn(bytes) + 1] = xmod
+ while x > 0 do
+ x, xmod = math_modf(x/255.0)
+ xmod = xmod * 255.0
+ bytes[getn(bytes) + 1] = xmod
+ end
+ if getn(bytes) == 1 and bytes[1] > 0 and bytes[1] < 250 then
+ return string_char(bytes[1])
+ else
+ for i = 1, getn(bytes) do bytes[i] = bytes[i] + 1 end
+ return string_char(256 - getn(bytes), unpack(bytes))
+ end
+end
+
+--decode converts a unique character sequence into its equivalent number, from ss, beginning at the ith char.
+-- returns the decoded number and the count of characters used in the decode process.
+local function decode(ss,i)
+ i = i or 1
+ local a = string_byte(ss,i,i)
+ if a > 249 then
+ local r = 0
+ a = 256 - a
+ for n = i+a, i+1, -1 do
+ r = r * 255 + string_byte(ss,n,n) - 1
+ end
+ return r, a + 1
+ else
+ return a, 1
+ end
+end
+
+--
+-- Added by Shino
+--
+function LibCompress:TableToString(t)
+ if t == nil then return nil end
+ if type(t)=="string" then return t end
+ local cache={}
+ local function sub_mod(t)
+ if (type(t)=="table") then
+ for pos,val in pairs(t) do
+ if (type(val)=="table") then
+ table_insert(cache, pos..">".."{")
+ sub_mod(val)
+ table_insert(cache, "}")
+ elseif (type(val)=="string") then
+ table_insert(cache, pos..'>"'..val..'"')
+ else
+ table_insert(cache, pos..">"..tostring(val))
+ end
+ end
+ else
+ table_insert(cache, tostring(t))
+ end
+ end
+ sub_mod(t)
+ return table_concat(cache, ",") -- ? maybe use a different delimiter
+end
+
+-- Adding a costum string.split function cause this one has a problem with too big tables
+-- Credits: https://gist.github.com/jaredallard/ddb152179831dd23b230
+function LibCompress:StringSplit(delimiter, str)
+ local result = { }
+ local from = 1
+ local delim_from, delim_to = strfind( str, delimiter, from )
+ while delim_from do
+ table_insert( result, strsub( str, from , delim_from-1 ) )
+ from = delim_to + 1
+ delim_from, delim_to = strfind( str, delimiter, from )
+ end
+ table.insert( result, strsub( str, from ) )
+ return result
+end
+
+function LibCompress:StringToTable(t)
+ if t=="" or t==nil then return nil end
+ if type(t)=="table" then return t end
+ local table = self:StringSplit(",",t)
+ local function fillSubTable(start)
+ local subT = {}
+ local cont = true
+ local po = nil
+ for k, v in pairs(table) do
+ if k>start then
+ cont = true
+ po = nil
+ for pos in strgfind(v, "(.+)>{") do -- opening sub table
+ po = tonumber(pos)
+ if po then
+ subT[po], start = fillSubTable(k)
+ else
+ subT[pos], start = fillSubTable(k)
+ end
+ end
+ if k>start then -- cause it could have changed if a new table was opened
+ for pos, val in strgfind(v, '(.+)%>"(.+)"') do
+ po = tonumber(pos)
+ if po then
+ subT[po] = ""..val
+ else
+ subT[pos] = ""..val
+ end
+ cont = false
+ end
+ if cont then
+ for pos, val in strgfind(v, "(.+)%>(.+)") do -- Do floats work too?
+ po = tonumber(pos)
+ if val == "false" then
+ if po then
+ subT[po] = false
+ else
+ subT[pos] = false
+ end
+ elseif val == "true" then
+ if po then
+ subT[po] = true
+ else
+ subT[pos] = true
+ end
+ else
+ if po then
+ subT[po] = tonumber(val)
+ else
+ subT[pos] = tonumber(val)
+ end
+ end
+ end
+ if v=="}" then -- closing sub table
+ return subT,k -- Returning the end
+ end
+ end
+ end
+ end
+ end
+ return subT, 0
+ end
+ return fillSubTable(0)
+end
+
+-- Shino end --
+
+-- Compresses the given uncompressed string.
+-- Unless the uncompressed string starts with "\002", this is guaranteed to return a string equal to or smaller than
+-- the passed string.
+-- the returned string will only contain "\000" characters in rare circumstances, and will contain none if the
+-- source string has none.
+local dict = {}
+function LibCompress:CompressLZW(uncompressed)
+ if type(uncompressed) == "string" then
+ local dict_size = 256
+ for k, _ in pairs(dict) do
+ dict[k] = nil
+ end
+ local result = {"\002"}
+ local w = ''
+ local ressize = 1
+ for i = 0, 255 do
+ dict[string_char(i)] = i
+ end
+ for i = 1, strlen(uncompressed) do
+ local c = string_sub(uncompressed, i,i)
+ local wc = w..c
+ if dict[wc] then
+ w = wc
+ else
+ dict[wc] = dict_size
+ dict_size = dict_size +1
+ local r = encode(dict[w])
+ ressize = ressize + strlen(r)
+ result[getn(result) + 1] = r
+ w = c
+ end
+ end
+ if w then
+ local r = encode(dict[w])
+ ressize = ressize + strlen(r)
+ result[getn(result) + 1] = r
+ end
+ if (strlen(uncompressed)+1) > ressize then
+ return table_concat(result, "")
+ else
+ return "\002"..uncompressed
+ end
+ else
+ return nil, "Can only compress strings"
+ end
+end
+
+-- if the passed string is a compressed string, this will decompress it and return the decompressed string.
+-- Otherwise it return an error message
+-- compressed strings are marked by beginning with "\002"
+function LibCompress:DecompressLZW(compressed)
+ if type(compressed) == "string" then
+ if string_sub(compressed,1,1) ~= "\002" then
+ return nil, "Can only decompress LZW compressed data ("..tostring(string_sub(compressed,1,1))..")"
+ end
+ compressed = string_sub(compressed,2)-- ?
+ local dict_size = 256
+ for k, _ in pairs(dict) do
+ dict[k] = nil
+ end
+ for i = 0, 255 do
+ dict[i] = string_char(i)
+ end
+ local result = {}
+ local t = 1
+ local delta, k
+ k, delta = decode(compressed,t)
+ t = t + delta
+ result[getn(result)+1] = dict[k]
+ local w = dict[k]
+ local entry
+ while t <= strlen(compressed) do
+ k, delta = decode(compressed,t)
+ t = t + delta
+ entry = dict[k] or (w..string_sub(w,1,1))
+ result[getn(result)+1] = entry
+ dict[dict_size] = w..string_sub(entry,1,1)
+ dict_size = dict_size + 1
+ w = entry
+ end
+ return table_concat(result)
+ else
+ return nil, "Can only uncompress strings"
+ end
+end
+
+
+--------------------------------------------------------------------------------
+-- Huffman codec
+-- implemented by Galmok of European Stormrage (Horde), galmok@gmail.com
+
+local function addCode(tree, bcode,len)
+ if tree then
+ tree.bcode = bcode;
+ tree.blength = len;
+ if tree.c1 then
+ addCode(tree.c1, bit_bor(bcode, bit_lshift(1,len)), len+1)
+ end
+ if tree.c2 then
+ addCode(tree.c2, bcode, len+1)
+ end
+ end
+end
+
+local function escape_code(code, len)
+ local escaped_code = 0;
+ local b;
+ local l = 0;
+ for i = len-1, 0,- 1 do
+ b = bit_band( code, bit_lshift(1,i))==0 and 0 or 1
+ escaped_code = bit_lshift(escaped_code,1+b) + b
+ l = l + b;
+ end
+ return escaped_code, len+l
+end
+
+tables.Huffman_compressed = {}
+tables.Huffman_large_compressed = {}
+
+local compressed_size = 0
+local remainder;
+local remainder_length;
+local function addBits(tbl, code, len)
+ remainder = remainder + bit_lshift(code, remainder_length)
+ remainder_length = len + remainder_length
+ if remainder_length > 32 then
+ return true -- Bits lost due to too long code-words.
+ end
+ while remainder_length>=8 do
+ compressed_size = compressed_size + 1
+ tbl[compressed_size] = string_char(bit_band(remainder, 255))
+ remainder = bit_rshift(remainder, 8)
+ remainder_length = remainder_length -8
+ end
+end
+
+-- word size for this huffman algorithm is 8 bits (1 byte). This means the best compression is representing 1 byte with 1 bit, i.e. compress to 0.125 of original size.
+function LibCompress:CompressHuffman(uncompressed)
+ if not type(uncompressed)=="string" then
+ return nil, "Can only compress strings"
+ end
+
+ -- make histogram
+ local hist = {}
+ local n = 0
+ -- dont have to use all datat to make the histogram
+ local uncompressed_size = string_len(uncompressed)
+ local c;
+ for i = 1, uncompressed_size do
+ c = string_byte(uncompressed, i)
+ hist[c] = (hist[c] or 0) + 1
+ end
+
+ --Start with as many leaves as there are symbols.
+ local leafs = {}
+ local leaf;
+ local symbols = {}
+ for symbol, weight in pairs(hist) do
+ leaf = { symbol=string_char(symbol), weight=weight };
+ symbols[symbol] = leaf;
+ table_insert(leafs, leaf)
+ end
+ --Enqueue all leaf nodes into the first queue (by probability in increasing order so that the least likely item is in the head of the queue).
+ sort(leafs, function(a,b) if a.weightb.weight then return false else return nil end end)
+
+ local nLeafs = getn(leafs)
+
+ -- create tree
+ local huff = {}
+ --While there is more than one node in the queues:
+ local l,h, li, hi, leaf1, leaf2
+ local newNode;
+ while (getn(leafs)+getn(huff) > 1) do
+ -- Dequeue the two nodes with the lowest weight.
+ -- Dequeue first
+ if not next(huff) then
+ li, leaf1 = next(leafs)
+ table_remove(leafs, li)
+ elseif not next(leafs) then
+ hi, leaf1 = next(huff)
+ table_remove(huff, hi)
+ else
+ li, l = next(leafs);
+ hi, h = next(huff);
+ if l.weight<=h.weight then
+ leaf1 = l;
+ table_remove(leafs, li)
+ else
+ leaf1 = h;
+ table_remove(huff, hi)
+ end
+ end
+ -- Dequeue second
+ if not next(huff) then
+ li, leaf2 = next(leafs)
+ table_remove(leafs, li)
+ elseif not next(leafs) then
+ hi, leaf2 = next(huff)
+ table_remove(huff, hi)
+ else
+ li, l = next(leafs);
+ hi, h = next(huff);
+ if l.weight<=h.weight then
+ leaf2 = l;
+ table_remove(leafs, li)
+ else
+ leaf2 = h;
+ table_remove(huff, hi)
+ end
+ end
+
+ --Create a new internal node, with the two just-removed nodes as children (either node can be either child) and the sum of their weights as the new weight.
+ newNode = { c1 = leaf1, c2 = leaf2, weight = leaf1.weight+leaf2.weight }
+ table_insert(huff,newNode)
+ end
+ if getn(leafs)>0 then
+ li, l = next(leafs)
+ table_insert(huff, l)
+ table_remove(leafs, li)
+ end
+ huff = huff[1];
+
+ -- assign codes to each symbol
+ -- c1 = "0", c2 = "1"
+ -- As a common convention, bit '0' represents following the left child and bit '1' represents following the right child.
+ -- c1 = left, c2 = right
+
+ addCode(huff,0,0);
+ if huff then
+ huff.bcode = 0
+ huff.blength = 1
+ end
+
+ -- READING
+ -- bitfield = 0
+ -- bitfield_len = 0
+ -- read byte1
+ -- bitfield = bitfield + bit_lshift(byte1, bitfield_len)
+ -- bitfield_len = bitfield_len + 8
+ -- read byte2
+ -- bitfield = bitfield + bit_lshift(byte2, bitfield_len)
+ -- bitfield_len = bitfield_len + 8
+ -- (use 5 bits)
+ -- word = bit_band( bitfield, bit_lshift(1,5)-1)
+ -- bitfield = bit_rshift( bitfield, 5)
+ -- bitfield_len = bitfield_len - 5
+ -- read byte3
+ -- bitfield = bitfield + bit_lshift(byte3, bitfield_len)
+ -- bitfield_len = bitfield_len + 8
+
+ -- WRITING
+ remainder = 0;
+ remainder_length = 0;
+
+ local compressed = tables.Huffman_compressed
+ --compressed_size = 0
+
+ -- first byte is version info. 0 = uncompressed, 1 = 8-bit word huffman compressed
+ compressed[1] = "\003"
+
+ -- Header: byte 0=#leafs, byte 1-3=size of uncompressed data
+ -- max 2^24 bytes
+ local l = string_len(uncompressed)
+ compressed[2] = string_char(bit_band(nLeafs-1, 255)) -- number of leafs
+ compressed[3] = string_char(bit_band(l, 255)) -- bit 0-7
+ compressed[4] = string_char(bit_band(bit_rshift(l, 8), 255)) -- bit 8-15
+ compressed[5] = string_char(bit_band(bit_rshift(l, 16), 255)) -- bit 16-23
+ compressed_size = 5
+
+ -- create symbol/code map
+ for symbol, leaf in pairs(symbols) do
+ addBits(compressed, symbol, 8);
+ if addBits(compressed, escape_code(leaf.bcode, leaf.blength)) then
+ -- code word too long. Needs new revision to be able to handle more than 32 bits
+ return string_char(0)..uncompressed
+ end
+ addBits(compressed, 3, 2);
+ end
+
+ -- create huffman code
+ local large_compressed = tables.Huffman_large_compressed
+ local large_compressed_size = 0
+ local ulimit
+ for i = 1, l, 200 do
+ ulimit = l<(i+199) and l or (i+199)
+ for sub_i = i, ulimit do
+ c = string_byte(uncompressed, sub_i)
+ addBits(compressed, symbols[c].bcode, symbols[c].blength)
+ end
+ large_compressed_size = large_compressed_size + 1
+ large_compressed[large_compressed_size] = table_concat(compressed, "", 1, compressed_size)
+ compressed_size = 0
+ end
+
+ -- add remainding bits (if any)
+ if remainder_length>0 then
+ large_compressed_size = large_compressed_size + 1
+ large_compressed[large_compressed_size] = string_char(remainder)
+ end
+ local compressed_string = table_concat(large_compressed, "", 1, large_compressed_size)
+
+ -- is compression worth it? If not, return uncompressed data.
+ if (strlen(uncompressed)+1) <= strlen(compressed_string) then
+ return "\001"..uncompressed
+ end
+
+ setCleanupTables("Huffman_compressed", "Huffman_large_compressed")
+ return compressed_string
+end
+
+-- lookuptable (cached between calls)
+local lshiftMask = {}
+setmetatable(lshiftMask, {
+ __index = function (t, k)
+ local v = bit_lshift(1, k)
+ rawset(t, k, v)
+ return v
+ end
+})
+
+-- lookuptable (cached between calls)
+local lshiftMinusOneMask = {}
+setmetatable(lshiftMinusOneMask, {
+ __index = function (t, k)
+ local v = bit_lshift(1, k)-1
+ rawset(t, k, v)
+ return v
+ end
+})
+
+local function getCode(bitfield, field_len)
+ if field_len>=2 then
+ local b;
+ local p = 0;
+ for i = 0, field_len-1 do
+ b = bit_band(bitfield, lshiftMask[i])
+ if not (p==0) and not (b == 0) then
+ -- found 2 bits set right after each other (stop bits)
+ return bit_band( bitfield, lshiftMinusOneMask[i-1]), i-1,
+ bit_rshift(bitfield, i+1), field_len-i-1
+ end
+ p = b
+ end
+ end
+ return nil
+end
+
+local function unescape_code(code, code_len)
+ local unescaped_code=0;
+ local b;
+ local l = 0;
+ local i = 0
+ while i < code_len do
+ b = bit_band( code, lshiftMask[i])
+ if not (b==0) then
+ unescaped_code = bit_bor(unescaped_code, lshiftMask[l])
+ i = i + 1
+ end
+ i = i + 1
+ l = l + 1
+ end
+ return unescaped_code, l
+end
+
+tables.Huffman_uncompressed = {}
+tables.Huffman_large_uncompressed = {} -- will always be as big as the larges string ever decompressed. Bad, but clearing i every timetakes precious time.
+
+function LibCompress:DecompressHuffman(compressed)
+ if type(compressed)~="string" or compressed == nil then
+ if type(compressed)=="table" then
+ return compressed
+ end
+ return nil
+ end
+
+ local compressed_size = strlen(compressed)
+ --decode header
+ local info_byte = string_byte(compressed)
+ -- is data compressed
+ if info_byte==1 then
+ return string_sub(compressed,2) --return uncompressed data
+ end
+ if not (info_byte==3) then
+ return nil, "Can only decompress Huffman compressed data ("..tostring(info_byte)..")"
+ end
+
+ local num_symbols = string_byte(string_sub(compressed, 2, 2)) + 1
+ local c0 = string_byte(string_sub(compressed, 3, 3))
+ local c1 = string_byte(string_sub(compressed, 4, 4))
+ local c2 = string_byte(string_sub(compressed, 5, 5))
+ local orig_size = c2*65536 + c1*256 + c0
+ if orig_size==0 then
+ return "";
+ end
+
+ -- decode code->symbal map
+ local bitfield = 0;
+ local bitfield_len = 0;
+ local map = {} -- only table not reused in Huffman decode.
+ setmetatable(map, {
+ __index = function (t, k)
+ local v = {}
+ rawset(t, k, v)
+ return v
+ end
+ })
+
+ local i = 6; -- byte 1-5 are header bytes
+ local c, cl;
+ local minCodeLen = 1000;
+ local maxCodeLen = 0;
+ local symbol, code, code_len, _bitfield, _bitfield_len;
+ local n = 0;
+ local state = 0; -- 0 = get symbol (8 bits), 1 = get code (varying bits, ends with 2 bits set)
+ while ncompressed_size then
+ return nil, "Cannot decode map"
+ end
+
+ c = string_byte(compressed, i)
+ bitfield = bit_bor(bitfield, bit_lshift(c, bitfield_len))
+ bitfield_len = bitfield_len + 8
+
+ if state == 0 then
+ symbol = bit_band(bitfield, 255)
+ bitfield = bit_rshift(bitfield, 8)
+ bitfield_len = bitfield_len -8
+ state = 1 -- search for code now
+ else
+ code, code_len, _bitfield, _bitfield_len = getCode(bitfield, bitfield_len)
+ if code then
+ bitfield, bitfield_len = _bitfield, _bitfield_len
+ c, cl = unescape_code(code, code_len)
+ map[cl][c]=string_char(symbol)
+ minCodeLen = clmaxCodeLen and cl or maxCodeLen
+ --print("symbol: "..string_char(symbol).." code: "..tobinary(c, cl))
+ n = n + 1
+ state = 0 -- search for next symbol (if any)
+ end
+ end
+ i=i+1
+ end
+
+ -- dont create new subtables for entries not in the map. Waste of space.
+ -- But do return an empty table to prevent runtime errors. (instead of returning nil)
+ local mt = {}
+ setmetatable(map, {
+ __index = function (t, k)
+ return mt
+ end
+ })
+
+ local uncompressed = tables.Huffman_uncompressed
+ local large_uncompressed = tables.Huffman_large_uncompressed
+ local uncompressed_size = 0
+ local large_uncompressed_size = 0
+ local test_code
+ local test_code_len = minCodeLen;
+ local symbol;
+ local dec_size = 0;
+ compressed_size = compressed_size + 1
+ local temp_limit = 200; -- first limit of uncompressed data. large_uncompressed will hold strings of length 200
+ while true do
+ if test_code_len<=bitfield_len then
+ test_code=bit_band( bitfield, lshiftMinusOneMask[test_code_len])
+ symbol = map[test_code_len][test_code]
+ if symbol then
+ uncompressed_size = uncompressed_size + 1
+ uncompressed[uncompressed_size]=symbol
+ dec_size = dec_size + 1
+
+ if dec_size>=orig_size then -- checked here for speed reasons
+ break;
+ end
+ -- process compressed bytes in smaller chunks
+ large_uncompressed_size = large_uncompressed_size + 1
+ large_uncompressed[large_uncompressed_size] = table_concat(uncompressed, "", 1, uncompressed_size)
+ uncompressed_size = 0
+ temp_limit = temp_limit + 200 -- repeated chunk size is 200 uncompressed bytes
+ temp_limit = temp_limit > orig_size and orig_size or temp_limit
+
+ bitfield = bit_rshift(bitfield, test_code_len)
+ bitfield_len = bitfield_len - test_code_len
+ test_code_len = minCodeLen
+ else
+ test_code_len = test_code_len + 1
+ if test_code_len>maxCodeLen then
+ return nil, "Decompression error at "..tostring(i).."/"..tostring(strlen(compressed))
+ end
+ end
+ else
+ c = string_byte(compressed, i)
+ bitfield = bitfield + bit_lshift(c or 0, bitfield_len)
+ bitfield_len = bitfield_len + 8
+ i = i + 1
+ if i > temp_limit then
+ if i > compressed_size then
+ break;
+ end
+ end
+ end
+ end
+
+ setCleanupTables("Huffman_uncompressed", "Huffman_large_uncompressed")
+ return table_concat(large_uncompressed, "", 1, large_uncompressed_size)..table_concat(uncompressed, "", 1, uncompressed_size)
+end
+
+--------------------------------------------------------------------------------
+-- Generic codec interface
+
+function LibCompress:DecompressUncompressed(data)
+ if type(data)~="string" then
+ return nil, "Can only handle strings"
+ end
+ if string.byte(data) ~= 1 then
+ return nil, "Can only handle uncompressed data"
+ end
+ return string_sub(data, 2)
+end
+
+local compression_methods = {
+ [2] = LibCompress.CompressLZW,
+ [3] = LibCompress.CompressHuffman
+}
+
+local decompression_methods = {
+ [1] = LibCompress.DecompressUncompressed,
+ [2] = LibCompress.DecompressLZW,
+ [3] = LibCompress.DecompressHuffman
+}
+
+-- try all compression codecs and return best result
+function LibCompress:Compress(data)
+ local method = next(compression_methods)
+ local result = compression_methods[method](self, data)
+ local nTable = {}
+ local rTable = {}
+ local n
+ method = next(compression_methods, method)
+ while method do
+ n = compression_methods[method](self, data)
+ nTable = {}
+ for i = 1, strlen(n) do
+ nTable[i] = string.sub(n, i, i)
+ end
+ for i = 1, strlen(result) do
+ rTable[i] = string.sub(result, i, i)
+ end
+ if getn(nTable) < getn(rTable) then
+ result = nTable
+ end
+ method = next(compression_methods, method)
+ end
+ return result
+end
+
+function LibCompress:Decompress(data)
+ local header_info = string.byte(data)
+ if decompression_methods[header_info] then
+ return decompression_methods[header_info](self, data)
+ else
+ return nil, "Unknown compression method ("..tostring(header_info)..")"
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibCompress/LibCompress.xml b/ElvUI/Libraries/LibCompress/LibCompress.xml
new file mode 100644
index 0000000..58cb27c
--- /dev/null
+++ b/ElvUI/Libraries/LibCompress/LibCompress.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibDataBroker/LibDataBroker-1.1.lua b/ElvUI/Libraries/LibDataBroker/LibDataBroker-1.1.lua
new file mode 100644
index 0000000..f47c0cd
--- /dev/null
+++ b/ElvUI/Libraries/LibDataBroker/LibDataBroker-1.1.lua
@@ -0,0 +1,90 @@
+
+assert(LibStub, "LibDataBroker-1.1 requires LibStub")
+assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
+
+local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
+if not lib then return end
+oldminor = oldminor or 0
+
+
+lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
+lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
+local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
+
+if oldminor < 2 then
+ lib.domt = {
+ __metatable = "access denied",
+ __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
+ }
+end
+
+if oldminor < 3 then
+ lib.domt.__newindex = function(self, key, value)
+ if not attributestorage[self] then attributestorage[self] = {} end
+ if attributestorage[self][key] == value then return end
+ attributestorage[self][key] = value
+ local name = namestorage[self]
+ if not name then return end
+ callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
+ callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
+ callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
+ callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
+ end
+end
+
+if oldminor < 2 then
+ function lib:NewDataObject(name, dataobj)
+ if self.proxystorage[name] then return end
+
+ if dataobj then
+ assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
+ self.attributestorage[dataobj] = {}
+ for i,v in pairs(dataobj) do
+ self.attributestorage[dataobj][i] = v
+ dataobj[i] = nil
+ end
+ end
+ dataobj = setmetatable(dataobj or {}, self.domt)
+ self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
+ self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
+ return dataobj
+ end
+end
+
+if oldminor < 1 then
+ function lib:DataObjectIterator()
+ return pairs(self.proxystorage)
+ end
+
+ function lib:GetDataObjectByName(dataobjectname)
+ return self.proxystorage[dataobjectname]
+ end
+
+ function lib:GetNameByDataObject(dataobject)
+ return self.namestorage[dataobject]
+ end
+end
+
+if oldminor < 4 then
+ local next = pairs(attributestorage)
+ function lib:pairs(dataobject_or_name)
+ local t = type(dataobject_or_name)
+ assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
+
+ local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+ assert(attributestorage[dataobj], "Data object not found")
+
+ return next, attributestorage[dataobj], nil
+ end
+
+ local ipairs_iter = ipairs(attributestorage)
+ function lib:ipairs(dataobject_or_name)
+ local t = type(dataobject_or_name)
+ assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
+
+ local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+ assert(attributestorage[dataobj], "Data object not found")
+
+ return ipairs_iter, attributestorage[dataobj], 0
+ end
+end
diff --git a/ElvUI/Libraries/LibDataBroker/LibDataBroker-1.1.xml b/ElvUI/Libraries/LibDataBroker/LibDataBroker-1.1.xml
new file mode 100644
index 0000000..7a70527
--- /dev/null
+++ b/ElvUI/Libraries/LibDataBroker/LibDataBroker-1.1.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibElvUIPlugin-1.0/LibElvUIPlugin-1.0.lua b/ElvUI/Libraries/LibElvUIPlugin-1.0/LibElvUIPlugin-1.0.lua
new file mode 100644
index 0000000..bea223d
--- /dev/null
+++ b/ElvUI/Libraries/LibElvUIPlugin-1.0/LibElvUIPlugin-1.0.lua
@@ -0,0 +1,244 @@
+local MAJOR, MINOR = "LibElvUIPlugin-1.0", 18
+local lib, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+if not lib then return end
+
+--Cache global variables
+--Lua functions
+local pairs, tonumber = pairs, tonumber
+local format, gsub, strmatch, strsplit = format, gsub, strmatch, strsplit
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local GetAddOnMetadata = GetAddOnMetadata
+local GetNumPartyMembers, GetNumRaidMembers = GetNumPartyMembers, GetNumRaidMembers
+local IsAddOnLoaded = IsAddOnLoaded
+local IsInInstance = IsInInstance
+local SendAddonMessage = SendAddonMessage
+
+--Global variables that we don't cache, list them here for the mikk's Find Globals script
+-- GLOBALS: ElvUI
+
+lib.plugins = {}
+lib.index = 0
+lib.prefix = "ElvUIPluginVC"
+
+-- MULTI Language Support (Default Language: English)
+local MSG_OUTDATED = "Your version of %s %s is out of date (latest is version %s). You can download the latest version from https://github.com/ElvUI-Vanilla/ElvUI/"
+local HDR_CONFIG = "Plugins"
+local HDR_INFORMATION = "LibElvUIPlugin-1.0.%d - Plugins Loaded (Green means you have current version, Red means out of date)"
+local INFO_BY = "by"
+local INFO_VERSION = "Version:"
+local INFO_NEW = "Newest:"
+local LIBRARY = "Library"
+
+if GetLocale() == "deDE" then -- German Translation
+ MSG_OUTDATED = "Deine Version von %s %s ist veraltet (akutelle Version ist %s). Du kannst die aktuelle Version von https://github.com/ElvUI-Vanilla/ElvUI/ herunterrladen."
+ HDR_CONFIG = "Plugins"
+ HDR_INFORMATION = "LibElvUIPlugin-1.0.%d - Plugins geladen (Grün bedeutet du hast die aktuelle Version, Rot bedeutet es ist veraltet)"
+ INFO_BY = "von"
+ INFO_VERSION = "Version:"
+ INFO_NEW = "Neuste:"
+ LIBRARY = "Bibliothek"
+end
+
+if GetLocale() == "ruRU" then -- Russian Translations
+ MSG_OUTDATED = "Ваша версия %s %s устарела (последняя версия %s). Вы можете скачать последнюю версию на https://github.com/ElvUI-Vanilla/ElvUI/"
+ HDR_CONFIG = "Плагины"
+ HDR_INFORMATION = "LibElvUIPlugin-1.0.%d - загруженные плагины (зеленый означает, что у вас последняя версия, красный - устаревшая)"
+ INFO_BY = "от"
+ INFO_VERSION = "Версия:"
+ INFO_NEW = "Последняя:"
+ LIBRARY = "Библиотека"
+end
+
+--
+-- Plugin table format:
+-- { name (string) - The name of the plugin,
+-- version (string) - The version of the plugin,
+-- optionCallback (string) - The callback to call when ElvUI_Config is loaded
+-- }
+--
+
+--
+-- RegisterPlugin(name,callback)
+-- Registers a module with the given name and option callback, pulls version info from metadata
+--
+
+function lib:RegisterPlugin(name, callback, isLib)
+ local plugin = {}
+ plugin.name = name
+ plugin.version = name == MAJOR and MINOR or GetAddOnMetadata(name, "Version")
+ if isLib then plugin.isLib = true; plugin.version = 1 end
+ plugin.callback = callback
+ lib.plugins[name] = plugin
+ local loaded = IsAddOnLoaded("ElvUI_Config")
+
+ if not lib.vcframe then
+ local f = CreateFrame("Frame")
+ f:RegisterEvent("RAID_ROSTER_UPDATE")
+ f:RegisterEvent("PARTY_MEMBERS_CHANGED")
+ f:RegisterEvent("CHAT_MSG_ADDON")
+ f:SetScript("OnEvent", lib.VersionCheck)
+ lib.vcframe = f
+ end
+
+ if not loaded then
+ if not lib.ConfigFrame then
+ local configFrame = CreateFrame("Frame")
+ configFrame:RegisterEvent("ADDON_LOADED")
+ configFrame:SetScript("OnEvent", function()
+ if arg1 == "ElvUI_Config" then
+ for _, PlugIn in pairs(lib.plugins) do
+ if PlugIn.callback then
+ PlugIn.callback()
+ end
+ end
+ end
+ end)
+ lib.ConfigFrame = configFrame
+ end
+ elseif loaded then
+ -- Need to update plugins list
+ if name ~= MAJOR then
+ ElvUI[1].Options.args.plugins.args.plugins.name = lib:GeneratePluginList()
+ end
+ callback()
+ end
+
+ return plugin
+end
+
+function lib:GetPluginOptions()
+ ElvUI[1].Options.args.plugins = {
+ order = -10,
+ type = "group",
+ name = HDR_CONFIG,
+ guiInline = false,
+ args = {
+ pluginheader = {
+ order = 1,
+ type = "header",
+ name = format(HDR_INFORMATION, MINOR),
+ },
+ plugins = {
+ order = 2,
+ type = "description",
+ name = lib:GeneratePluginList(),
+ },
+ }
+ }
+end
+
+function lib:GenerateVersionCheckMessage()
+ local list = ""
+ for _, plugin in pairs(lib.plugins) do
+ if plugin.name ~= MAJOR then
+ list = list..plugin.name.."="..plugin.version..";"
+ end
+ end
+ return list
+end
+
+local function SendPluginVersionCheck(self)
+ lib:SendPluginVersionCheck(lib:GenerateVersionCheckMessage())
+
+ if self["ElvUIPluginSendMSGTimer"] then
+ self:CancelTimer(self["ElvUIPluginSendMSGTimer"])
+ self["ElvUIPluginSendMSGTimer"] = nil
+ end
+end
+
+function lib:VersionCheck()
+ if not ElvUI[1].global.general.versionCheck then return end
+
+ local E = ElvUI[1]
+ if event == "CHAT_MSG_ADDON" then
+ if not (arg1 == lib.prefix and arg4 and arg1 and not strmatch(arg1, "^%s-$")) then return end
+ if arg4 == E.myname then return end
+
+ if not E["pluginRecievedOutOfDateMessage"] then
+ local name, version, plugin, Pname
+ for _, p in pairs({strsplit(";", arg2)}) do
+ if not strmatch(p, "^%s-$") then
+ name, version = strmatch(p, "([%w_]+)=([%d%p]+)")
+ if lib.plugins[name] then
+ plugin = lib.plugins[name]
+ if plugin.version ~= "BETA" and version and tonumber(version) and plugin.version and tonumber(plugin.version) and tonumber(version) > tonumber(plugin.version) then
+ plugin.old = true
+ plugin.newversion = tonumber(version)
+ Pname = GetAddOnMetadata(plugin.name, "Title")
+ E:Print(format(MSG_OUTDATED, Pname, plugin.version, plugin.newversion))
+ E["pluginRecievedOutOfDateMessage"] = true
+ end
+ end
+ end
+ end
+ end
+ else
+ if not E.SendPluginVersionCheck then
+ E.SendPluginVersionCheck = SendPluginVersionCheck
+ end
+
+ local numRaid, numParty = GetNumRaidMembers(), GetNumPartyMembers() + 1
+ local num = numRaid > 0 and numRaid or numParty
+ if num ~= lib.groupSize then
+ if num > 1 and ((lib.groupSize and num > lib.groupSize) or not lib.groupSize) then
+ E["ElvUIPluginSendMSGTimer"] = E:ScheduleTimer("SendPluginVersionCheck", 12)
+ end
+ lib.groupSize = num
+ end
+ end
+end
+
+function lib:GeneratePluginList()
+ local list, E = "", ElvUI[1]
+ local author, Pname, color
+ for _, plugin in pairs(lib.plugins) do
+ if plugin.name ~= MAJOR then
+ author = GetAddOnMetadata(plugin.name, "Author")
+ Pname = GetAddOnMetadata(plugin.name, "Title") or plugin.name
+ color = plugin.old and E:RGBToHex(1, 0, 0) or E:RGBToHex(0, 1, 0)
+ list = list .. Pname
+ if author then
+ list = list .. " ".. INFO_BY .." " .. author
+ end
+ list = list .. color .. (plugin.isLib and " " .. LIBRARY or " - " .. INFO_VERSION .. " " .. plugin.version)
+ if plugin.old then
+ list = list .. " (" .. INFO_NEW .." " .. plugin.newversion .. ")"
+ end
+ list = list .. "|r\n"
+ end
+ end
+ return list
+end
+
+function lib:SendPluginVersionCheck(message)
+ if not message or strmatch(message, "^%s-$") then return end
+
+ local ChatType
+ if GetNumRaidMembers() > 1 then
+ local _, instanceType = IsInInstance()
+ ChatType = instanceType == "pvp" and "BATTLEGROUND" or "RAID"
+ elseif GetNumPartyMembers() > 0 then
+ ChatType = "PARTY"
+ end
+ if not ChatType then return end
+
+ local maxChar, msgLength = 254 - strlen(lib.prefix), strlen(message)
+ if msgLength > maxChar then
+ local delay, splitMessage = 0
+
+ for _ = 1, ceil(msgLength / maxChar) do
+ splitMessage = strmatch(strsub(message, 1, maxChar), ".+;")
+
+ if splitMessage then -- incase the string is over `maxChar` but doesnt contain `;`
+ message = gsub(message, "^"..gsub(splitMessage, "([%-%.%+%[%]%(%)%$%^%%%?%*])","%%%1"), "")
+ ElvUI[1]:Delay(delay, SendAddonMessage, lib.prefix, splitMessage, ChatType)
+ delay = delay + 1
+ end
+ end
+ else
+ SendAddonMessage(lib.prefix, message, ChatType)
+ end
+end
+
+lib:RegisterPlugin(MAJOR, lib.GetPluginOptions)
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibElvUIPlugin-1.0/LibElvUIPlugin-1.0.xml b/ElvUI/Libraries/LibElvUIPlugin-1.0/LibElvUIPlugin-1.0.xml
new file mode 100644
index 0000000..406533d
--- /dev/null
+++ b/ElvUI/Libraries/LibElvUIPlugin-1.0/LibElvUIPlugin-1.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua b/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua
new file mode 100644
index 0000000..610654e
--- /dev/null
+++ b/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua
@@ -0,0 +1,204 @@
+--[[
+Copyright 2013 João Cardoso
+CustomSearch is distributed under the terms of the GNU General Public License (Version 3).
+As a special exception, the copyright holders of this library give you permission to embed it
+with independent modules to produce an addon, regardless of the license terms of these
+independent modules, and to copy and distribute the resulting software under terms of your
+choice, provided that you also meet, for each embedded independent module, the terms and
+conditions of the license of that module. Permission is not granted to modify this library.
+
+This library 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 the library. If not, see .
+
+This file is part of CustomSearch.
+--]]
+
+local Lib = LibStub:NewLibrary('CustomSearch-1.0', 9)
+if not Lib then
+ return
+end
+
+local find, gmatch, lower, match = string.find, string.gmatch, string.lower, string.match
+
+--[[ Parsing ]]--
+
+function Lib:Matches(object, search, filters)
+ if object then
+ self.filters = filters
+ self.object = object
+
+ return self:MatchAll(search or '')
+ end
+end
+
+function Lib:MatchAll(search)
+ for phrase in gmatch(self:Clean(search), '[^&]+') do
+ if not self:MatchAny(phrase) then
+ return
+ end
+ end
+
+ return true
+end
+
+function Lib:MatchAny(search)
+ for phrase in gmatch(search, '[^|]+') do
+ if self:Match(phrase) then
+ return true
+ end
+ end
+end
+
+function Lib:Match(search)
+ local tag, rest = match(search, '^%s*(%S+):(.*)$')
+ if tag then
+ tag = '^' .. tag
+ search = rest
+ end
+
+ local words = gmatch(search, '%S+')
+ local failed
+
+ for word in words do
+ if word == self.OR then
+ if failed then
+ failed = false
+ else
+ break
+ end
+
+ else
+ local negate, rest = match(word, '^([!~]=*)(.*)$')
+ if negate or word == self.NOT_MATCH then
+ word = rest and rest ~= '' and rest or words() or ''
+ negate = -1
+ else
+ negate = 1
+ end
+
+ local operator, rest = match(word, '^(=*[<>]=*)(.*)$')
+ if operator then
+ word = rest ~= '' and rest or words()
+ end
+
+ local result = self:Filter(tag, operator, word) and 1 or -1
+ if result * negate ~= 1 then
+ failed = true
+ end
+ end
+ end
+
+ return not failed
+end
+
+
+--[[ Filtering ]]--
+
+function Lib:Filter(tag, operator, search)
+ if not search then
+ return true
+ end
+
+ if tag then
+ for _, filter in pairs(self.filters) do
+ for _, value in pairs(filter.tags or {}) do
+ if find(value, tag) then
+ return self:UseFilter(filter, operator, search)
+ end
+ end
+ end
+ else
+ for _, filter in pairs(self.filters) do
+ if not filter.onlyTags and self:UseFilter(filter, operator, search) then
+ return true
+ end
+ end
+ end
+end
+
+function Lib:UseFilter(filter, operator, search)
+ local data = {filter:canSearch(operator, search, self.object)}
+ if data[1] then
+ return match(filter, self.object, operator, unpack(data))
+ end
+end
+
+
+--[[ Utilities ]]--
+
+function Lib:Find(search, ...)
+ for i = 1, getn(arg) do
+ local text = arg[i]
+ if text and find(self:Clean(text), search) then
+ return true
+ end
+ end
+end
+
+function Lib:Clean(string)
+ string = lower(string)
+ string = gsub(string, '[%(%)%.%%%+%-%*%?%[%]%^%$]', function(c) return '%'..c end)
+
+ for accent, char in pairs(self.ACCENTS) do
+ string = gsub(string, accent, char)
+ end
+
+ return string
+end
+
+function Lib:Compare(op, a, b)
+ if op then
+ if find(op, '<') then
+ if find(op, '=') then
+ return a <= b
+ end
+
+ return a < b
+ end
+
+ if find(op, '>')then
+ if find(op, '=') then
+ return a >= b
+ end
+
+ return a > b
+ end
+ end
+
+ return a == b
+end
+
+
+--[[ Localization ]]--
+
+do
+ local no = {enUS = 'Not', frFR = 'Pas', deDE = 'Nicht', ruRU = 'Нет'}
+ local just_or = {enUS = 'Or', frFR = 'Ou', deDE = 'Oder', ruRU = 'Или'}
+ local accents = {
+ a = {'à','â','ã','å'},
+ e = {'è','é','ê','ê','ë'},
+ i = {'ì', 'í', 'î', 'ï'},
+ o = {'ó','ò','ô','õ'},
+ u = {'ù', 'ú', 'û', 'ü'},
+ c = {'ç'}, n = {'ñ'}
+ }
+
+ Lib.ACCENTS = {}
+ for char, accents in pairs(accents) do
+ for _, accent in ipairs(accents) do
+ Lib.ACCENTS[accent] = char
+ end
+ end
+
+ Lib.OR = Lib:Clean(just_or[GetLocale()] or "")
+ Lib.NOT = no[GetLocale()] or NO
+ Lib.NOT_MATCH = Lib:Clean(Lib.NOT)
+ setmetatable(Lib, {__call = Lib.Matches})
+end
+
+return Lib
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.xml b/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.xml
new file mode 100644
index 0000000..8a31987
--- /dev/null
+++ b/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua b/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua
new file mode 100644
index 0000000..34a7d75
--- /dev/null
+++ b/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua
@@ -0,0 +1,212 @@
+--[[
+ ItemSearch
+ An item text search engine of some sort
+--]]
+
+local Search = LibStub("CustomSearch-1.0");
+local Unfit = LibStub("Unfit-1.0");
+local Lib = LibStub:NewLibrary("LibItemSearch-1.2", 11);
+if Lib then
+ Lib.Filters = {}
+else
+ return
+end
+
+local tonumber = tonumber
+local find, strmatch, lower = string.find, string.match, string.lower
+
+--[[ User API ]]--
+
+function Lib:Matches(link, search)
+ return Search(link, search, self.Filters)
+end
+
+function Lib:Tooltip(link, search)
+ return link and strmatch(self.Filters.tip, link, nil, search)
+end
+
+function Lib:TooltipPhrase(link, search)
+ return link and strmatch(self.Filters.tipPhrases, link, nil, search)
+end
+
+--[[ Basics ]]--
+
+Lib.Filters.name = {
+ tags = {"n", "name"},
+
+ canSearch = function(self, operator, search)
+ return not operator and search
+ end,
+
+ match = function(self, item, _, search)
+ local name = strmatch(item, "%[(.-)%]")
+ return Search:Find(search, name)
+ end
+}
+
+Lib.Filters.type = {
+ tags = {"t", "type", "s", "slot"},
+
+ canSearch = function(self, operator, search)
+ return not operator and search
+ end,
+
+ match = function(self, item, _, search)
+ local type, subType, _, equipSlot = select(6, GetItemInfo(item))
+ return Search:Find(search, type, subType, _G[equipSlot])
+ end
+}
+
+Lib.Filters.level = {
+ tags = {"l", "level", "lvl", "ilvl"},
+
+ canSearch = function(self, _, search)
+ return tonumber(search)
+ end,
+
+ match = function(self, link, operator, num)
+ local _, _, _, lvl = GetItemInfo(link)
+ if lvl then
+ return Search:Compare(operator, lvl, num)
+ end
+ end
+}
+
+Lib.Filters.requiredlevel = {
+ tags = {"r", "req", "rl", "reql", "reqlvl"},
+
+ canSearch = function(self, _, search)
+ return tonumber(search)
+ end,
+
+ match = function(self, link, operator, num)
+ local _, _, _, _, lvl = GetItemInfo(link)
+ if lvl then
+ return Search:Compare(operator, lvl, num)
+ end
+ end
+}
+
+--[[ Quality ]]--
+
+local qualities = {}
+for i = 0, getn(ITEM_QUALITY_COLORS) do
+ qualities[i] = lower(_G["ITEM_QUALITY"..i.."_DESC"])
+end
+
+Lib.Filters.quality = {
+ tags = {"q", "quality"},
+
+ canSearch = function(self, _, search)
+ for i, name in pairs(qualities) do
+ if find(namesearch) then
+ return i
+ end
+ end
+ end,
+
+ match = function(self, link, operator, num)
+ local _, _, quality = GetItemInfo(link)
+ return Search:Compare(operator, quality, num)
+ end
+}
+
+--[[ Usable ]]--
+
+Lib.Filters.usable = {
+ tags = {},
+
+ canSearch = function(self, operator, search)
+ return not operator and search == "usable"
+ end,
+
+ match = function(self, link)
+ if(not Unfit:IsItemUnusable(link)) then
+ local _, _, _, _, lvl = GetItemInfo(link)
+ return lvl and (lvl ~= 0 and lvl <= UnitLevel("player"))
+ end
+ end
+}
+
+--[[ Tooltip Searches ]]--
+
+local scanner = LibItemSearchTooltipScanner or CreateFrame("GameTooltip", "LibItemSearchTooltipScanner", UIParent, "GameTooltipTemplate")
+
+Lib.Filters.tip = {
+ tags = {"tt", "tip", "tooltip"},
+
+ onlyTags = true,
+
+ canSearch = function(self, _, search)
+ return search
+ end,
+
+ match = function(self, link, _, search)
+ if find(link, "item:") then
+ scanner:SetOwner(UIParent, "ANCHOR_NONE")
+ scanner:SetHyperlink(link)
+
+ for i = 1, scanner:NumLines() do
+ if Search:Find(search, _G[scanner:GetName().."TextLeft"..i]:GetText()) then
+ return true
+ end
+ end
+ end
+ end
+}
+
+local escapes = {
+ ["|c%x%x%x%x%x%x%x%x"] = "",
+ ["|r"] = ""
+}
+
+local function CleanString(str)
+ for k, v in pairs(escapes) do
+ str = string.gsub(str, k, v)
+ end
+ return str
+end
+
+Lib.Filters.tipPhrases = {
+ canSearch = function(self, _, search)
+ return self.keywords[search]
+ end,
+
+ match = function(self, link, _, search)
+ local id = strmatch(link, "item:(%d+)")
+ if not id then
+ return
+ end
+
+ local cached = self.cache[search][id]
+ if cached ~= nil then
+ return cached
+ end
+
+ scanner:SetOwner(UIParent, "ANCHOR_NONE")
+ scanner:SetHyperlink(link)
+
+ local matches = false
+ for i = 1, scanner:NumLines() do
+ local text = _G["LibItemSearchTooltipScannerTextLeft"..i]:GetText()
+ text = CleanString(text)
+ if search == text then
+ matches = true
+ break
+ end
+ end
+
+ self.cache[search][id] = matches
+ return matches
+ end,
+
+ cache = setmetatable({}, {__index = function(t, k) local v = {} t[k] = v return v end}),
+
+ keywords = {
+ [lower(ITEM_SOULBOUND)] = ITEM_BIND_ON_PICKUP,
+ ["bound"] = ITEM_BIND_ON_PICKUP,
+ ["bop"] = ITEM_BIND_ON_PICKUP,
+ ["boe"] = ITEM_BIND_ON_EQUIP,
+ ["bou"] = ITEM_BIND_ON_USE
+ }
+}
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.xml b/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.xml
new file mode 100644
index 0000000..5030577
--- /dev/null
+++ b/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibItemSearch-1.2/Unfit-1.0/Unfit-1.0.lua b/ElvUI/Libraries/LibItemSearch-1.2/Unfit-1.0/Unfit-1.0.lua
new file mode 100644
index 0000000..fb9f78d
--- /dev/null
+++ b/ElvUI/Libraries/LibItemSearch-1.2/Unfit-1.0/Unfit-1.0.lua
@@ -0,0 +1,111 @@
+--[[
+Copyright 2011-2016 João Cardoso
+Unfit is distributed under the terms of the GNU General Public License (Version 3).
+As a special exception, the copyright holders of this library give you permission to embed it
+with independent modules to produce an addon, regardless of the license terms of these
+independent modules, and to copy and distribute the resulting software under terms of your
+choice, provided that you also meet, for each embedded independent module, the terms and
+conditions of the license of that module. Permission is not granted to modify this library.
+
+This library 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 the library. If not, see .
+
+This file is part of Unfit.
+--]]
+
+local Lib = LibStub:NewLibrary('Unfit-1.0', 9)
+if not Lib then
+ return
+end
+
+
+--[[ Data ]]--
+
+do
+ local _, Class = UnitClass('player')
+ local Unusable
+
+ if Class == 'DRUID' then
+ Unusable = {
+ {1, 2, 3, 4, 8, 9, 14, 15, 16},
+ {4, 5, 7},
+ true
+ }
+ elseif Class == 'HUNTER' then
+ Unusable = {
+ {5, 6, 16},
+ {5, 6}
+ }
+ elseif Class == 'MAGE' then
+ Unusable = {
+ {1, 2, 3, 4, 5, 6, 7, 9, 11, 14, 15},
+ {3, 4, 5, 7},
+ true
+ }
+ elseif Class == 'PALADIN' then
+ Unusable = {
+ {3, 4, 10, 11, 13, 14, 15, 16},
+ {},
+ true
+ }
+ elseif Class == 'PRIEST' then
+ Unusable = {
+ {1, 2, 3, 4, 6, 7, 8, 9, 11, 14, 15},
+ {3, 4, 5, 7},
+ true
+ }
+ elseif Class == 'ROGUE' then
+ Unusable = {
+ {2, 6, 7, 9, 10, 16},
+ {4, 5, 6}
+ }
+ elseif Class == 'SHAMAN' then
+ Unusable = {
+ {3, 4, 7, 8, 9, 14, 15, 16},
+ {5}
+ }
+ elseif Class == 'WARLOCK' then
+ Unusable = {
+ {1, 2, 3, 4, 5, 6, 7, 9, 11, 14, 15},
+ {3, 4, 5, 7},
+ true
+ }
+ elseif Class == 'WARRIOR' then
+ Unusable = {{16}, {}}
+ else
+ Unusable = {{}, {}}
+ end
+
+ for class = 1, 2 do
+ local subs = {GetAuctionItemSubClasses(class)}
+ for i, subclass in ipairs(Unusable[class]) do
+ Unusable[subs[subclass]] = true
+ end
+
+ Unusable[class] = nil
+ subs = nil
+ end
+
+ Lib.unusable = Unusable
+ Lib.cannotDual = Unusable[3]
+end
+
+--[[ API ]]--
+
+function Lib:IsItemUnusable(arg1)
+ if arg1 then
+ local subclass, _, slot = select(7, GetItemInfo(arg1))
+ return Lib:IsClassUnusable(subclass, slot)
+ end
+end
+
+function Lib:IsClassUnusable(subclass, slot)
+ if subclass then
+ return slot ~= '' and Unusable[subclass] or slot == 'INVTYPE_WEAPONOFFHAND' and Lib.cannotDual
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibItemSearch-1.2/Unfit-1.0/Unfit-1.0.xml b/ElvUI/Libraries/LibItemSearch-1.2/Unfit-1.0/Unfit-1.0.xml
new file mode 100644
index 0000000..3dc9289
--- /dev/null
+++ b/ElvUI/Libraries/LibItemSearch-1.2/Unfit-1.0/Unfit-1.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibSharedMedia-3.0/LibSharedMedia-3.0.lua b/ElvUI/Libraries/LibSharedMedia-3.0/LibSharedMedia-3.0.lua
new file mode 100644
index 0000000..f250cb3
--- /dev/null
+++ b/ElvUI/Libraries/LibSharedMedia-3.0/LibSharedMedia-3.0.lua
@@ -0,0 +1,237 @@
+--[[
+Name: LibSharedMedia-3.0
+Revision: $Revision: 62 $
+Author: Elkano (elkano@gmx.de)
+Inspired By: SurfaceLib by Haste/Otravi (troeks@gmail.com)
+Website: http://www.wowace.com/projects/libsharedmedia-3-0/
+Description: Shared handling of media data (fonts, sounds, textures, ...) between addons.
+Dependencies: LibStub, CallbackHandler-1.0
+License: LGPL v2.1
+]]
+
+local MAJOR, MINOR = "LibSharedMedia-3.0", 2040001 -- 2.4.3 / increase manually on changes
+local lib = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not lib then return end
+
+local _G = _G
+
+local pairs = _G.pairs
+local type = _G.type
+
+local band = _G.bit.band
+
+local table_insert = _G.table.insert
+local table_sort = _G.table.sort
+
+local locale = GetLocale()
+local locale_is_western
+local LOCALE_MASK = 0
+lib.LOCALE_BIT_koKR = 1
+lib.LOCALE_BIT_ruRU = 2
+lib.LOCALE_BIT_zhCN = 4
+lib.LOCALE_BIT_zhTW = 8
+lib.LOCALE_BIT_western = 128
+
+local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
+
+lib.callbacks = lib.callbacks or CallbackHandler:New(lib)
+
+lib.DefaultMedia = lib.DefaultMedia or {}
+lib.MediaList = lib.MediaList or {}
+lib.MediaTable = lib.MediaTable or {}
+lib.MediaType = lib.MediaType or {}
+lib.OverrideMedia = lib.OverrideMedia or {}
+
+local defaultMedia = lib.DefaultMedia
+local mediaList = lib.MediaList
+local mediaTable = lib.MediaTable
+local overrideMedia = lib.OverrideMedia
+
+
+-- create mediatype constants
+lib.MediaType.BACKGROUND = "background" -- background textures
+lib.MediaType.BORDER = "border" -- border textures
+lib.MediaType.FONT = "font" -- fonts
+lib.MediaType.STATUSBAR = "statusbar" -- statusbar textures
+lib.MediaType.SOUND = "sound" -- sound files
+
+-- populate lib with default Blizzard data
+-- BACKGROUND
+if not lib.MediaTable.background then lib.MediaTable.background = {} end
+lib.MediaTable.background["None"] = [[]]
+lib.MediaTable.background["Blizzard Dialog Background"] = [[Interface\DialogFrame\UI-DialogBox-Background]]
+lib.MediaTable.background["Blizzard Dialog Background Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Background]]
+lib.MediaTable.background["Blizzard Low Health"] = [[Interface\FullScreenTextures\LowHealth]]
+lib.MediaTable.background["Blizzard Out of Control"] = [[Interface\FullScreenTextures\OutOfControl]]
+lib.MediaTable.background["Blizzard Tabard Background"] = [[Interface\TabardFrame\TabardFrameBackground]]
+lib.MediaTable.background["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Background]]
+lib.MediaTable.background["Solid"] = [[Interface\Buttons\WHITE8X8]]
+lib.DefaultMedia.background = "None"
+
+-- BORDER
+if not lib.MediaTable.border then lib.MediaTable.border = {} end
+lib.MediaTable.border["None"] = [[]]
+lib.MediaTable.border["Blizzard Chat Bubble"] = [[Interface\Tooltips\ChatBubble-Backdrop]]
+lib.MediaTable.border["Blizzard Dialog"] = [[Interface\DialogFrame\UI-DialogBox-Border]]
+lib.MediaTable.border["Blizzard Dialog Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Border]]
+lib.MediaTable.border["Blizzard Party"] = [[Interface\CHARACTERFRAME\UI-Party-Border]]
+lib.MediaTable.border["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Border]]
+lib.DefaultMedia.border = "None"
+
+-- FONT
+if not lib.MediaTable.font then lib.MediaTable.font = {} end
+local SML_MT_font = lib.MediaTable.font
+if locale == "koKR" then
+ LOCALE_MASK = lib.LOCALE_BIT_koKR
+--
+ SML_MT_font["굵은 글꼴"] = [[Fonts\2002B.TTF]]
+ SML_MT_font["기본 글꼴"] = [[Fonts\2002.TTF]]
+ SML_MT_font["데미지 글꼴"] = [[Fonts\K_Damage.TTF]]
+ SML_MT_font["퀘스트 글꼴"] = [[Fonts\K_Pagetext.TTF]]
+--
+ lib.DefaultMedia["font"] = "기본 글꼴" -- someone from koKR please adjust if needed
+--
+elseif locale == "zhCN" then
+ LOCALE_MASK = lib.LOCALE_BIT_zhCN
+--
+ SML_MT_font["伤害数字"] = [[Fonts\ZYKai_C.ttf]]
+ SML_MT_font["默认"] = [[Fonts\ZYKai_T.ttf]]
+ SML_MT_font["聊天"] = [[Fonts\ZYHei.ttf]]
+--
+ lib.DefaultMedia["font"] = "默认" -- someone from zhCN please adjust if needed
+--
+elseif locale == "zhTW" then
+ LOCALE_MASK = lib.LOCALE_BIT_zhTW
+--
+ SML_MT_font["提示訊息"] = [[Fonts\bHEI00M.ttf]]
+ SML_MT_font["聊天"] = [[Fonts\bHEI01B.ttf]]
+ SML_MT_font["傷害數字"] = [[Fonts\bKAI00M.ttf]]
+ SML_MT_font["預設"] = [[Fonts\bLEI00D.ttf]]
+--
+ lib.DefaultMedia["font"] = "預設" -- someone from zhTW please adjust if needed
+
+elseif locale == "ruRU" then
+ LOCALE_MASK = lib.LOCALE_BIT_ruRU
+--
+ SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]]
+ SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]]
+ SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]]
+ SML_MT_font["Nimrod MT"] = [[Fonts\NIM_____.ttf]]
+ SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]]
+
+ lib.DefaultMedia.font = "Arial Narrow"
+--
+else
+ LOCALE_MASK = lib.LOCALE_BIT_western
+ locale_is_western = true
+--
+ SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]]
+ SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]]
+ SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]]
+ SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]]
+--
+ lib.DefaultMedia.font = "Friz Quadrata TT"
+--
+end
+
+-- STATUSBAR
+if not lib.MediaTable.statusbar then lib.MediaTable.statusbar = {} end
+lib.MediaTable.statusbar["Blizzard"] = [[Interface\TargetingFrame\UI-StatusBar]]
+lib.DefaultMedia.statusbar = "Blizzard"
+
+-- SOUND
+if not lib.MediaTable.sound then lib.MediaTable.sound = {} end
+lib.MediaTable.sound["None"] = [[Interface\Quiet.ogg]] -- Relies on the fact that PlaySound[File] doesn't error on non-existing input.
+lib.DefaultMedia.sound = "None"
+
+local function rebuildMediaList(mediatype)
+ local mtable = mediaTable[mediatype]
+ if not mtable then return end
+ if not mediaList[mediatype] then mediaList[mediatype] = {} end
+ local mlist = mediaList[mediatype]
+ -- list can only get larger, so simply overwrite it
+ local i = 0
+ for k in pairs(mtable) do
+ i = i + 1
+ mlist[i] = k
+ end
+ table_sort(mlist)
+end
+
+function lib:Register(mediatype, key, data, langmask)
+ if type(mediatype) ~= "string" then
+ error(MAJOR..":Register(mediatype, key, data, langmask) - mediatype must be string, got "..type(mediatype))
+ end
+ if type(key) ~= "string" then
+ error(MAJOR..":Register(mediatype, key, data, langmask) - key must be string, got "..type(key))
+ end
+ mediatype = string.lower(mediatype)
+ if mediatype == lib.MediaType.FONT and ((langmask and band(langmask, LOCALE_MASK) == 0) or not (langmask or locale_is_western)) then return false end
+ if mediatype == lib.MediaType.SOUND and type(data) == "string" then
+ local path = data
+ -- Only wav, ogg and mp3 are valid sounds.
+ if not string.find(path, ".ogg", nil, true) and not string.find(path, ".mp3", nil, true) and not string.find(path, ".wav", nil, true) then
+ return false
+ end
+ end
+ if not mediaTable[mediatype] then mediaTable[mediatype] = {} end
+ local mtable = mediaTable[mediatype]
+ if mtable[key] then return false end
+
+ mtable[key] = data
+ rebuildMediaList(mediatype)
+ self.callbacks:Fire("LibSharedMedia_Registered", mediatype, key)
+ return true
+end
+
+function lib:Fetch(mediatype, key, noDefault)
+ local mtt = mediaTable[mediatype]
+ local overridekey = overrideMedia[mediatype]
+ local result = mtt and ((overridekey and mtt[overridekey] or mtt[key]) or (not noDefault and defaultMedia[mediatype] and mtt[defaultMedia[mediatype]])) or nil
+ return result ~= "" and result or nil
+end
+
+function lib:IsValid(mediatype, key)
+ return mediaTable[mediatype] and (not key or mediaTable[mediatype][key]) and true or false
+end
+
+function lib:HashTable(mediatype)
+ return mediaTable[mediatype]
+end
+
+function lib:List(mediatype)
+ if not mediaTable[mediatype] then
+ return nil
+ end
+ if not mediaList[mediatype] then
+ rebuildMediaList(mediatype)
+ end
+ return mediaList[mediatype]
+end
+
+function lib:GetGlobal(mediatype)
+ return overrideMedia[mediatype]
+end
+
+function lib:SetGlobal(mediatype, key)
+ if not mediaTable[mediatype] then
+ return false
+ end
+ overrideMedia[mediatype] = (key and mediaTable[mediatype][key]) and key or nil
+ self.callbacks:Fire("LibSharedMedia_SetGlobal", mediatype, overrideMedia[mediatype])
+ return true
+end
+
+function lib:GetDefault(mediatype)
+ return defaultMedia[mediatype]
+end
+
+function lib:SetDefault(mediatype, key)
+ if mediaTable[mediatype] and mediaTable[mediatype][key] and not defaultMedia[mediatype] then
+ defaultMedia[mediatype] = key
+ return true
+ else
+ return false
+ end
+end
diff --git a/ElvUI/Libraries/LibSharedMedia-3.0/LibSharedMedia-3.0.xml b/ElvUI/Libraries/LibSharedMedia-3.0/LibSharedMedia-3.0.xml
new file mode 100644
index 0000000..c691dab
--- /dev/null
+++ b/ElvUI/Libraries/LibSharedMedia-3.0/LibSharedMedia-3.0.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua b/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua
new file mode 100644
index 0000000..f05295d
--- /dev/null
+++ b/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua
@@ -0,0 +1,280 @@
+--[[---------------------------------------------------------------------------------
+ General Library providing an alternate StartMoving() that allows you to
+ specify a number of frames to snap-to when moving the frame around
+
+ Example Usage:
+
+
+ this:RegisterForDrag("LeftButton")
+
+
+ StickyFrames:StartMoving(this, {WatchDogFrame_player, WatchDogFrame_target, WatchDogFrame_party1, WatchDogFrame_party2, WatchDogFrame_party3, WatchDogFrame_party4},3,3,3,3)
+
+
+ StickyFrames:StopMoving(this)
+ StickyFrames:AnchorFrame(this)
+
+
+------------------------------------------------------------------------------------
+This is a modified version by Elv for ElvUI
+------------------------------------------------------------------------------------]]
+
+local MAJOR, MINOR = "LibSimpleSticky-1.0", 2
+local StickyFrames, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not StickyFrames then return end
+
+--[[---------------------------------------------------------------------------------
+ Class declaration, along with a temporary table to hold any existing OnUpdate
+ scripts.
+------------------------------------------------------------------------------------]]
+
+StickyFrames.scripts = StickyFrames.scripts or {}
+StickyFrames.rangeX = 15
+StickyFrames.rangeY = 15
+StickyFrames.sticky = StickyFrames.sticky or {}
+
+--[[---------------------------------------------------------------------------------
+ StickyFrames:StartMoving() - Sets a custom OnUpdate for the frame so it follows
+ the mouse and snaps to the frames you specify
+
+ frame: The frame we want to move. Is typically "this"
+
+ frameList: A integer indexed list of frames that the given frame should try to
+ stick to. These don't have to have anything special done to them,
+ and they don't really even need to exist. You can inclue the
+ moving frame in this list, it will be ignored. This helps you
+ if you have a number of frames, just make ONE list to pass.
+
+ {WatchDogFrame_player, WatchDogFrame_party1, .. WatchDogFrame_party4}
+
+ left: If your frame has a tranparent border around the entire frame
+ (think backdrops with borders). This can be used to fine tune the
+ edges when you're stickying groups. Refers to any offset on the
+ LEFT edge of the frame being moved.
+
+ top: same
+ right: same
+ bottom: same
+------------------------------------------------------------------------------------]]
+
+function StickyFrames:StartMoving(frame, frameList, left, top, right, bottom)
+ local x,y = GetCursorPosition()
+ local aX,aY = frame:GetCenter()
+ local aS = frame:GetEffectiveScale()
+
+ aX,aY = aX*aS,aY*aS
+ local xoffset,yoffset = (aX - x),(aY - y)
+ self.scripts[frame] = frame:GetScript("OnUpdate")
+ frame:SetScript("OnUpdate", self:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom))
+end
+
+--[[---------------------------------------------------------------------------------
+ This stops the OnUpdate, leaving the frame at its last position. This will
+ leave it anchored to UIParent. You can call StickyFrames:AnchorFrame() to
+ anchor it back "TOPLEFT" , "TOPLEFT" to the parent.
+------------------------------------------------------------------------------------]]
+
+function StickyFrames:StopMoving(frame)
+ frame:SetScript("OnUpdate", self.scripts[frame])
+ self.scripts[frame] = nil
+
+ if StickyFrames.sticky[frame] then
+ local sticky = StickyFrames.sticky[frame]
+ StickyFrames.sticky[frame] = nil
+ return true, sticky
+ else
+ return false, nil
+ end
+end
+
+--[[---------------------------------------------------------------------------------
+ This can be called in conjunction with StickyFrames:StopMoving() to anchor the
+ frame right back to the parent, so you can manipulate its children as a group
+ (This is useful in WatchDog)
+------------------------------------------------------------------------------------]]
+
+function StickyFrames:AnchorFrame(frame)
+ local xA,yA = frame:GetCenter()
+ local parent = frame:GetParent() or UIParent
+ local xP,yP = parent:GetCenter()
+ local sA,sP = frame:GetEffectiveScale(), parent:GetEffectiveScale()
+
+ xP,yP = (xP*sP) / sA, (yP*sP) / sA
+
+ local xo,yo = (xP - xA)*-1, (yP - yA)*-1
+
+ frame:ClearAllPoints()
+ frame:SetPoint("CENTER", parent, "CENTER", xo, yo)
+end
+
+
+--[[---------------------------------------------------------------------------------
+ Internal Functions -- Do not call these.
+------------------------------------------------------------------------------------]]
+
+
+
+--[[---------------------------------------------------------------------------------
+ Returns an anonymous OnUpdate function for the frame in question. Need
+ to provide the frame, frameList along with the x and y offset (difference between
+ where the mouse picked up the frame, and the insets (left,top,right,bottom) in the
+ case of borders, etc.w
+------------------------------------------------------------------------------------]]
+
+function StickyFrames:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom)
+ return function()
+ local x,y = GetCursorPosition()
+ local s = frame:GetEffectiveScale()
+ local sticky = nil
+
+ x,y = x/s,y/s
+
+ frame:ClearAllPoints()
+ frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x+xoffset, y+yoffset)
+
+ StickyFrames.sticky[frame] = nil
+ for i = 1, table.getn(frameList) do
+ local v = frameList[i]
+ if frame ~= v and frame ~= v:GetParent() and not IsShiftKeyDown() and v:IsVisible() then
+ if self:SnapFrame(frame, v, left, top, right, bottom) then
+ StickyFrames.sticky[frame] = v
+ break
+ end
+ end
+ end
+ end
+end
+
+
+--[[---------------------------------------------------------------------------------
+ Internal debug function.
+------------------------------------------------------------------------------------]]
+
+function StickyFrames:debug(msg)
+ DEFAULT_CHAT_FRAME:AddMessage("|cffffff00StickyFrames: |r"..tostring(msg))
+end
+
+--[[---------------------------------------------------------------------------------
+ This is called when finding an overlap between two sticky frame. If frameA is near
+ a sticky edge of frameB, then it will snap to that edge and return true. If there
+ is no sticky edge collision, will return false so we can test other frames for
+ stickyness.
+------------------------------------------------------------------------------------]]
+function StickyFrames:SnapFrame(frameA, frameB, left, top, right, bottom)
+ local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
+ local xA, yA = frameA:GetCenter()
+ local xB, yB = frameB:GetCenter()
+ local hA, hB = frameA:GetHeight() / 2, ((frameB:GetHeight() * sB) / sA) / 2
+ local wA, wB = frameA:GetWidth() / 2, ((frameB:GetWidth() * sB) / sA) / 2
+
+ local newX, newY = xA, yA
+
+ if not left then left = 0 end
+ if not top then top = 0 end
+ if not right then right = 0 end
+ if not bottom then bottom = 0 end
+
+ -- Lets translate B's coords into A's scale
+ if not xB or not yB or not sB or not sA or not sB then return end
+ xB, yB = (xB*sB) / sA, (yB*sB) / sA
+
+ local stickyAx, stickyAy = wA * 0.75, hA * 0.75
+ local stickyBx, stickyBy = wB * 0.75, hB * 0.75
+
+ -- Grab the edges of each frame, for easier comparison
+
+ local lA, tA, rA, bA = frameA:GetLeft(), frameA:GetTop(), frameA:GetRight(), frameA:GetBottom()
+ local lB, tB, rB, bB = frameB:GetLeft(), frameB:GetTop(), frameB:GetRight(), frameB:GetBottom()
+ local snap = nil
+
+ -- Translate into A's scale
+ lB, tB, rB, bB = (lB * sB) / sA, (tB * sB) / sA, (rB * sB) / sA, (bB * sB) / sA
+
+ if (bA <= tB and bB <= tA) then
+
+ -- Horizontal Centers
+ if xA <= (xB + StickyFrames.rangeX) and xA >= (xB - StickyFrames.rangeX) then
+ newX = xB
+ snap = true
+ end
+
+ -- Interior Left
+ if lA <= (lB + StickyFrames.rangeX) and lA >= (lB - StickyFrames.rangeX) then
+ newX = lB + wA
+ if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
+ newX = newX + 4
+ end
+ snap = true
+ end
+
+ -- Interior Right
+ if rA <= (rB + StickyFrames.rangeX) and rA >= (rB - StickyFrames.rangeX) then
+ newX = rB - wA
+ if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
+ newX = newX - 4
+ end
+ snap = true
+ end
+
+ -- Exterior Left to Right
+ if lA <= (rB + StickyFrames.rangeX) and lA >= (rB - StickyFrames.rangeX) then
+ newX = rB + (wA - left)
+
+ snap = true
+ end
+
+ -- Exterior Right to Left
+ if rA <= (lB + StickyFrames.rangeX) and rA >= (lB - StickyFrames.rangeX) then
+ newX = lB - (wA - right)
+ snap = true
+ end
+
+ end
+
+ if (lA <= rB and lB <= rA) then
+
+ -- Vertical Centers
+ if yA <= (yB + StickyFrames.rangeY) and yA >= (yB - StickyFrames.rangeY) then
+ newY = yB
+ snap = true
+ end
+
+ -- Interior Top
+ if tA <= (tB + StickyFrames.rangeY) and tA >= (tB - StickyFrames.rangeY) then
+ newY = tB - hA
+ if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
+ newY = newY - 4
+ end
+ snap = true
+ end
+
+ -- Interior Bottom
+ if bA <= (bB + StickyFrames.rangeY) and bA >= (bB - StickyFrames.rangeY) then
+ newY = bB + hA
+ if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
+ newY = newY + 4
+ end
+ snap = true
+ end
+
+ -- Exterior Top to Bottom
+ if tA <= (bB + StickyFrames.rangeY + bottom) and tA >= (bB - StickyFrames.rangeY + bottom) then
+ newY = bB - (hA - top)
+ snap = true
+ end
+
+ -- Exterior Bottom to Top
+ if bA <= (tB + StickyFrames.rangeY - top) and bA >= (tB - StickyFrames.rangeY - top) then
+ newY = tB + (hA - bottom)
+ snap = true
+ end
+
+ end
+
+ if snap then
+ frameA:ClearAllPoints()
+ frameA:SetPoint("CENTER", UIParent, "BOTTOMLEFT", newX, newY)
+ return true
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.xml b/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.xml
new file mode 100644
index 0000000..d932950
--- /dev/null
+++ b/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibStub/LibStub.lua b/ElvUI/Libraries/LibStub/LibStub.lua
new file mode 100644
index 0000000..b4c38e1
--- /dev/null
+++ b/ElvUI/Libraries/LibStub/LibStub.lua
@@ -0,0 +1,33 @@
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local _G = _G
+local strfind, strfmt = string.find, string.format
+local LibStub = _G[LIBSTUB_MAJOR]
+
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or { libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ local _,_,num = strfind(minor, "(%d+)")
+ minor = assert(tonumber(num), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(strfmt("Cannot find a library instance of %q.", tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ function LibStub:IterateLibraries() return pairs(self.libs) end
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibStub/LibStub.xml b/ElvUI/Libraries/LibStub/LibStub.xml
new file mode 100644
index 0000000..784fcaa
--- /dev/null
+++ b/ElvUI/Libraries/LibStub/LibStub.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibUIDropDownMenu/LibEasyMenu.lua b/ElvUI/Libraries/LibUIDropDownMenu/LibEasyMenu.lua
new file mode 100644
index 0000000..7bad616
--- /dev/null
+++ b/ElvUI/Libraries/LibUIDropDownMenu/LibEasyMenu.lua
@@ -0,0 +1,47 @@
+--$Id: LibEasyMenu.lua 19 2017-07-02 13:34:55Z arith $
+-- Simplified Menu Display System
+-- This is a basic system for displaying a menu from a structure table.
+--
+-- See UIDropDownMenu.lua for the menuList details.
+--
+-- Args:
+-- menuList - menu table
+-- menuFrame - the UI frame to populate
+-- anchor - where to anchor the frame (e.g. CURSOR)
+-- x - x offset
+-- y - y offset
+-- displayMode - border type
+-- autoHideDelay - how long until the menu disappears
+--
+--
+-- ----------------------------------------------------------------------------
+-- Localized Lua globals.
+-- ----------------------------------------------------------------------------
+local _G = _G
+-- ----------------------------------------------------------------------------
+local MAJOR_VERSION = "LibEasyMenu-1.04.7030024484"
+local MINOR_VERSION = 90000 + 19
+
+local LibStub = _G.LibStub
+if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
+local Lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
+if not Lib then return end
+
+function L_EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay )
+ if ( displayMode == "MENU" ) then
+ menuFrame.displayMode = displayMode;
+ end
+ L_UIDropDownMenu_Initialize(menuFrame, L_EasyMenu_Initialize, displayMode, nil, menuList);
+ L_ToggleDropDownMenu(1, nil, menuFrame, anchor, x, y, menuList, nil, autoHideDelay);
+end
+
+function L_EasyMenu_Initialize( frame, level, menuList )
+ for index = 1, getn(menuList) do
+ local value = menuList[index]
+ if (value.text) then
+ value.index = index;
+ L_UIDropDownMenu_AddButton( value, level );
+ end
+ end
+end
+
diff --git a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua
new file mode 100644
index 0000000..da3897f
--- /dev/null
+++ b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua
@@ -0,0 +1,1208 @@
+-- $Id: LibUIDropDownMenu.lua 19 2017-07-02 13:34:55Z arith $
+-- ----------------------------------------------------------------------------
+-- Localized Lua globals.
+-- ----------------------------------------------------------------------------
+local _G = _G
+local strsub, strlen, strmatch, gsub = strsub, strlen, strmatch, gsub
+local max, match = max, match
+local securecall, issecure = securecall, issecure
+local tonumber = tonumber
+local type = type
+local wipe = table.wipe
+local tinsert = table.insert
+
+local CreateFrame, GetCursorPosition, GetCVar, GetScreenHeight, GetScreenWidth, OpenColorPicker, PlaySound = CreateFrame, GetCursorPosition, GetCVar, GetScreenHeight, GetScreenWidth, OpenColorPicker, PlaySound
+
+-- ----------------------------------------------------------------------------
+local MAJOR_VERSION = "LibUIDropDownMenu-1.04.7030024484"
+local MINOR_VERSION = 90000 + 19
+
+local LibStub = _G.LibStub
+if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
+local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
+if not lib then return end
+
+-- //////////////////////////////////////////////////////////////
+L_UIDROPDOWNMENU_MINBUTTONS = 32;
+L_UIDROPDOWNMENU_MAXBUTTONS = 32;
+L_UIDROPDOWNMENU_MAXLEVELS = 2;
+L_UIDROPDOWNMENU_BUTTON_HEIGHT = 16;
+L_UIDROPDOWNMENU_BORDER_HEIGHT = 15;
+-- The current open menu
+L_UIDROPDOWNMENU_OPEN_MENU = nil;
+-- The current menu being initialized
+L_UIDROPDOWNMENU_INIT_MENU = nil;
+-- Current level shown of the open menu
+L_UIDROPDOWNMENU_MENU_LEVEL = 1;
+-- Current value of the open menu
+L_UIDROPDOWNMENU_MENU_VALUE = nil;
+-- Time to wait to hide the menu
+L_UIDROPDOWNMENU_SHOW_TIME = 2;
+-- Default dropdown text height
+L_UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = nil;
+-- List of open menus
+L_OPEN_DROPDOWNMENUS = {};
+
+local UIDropDownMenuDelegate = CreateFrame("FRAME");
+
+function L_UIDropDownMenu_InitializeHelper (frame)
+ -- This deals with the potentially tainted stuff!
+ if ( frame ~= L_UIDROPDOWNMENU_OPEN_MENU ) then
+ L_UIDROPDOWNMENU_MENU_LEVEL = 1;
+ end
+
+ -- Set the frame that's being intialized
+ L_UIDROPDOWNMENU_INIT_MENU = frame
+
+ -- Hide all the buttons
+ local button, dropDownList;
+ for i = 1, L_UIDROPDOWNMENU_MAXLEVELS, 1 do
+ dropDownList = _G["L_DropDownList"..i];
+ if ( i >= L_UIDROPDOWNMENU_MENU_LEVEL or frame ~= L_UIDROPDOWNMENU_OPEN_MENU ) then
+ dropDownList.numButtons = 0;
+ dropDownList.maxWidth = 0;
+ for j=1, L_UIDROPDOWNMENU_MAXBUTTONS, 1 do
+ button = _G["L_DropDownList"..i.."Button"..j];
+ button:Hide();
+ end
+ dropDownList:Hide();
+ end
+ end
+ frame:SetHeight(L_UIDROPDOWNMENU_BUTTON_HEIGHT * 2);
+end
+
+function L_UIDropDownMenu_Initialize(frame, initFunction, displayMode, level, menuList)
+ frame.menuList = menuList;
+
+ L_UIDropDownMenu_InitializeHelper(frame);
+
+ -- Set the initialize function and call it. The initFunction populates the dropdown list.
+ if ( initFunction ) then
+ L_UIDropDownMenu_SetInitializeFunction(frame, initFunction);
+ initFunction(frame, level, frame.menuList);
+ end
+
+ --master frame
+ if(level == nil) then
+ level = 1;
+ end
+
+ local dropDownList = _G["L_DropDownList"..level]
+ dropDownList.dropdown = frame;
+ dropDownList.shouldRefresh = true;
+
+ -- Change appearance based on the displayMode
+ if ( displayMode == "MENU" ) then
+ local name = frame:GetName();
+ _G[name.."Left"]:Hide();
+ _G[name.."Middle"]:Hide();
+ _G[name.."Right"]:Hide();
+ _G[name.."ButtonNormalTexture"]:SetTexture("");
+ _G[name.."ButtonDisabledTexture"]:SetTexture("");
+ _G[name.."ButtonPushedTexture"]:SetTexture("");
+ _G[name.."ButtonHighlightTexture"]:SetTexture("");
+
+ local button = _G[name.."Button"]
+ button:ClearAllPoints();
+ button:SetPoint("LEFT", name.."Text", "LEFT", -9, 0);
+ button:SetPoint("RIGHT", name.."Text", "RIGHT", 6, 0);
+ frame.displayMode = "MENU";
+ end
+end
+
+function L_UIDropDownMenu_SetInitializeFunction(frame, initFunction)
+ frame.initialize = initFunction;
+end
+
+function L_UIDropDownMenu_RefreshDropDownSize(self)
+ self.maxWidth = L_UIDropDownMenu_GetMaxButtonWidth(self);
+ self:SetWidth(self.maxWidth + 25);
+
+ for i=1, L_UIDROPDOWNMENU_MAXBUTTONS, 1 do
+ local icon = _G[self:GetName().."Button"..i.."Icon"];
+
+ if ( icon.tFitDropDownSizeX ) then
+ icon:SetWidth(self.maxWidth - 5);
+ end
+ end
+end
+
+-- If dropdown is visible then see if its timer has expired, if so hide the frame
+function L_UIDropDownMenu_OnUpdate(self, elapsed)
+ if ( self.shouldRefresh ) then
+ L_UIDropDownMenu_RefreshDropDownSize(self);
+ self.shouldRefresh = false;
+ end
+
+ if ( not self.showTimer or not self.isCounting ) then
+ return;
+ elseif ( self.showTimer < 0 ) then
+ self:Hide();
+ self.showTimer = nil;
+ self.isCounting = nil;
+ else
+ self.showTimer = self.showTimer - elapsed;
+ end
+end
+
+-- Start the countdown on a frame
+function L_UIDropDownMenu_StartCounting(frame)
+ if ( frame.parent ) then
+ L_UIDropDownMenu_StartCounting(frame.parent);
+ else
+ frame.showTimer = L_UIDROPDOWNMENU_SHOW_TIME;
+ frame.isCounting = 1;
+ end
+end
+
+-- Stop the countdown on a frame
+function L_UIDropDownMenu_StopCounting(frame)
+ if ( frame.parent ) then
+ L_UIDropDownMenu_StopCounting(frame.parent);
+ else
+ frame.isCounting = nil;
+ end
+end
+
+--[[
+List of button attributes
+======================================================
+info.text = [STRING] -- The text of the button
+info.value = [ANYTHING] -- The value that L_UIDROPDOWNMENU_MENU_VALUE is set to when the button is clicked
+info.func = [function()] -- The function that is called when you click the button
+info.checked = [nil, true, function] -- Check the button if true or function returns true
+info.isTitle = [nil, true] -- If it's a title the button is disabled and the font color is set to yellow
+info.disabled = [nil, true] -- Disable the button and show an invisible button that still traps the mouseover event so menu doesn't time out
+info.tooltipWhileDisabled = [nil, 1] -- Show the tooltip, even when the button is disabled.
+info.hasArrow = [nil, true] -- Show the expand arrow for multilevel menus
+info.hasColorSwatch = [nil, true] -- Show color swatch or not, for color selection
+info.r = [1 - 255] -- Red color value of the color swatch
+info.g = [1 - 255] -- Green color value of the color swatch
+info.b = [1 - 255] -- Blue color value of the color swatch
+info.colorCode = [STRING] -- "|cAARRGGBB" embedded hex value of the button text color. Only used when button is enabled
+info.swatchFunc = [function()] -- Function called by the color picker on color change
+info.hasOpacity = [nil, 1] -- Show the opacity slider on the colorpicker frame
+info.opacity = [0.0 - 1.0] -- Percentatge of the opacity, 1.0 is fully shown, 0 is transparent
+info.opacityFunc = [function()] -- Function called by the opacity slider when you change its value
+info.cancelFunc = [function(previousValues)] -- Function called by the colorpicker when you click the cancel button (it takes the previous values as its argument)
+info.notClickable = [nil, 1] -- Disable the button and color the font white
+info.notCheckable = [nil, 1] -- Shrink the size of the buttons and don't display a check box
+info.owner = [Frame] -- Dropdown frame that "owns" the current dropdownlist
+info.keepShownOnClick = [nil, 1] -- Don't hide the dropdownlist after a button is clicked
+info.tooltipTitle = [nil, STRING] -- Title of the tooltip shown on mouseover
+info.tooltipText = [nil, STRING] -- Text of the tooltip shown on mouseover
+info.tooltipOnButton = [nil, 1] -- Show the tooltip attached to the button instead of as a Newbie tooltip.
+info.justifyH = [nil, "CENTER"] -- Justify button text
+info.arg1 = [ANYTHING] -- This is the first argument used by info.func
+info.arg2 = [ANYTHING] -- This is the second argument used by info.func
+info.menuTable = [TABLE] -- This contains an array of info tables to be displayed as a child menu
+info.noClickSound = [nil, 1] -- Set to 1 to suppress the sound when clicking the button. The sound only plays if .func is set.
+info.padding = [nil, NUMBER] -- Number of pixels to pad the text on the right side
+info.leftPadding = [nil, NUMBER] -- Number of pixels to pad the button on the left side
+info.minWidth = [nil, NUMBER] -- Minimum width for this line
+]]
+
+local UIDropDownMenu_ButtonInfo = {};
+
+--Until we get around to making this betterz...
+local UIDropDownMenu_SecureInfo = {};
+
+--local wipe = table.wipe;
+
+function L_UIDropDownMenu_CreateInfo()
+ -- Reuse the same table to prevent memory churn
+
+-- if ( issecure() ) then
+-- securecall(wipe, UIDropDownMenu_SecureInfo);
+-- return UIDropDownMenu_SecureInfo;
+-- else
+ return wipe(UIDropDownMenu_ButtonInfo);
+-- end
+end
+
+function L_UIDropDownMenu_CreateFrames(level, index)
+
+ while ( level > L_UIDROPDOWNMENU_MAXLEVELS ) do
+ L_UIDROPDOWNMENU_MAXLEVELS = L_UIDROPDOWNMENU_MAXLEVELS + 1;
+ local newList = CreateFrame("Button", "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS, nil, "L_UIDropDownListTemplate");
+ newList:SetFrameStrata("FULLSCREEN_DIALOG");
+ newList:SetToplevel(true);
+ newList:Hide();
+ newList:SetID(L_UIDROPDOWNMENU_MAXLEVELS);
+ newList:SetWidth(180)
+ newList:SetHeight(10)
+
+ --Allow closing with escape
+ tinsert(UIMenus, "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS)
+
+ for i=L_UIDROPDOWNMENU_MINBUTTONS+1, L_UIDROPDOWNMENU_MAXBUTTONS do
+ local newButton = CreateFrame("Button", "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS.."Button"..i, newList, "L_UIDropDownMenuButtonTemplate");
+ newButton:SetID(i);
+ end
+ end
+
+ while ( index > L_UIDROPDOWNMENU_MAXBUTTONS ) do
+ L_UIDROPDOWNMENU_MAXBUTTONS = L_UIDROPDOWNMENU_MAXBUTTONS + 1;
+ for i=1, L_UIDROPDOWNMENU_MAXLEVELS do
+ local newButton = CreateFrame("Button", "L_DropDownList"..i.."Button"..L_UIDROPDOWNMENU_MAXBUTTONS, _G["L_DropDownList"..i], "L_UIDropDownMenuButtonTemplate");
+ newButton:SetID(L_UIDROPDOWNMENU_MAXBUTTONS);
+ end
+ end
+end
+
+function L_UIDropDownMenu_AddSeparator(info, level)
+ info.text = nil;
+ info.hasArrow = false;
+ info.dist = 0;
+ info.isTitle = true;
+ info.isUninteractable = true;
+ info.notCheckable = true;
+ info.iconOnly = true;
+ info.icon = "Interface\\Common\\UI-TooltipDivider-Transparent";
+ info.tCoordLeft = 0;
+ info.tCoordRight = 1;
+ info.tCoordTop = 0;
+ info.tCoordBottom = 1;
+ info.tSizeX = 0;
+ info.tSizeY = 8;
+ info.tFitDropDownSizeX = true;
+ info.iconInfo = { tCoordLeft = info.tCoordLeft,
+ tCoordRight = info.tCoordRight,
+ tCoordTop = info.tCoordTop,
+ tCoordBottom = info.tCoordBottom,
+ tSizeX = info.tSizeX,
+ tSizeY = info.tSizeY,
+ tFitDropDownSizeX = info.tFitDropDownSizeX };
+
+ L_UIDropDownMenu_AddButton(info, level);
+end
+
+function L_UIDropDownMenu_AddButton(info, level)
+ --[[
+ Might to uncomment this if there are performance issues
+ if ( not L_UIDROPDOWNMENU_OPEN_MENU ) then
+ return;
+ end
+ ]]
+ if ( not level ) then
+ level = 1;
+ end
+
+ local listFrame = _G["L_DropDownList"..level];
+ local index = listFrame and (listFrame.numButtons + 1) or 1;
+ local width;
+
+ --UIDropDownMenuDelegate:SetAttribute("createframes-level", level);
+ --UIDropDownMenuDelegate:SetAttribute("createframes-index", index);
+ --UIDropDownMenuDelegate:SetAttribute("createframes", true);
+
+ listFrame = listFrame or _G["L_DropDownList"..level];
+ local listFrameName = listFrame:GetName();
+
+ -- Set the number of buttons in the listframe
+ listFrame.numButtons = index;
+
+ local button = _G[listFrameName.."Button"..index];
+ local normalText = _G[button:GetName().."NormalText"];
+ local icon = _G[button:GetName().."Icon"];
+ -- This button is used to capture the mouse OnEnter/OnLeave events if the dropdown button is disabled, since a disabled button doesn't receive any events
+ -- This is used specifically for drop down menu time outs
+ local invisibleButton = _G[button:GetName().."InvisibleButton"];
+
+ -- Default settings
+ button:SetDisabledTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
+ invisibleButton:Hide();
+ button:Enable();
+
+ -- If not clickable then disable the button and set it white
+ if ( info.notClickable ) then
+ info.disabled = true;
+ button:SetDisabledTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
+ end
+
+ -- Set the text color and disable it if its a title
+ if ( info.isTitle ) then
+ info.disabled = true;
+ button:SetDisabledTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
+ end
+
+ -- Disable the button if disabled and turn off the color code
+ if ( info.disabled ) then
+ button:Disable();
+ invisibleButton:Show();
+ info.colorCode = nil;
+ end
+
+ -- If there is a color for a disabled line, set it
+ if( info.disablecolor ) then
+ info.colorCode = info.disablecolor;
+ end
+
+ -- Configure button
+ if ( info.text ) then
+ -- look for inline color code this is only if the button is enabled
+ if ( info.colorCode ) then
+ button:SetText(info.colorCode..info.text.."|r");
+ else
+ button:SetText(info.text);
+ end
+
+ -- Set icon
+ if ( info.icon ) then
+ icon:SetTexture(info.icon);
+ if ( info.tCoordLeft ) then
+ icon:SetTexCoord(info.tCoordLeft, info.tCoordRight, info.tCoordTop, info.tCoordBottom);
+ else
+ icon:SetTexCoord(0, 1, 0, 1);
+ end
+ icon:Show();
+ else
+ icon:Hide();
+ end
+ else
+ button:SetText("");
+ icon:Hide();
+ end
+
+ button.iconOnly = nil;
+ button.icon = nil;
+ button.iconInfo = nil;
+
+ if (info.iconInfo) then
+ icon.tFitDropDownSizeX = info.iconInfo.tFitDropDownSizeX;
+ else
+ icon.tFitDropDownSizeX = nil;
+ end
+ if (info.iconOnly and info.icon) then
+ button.iconOnly = true;
+ button.icon = info.icon;
+ button.iconInfo = info.iconInfo;
+
+ L_UIDropDownMenu_SetIconImage(icon, info.icon, info.iconInfo);
+ icon:ClearAllPoints();
+ icon:SetPoint("LEFT");
+ end
+
+ -- Pass through attributes
+ button.func = info.func;
+ button.owner = info.owner;
+ button.hasOpacity = info.hasOpacity;
+ button.opacity = info.opacity;
+ button.opacityFunc = info.opacityFunc;
+ button.cancelFunc = info.cancelFunc;
+ button.swatchFunc = info.swatchFunc;
+ button.keepShownOnClick = info.keepShownOnClick;
+ button.tooltipTitle = info.tooltipTitle;
+ button.tooltipText = info.tooltipText;
+ button.arg1 = info.arg1;
+ button.arg2 = info.arg2;
+ button.hasArrow = info.hasArrow;
+ button.hasColorSwatch = info.hasColorSwatch;
+ button.notCheckable = info.notCheckable;
+ button.menuList = info.menuList;
+ button.tooltipWhileDisabled = info.tooltipWhileDisabled;
+ button.tooltipOnButton = info.tooltipOnButton;
+ button.noClickSound = info.noClickSound;
+ button.padding = info.padding;
+
+ if ( info.value ) then
+ button.value = info.value;
+ elseif ( info.text ) then
+ button.value = info.text;
+ else
+ button.value = nil;
+ end
+
+ -- Show the expand arrow if it has one
+ if ( info.hasArrow ) then
+ _G[listFrameName.."Button"..index.."ExpandArrow"]:Show();
+ else
+ _G[listFrameName.."Button"..index.."ExpandArrow"]:Hide();
+ end
+ button.hasArrow = info.hasArrow;
+
+ -- If not checkable move everything over to the left to fill in the gap where the check would be
+ local xPos = 5;
+ local yPos = -((button:GetID() - 1) * L_UIDROPDOWNMENU_BUTTON_HEIGHT) - L_UIDROPDOWNMENU_BORDER_HEIGHT;
+ local displayInfo = normalText;
+ if (info.iconOnly) then
+ displayInfo = icon;
+ end
+
+ displayInfo:ClearAllPoints();
+ if ( info.notCheckable ) then
+ if ( info.justifyH and info.justifyH == "CENTER" ) then
+ displayInfo:SetPoint("CENTER", button, "CENTER", -7, 0);
+ else
+ displayInfo:SetPoint("LEFT", button, "LEFT", 0, 0);
+ end
+ xPos = xPos + 10;
+
+ else
+ xPos = xPos + 12;
+ displayInfo:SetPoint("LEFT", button, "LEFT", 20, 0);
+ end
+
+ -- Adjust offset if displayMode is menu
+ local frame = L_UIDROPDOWNMENU_OPEN_MENU;
+ if ( frame and frame.displayMode == "MENU" ) then
+ if ( not info.notCheckable ) then
+ xPos = xPos - 6;
+ end
+ end
+
+ -- If no open frame then set the frame to the currently initialized frame
+ frame = frame or L_UIDROPDOWNMENU_INIT_MENU;
+
+ if ( info.leftPadding ) then
+ xPos = xPos + info.leftPadding;
+ end
+ button:SetPoint("TOPLEFT", button:GetParent(), "TOPLEFT", xPos, yPos);
+
+ -- See if button is selected by id or name
+ if ( frame ) then
+ if ( L_UIDropDownMenu_GetSelectedName(frame) ) then
+ if ( button:GetText() == L_UIDropDownMenu_GetSelectedName(frame) ) then
+ info.checked = 1;
+ end
+ elseif ( L_UIDropDownMenu_GetSelectedID(frame) ) then
+ if ( button:GetID() == L_UIDropDownMenu_GetSelectedID(frame) ) then
+ info.checked = 1;
+ end
+ elseif ( L_UIDropDownMenu_GetSelectedValue(frame) ) then
+ if ( button.value == L_UIDropDownMenu_GetSelectedValue(frame) ) then
+ info.checked = 1;
+ end
+ end
+ end
+
+
+ if not info.notCheckable then
+ if ( info.disabled ) then
+ _G[listFrameName.."Button"..index.."Check"]:SetDesaturated(true);
+ _G[listFrameName.."Button"..index.."Check"]:SetAlpha(0.5);
+ else
+ _G[listFrameName.."Button"..index.."Check"]:SetDesaturated(false);
+ _G[listFrameName.."Button"..index.."Check"]:SetAlpha(1);
+ end
+
+ -- Checked can be a function now
+ local checked = info.checked;
+ if ( type(checked) == "function" ) then
+ checked = checked(button);
+ end
+
+ -- Show the check if checked
+ if ( checked ) then
+ button:LockHighlight();
+ _G[listFrameName.."Button"..index.."Check"]:Show();
+ else
+ button:UnlockHighlight();
+ _G[listFrameName.."Button"..index.."Check"]:Hide();
+ end
+ else
+ _G[listFrameName.."Button"..index.."Check"]:Hide();
+ end
+ button.checked = info.checked;
+
+ -- If has a colorswatch, show it and vertex color it
+ local colorSwatch = _G[listFrameName.."Button"..index.."ColorSwatch"];
+ if ( info.hasColorSwatch ) then
+ _G["L_DropDownList"..level.."Button"..index.."ColorSwatch".."NormalTexture"]:SetVertexColor(info.r, info.g, info.b);
+ button.r = info.r;
+ button.g = info.g;
+ button.b = info.b;
+ colorSwatch:Show();
+ else
+ colorSwatch:Hide();
+ end
+
+ width = max(L_UIDropDownMenu_GetButtonWidth(button), info.minWidth or 0);
+ --Set maximum button width
+ if ( width > listFrame.maxWidth ) then
+ listFrame.maxWidth = width;
+ end
+
+ -- Set the height of the listframe
+ listFrame:SetHeight((index * L_UIDROPDOWNMENU_BUTTON_HEIGHT) + (L_UIDROPDOWNMENU_BORDER_HEIGHT * 2));
+
+ button:Show();
+end
+
+function L_UIDropDownMenu_GetMaxButtonWidth(self)
+ local maxWidth = 0;
+ for i=1, self.numButtons do
+ local button = _G[self:GetName().."Button"..i];
+ if ( button:IsShown() ) then
+ local width = L_UIDropDownMenu_GetButtonWidth(button);
+ if ( width > maxWidth ) then
+ maxWidth = width;
+ end
+ end
+ end
+ return maxWidth;
+end
+
+function L_UIDropDownMenu_GetButtonWidth(button)
+ local width;
+ local buttonName = button:GetName();
+ local icon = _G[buttonName.."Icon"];
+ local normalText = _G[buttonName.."NormalText"];
+
+ if ( button.iconOnly and icon ) then
+ width = icon:GetWidth();
+ elseif ( normalText and normalText:GetText() ) then
+ width = normalText:GetWidth() + 40;
+
+ if ( button.icon ) then
+ -- Add padding for the icon
+ width = width + 10;
+ end
+ else
+ return 0;
+ end
+
+ -- Add padding if has and expand arrow or color swatch
+ if ( button.hasArrow or button.hasColorSwatch ) then
+ width = width + 10;
+ end
+ if ( button.notCheckable ) then
+ width = width - 30;
+ end
+ if ( button.padding ) then
+ width = width + button.padding;
+ end
+
+ return width;
+end
+
+function L_UIDropDownMenu_Refresh(frame, useValue, dropdownLevel)
+ local button, checked, checkImage, normalText, width;
+ local maxWidth = 0;
+ local somethingChecked = nil;
+ if ( not dropdownLevel ) then
+ dropdownLevel = L_UIDROPDOWNMENU_MENU_LEVEL;
+ end
+
+ local listFrame = _G["L_DropDownList"..dropdownLevel];
+ listFrame.numButtons = listFrame.numButtons or 0;
+ -- Just redraws the existing menu
+ for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do
+ button = _G["L_DropDownList"..dropdownLevel.."Button"..i];
+ checked = nil;
+
+ if(i <= listFrame.numButtons) then
+ -- See if checked or not
+ if ( L_UIDropDownMenu_GetSelectedName(frame) ) then
+ if ( button:GetText() == L_UIDropDownMenu_GetSelectedName(frame) ) then
+ checked = 1;
+ end
+ elseif ( L_UIDropDownMenu_GetSelectedID(frame) ) then
+ if ( button:GetID() == L_UIDropDownMenu_GetSelectedID(frame) ) then
+ checked = 1;
+ end
+ elseif ( L_UIDropDownMenu_GetSelectedValue(frame) ) then
+ if ( button.value == L_UIDropDownMenu_GetSelectedValue(frame) ) then
+ checked = 1;
+ end
+ end
+ end
+ if (button.checked and type(button.checked) == "function") then
+ checked = button.checked(button);
+ end
+
+ if not button.notCheckable and button:IsShown() then
+ -- If checked show check image
+ checkImage = _G["L_DropDownList"..dropdownLevel.."Button"..i.."Check"];
+ if ( checked ) then
+ somethingChecked = true;
+ local icon = _G[frame:GetName().."Icon"];
+ if (button.iconOnly and icon and button.icon) then
+ L_UIDropDownMenu_SetIconImage(icon, button.icon, button.iconInfo);
+ elseif ( useValue ) then
+ L_UIDropDownMenu_SetText(frame, button.value);
+ icon:Hide();
+ else
+ L_UIDropDownMenu_SetText(frame, button:GetText());
+ icon:Hide();
+ end
+ button:LockHighlight();
+ checkImage:Show();
+ else
+ button:UnlockHighlight();
+ checkImage:Hide();
+ end
+ end
+
+ if ( button:IsShown() ) then
+ width = L_UIDropDownMenu_GetButtonWidth(button);
+ if ( width > maxWidth ) then
+ maxWidth = width;
+ end
+ end
+ end
+ if(somethingChecked == nil) then
+ L_UIDropDownMenu_SetText(frame, VIDEO_QUALITY_LABEL6);
+ end
+ if (not frame.noResize) then
+ for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do
+ button = _G["L_DropDownList"..dropdownLevel.."Button"..i];
+ button:SetWidth(maxWidth);
+ end
+ L_UIDropDownMenu_RefreshDropDownSize(_G["L_DropDownList"..dropdownLevel]);
+ end
+end
+
+function L_UIDropDownMenu_RefreshAll(frame, useValue)
+ for dropdownLevel = L_UIDROPDOWNMENU_MENU_LEVEL, 2, -1 do
+ local listFrame = _G["L_DropDownList"..dropdownLevel];
+ if ( listFrame:IsShown() ) then
+ L_UIDropDownMenu_Refresh(frame, nil, dropdownLevel);
+ end
+ end
+ -- useValue is the text on the dropdown, only needs to be set once
+ L_UIDropDownMenu_Refresh(frame, useValue, 1);
+end
+
+function L_UIDropDownMenu_SetIconImage(icon, texture, info)
+ icon:SetTexture(texture);
+ if ( info.tCoordLeft ) then
+ icon:SetTexCoord(info.tCoordLeft, info.tCoordRight, info.tCoordTop, info.tCoordBottom);
+ else
+ icon:SetTexCoord(0, 1, 0, 1);
+ end
+ if ( info.tSizeX ) then
+ icon:SetWidth(info.tSizeX);
+ else
+ icon:SetWidth(16);
+ end
+ if ( info.tSizeY ) then
+ icon:SetHeight(info.tSizeY);
+ else
+ icon:SetHeight(16);
+ end
+ icon:Show();
+end
+
+function L_UIDropDownMenu_SetSelectedName(frame, name, useValue)
+ frame.selectedName = name;
+ frame.selectedID = nil;
+ frame.selectedValue = nil;
+ L_UIDropDownMenu_Refresh(frame, useValue);
+end
+
+function L_UIDropDownMenu_SetSelectedValue(frame, value, useValue)
+ -- useValue will set the value as the text, not the name
+ frame.selectedName = nil;
+ frame.selectedID = nil;
+ frame.selectedValue = value;
+ L_UIDropDownMenu_Refresh(frame, useValue);
+end
+
+function L_UIDropDownMenu_SetSelectedID(frame, id, useValue)
+ frame.selectedID = id;
+ frame.selectedName = nil;
+ frame.selectedValue = nil;
+ L_UIDropDownMenu_Refresh(frame, useValue);
+end
+
+function L_UIDropDownMenu_GetSelectedName(frame)
+ return frame.selectedName;
+end
+
+function L_UIDropDownMenu_GetSelectedID(frame)
+ if ( frame.selectedID ) then
+ return frame.selectedID;
+ else
+ -- If no explicit selectedID then try to send the id of a selected value or name
+ local button;
+ for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do
+ button = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i];
+ -- See if checked or not
+ if ( L_UIDropDownMenu_GetSelectedName(frame) ) then
+ if ( button:GetText() == L_UIDropDownMenu_GetSelectedName(frame) ) then
+ return i;
+ end
+ elseif ( L_UIDropDownMenu_GetSelectedValue(frame) ) then
+ if ( button.value == L_UIDropDownMenu_GetSelectedValue(frame) ) then
+ return i;
+ end
+ end
+ end
+ end
+end
+
+function L_UIDropDownMenu_GetSelectedValue(frame)
+ return frame.selectedValue;
+end
+
+function L_UIDropDownMenuButton_OnClick()
+ local checked = this.checked;
+ if ( type (checked) == "function" ) then
+ checked = checked(this);
+ end
+
+
+ if ( this.keepShownOnClick ) then
+ if not this.notCheckable then
+ if ( checked ) then
+ _G[this:GetName().."Check"]:Hide();
+ checked = false;
+ else
+ _G[this:GetName().."Check"]:Show();
+ checked = true;
+ end
+ end
+ else
+ this:GetParent():Hide();
+ end
+
+ if ( type (this.checked) ~= "function" ) then
+ this.checked = checked;
+ end
+
+ -- saving this here because func might use a dropdown, changing this self's attributes
+ local playSound = true;
+ if ( this.noClickSound ) then
+ playSound = false;
+ end
+
+ local func = this.func;
+ if ( func ) then
+ func(this.arg1, this.arg2, checked);
+ else
+ return;
+ end
+
+ if ( playSound ) then
+ PlaySound("UChatScrollButton");
+ end
+end
+
+function L_HideDropDownMenu(level)
+ local listFrame = _G["L_DropDownList"..level];
+ listFrame:Hide();
+end
+
+function L_ToggleDropDownMenu(level, value, dropDownFrame, anchorName, xOffset, yOffset, menuList, button, autoHideDelay)
+ if ( not level ) then
+ level = 1;
+ end
+
+ --UIDropDownMenuDelegate:SetAttribute("createframes-level", level);
+ --UIDropDownMenuDelegate:SetAttribute("createframes-index", 0);
+ --UIDropDownMenuDelegate:SetAttribute("createframes", true);
+ L_UIDROPDOWNMENU_MENU_LEVEL = level;
+ L_UIDROPDOWNMENU_MENU_VALUE = value;
+ local listFrame = _G["L_DropDownList"..level];
+ local listFrameName = "L_DropDownList"..level;
+ local tempFrame;
+ local point, relativePoint, relativeTo;
+ if ( not dropDownFrame ) then
+ tempFrame = button:GetParent();
+ else
+ tempFrame = dropDownFrame;
+ end
+ if ( listFrame:IsShown() and (L_UIDROPDOWNMENU_OPEN_MENU == tempFrame) ) then
+ listFrame:Hide();
+ else
+ -- Set the dropdownframe scale
+ local uiScale;
+ local uiParentScale = UIParent:GetScale();
+ if ( GetCVar("useUIScale") == "1" ) then
+ uiScale = tonumber(GetCVar("uiscale"));
+ if ( uiParentScale < uiScale ) then
+ uiScale = uiParentScale;
+ end
+ else
+ uiScale = uiParentScale;
+ end
+ listFrame:SetScale(uiScale);
+
+ -- Hide the listframe anyways since it is redrawn OnShow()
+ listFrame:Hide();
+
+ -- Frame to anchor the dropdown menu to
+ local anchorFrame;
+
+ -- Display stuff
+ -- Level specific stuff
+ if ( level == 1 ) then
+ L_UIDROPDOWNMENU_OPEN_MENU = dropDownFrame;
+ listFrame:ClearAllPoints();
+ -- If there's no specified anchorName then use left side of the dropdown menu
+ if ( not anchorName ) then
+ -- See if the anchor was set manually using setanchor
+ if ( dropDownFrame.xOffset ) then
+ xOffset = dropDownFrame.xOffset;
+ end
+ if ( dropDownFrame.yOffset ) then
+ yOffset = dropDownFrame.yOffset;
+ end
+ if ( dropDownFrame.point ) then
+ point = dropDownFrame.point;
+ end
+ if ( dropDownFrame.relativeTo ) then
+ relativeTo = dropDownFrame.relativeTo;
+ else
+ relativeTo = L_UIDROPDOWNMENU_OPEN_MENU:GetName().."Left";
+ end
+ if ( dropDownFrame.relativePoint ) then
+ relativePoint = dropDownFrame.relativePoint;
+ end
+ elseif ( anchorName == "cursor" ) then
+ relativeTo = nil;
+ local cursorX, cursorY = GetCursorPosition();
+ cursorX = cursorX/uiScale;
+ cursorY = cursorY/uiScale;
+
+ if ( not xOffset ) then
+ xOffset = 0;
+ end
+ if ( not yOffset ) then
+ yOffset = 0;
+ end
+ xOffset = cursorX + xOffset;
+ yOffset = cursorY + yOffset;
+ else
+ -- See if the anchor was set manually using setanchor
+ if ( dropDownFrame.xOffset ) then
+ xOffset = dropDownFrame.xOffset;
+ end
+ if ( dropDownFrame.yOffset ) then
+ yOffset = dropDownFrame.yOffset;
+ end
+ if ( dropDownFrame.point ) then
+ point = dropDownFrame.point;
+ end
+ if ( dropDownFrame.relativeTo ) then
+ relativeTo = dropDownFrame.relativeTo;
+ else
+ relativeTo = anchorName;
+ end
+ if ( dropDownFrame.relativePoint ) then
+ relativePoint = dropDownFrame.relativePoint;
+ end
+ end
+ if ( not xOffset or not yOffset ) then
+ xOffset = 8;
+ yOffset = 22;
+ end
+ if ( not point ) then
+ point = "TOPLEFT";
+ end
+ if ( not relativePoint ) then
+ relativePoint = "BOTTOMLEFT";
+ end
+ listFrame:SetPoint(point, relativeTo, relativePoint, xOffset, yOffset);
+ else
+ if ( not dropDownFrame ) then
+ dropDownFrame = L_UIDROPDOWNMENU_OPEN_MENU;
+ end
+ listFrame:ClearAllPoints();
+ -- If this is a dropdown button, not the arrow anchor it to itself
+ if ( strsub(button:GetParent():GetName(), 0,14) == "L_DropDownList" and strlen(button:GetParent():GetName()) == 15 ) then
+ anchorFrame = button;
+ else
+ anchorFrame = button:GetParent();
+ end
+ point = "TOPLEFT";
+ relativePoint = "TOPRIGHT";
+ listFrame:SetPoint(point, anchorFrame, relativePoint, 0, 0);
+ end
+
+ -- Change list box appearance depending on display mode
+ if ( dropDownFrame and dropDownFrame.displayMode == "MENU" ) then
+ _G[listFrameName.."Backdrop"]:Hide();
+ _G[listFrameName.."MenuBackdrop"]:Show();
+ else
+ _G[listFrameName.."Backdrop"]:Show();
+ _G[listFrameName.."MenuBackdrop"]:Hide();
+ end
+ dropDownFrame.menuList = menuList;
+ L_UIDropDownMenu_Initialize(dropDownFrame, dropDownFrame.initialize, nil, level, menuList);
+ -- If no items in the drop down don't show it
+ if ( listFrame.numButtons == 0 ) then
+ return;
+ end
+
+ -- Check to see if the dropdownlist is off the screen, if it is anchor it to the top of the dropdown button
+ listFrame:Show();
+ -- Hack since GetCenter() is returning coords relative to 1024x768
+ local x, y = listFrame:GetCenter();
+ -- Hack will fix this in next revision of dropdowns
+ if ( not x or not y ) then
+ listFrame:Hide();
+ return;
+ end
+
+ listFrame.onHide = dropDownFrame.onHide;
+
+
+ -- We just move level 1 enough to keep it on the screen. We don't necessarily change the anchors.
+ if ( level == 1 ) then
+ local offLeft = listFrame:GetLeft()/uiScale;
+ local offRight = (GetScreenWidth() - listFrame:GetRight())/uiScale;
+ local offTop = (GetScreenHeight() - listFrame:GetTop())/uiScale;
+ local offBottom = listFrame:GetBottom()/uiScale;
+
+ local xAddOffset, yAddOffset = 0, 0;
+ if ( offLeft < 0 ) then
+ xAddOffset = -offLeft;
+ elseif ( offRight < 0 ) then
+ xAddOffset = offRight;
+ end
+
+ if ( offTop < 0 ) then
+ yAddOffset = offTop;
+ elseif ( offBottom < 0 ) then
+ yAddOffset = -offBottom;
+ end
+
+ listFrame:ClearAllPoints();
+ if ( anchorName == "cursor" ) then
+ listFrame:SetPoint(point, relativeTo, relativePoint, xOffset + xAddOffset, yOffset + yAddOffset);
+ else
+ listFrame:SetPoint(point, relativeTo, relativePoint, xOffset + xAddOffset, yOffset + yAddOffset);
+ end
+ else
+ -- Determine whether the menu is off the screen or not
+ local offscreenY, offscreenX;
+ if ( (y - listFrame:GetHeight()/2) < 0 ) then
+ offscreenY = 1;
+ end
+ if ( listFrame:GetRight() > GetScreenWidth() ) then
+ offscreenX = 1;
+ end
+ if ( offscreenY and offscreenX ) then
+ point = gsub(point, "TOP(.*)", "BOTTOM%1");
+ point = gsub(point, "(.*)LEFT", "%1RIGHT");
+ relativePoint = gsub(relativePoint, "TOP(.*)", "BOTTOM%1");
+ relativePoint = gsub(relativePoint, "(.*)RIGHT", "%1LEFT");
+ xOffset = -11;
+ yOffset = -14;
+ elseif ( offscreenY ) then
+ point = gsub(point, "TOP(.*)", "BOTTOM%1");
+ relativePoint = gsub(relativePoint, "TOP(.*)", "BOTTOM%1");
+ xOffset = 0;
+ yOffset = -14;
+ elseif ( offscreenX ) then
+ point = gsub(point, "(.*)LEFT", "%1RIGHT");
+ relativePoint = gsub(relativePoint, "(.*)RIGHT", "%1LEFT");
+ xOffset = -11;
+ yOffset = 14;
+ else
+ xOffset = 0;
+ yOffset = 14;
+ end
+
+ listFrame:ClearAllPoints();
+ listFrame.parentLevel = tonumber(strmatch(anchorFrame:GetName(), "L_DropDownList(%d+)"));
+ listFrame.parentID = anchorFrame:GetID();
+ listFrame:SetPoint(point, anchorFrame, relativePoint, xOffset, yOffset);
+ end
+
+ if ( autoHideDelay and tonumber(autoHideDelay)) then
+ listFrame.showTimer = autoHideDelay;
+ listFrame.isCounting = 1;
+ end
+ end
+end
+
+function L_CloseDropDownMenus(level)
+ if ( not level ) then
+ level = 1;
+ end
+ for i=level, L_UIDROPDOWNMENU_MAXLEVELS do
+ _G["L_DropDownList"..i]:Hide();
+ end
+end
+
+function L_UIDropDownMenu_OnHide(self)
+ local id = self:GetID()
+ if ( self.onHide ) then
+ self.onHide(id+1);
+ self.onHide = nil;
+ end
+ L_CloseDropDownMenus(id+1);
+ L_OPEN_DROPDOWNMENUS[id] = nil;
+ if (id == 1) then
+ L_UIDROPDOWNMENU_OPEN_MENU = nil;
+ end
+end
+
+function L_UIDropDownMenu_SetWidth(frame, width, padding)
+ _G[frame:GetName().."Middle"]:SetWidth(width);
+ local defaultPadding = 25;
+ if ( padding ) then
+ frame:SetWidth(width + padding);
+ else
+ frame:SetWidth(width + defaultPadding + defaultPadding);
+ end
+ if ( padding ) then
+ _G[frame:GetName().."Text"]:SetWidth(width);
+ else
+ _G[frame:GetName().."Text"]:SetWidth(width - defaultPadding);
+ end
+ frame.noResize = 1;
+end
+
+function L_UIDropDownMenu_SetButtonWidth(frame, width)
+ if ( width == "TEXT" ) then
+ width = _G[frame:GetName().."Text"]:GetWidth();
+ end
+
+ _G[frame:GetName().."Button"]:SetWidth(width);
+ frame.noResize = 1;
+end
+
+function L_UIDropDownMenu_SetText(frame, text)
+ local filterText = _G[frame:GetName().."Text"];
+ filterText:SetText(text);
+end
+
+function L_UIDropDownMenu_GetText(frame)
+ local filterText = _G[frame:GetName().."Text"];
+ return filterText:GetText();
+end
+
+function L_UIDropDownMenu_ClearAll(frame)
+ -- Previous code refreshed the menu quite often and was a performance bottleneck
+ frame.selectedID = nil;
+ frame.selectedName = nil;
+ frame.selectedValue = nil;
+ L_UIDropDownMenu_SetText(frame, "");
+
+ local button, checkImage;
+ for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do
+ button = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i];
+ button:UnlockHighlight();
+
+ checkImage = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i.."Check"];
+ checkImage:Hide();
+ end
+end
+
+function L_UIDropDownMenu_JustifyText(frame, justification)
+ local text = _G[frame:GetName().."Text"];
+ text:ClearAllPoints();
+ if ( justification == "LEFT" ) then
+ text:SetPoint("LEFT", frame:GetName().."Left", "LEFT", 27, 2);
+ text:SetJustifyH("LEFT");
+ elseif ( justification == "RIGHT" ) then
+ text:SetPoint("RIGHT", frame:GetName().."Right", "RIGHT", -43, 2);
+ text:SetJustifyH("RIGHT");
+ elseif ( justification == "CENTER" ) then
+ text:SetPoint("CENTER", frame:GetName().."Middle", "CENTER", -5, 2);
+ text:SetJustifyH("CENTER");
+ end
+end
+
+function L_UIDropDownMenu_SetAnchor(dropdown, xOffset, yOffset, point, relativeTo, relativePoint)
+ dropdown.xOffset = xOffset;
+ dropdown.yOffset = yOffset;
+ dropdown.point = point;
+ dropdown.relativeTo = relativeTo;
+ dropdown.relativePoint = relativePoint;
+end
+
+function L_UIDropDownMenu_GetCurrentDropDown()
+ if ( L_UIDROPDOWNMENU_OPEN_MENU ) then
+ return L_UIDROPDOWNMENU_OPEN_MENU;
+ elseif ( L_UIDROPDOWNMENU_INIT_MENU ) then
+ return L_UIDROPDOWNMENU_INIT_MENU;
+ end
+end
+
+function L_UIDropDownMenuButton_GetChecked(self)
+ return _G[self:GetName().."Check"]:IsShown();
+end
+
+function L_UIDropDownMenuButton_GetName(self)
+ return _G[self:GetName().."NormalText"]:GetText();
+end
+
+function L_UIDropDownMenuButton_OpenColorPicker(self, button)
+ securecall("CloseMenus");
+ if ( not button ) then
+ button = self;
+ end
+ L_UIDROPDOWNMENU_MENU_VALUE = button.value;
+ OpenColorPicker(button); --remains shared through color picker frame
+end
+
+function L_UIDropDownMenu_DisableButton(level, id)
+ _G["L_DropDownList"..level.."Button"..id]:Disable();
+end
+
+function L_UIDropDownMenu_EnableButton(level, id)
+ _G["L_DropDownList"..level.."Button"..id]:Enable();
+end
+
+function L_UIDropDownMenu_SetButtonText(level, id, text, colorCode)
+ local button = _G["L_DropDownList"..level.."Button"..id];
+ if ( colorCode) then
+ button:SetText(colorCode..text.."|r");
+ else
+ button:SetText(text);
+ end
+end
+
+function L_UIDropDownMenu_SetButtonNotClickable(level, id)
+ _G["L_DropDownList"..level.."Button"..id]:SetDisabledFontObject(GameFontHighlightSmallLeft);
+end
+
+function L_UIDropDownMenu_SetButtonClickable(level, id)
+ _G["L_DropDownList"..level.."Button"..id]:SetDisabledFontObject(GameFontDisableSmallLeft);
+end
+
+function L_UIDropDownMenu_DisableDropDown(dropDown)
+ local label = _G[dropDown:GetName().."Label"];
+ if ( label ) then
+ label:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
+ end
+ _G[dropDown:GetName().."Text"]:SetVertexColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
+ _G[dropDown:GetName().."Button"]:Disable();
+ dropDown.isDisabled = 1;
+end
+
+function L_UIDropDownMenu_EnableDropDown(dropDown)
+ local label = _G[dropDown:GetName().."Label"];
+ if ( label ) then
+ label:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
+ end
+ _G[dropDown:GetName().."Text"]:SetVertexColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
+ _G[dropDown:GetName().."Button"]:Enable();
+ dropDown.isDisabled = nil;
+end
+
+function L_UIDropDownMenu_IsEnabled(dropDown)
+ return not dropDown.isDisabled;
+end
+
+function L_UIDropDownMenu_GetValue(id)
+ --Only works if the dropdown has just been initialized, lame, I know =(
+ local button = _G["L_DropDownList1Button"..id];
+ if ( button ) then
+ return _G["L_DropDownList1Button"..id].value;
+ else
+ return nil;
+ end
+end
+
+function OpenColorPicker(info) --ColorPicker stuff not changed
+ ColorPickerFrame.func = info.swatchFunc;
+ ColorPickerFrame.hasOpacity = info.hasOpacity;
+ ColorPickerFrame.opacityFunc = info.opacityFunc;
+ ColorPickerFrame.opacity = info.opacity;
+ ColorPickerFrame.previousValues = {r = info.r, g = info.g, b = info.b, opacity = info.opacity};
+ ColorPickerFrame.cancelFunc = info.cancelFunc;
+ ColorPickerFrame.extraInfo = info.extraInfo;
+ -- This must come last, since it triggers a call to ColorPickerFrame.func()
+ ColorPickerFrame:SetColorRGB(info.r, info.g, info.b);
+ ShowUIPanel(ColorPickerFrame);
+end
+
+function ColorPicker_GetPreviousValues()
+ return ColorPickerFrame.previousValues.r, ColorPickerFrame.previousValues.g, ColorPickerFrame.previousValues.b;
+end
diff --git a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.xml b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.xml
new file mode 100644
index 0000000..c034029
--- /dev/null
+++ b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenuTemplates.xml b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenuTemplates.xml
new file mode 100644
index 0000000..32d1877
--- /dev/null
+++ b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenuTemplates.xml
@@ -0,0 +1,424 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b);
+ this:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:Hide();
+
+
+ L_UIDropDownMenu_StopCounting(this, arg1);
+
+
+ L_UIDropDownMenu_StartCounting(this, arg1);
+
+
+ L_UIDropDownMenu_OnUpdate(this, arg1);
+
+
+ for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do
+ if (not this.noResize) then
+ getglobal(this:GetName().."Button"..i):SetWidth(this.maxWidth);
+ end
+ end
+ if (not this.noResize) then
+ this:SetWidth(this.maxWidth+25);
+ end
+ this.showTimer = nil;
+ if ( this:GetID() > 1 ) then
+ this.parent = getglobal("L_DropDownList"..(this:GetID() - 1));
+ end
+
+
+ L_UIDropDownMenu_OnHide(this);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ local parent = this:GetParent();
+ local myscript = parent:GetScript("OnEnter");
+ if(myscript ~= nil) then
+ myscript(parent);
+ end
+
+
+ local parent = this:GetParent();
+ local myscript = parent:GetScript("OnLeave");
+ if(myscript ~= nil) then
+ myscript(parent);
+ end
+
+
+ L_ToggleDropDownMenu(nil, nil, this:GetParent());
+ PlaySound(PlaySoundKitID and "igMainMenuOptionCheckBoxOn" or SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ L_CloseDropDownMenus();
+
+
+
+
diff --git a/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua b/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua
new file mode 100644
index 0000000..60c2f2a
--- /dev/null
+++ b/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua
@@ -0,0 +1,939 @@
+---
+--- check for an already loaded old WhoLib
+---
+
+if WhoLibByALeX or WhoLib then
+ -- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
+ error("an other WhoLib is already running - disable them first!\n")
+ return
+end -- if
+
+---
+--- check version
+---
+
+assert(LibStub, "LibWho-2.0 requires LibStub")
+
+
+local major_version = 'LibWho-2.0'
+local minor_version = tonumber("154") or 99999
+
+local lib = LibStub:NewLibrary(major_version, minor_version)
+
+
+if not lib then
+ return -- already loaded and no upgrade necessary
+end
+
+lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
+local callbacks = lib.callbacks
+
+local am = {}
+local om = getmetatable(lib)
+if om then
+ for k, v in pairs(om) do am[k] = v end
+end
+am.__tostring = function() return major_version end
+setmetatable(lib, am)
+
+local function dbgfunc(...) if lib.Debug then print(unpack(arg)) end end
+local function NOP() return end
+local dbg = NOP
+
+---
+--- initalize base
+---
+
+if type(lib['hooked']) ~= 'table' then
+ lib['hooked'] = {}
+end -- if
+
+if type(lib['hook']) ~= 'table' then
+ lib['hook'] = {}
+end -- if
+
+if type(lib['events']) ~= 'table' then
+ lib['events'] = {}
+end -- if
+
+if type(lib['embeds']) ~= 'table' then
+ lib['embeds'] = {}
+end -- if
+
+if type(lib['frame']) ~= 'table' then
+ lib['frame'] = CreateFrame('Frame', major_version);
+end -- if
+lib['frame']:Hide()
+
+lib.Queue = {[1]={}, [2]={}, [3]={}}
+lib.WhoInProgress = false
+lib.Result = nil
+lib.Args = nil
+lib.Total = nil
+lib.Quiet = nil
+lib.Debug = false
+lib.Cache = {}
+lib.CacheQueue = {}
+lib.SetWhoToUIState = false
+
+
+lib.MinInterval = 2.5
+lib.MaxInterval = 10
+
+---
+--- locale
+---
+
+if (GetLocale() == "ruRU") then
+ lib.L = {
+ ['console_queued'] = 'Добавлено в очередь "/who %s"',
+ ['console_query'] = 'Результат "/who %s"',
+ ['gui_wait'] = '- Пожалуйста подождите -',
+ }
+else
+ -- enUS is the default
+ lib.L = {
+ ['console_queued'] = 'Added "/who %s" to queue',
+ ['console_query'] = 'Result of "/who %s"',
+ ['gui_wait'] = '- Please Wait -',
+ }
+end -- if
+
+
+---
+--- external functions/constants
+---
+
+lib['external'] = {
+ 'WHOLIB_QUEUE_USER',
+ 'WHOLIB_QUEUE_QUIET',
+ 'WHOLIB_QUEUE_SCANNING',
+ 'WHOLIB_FLAG_ALWAYS_CALLBACK',
+ 'Who',
+ 'UserInfo',
+ 'CachedUserInfo',
+ 'GetWhoLibDebug',
+ 'SetWhoLibDebug',
+-- 'RegisterWhoLibEvent',
+}
+
+-- queues
+lib['WHOLIB_QUEUE_USER'] = 1
+lib['WHOLIB_QUEUE_QUIET'] = 2
+lib['WHOLIB_QUEUE_SCANNING'] = 3
+
+
+
+local queue_all = {
+ [1] = 'WHOLIB_QUEUE_USER',
+ [2] = 'WHOLIB_QUEUE_QUIET',
+ [3] = 'WHOLIB_QUEUE_SCANNING',
+}
+
+local queue_quiet = {
+ [2] = 'WHOLIB_QUEUE_QUIET',
+ [3] = 'WHOLIB_QUEUE_SCANNING',
+}
+
+-- bit masks!
+lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
+
+function lib:Reset()
+ self.Queue = {[1]={}, [2]={}, [3]={}}
+ self.Cache = {}
+ self.CacheQueue = {}
+end
+
+function lib.Who(defhandler, query, opts)
+ local self, args, usage = lib, {}, 'Who(query, [opts])'
+
+ args.query = self:CheckArgument(usage, 'query', 'string', query)
+ opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
+ args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING)
+ args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
+ args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
+ -- now args - copied and verified from opts
+
+ if args.queue == self.WHOLIB_QUEUE_USER then
+ if WhoFrame:IsShown() then
+ self:GuiWho(args.query)
+ else
+ self:ConsoleWho(args.query)
+ end
+ else
+ self:AskWho(args)
+ end
+end
+
+function lib.UserInfo(defhandler, name, opts)
+ local self, args, usage = lib, {}, 'UserInfo(name, [opts])'
+ local now = time()
+
+ name = self:CheckArgument(usage, 'name', 'string', name)
+ if strlen(name) == 0 then return end
+
+ if string.find(name, "%-") then --[[dbg("ignoring xrealm: "..name)]] return end
+
+ args.name = self:CapitalizeInitial(name)
+ opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
+ args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING)
+ args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
+ args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5)
+ args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
+
+ -- now args - copied and verified from opts
+ local cachedName = self.Cache[args.name]
+
+ if(cachedName ~= nil)then
+ -- user is in cache
+ if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then
+ -- cache is valid and timeout is in range
+ --dbg('Info(' .. args.name ..') returned immedeatly')
+ if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then
+ self:RaiseCallback(args, cachedName.data)
+ return false
+ else
+ return self:DupAll(self:ReturnUserInfo(args.name))
+ end
+ elseif(cachedName.valid == false)then
+ -- query is already running (first try)
+ if(args.callback ~= nil)then
+ tinsert(cachedName.callback, args)
+ end
+ --dbg('Info(' .. args.name ..') returned cause it\'s already searching')
+ return nil
+ end
+ else
+ self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now }
+ end
+
+ local cachedName = self.Cache[args.name]
+
+ if(cachedName.inqueue)then
+ -- query is running!
+ if(args.callback ~= nil)then
+ tinsert(cachedName.callback, args)
+ end
+ dbg('Info(' .. args.name ..') returned cause it\'s already searching')
+ return nil
+ end
+ if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon
+ if args.name and strlen(args.name) > 0 then
+ local query = 'и-"' .. args.name .. '"'
+ cachedName.inqueue = true
+ if(args.callback ~= nil)then
+ tinsert(cachedName.callback, args)
+ end
+ self.CacheQueue[query] = args.name
+ dbg('Info(' .. args.name ..') added to queue')
+ self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
+ end
+ else
+ if args.name and strlen(args.name) > 0 then
+ local query = 'n-"' .. args.name .. '"'
+ cachedName.inqueue = true
+ if(args.callback ~= nil)then
+ tinsert(cachedName.callback, args)
+ end
+ self.CacheQueue[query] = args.name
+ dbg('Info(' .. args.name ..') added to queue')
+ self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
+ end
+ end
+ return nil
+end
+
+function lib.CachedUserInfo(_, name)
+ local self, usage = lib, 'CachedUserInfo(name)'
+
+ name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name))
+
+ if self.Cache[name] == nil then
+ return nil
+ else
+ return self:DupAll(self:ReturnUserInfo(name))
+ end
+end
+
+function lib.GetWhoLibDebug(_, mode)
+ return lib.Debug
+end
+
+function lib.SetWhoLibDebug(_, mode)
+ lib.Debug = mode
+ dbg = mode and dbgfunc or NOP
+end
+
+--function lib.RegisterWhoLibEvent(defhandler, event, callback, handler)
+-- local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])'
+--
+-- self:CheckPreset(usage, 'event', self.events, event)
+-- local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
+-- table.insert(self.events[event], {callback=callback, handler=handler})
+--end
+
+-- non-embedded externals
+
+function lib.Embed(_, handler)
+ local self, usage = lib, 'Embed(handler)'
+
+ self:CheckArgument(usage, 'handler', 'table', handler)
+
+ for _,name in pairs(self.external) do
+ handler[name] = self[name]
+ end -- do
+ self['embeds'][handler] = true
+
+ return handler
+end
+
+function lib.Library(_)
+ local self = lib
+
+ return self:Embed({})
+end
+
+---
+--- internal functions
+---
+
+function lib:AllQueuesEmpty()
+ local queueCount = getn(self.Queue[1]) + getn(self.Queue[2]) + getn(self.Queue[3]) + getn(self.CacheQueue)
+
+ -- Be sure that we have cleared the in-progress status
+ if self.WhoInProgress then
+ queueCount = queueCount + 1
+ end
+
+ return queueCount == 0
+end
+
+local queryInterval = 5
+
+function lib:GetQueryInterval() return queryInterval end
+
+function lib:AskWhoNextIn5sec()
+ if self.frame:IsShown() then return end
+
+ dbg("Waiting to send next who")
+ self.Timeout_time = queryInterval
+ self['frame']:Show()
+end
+
+function lib:CancelPendingWhoNext()
+ lib['frame']:Hide()
+end
+
+lib['frame']:SetScript("OnUpdate", function()
+ lib.Timeout_time = lib.Timeout_time - arg1
+ if lib.Timeout_time <= 0 then
+ lib['frame']:Hide()
+ lib:AskWhoNext()
+ end -- if
+end);
+
+
+-- queue scheduler
+local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
+local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
+
+-- allow for single queries from the user to get processed faster
+local lastInstantQuery = time()
+local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
+
+function lib:UpdateWeights()
+ local weightsum, sum, count = 0, 0, 0
+ for k,v in pairs(queue_weights) do
+ sum = sum + v
+ weightsum = weightsum + v * getn(self.Queue[k])
+ end
+
+ if weightsum == 0 then
+ for k,v in pairs(queue_weights) do queue_bounds[k] = v end
+ return
+ end
+
+ local adjust = sum / weightsum
+
+ for k,v in pairs(queue_bounds) do
+ queue_bounds[k] = queue_weights[k] * adjust * getn(self.Queue[k])
+ end
+end
+
+function lib:GetNextFromScheduler()
+ self:UpdateWeights()
+
+ -- Since an addon could just fill up the user q for instant processing
+ -- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL
+ -- and only try instant fulfilment if it will empty the user queue
+ if getn(self.Queue[1]) == 1 then
+ if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then
+ dbg("INSTANT")
+ lastInstantQuery = time()
+ return 1, self.Queue[1]
+ end
+ end
+
+ local n,i = math.random(),0
+ repeat
+ i=i+1
+ n = n - queue_bounds[i]
+ until i >= getn(self.Queue) or n <= 0
+
+ dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i]))
+
+ if getn(self.Queue[i]) > 0 then
+ dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i]))
+ return i, self.Queue[i]
+ else
+ dbg("Queues empty, waiting")
+ end
+end
+
+lib.queue_bounds = queue_bounds
+
+function lib:AskWhoNext()
+ if lib.frame:IsShown() then
+ dbg("Already waiting")
+ return
+ end
+
+ self:CancelPendingWhoNext()
+
+ if self.WhoInProgress then
+ -- if we had a who going, it didnt complete
+ dbg("TIMEOUT: "..self.Args.query)
+ local args = self.Args
+ self.Args = nil
+-- if args.info and self.CacheQueue[args.query] ~= nil then
+ dbg("Requeing "..args.query)
+ tinsert(self.Queue[args.queue], args)
+ if args.console_show ~= nil then
+ DEFAULT_CHAT_FRAME:AddMessage(string.format("Timeout on result of '%s' - retrying...", args.query), 1, 1, 0)
+ args.console_show = true
+ end
+-- end
+
+ if queryInterval < lib.MaxInterval then
+ queryInterval = queryInterval + 0.5
+ dbg("--Throttling down to 1 who per " .. queryInterval .. "s")
+ end
+ end
+
+
+ self.WhoInProgress = false
+
+ local v,k,args = nil
+ local kludge = 10
+ repeat
+ k, v = self:GetNextFromScheduler()
+ if not k then break end
+ if WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET then
+ break
+ end
+ if getn(v) > 0 then
+ args = tremove(v, 1)
+ break
+ end
+ kludge = kludge - 1
+ until kludge <= 0
+
+ if args then
+ self.WhoInProgress = true
+ self.Result = {}
+ self.Args = args
+ self.Total = -1
+ if(args.console_show == true)then
+ DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0)
+
+ end
+
+ if args.queue == self.WHOLIB_QUEUE_USER then
+ WhoFrameEditBox:SetText(args.query)
+ self.Quiet = false
+
+ if args.whotoui then
+ -- self.hooked.SetWhoToUI(args.whotoui)
+ else
+ -- self.hooked.SetWhoToUI(args.gui and true or false)
+ end
+ else
+ -- self.hooked.SetWhoToUI(true)
+ self.Quiet = true
+ end
+
+ dbg("QUERY: "..args.query)
+ -- self.hooked.SendWho(args.query)
+ else
+ self.Args = nil
+ self.WhoInProgress = false
+ end
+
+ -- Keep processing the who queue if there is more work
+ if not self:AllQueuesEmpty() then
+ self:AskWhoNextIn5sec()
+ else
+ dbg("*** Done processing requests ***")
+ end
+end
+
+function lib:AskWho(args)
+ tinsert(self.Queue[args.queue], args)
+ dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. getn(self.Queue[1]) .. '/'.. getn(self.Queue[2]) .. '/'.. getn(self.Queue[3]))
+ self:TriggerEvent('WHOLIB_QUERY_ADDED')
+
+ self:AskWhoNext()
+end
+
+function lib:ReturnWho()
+ if not self.Args then
+ self.Quiet = nil
+ return
+ end
+
+ if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then
+ self.Quiet = nil
+ end
+
+ if queryInterval > self.MinInterval then
+ queryInterval = queryInterval - 0.5
+ dbg("--Throttling up to 1 who per " .. queryInterval .. "s")
+ end
+
+ self.WhoInProgress = false
+ dbg("RESULT: "..self.Args.query)
+ dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. getn(self.Queue[1]) .. '/'.. getn(self.Queue[2]) .. '/'.. getn(self.Queue[3]))
+ local now = time()
+ local complete = (self.Total == getn(self.Result)) and (self.Total < MAX_WHOS_FROM_SERVER)
+ for _,v in pairs(self.Result)do
+ if v.Name then
+ if(self.Cache[v.Name] == nil)then
+ self.Cache[v.Name] = { inqueue = false, callback = {} }
+ end
+
+ local cachedName = self.Cache[v.Name]
+
+ cachedName.valid = true -- is now valid
+ cachedName.data = v -- update data
+ cachedName.data.Online = true -- player is online
+ cachedName.last = now -- update timestamp
+ if(cachedName.inqueue)then
+ if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then
+ -- found by the query which was created to -> remove us from query
+ self.CacheQueue[self.Args.query] = nil
+ else
+ -- found by another query
+ for k2,v2 in pairs(self.CacheQueue) do
+ if(v2 == v.Name)then
+ for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
+ for k3,v3 in pairs(self.Queue[i]) do
+ if(v3.query == k2 and v3.info)then
+ -- remove the query which was generated for this user, cause another query was faster...
+ dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
+ table.remove(self.Queue[i], k3)
+ self.CacheQueue[k2] = nil
+ end
+ end
+ end
+ end
+ end
+ end
+ dbg('Info(' .. v.Name ..') returned: on')
+ for _,v2 in pairs(cachedName.callback) do
+ self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
+ end
+ cachedName.callback = {}
+ end
+ cachedName.inqueue = false -- query is done
+ end
+ end
+ if(self.Args.info and self.CacheQueue[self.Args.query])then
+ -- the query did not deliver the result => not online!
+ local name = self.CacheQueue[self.Args.query]
+ local cachedName = self.Cache[name]
+ if (cachedName.inqueue)then
+ -- nothing found (yet)
+ cachedName.valid = true -- is now valid
+ cachedName.inqueue = false -- query is done?
+ cachedName.last = now -- update timestamp
+ if(complete)then
+ cachedName.data.Online = false -- player is offline
+ else
+ cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
+ end
+ end
+ dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn'))
+ for _,v in pairs(cachedName.callback) do
+ self:RaiseCallback(v, self:ReturnUserInfo(name))
+ end
+ cachedName.callback = {}
+ self.CacheQueue[self.Args.query] = nil
+ end
+ self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info)
+ self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info)
+
+ if not self:AllQueuesEmpty() then
+ self:AskWhoNextIn5sec()
+ end
+end
+
+function lib:GuiWho(msg)
+ if(msg == self.L['gui_wait'])then
+ return
+ end
+
+ for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
+ if(v.gui == true)then
+ return
+ end
+ end
+ if(self.WhoInProgress)then
+ WhoFrameEditBox:SetText(self.L['gui_wait'])
+ end
+ self.savedText = msg
+ self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
+ WhoFrameEditBox:ClearFocus();
+end
+
+function lib:ConsoleWho(msg)
+ --WhoFrameEditBox:SetText(msg)
+ local console_show = false
+ local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
+ local q1count = getn(q1)
+
+ if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop
+ return
+ end
+
+ if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown
+ DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0)
+ q1[q1count].console_show = true
+ end
+ if(q1count > 0 or self.WhoInProgress)then
+ DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0)
+ console_show = true
+ end
+ self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
+end
+
+function lib:ReturnUserInfo(name)
+ if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then
+ return self.Cache[name].data, (time() - self.Cache[name].last) / 60
+ end
+end
+
+function lib:RaiseCallback(args, ...)
+ if type(args.callback) == 'function' then
+ args.callback(self:DupAll(unpack(args)))
+ elseif args.callback then -- must be a string
+ args.handler[args.callback](args.handler, self:DupAll(unpack(args)))
+ end -- if
+end
+
+-- Argument checking
+
+function lib:CheckArgument(func, name, argtype, arg, defarg)
+ if arg == nil and defarg ~= nil then
+ return defarg
+ elseif type(arg) == argtype then
+ return arg
+ else
+ error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
+ end -- if
+end
+
+function lib:CheckPreset(func, name, preset, arg, defarg)
+ if arg == nil and defarg ~= nil then
+ return defarg
+ elseif arg ~= nil and preset[arg] ~= nil then
+ return arg
+ else
+ local p = {}
+ for k,v in pairs(preset) do
+ if type(v) ~= 'string' then
+ table.insert(p, k)
+ else
+ table.insert(p, v)
+ end -- if
+ end -- for
+ error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3)
+ end -- if
+end
+
+function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
+ if not nonil and callback == nil then
+ -- no callback: ignore handler
+ return nil, nil
+ elseif type(callback) == 'function' then
+ -- simple function
+ if handler ~= nil then
+ error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
+ end -- if
+ elseif type(callback) == 'string' then
+ -- method
+ if handler == nil then
+ handler = defhandler
+ end -- if
+ if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then
+ error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3)
+ end -- if
+ else
+ error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
+ end -- if
+
+ return callback, handler
+end
+
+-- helpers
+
+function lib:simple_dump(x)
+ if type(x) == 'string' then
+ return 'string \''..x..'\''
+ elseif type(x) == 'number' then
+ return 'number '..x
+ else
+ return type(x)
+ end
+end
+
+function lib:Dup(from)
+ local to = {}
+
+ for k,v in pairs(from) do
+ if type(v) == 'table' then
+ to[k] = self:Dup(v)
+ else
+ to[k] = v
+ end -- if
+ end -- for
+
+ return to
+end
+
+function lib:DupAll(x, ...)
+ if type(x) == 'table' then
+ return self:Dup(x), self:DupAll(unpack(args))
+ elseif x ~= nil then
+ return x, self:DupAll(unpack(args))
+ else
+ return nil
+ end -- if
+end
+
+local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
+
+function lib:CapitalizeInitial(name)
+ return string.gsub(name, MULTIBYTE_FIRST_CHAR, string.upper, 1)
+end
+
+---
+--- user events (Using CallbackHandler)
+---
+
+lib.PossibleEvents = {
+ 'WHOLIB_QUERY_RESULT',
+ 'WHOLIB_QUERY_ADDED',
+}
+
+function lib:TriggerEvent(...)
+ callbacks:Fire(event, unpack(arg))
+end
+
+---
+--- slash commands
+---
+
+SlashCmdList['WHO'] = function(msg)
+ dbg("console /who: "..msg)
+ -- new /who function
+ --local self = lib
+
+ if(msg == '')then
+ lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
+ elseif(WhoFrame:IsVisible())then
+ lib:GuiWho(msg)
+ else
+ lib:ConsoleWho(msg)
+ end
+end
+
+SlashCmdList['WHOLIB_DEBUG'] = function()
+ -- /wholibdebug: toggle debug on/off
+ local self = lib
+
+ self:SetWhoLibDebug(not self.Debug)
+end
+
+SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
+
+
+---
+--- hook activation
+---
+
+-- functions to hook
+local hooks = {
+ -- 'SendWho',
+ -- 'WhoFrameEditBox_OnEnterPressed',
+-- 'FriendsFrame_OnEvent',
+ -- 'SetWhoToUI',
+}
+
+-- hook all functions (which are not yet hooked)
+for _, name in pairs(hooks) do
+ if not lib['hooked'][name] then
+ lib['hooked'][name] = _G[name]
+ _G[name] = function(...)
+ lib.hook[name](lib, unpack(arg))
+ end -- function
+ end -- if
+end -- for
+
+-- fake 'WhoFrame:Hide' as hooked
+table.insert(hooks, 'WhoFrame_Hide')
+
+-- check for unused hooks -> remove function
+for name, _ in pairs(lib['hook']) do
+ if not hooks[name] then
+ lib['hook'][name] = function() end
+ end -- if
+end -- for
+
+-- secure hook 'WhoFrame:Hide'
+if not lib['hooked']['WhoFrame_Hide'] then
+ lib['hooked']['WhoFrame_Hide'] = true
+ hooksecurefunc(WhoFrame, 'Hide', function(...)
+ lib['hook']['WhoFrame_Hide'](lib, unpack(arg))
+ end -- function
+ )
+end -- if
+
+
+
+----- Coroutine based implementation (future)
+--function lib:sendWhoResult(val)
+-- coroutine.yield(val)
+--end
+--
+--function lib:sendWaitState(val)
+-- coroutine.yield(val)
+--end
+--
+--function lib:producer()
+-- return coroutine.create(
+-- function()
+-- lib:AskWhoNext()
+-- lib:sendWaitState(true)
+--
+-- -- Resumed look for data
+--
+-- end)
+--end
+
+
+
+
+
+---
+--- hook replacements
+---
+
+function lib.hook.SendWho(self, msg)
+ dbg("SendWho: "..msg)
+ lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
+end
+
+function lib.hook.WhoFrameEditBox_OnEnterPressed(self)
+ lib:GuiWho(WhoFrameEditBox:GetText())
+end
+
+--[[
+function lib.hook.FriendsFrame_OnEvent(self, ...)
+ if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
+ lib.hooked.FriendsFrame_OnEvent(...)
+ end
+end
+]]
+
+hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event)
+ if(event == "WHO_LIST_UPDATE") then
+ self:UnregisterEvent("WHO_LIST_UPDATE");
+ end
+ end);
+
+
+function lib.hook.SetWhoToUI(self, state)
+ lib.SetWhoToUIState = state
+end
+
+function lib.hook.WhoFrame_Hide(self)
+ if(not lib.WhoInProgress)then
+ lib:AskWhoNextIn5sec()
+ end
+end
+
+
+---
+--- WoW events
+---
+
+local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
+
+
+function lib:CHAT_MSG_SYSTEM(arg1)
+ if arg1 and string.find(arg1, who_pattern) then
+ lib:ProcessWhoResults()
+ end
+end
+
+FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
+
+function lib:WHO_LIST_UPDATE()
+ if not lib.Quiet then
+ WhoList_Update()
+ FriendsFrame_Update()
+ end
+
+ lib:ProcessWhoResults()
+end
+
+function lib:ProcessWhoResults()
+ self.Result = self.Result and table.wipe(self.Result) or {}
+
+ local num
+ self.Total, num = GetNumWhoResults()
+ for i=1, num do
+ local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i)
+ self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex }
+ end
+
+ self:ReturnWho()
+end
+
+---
+--- event activation
+---
+
+lib['frame']:UnregisterAllEvents();
+
+lib['frame']:SetScript("OnEvent", function(...)
+ lib[event](lib, unpack(arg))
+end);
+
+for _,name in pairs({
+ 'CHAT_MSG_SYSTEM',
+ 'WHO_LIST_UPDATE',
+}) do
+ lib['frame']:RegisterEvent(name);
+end -- for
+
+
+---
+--- re-embed
+---
+
+for target,_ in pairs(lib['embeds']) do
+ if type(target) == 'table' then
+ lib:Embed(target)
+ end -- if
+end -- for
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.xml b/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.xml
new file mode 100644
index 0000000..8c9955e
--- /dev/null
+++ b/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/Load_Libraries.xml b/ElvUI/Libraries/Load_Libraries.xml
new file mode 100644
index 0000000..765eb07
--- /dev/null
+++ b/ElvUI/Libraries/Load_Libraries.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/UTF8/UTF8.xml b/ElvUI/Libraries/UTF8/UTF8.xml
new file mode 100644
index 0000000..9c0790e
--- /dev/null
+++ b/ElvUI/Libraries/UTF8/UTF8.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/UTF8/utf8.lua b/ElvUI/Libraries/UTF8/utf8.lua
new file mode 100644
index 0000000..5e23002
--- /dev/null
+++ b/ElvUI/Libraries/UTF8/utf8.lua
@@ -0,0 +1,318 @@
+-- $Id: utf8.lua 179 2009-04-03 18:10:03Z pasta $
+--
+-- Provides UTF-8 aware string functions implemented in pure lua:
+-- * string.utf8len(s)
+-- * string.utf8sub(s, i, j)
+-- * string.utf8reverse(s)
+--
+-- If utf8data.lua (containing the lower<->upper case mappings) is loaded, these
+-- additional functions are available:
+-- * string.utf8upper(s)
+-- * string.utf8lower(s)
+--
+-- All functions behave as their non UTF-8 aware counterparts with the exception
+-- that UTF-8 characters are used instead of bytes for all units.
+
+--[[
+Copyright (c) 2006-2007, Kyle Smith
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--]]
+
+-- ABNF from RFC 3629
+--
+-- UTF8-octets = *( UTF8-char )
+-- UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
+-- UTF8-1 = %x00-7F
+-- UTF8-2 = %xC2-DF UTF8-tail
+-- UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
+-- %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
+-- UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
+-- %xF4 %x80-8F 2( UTF8-tail )
+-- UTF8-tail = %x80-BF
+--
+
+local strbyte, strlen, strsub, type = string.byte, string.len, string.sub, type
+
+-- returns the number of bytes used by the UTF-8 character at byte i in s
+-- also doubles as a UTF-8 character validator
+local function utf8charbytes(s, i)
+ -- argument defaults
+ i = i or 1
+
+ -- argument checking
+ if type(s) ~= "string" then
+ error("bad argument #1 to 'utf8charbytes' (string expected, got ".. type(s).. ")")
+ end
+ if type(i) ~= "number" then
+ error("bad argument #2 to 'utf8charbytes' (number expected, got ".. type(i).. ")")
+ end
+
+ local c = strbyte(s, i)
+
+ -- determine bytes needed for character, based on RFC 3629
+ -- validate byte 1
+ if c > 0 and c <= 127 then
+ -- UTF8-1
+ return 1
+
+ elseif c >= 194 and c <= 223 then
+ -- UTF8-2
+ local c2 = strbyte(s, i + 1)
+
+ if not c2 then
+ error("UTF-8 string terminated early")
+ end
+
+ -- validate byte 2
+ if c2 < 128 or c2 > 191 then
+ error("Invalid UTF-8 character")
+ end
+
+ return 2
+
+ elseif c >= 224 and c <= 239 then
+ -- UTF8-3
+ local c2 = strbyte(s, i + 1)
+ local c3 = strbyte(s, i + 2)
+
+ if not c2 or not c3 then
+ error("UTF-8 string terminated early")
+ end
+
+ -- validate byte 2
+ if c == 224 and (c2 < 160 or c2 > 191) then
+ error("Invalid UTF-8 character")
+ elseif c == 237 and (c2 < 128 or c2 > 159) then
+ error("Invalid UTF-8 character")
+ elseif c2 < 128 or c2 > 191 then
+ error("Invalid UTF-8 character")
+ end
+
+ -- validate byte 3
+ if c3 < 128 or c3 > 191 then
+ error("Invalid UTF-8 character")
+ end
+
+ return 3
+
+ elseif c >= 240 and c <= 244 then
+ -- UTF8-4
+ local c2 = strbyte(s, i + 1)
+ local c3 = strbyte(s, i + 2)
+ local c4 = strbyte(s, i + 3)
+
+ if not c2 or not c3 or not c4 then
+ error("UTF-8 string terminated early")
+ end
+
+ -- validate byte 2
+ if c == 240 and (c2 < 144 or c2 > 191) then
+ error("Invalid UTF-8 character")
+ elseif c == 244 and (c2 < 128 or c2 > 143) then
+ error("Invalid UTF-8 character")
+ elseif c2 < 128 or c2 > 191 then
+ error("Invalid UTF-8 character")
+ end
+
+ -- validate byte 3
+ if c3 < 128 or c3 > 191 then
+ error("Invalid UTF-8 character")
+ end
+
+ -- validate byte 4
+ if c4 < 128 or c4 > 191 then
+ error("Invalid UTF-8 character")
+ end
+
+ return 4
+
+ else
+ error("Invalid UTF-8 character")
+ end
+end
+
+-- returns the number of characters in a UTF-8 string
+local function utf8len(s)
+ -- argument checking
+ if type(s) ~= "string" then
+ error("bad argument #1 to 'utf8len' (string expected, got ".. type(s).. ")")
+ end
+
+ local pos = 1
+ local bytes = strlen(s)
+ local len = 0
+
+ while pos <= bytes do
+ len = len + 1
+ pos = pos + utf8charbytes(s, pos)
+ end
+
+ return len
+end
+
+-- install in the string library
+if not string.utf8len then
+ string.utf8len = utf8len
+end
+
+-- functions identically to string.sub except that i and j are UTF-8 characters
+-- instead of bytes
+local function utf8sub(s, i, j)
+ -- argument defaults
+ j = j or -1
+
+ -- argument checking
+ if type(s) ~= "string" then
+ error("bad argument #1 to 'utf8sub' (string expected, got ".. type(s).. ")")
+ end
+ if type(i) ~= "number" then
+ error("bad argument #2 to 'utf8sub' (number expected, got ".. type(i).. ")")
+ end
+ if type(j) ~= "number" then
+ error("bad argument #3 to 'utf8sub' (number expected, got ".. type(j).. ")")
+ end
+
+ local pos = 1
+ local bytes = strlen(s)
+ local len = 0
+
+ -- only set l if i or j is negative
+ local l = (i >= 0 and j >= 0) or utf8len(s)
+ local startChar = (i >= 0) and i or l + i + 1
+ local endChar = (j >= 0) and j or l + j + 1
+
+ -- can't have start before end!
+ if startChar > endChar then
+ return ""
+ end
+
+ -- byte offsets to pass to string.sub
+ local startByte, endByte = 1, bytes
+
+ while pos <= bytes do
+ len = len + 1
+
+ if len == startChar then
+ startByte = pos
+ end
+
+ pos = pos + utf8charbytes(s, pos)
+
+ if len == endChar then
+ endByte = pos - 1
+ break
+ end
+ end
+
+ return strsub(s, startByte, endByte)
+end
+
+-- install in the string library
+if not string.utf8sub then
+ string.utf8sub = utf8sub
+end
+
+-- replace UTF-8 characters based on a mapping table
+local function utf8replace(s, mapping)
+ -- argument checking
+ if type(s) ~= "string" then
+ error("bad argument #1 to 'utf8replace' (string expected, got ".. type(s).. ")")
+ end
+ if type(mapping) ~= "table" then
+ error("bad argument #2 to 'utf8replace' (table expected, got ".. type(mapping).. ")")
+ end
+
+ local pos = 1
+ local bytes = strlen(s)
+ local charbytes
+ local newstr = ""
+
+ while pos <= bytes do
+ charbytes = utf8charbytes(s, pos)
+ local c = strsub(s, pos, pos + charbytes - 1)
+
+ newstr = newstr .. (mapping[c] or c)
+
+ pos = pos + charbytes
+ end
+
+ return newstr
+end
+
+-- identical to string.upper except it knows about unicode simple case conversions
+local function utf8upper(s)
+ return utf8replace(s, utf8_lc_uc)
+end
+
+-- install in the string library
+if not string.utf8upper and utf8_lc_uc then
+ string.utf8upper = utf8upper
+end
+
+-- identical to string.lower except it knows about unicode simple case conversions
+local function utf8lower(s)
+ return utf8replace(s, utf8_uc_lc)
+end
+
+-- install in the string library
+if not string.utf8lower and utf8_uc_lc then
+ string.utf8lower = utf8lower
+end
+
+-- identical to string.reverse except that it supports UTF-8
+local function utf8reverse(s)
+ -- argument checking
+ if type(s) ~= "string" then
+ error("bad argument #1 to 'utf8reverse' (string expected, got ".. type(s).. ")")
+ end
+
+ local bytes = strlen(s)
+ local pos = bytes
+ local charbytes
+ local newstr = ""
+ local c
+
+ while pos > 0 do
+ c = strbyte(s, pos)
+ while c >= 128 and c <= 191 do
+ pos = pos - 1
+ c = strbyte(pos)
+ end
+
+ charbytes = utf8charbytes(s, pos)
+
+ newstr = newstr .. strsub(s, pos, pos + charbytes - 1)
+
+ pos = pos - 1
+ end
+
+ return newstr
+end
+
+-- install in the string library
+if not string.utf8reverse then
+ string.utf8reverse = utf8reverse
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/UTF8/utf8data.lua b/ElvUI/Libraries/UTF8/utf8data.lua
new file mode 100644
index 0000000..655f719
--- /dev/null
+++ b/ElvUI/Libraries/UTF8/utf8data.lua
@@ -0,0 +1,1860 @@
+utf8_lc_uc = {
+ ["a"] = "A",
+ ["b"] = "B",
+ ["c"] = "C",
+ ["d"] = "D",
+ ["e"] = "E",
+ ["f"] = "F",
+ ["g"] = "G",
+ ["h"] = "H",
+ ["i"] = "I",
+ ["j"] = "J",
+ ["k"] = "K",
+ ["l"] = "L",
+ ["m"] = "M",
+ ["n"] = "N",
+ ["o"] = "O",
+ ["p"] = "P",
+ ["q"] = "Q",
+ ["r"] = "R",
+ ["s"] = "S",
+ ["t"] = "T",
+ ["u"] = "U",
+ ["v"] = "V",
+ ["w"] = "W",
+ ["x"] = "X",
+ ["y"] = "Y",
+ ["z"] = "Z",
+ ["µ"] = "Μ",
+ ["à"] = "À",
+ ["á"] = "Á",
+ ["â"] = "Â",
+ ["ã"] = "Ã",
+ ["ä"] = "Ä",
+ ["å"] = "Å",
+ ["æ"] = "Æ",
+ ["ç"] = "Ç",
+ ["è"] = "È",
+ ["é"] = "É",
+ ["ê"] = "Ê",
+ ["ë"] = "Ë",
+ ["ì"] = "Ì",
+ ["í"] = "Í",
+ ["î"] = "Î",
+ ["ï"] = "Ï",
+ ["ð"] = "Ð",
+ ["ñ"] = "Ñ",
+ ["ò"] = "Ò",
+ ["ó"] = "Ó",
+ ["ô"] = "Ô",
+ ["õ"] = "Õ",
+ ["ö"] = "Ö",
+ ["ø"] = "Ø",
+ ["ù"] = "Ù",
+ ["ú"] = "Ú",
+ ["û"] = "Û",
+ ["ü"] = "Ü",
+ ["ý"] = "Ý",
+ ["þ"] = "Þ",
+ ["ÿ"] = "Ÿ",
+ ["ā"] = "Ā",
+ ["ă"] = "Ă",
+ ["ą"] = "Ą",
+ ["ć"] = "Ć",
+ ["ĉ"] = "Ĉ",
+ ["ċ"] = "Ċ",
+ ["č"] = "Č",
+ ["ď"] = "Ď",
+ ["đ"] = "Đ",
+ ["ē"] = "Ē",
+ ["ĕ"] = "Ĕ",
+ ["ė"] = "Ė",
+ ["ę"] = "Ę",
+ ["ě"] = "Ě",
+ ["ĝ"] = "Ĝ",
+ ["ğ"] = "Ğ",
+ ["ġ"] = "Ġ",
+ ["ģ"] = "Ģ",
+ ["ĥ"] = "Ĥ",
+ ["ħ"] = "Ħ",
+ ["ĩ"] = "Ĩ",
+ ["ī"] = "Ī",
+ ["ĭ"] = "Ĭ",
+ ["į"] = "Į",
+ ["ı"] = "I",
+ ["ij"] = "IJ",
+ ["ĵ"] = "Ĵ",
+ ["ķ"] = "Ķ",
+ ["ĺ"] = "Ĺ",
+ ["ļ"] = "Ļ",
+ ["ľ"] = "Ľ",
+ ["ŀ"] = "Ŀ",
+ ["ł"] = "Ł",
+ ["ń"] = "Ń",
+ ["ņ"] = "Ņ",
+ ["ň"] = "Ň",
+ ["ŋ"] = "Ŋ",
+ ["ō"] = "Ō",
+ ["ŏ"] = "Ŏ",
+ ["ő"] = "Ő",
+ ["œ"] = "Œ",
+ ["ŕ"] = "Ŕ",
+ ["ŗ"] = "Ŗ",
+ ["ř"] = "Ř",
+ ["ś"] = "Ś",
+ ["ŝ"] = "Ŝ",
+ ["ş"] = "Ş",
+ ["š"] = "Š",
+ ["ţ"] = "Ţ",
+ ["ť"] = "Ť",
+ ["ŧ"] = "Ŧ",
+ ["ũ"] = "Ũ",
+ ["ū"] = "Ū",
+ ["ŭ"] = "Ŭ",
+ ["ů"] = "Ů",
+ ["ű"] = "Ű",
+ ["ų"] = "Ų",
+ ["ŵ"] = "Ŵ",
+ ["ŷ"] = "Ŷ",
+ ["ź"] = "Ź",
+ ["ż"] = "Ż",
+ ["ž"] = "Ž",
+ ["ſ"] = "S",
+ ["ƀ"] = "Ƀ",
+ ["ƃ"] = "Ƃ",
+ ["ƅ"] = "Ƅ",
+ ["ƈ"] = "Ƈ",
+ ["ƌ"] = "Ƌ",
+ ["ƒ"] = "Ƒ",
+ ["ƕ"] = "Ƕ",
+ ["ƙ"] = "Ƙ",
+ ["ƚ"] = "Ƚ",
+ ["ƞ"] = "Ƞ",
+ ["ơ"] = "Ơ",
+ ["ƣ"] = "Ƣ",
+ ["ƥ"] = "Ƥ",
+ ["ƨ"] = "Ƨ",
+ ["ƭ"] = "Ƭ",
+ ["ư"] = "Ư",
+ ["ƴ"] = "Ƴ",
+ ["ƶ"] = "Ƶ",
+ ["ƹ"] = "Ƹ",
+ ["ƽ"] = "Ƽ",
+ ["ƿ"] = "Ƿ",
+ ["Dž"] = "DŽ",
+ ["dž"] = "DŽ",
+ ["Lj"] = "LJ",
+ ["lj"] = "LJ",
+ ["Nj"] = "NJ",
+ ["nj"] = "NJ",
+ ["ǎ"] = "Ǎ",
+ ["ǐ"] = "Ǐ",
+ ["ǒ"] = "Ǒ",
+ ["ǔ"] = "Ǔ",
+ ["ǖ"] = "Ǖ",
+ ["ǘ"] = "Ǘ",
+ ["ǚ"] = "Ǚ",
+ ["ǜ"] = "Ǜ",
+ ["ǝ"] = "Ǝ",
+ ["ǟ"] = "Ǟ",
+ ["ǡ"] = "Ǡ",
+ ["ǣ"] = "Ǣ",
+ ["ǥ"] = "Ǥ",
+ ["ǧ"] = "Ǧ",
+ ["ǩ"] = "Ǩ",
+ ["ǫ"] = "Ǫ",
+ ["ǭ"] = "Ǭ",
+ ["ǯ"] = "Ǯ",
+ ["Dz"] = "DZ",
+ ["dz"] = "DZ",
+ ["ǵ"] = "Ǵ",
+ ["ǹ"] = "Ǹ",
+ ["ǻ"] = "Ǻ",
+ ["ǽ"] = "Ǽ",
+ ["ǿ"] = "Ǿ",
+ ["ȁ"] = "Ȁ",
+ ["ȃ"] = "Ȃ",
+ ["ȅ"] = "Ȅ",
+ ["ȇ"] = "Ȇ",
+ ["ȉ"] = "Ȉ",
+ ["ȋ"] = "Ȋ",
+ ["ȍ"] = "Ȍ",
+ ["ȏ"] = "Ȏ",
+ ["ȑ"] = "Ȑ",
+ ["ȓ"] = "Ȓ",
+ ["ȕ"] = "Ȕ",
+ ["ȗ"] = "Ȗ",
+ ["ș"] = "Ș",
+ ["ț"] = "Ț",
+ ["ȝ"] = "Ȝ",
+ ["ȟ"] = "Ȟ",
+ ["ȣ"] = "Ȣ",
+ ["ȥ"] = "Ȥ",
+ ["ȧ"] = "Ȧ",
+ ["ȩ"] = "Ȩ",
+ ["ȫ"] = "Ȫ",
+ ["ȭ"] = "Ȭ",
+ ["ȯ"] = "Ȯ",
+ ["ȱ"] = "Ȱ",
+ ["ȳ"] = "Ȳ",
+ ["ȼ"] = "Ȼ",
+ ["ɂ"] = "Ɂ",
+ ["ɇ"] = "Ɇ",
+ ["ɉ"] = "Ɉ",
+ ["ɋ"] = "Ɋ",
+ ["ɍ"] = "Ɍ",
+ ["ɏ"] = "Ɏ",
+ ["ɓ"] = "Ɓ",
+ ["ɔ"] = "Ɔ",
+ ["ɖ"] = "Ɖ",
+ ["ɗ"] = "Ɗ",
+ ["ə"] = "Ə",
+ ["ɛ"] = "Ɛ",
+ ["ɠ"] = "Ɠ",
+ ["ɣ"] = "Ɣ",
+ ["ɨ"] = "Ɨ",
+ ["ɩ"] = "Ɩ",
+ ["ɫ"] = "Ɫ",
+ ["ɯ"] = "Ɯ",
+ ["ɲ"] = "Ɲ",
+ ["ɵ"] = "Ɵ",
+ ["ɽ"] = "Ɽ",
+ ["ʀ"] = "Ʀ",
+ ["ʃ"] = "Ʃ",
+ ["ʈ"] = "Ʈ",
+ ["ʉ"] = "Ʉ",
+ ["ʊ"] = "Ʊ",
+ ["ʋ"] = "Ʋ",
+ ["ʌ"] = "Ʌ",
+ ["ʒ"] = "Ʒ",
+ ["ͅ"] = "Ι",
+ ["ͻ"] = "Ͻ",
+ ["ͼ"] = "Ͼ",
+ ["ͽ"] = "Ͽ",
+ ["ά"] = "Ά",
+ ["έ"] = "Έ",
+ ["ή"] = "Ή",
+ ["ί"] = "Ί",
+ ["α"] = "Α",
+ ["β"] = "Β",
+ ["γ"] = "Γ",
+ ["δ"] = "Δ",
+ ["ε"] = "Ε",
+ ["ζ"] = "Ζ",
+ ["η"] = "Η",
+ ["θ"] = "Θ",
+ ["ι"] = "Ι",
+ ["κ"] = "Κ",
+ ["λ"] = "Λ",
+ ["μ"] = "Μ",
+ ["ν"] = "Ν",
+ ["ξ"] = "Ξ",
+ ["ο"] = "Ο",
+ ["π"] = "Π",
+ ["ρ"] = "Ρ",
+ ["ς"] = "Σ",
+ ["σ"] = "Σ",
+ ["τ"] = "Τ",
+ ["υ"] = "Υ",
+ ["φ"] = "Φ",
+ ["χ"] = "Χ",
+ ["ψ"] = "Ψ",
+ ["ω"] = "Ω",
+ ["ϊ"] = "Ϊ",
+ ["ϋ"] = "Ϋ",
+ ["ό"] = "Ό",
+ ["ύ"] = "Ύ",
+ ["ώ"] = "Ώ",
+ ["ϐ"] = "Β",
+ ["ϑ"] = "Θ",
+ ["ϕ"] = "Φ",
+ ["ϖ"] = "Π",
+ ["ϙ"] = "Ϙ",
+ ["ϛ"] = "Ϛ",
+ ["ϝ"] = "Ϝ",
+ ["ϟ"] = "Ϟ",
+ ["ϡ"] = "Ϡ",
+ ["ϣ"] = "Ϣ",
+ ["ϥ"] = "Ϥ",
+ ["ϧ"] = "Ϧ",
+ ["ϩ"] = "Ϩ",
+ ["ϫ"] = "Ϫ",
+ ["ϭ"] = "Ϭ",
+ ["ϯ"] = "Ϯ",
+ ["ϰ"] = "Κ",
+ ["ϱ"] = "Ρ",
+ ["ϲ"] = "Ϲ",
+ ["ϵ"] = "Ε",
+ ["ϸ"] = "Ϸ",
+ ["ϻ"] = "Ϻ",
+ ["а"] = "А",
+ ["б"] = "Б",
+ ["в"] = "В",
+ ["г"] = "Г",
+ ["д"] = "Д",
+ ["е"] = "Е",
+ ["ж"] = "Ж",
+ ["з"] = "З",
+ ["и"] = "И",
+ ["й"] = "Й",
+ ["к"] = "К",
+ ["л"] = "Л",
+ ["м"] = "М",
+ ["н"] = "Н",
+ ["о"] = "О",
+ ["п"] = "П",
+ ["р"] = "Р",
+ ["с"] = "С",
+ ["т"] = "Т",
+ ["у"] = "У",
+ ["ф"] = "Ф",
+ ["х"] = "Х",
+ ["ц"] = "Ц",
+ ["ч"] = "Ч",
+ ["ш"] = "Ш",
+ ["щ"] = "Щ",
+ ["ъ"] = "Ъ",
+ ["ы"] = "Ы",
+ ["ь"] = "Ь",
+ ["э"] = "Э",
+ ["ю"] = "Ю",
+ ["я"] = "Я",
+ ["ѐ"] = "Ѐ",
+ ["ё"] = "Ё",
+ ["ђ"] = "Ђ",
+ ["ѓ"] = "Ѓ",
+ ["є"] = "Є",
+ ["ѕ"] = "Ѕ",
+ ["і"] = "І",
+ ["ї"] = "Ї",
+ ["ј"] = "Ј",
+ ["љ"] = "Љ",
+ ["њ"] = "Њ",
+ ["ћ"] = "Ћ",
+ ["ќ"] = "Ќ",
+ ["ѝ"] = "Ѝ",
+ ["ў"] = "Ў",
+ ["џ"] = "Џ",
+ ["ѡ"] = "Ѡ",
+ ["ѣ"] = "Ѣ",
+ ["ѥ"] = "Ѥ",
+ ["ѧ"] = "Ѧ",
+ ["ѩ"] = "Ѩ",
+ ["ѫ"] = "Ѫ",
+ ["ѭ"] = "Ѭ",
+ ["ѯ"] = "Ѯ",
+ ["ѱ"] = "Ѱ",
+ ["ѳ"] = "Ѳ",
+ ["ѵ"] = "Ѵ",
+ ["ѷ"] = "Ѷ",
+ ["ѹ"] = "Ѹ",
+ ["ѻ"] = "Ѻ",
+ ["ѽ"] = "Ѽ",
+ ["ѿ"] = "Ѿ",
+ ["ҁ"] = "Ҁ",
+ ["ҋ"] = "Ҋ",
+ ["ҍ"] = "Ҍ",
+ ["ҏ"] = "Ҏ",
+ ["ґ"] = "Ґ",
+ ["ғ"] = "Ғ",
+ ["ҕ"] = "Ҕ",
+ ["җ"] = "Җ",
+ ["ҙ"] = "Ҙ",
+ ["қ"] = "Қ",
+ ["ҝ"] = "Ҝ",
+ ["ҟ"] = "Ҟ",
+ ["ҡ"] = "Ҡ",
+ ["ң"] = "Ң",
+ ["ҥ"] = "Ҥ",
+ ["ҧ"] = "Ҧ",
+ ["ҩ"] = "Ҩ",
+ ["ҫ"] = "Ҫ",
+ ["ҭ"] = "Ҭ",
+ ["ү"] = "Ү",
+ ["ұ"] = "Ұ",
+ ["ҳ"] = "Ҳ",
+ ["ҵ"] = "Ҵ",
+ ["ҷ"] = "Ҷ",
+ ["ҹ"] = "Ҹ",
+ ["һ"] = "Һ",
+ ["ҽ"] = "Ҽ",
+ ["ҿ"] = "Ҿ",
+ ["ӂ"] = "Ӂ",
+ ["ӄ"] = "Ӄ",
+ ["ӆ"] = "Ӆ",
+ ["ӈ"] = "Ӈ",
+ ["ӊ"] = "Ӊ",
+ ["ӌ"] = "Ӌ",
+ ["ӎ"] = "Ӎ",
+ ["ӏ"] = "Ӏ",
+ ["ӑ"] = "Ӑ",
+ ["ӓ"] = "Ӓ",
+ ["ӕ"] = "Ӕ",
+ ["ӗ"] = "Ӗ",
+ ["ә"] = "Ә",
+ ["ӛ"] = "Ӛ",
+ ["ӝ"] = "Ӝ",
+ ["ӟ"] = "Ӟ",
+ ["ӡ"] = "Ӡ",
+ ["ӣ"] = "Ӣ",
+ ["ӥ"] = "Ӥ",
+ ["ӧ"] = "Ӧ",
+ ["ө"] = "Ө",
+ ["ӫ"] = "Ӫ",
+ ["ӭ"] = "Ӭ",
+ ["ӯ"] = "Ӯ",
+ ["ӱ"] = "Ӱ",
+ ["ӳ"] = "Ӳ",
+ ["ӵ"] = "Ӵ",
+ ["ӷ"] = "Ӷ",
+ ["ӹ"] = "Ӹ",
+ ["ӻ"] = "Ӻ",
+ ["ӽ"] = "Ӽ",
+ ["ӿ"] = "Ӿ",
+ ["ԁ"] = "Ԁ",
+ ["ԃ"] = "Ԃ",
+ ["ԅ"] = "Ԅ",
+ ["ԇ"] = "Ԇ",
+ ["ԉ"] = "Ԉ",
+ ["ԋ"] = "Ԋ",
+ ["ԍ"] = "Ԍ",
+ ["ԏ"] = "Ԏ",
+ ["ԑ"] = "Ԑ",
+ ["ԓ"] = "Ԓ",
+ ["ա"] = "Ա",
+ ["բ"] = "Բ",
+ ["գ"] = "Գ",
+ ["դ"] = "Դ",
+ ["ե"] = "Ե",
+ ["զ"] = "Զ",
+ ["է"] = "Է",
+ ["ը"] = "Ը",
+ ["թ"] = "Թ",
+ ["ժ"] = "Ժ",
+ ["ի"] = "Ի",
+ ["լ"] = "Լ",
+ ["խ"] = "Խ",
+ ["ծ"] = "Ծ",
+ ["կ"] = "Կ",
+ ["հ"] = "Հ",
+ ["ձ"] = "Ձ",
+ ["ղ"] = "Ղ",
+ ["ճ"] = "Ճ",
+ ["մ"] = "Մ",
+ ["յ"] = "Յ",
+ ["ն"] = "Ն",
+ ["շ"] = "Շ",
+ ["ո"] = "Ո",
+ ["չ"] = "Չ",
+ ["պ"] = "Պ",
+ ["ջ"] = "Ջ",
+ ["ռ"] = "Ռ",
+ ["ս"] = "Ս",
+ ["վ"] = "Վ",
+ ["տ"] = "Տ",
+ ["ր"] = "Ր",
+ ["ց"] = "Ց",
+ ["ւ"] = "Ւ",
+ ["փ"] = "Փ",
+ ["ք"] = "Ք",
+ ["օ"] = "Օ",
+ ["ֆ"] = "Ֆ",
+ ["ᵽ"] = "Ᵽ",
+ ["ḁ"] = "Ḁ",
+ ["ḃ"] = "Ḃ",
+ ["ḅ"] = "Ḅ",
+ ["ḇ"] = "Ḇ",
+ ["ḉ"] = "Ḉ",
+ ["ḋ"] = "Ḋ",
+ ["ḍ"] = "Ḍ",
+ ["ḏ"] = "Ḏ",
+ ["ḑ"] = "Ḑ",
+ ["ḓ"] = "Ḓ",
+ ["ḕ"] = "Ḕ",
+ ["ḗ"] = "Ḗ",
+ ["ḙ"] = "Ḙ",
+ ["ḛ"] = "Ḛ",
+ ["ḝ"] = "Ḝ",
+ ["ḟ"] = "Ḟ",
+ ["ḡ"] = "Ḡ",
+ ["ḣ"] = "Ḣ",
+ ["ḥ"] = "Ḥ",
+ ["ḧ"] = "Ḧ",
+ ["ḩ"] = "Ḩ",
+ ["ḫ"] = "Ḫ",
+ ["ḭ"] = "Ḭ",
+ ["ḯ"] = "Ḯ",
+ ["ḱ"] = "Ḱ",
+ ["ḳ"] = "Ḳ",
+ ["ḵ"] = "Ḵ",
+ ["ḷ"] = "Ḷ",
+ ["ḹ"] = "Ḹ",
+ ["ḻ"] = "Ḻ",
+ ["ḽ"] = "Ḽ",
+ ["ḿ"] = "Ḿ",
+ ["ṁ"] = "Ṁ",
+ ["ṃ"] = "Ṃ",
+ ["ṅ"] = "Ṅ",
+ ["ṇ"] = "Ṇ",
+ ["ṉ"] = "Ṉ",
+ ["ṋ"] = "Ṋ",
+ ["ṍ"] = "Ṍ",
+ ["ṏ"] = "Ṏ",
+ ["ṑ"] = "Ṑ",
+ ["ṓ"] = "Ṓ",
+ ["ṕ"] = "Ṕ",
+ ["ṗ"] = "Ṗ",
+ ["ṙ"] = "Ṙ",
+ ["ṛ"] = "Ṛ",
+ ["ṝ"] = "Ṝ",
+ ["ṟ"] = "Ṟ",
+ ["ṡ"] = "Ṡ",
+ ["ṣ"] = "Ṣ",
+ ["ṥ"] = "Ṥ",
+ ["ṧ"] = "Ṧ",
+ ["ṩ"] = "Ṩ",
+ ["ṫ"] = "Ṫ",
+ ["ṭ"] = "Ṭ",
+ ["ṯ"] = "Ṯ",
+ ["ṱ"] = "Ṱ",
+ ["ṳ"] = "Ṳ",
+ ["ṵ"] = "Ṵ",
+ ["ṷ"] = "Ṷ",
+ ["ṹ"] = "Ṹ",
+ ["ṻ"] = "Ṻ",
+ ["ṽ"] = "Ṽ",
+ ["ṿ"] = "Ṿ",
+ ["ẁ"] = "Ẁ",
+ ["ẃ"] = "Ẃ",
+ ["ẅ"] = "Ẅ",
+ ["ẇ"] = "Ẇ",
+ ["ẉ"] = "Ẉ",
+ ["ẋ"] = "Ẋ",
+ ["ẍ"] = "Ẍ",
+ ["ẏ"] = "Ẏ",
+ ["ẑ"] = "Ẑ",
+ ["ẓ"] = "Ẓ",
+ ["ẕ"] = "Ẕ",
+ ["ẛ"] = "Ṡ",
+ ["ạ"] = "Ạ",
+ ["ả"] = "Ả",
+ ["ấ"] = "Ấ",
+ ["ầ"] = "Ầ",
+ ["ẩ"] = "Ẩ",
+ ["ẫ"] = "Ẫ",
+ ["ậ"] = "Ậ",
+ ["ắ"] = "Ắ",
+ ["ằ"] = "Ằ",
+ ["ẳ"] = "Ẳ",
+ ["ẵ"] = "Ẵ",
+ ["ặ"] = "Ặ",
+ ["ẹ"] = "Ẹ",
+ ["ẻ"] = "Ẻ",
+ ["ẽ"] = "Ẽ",
+ ["ế"] = "Ế",
+ ["ề"] = "Ề",
+ ["ể"] = "Ể",
+ ["ễ"] = "Ễ",
+ ["ệ"] = "Ệ",
+ ["ỉ"] = "Ỉ",
+ ["ị"] = "Ị",
+ ["ọ"] = "Ọ",
+ ["ỏ"] = "Ỏ",
+ ["ố"] = "Ố",
+ ["ồ"] = "Ồ",
+ ["ổ"] = "Ổ",
+ ["ỗ"] = "Ỗ",
+ ["ộ"] = "Ộ",
+ ["ớ"] = "Ớ",
+ ["ờ"] = "Ờ",
+ ["ở"] = "Ở",
+ ["ỡ"] = "Ỡ",
+ ["ợ"] = "Ợ",
+ ["ụ"] = "Ụ",
+ ["ủ"] = "Ủ",
+ ["ứ"] = "Ứ",
+ ["ừ"] = "Ừ",
+ ["ử"] = "Ử",
+ ["ữ"] = "Ữ",
+ ["ự"] = "Ự",
+ ["ỳ"] = "Ỳ",
+ ["ỵ"] = "Ỵ",
+ ["ỷ"] = "Ỷ",
+ ["ỹ"] = "Ỹ",
+ ["ἀ"] = "Ἀ",
+ ["ἁ"] = "Ἁ",
+ ["ἂ"] = "Ἂ",
+ ["ἃ"] = "Ἃ",
+ ["ἄ"] = "Ἄ",
+ ["ἅ"] = "Ἅ",
+ ["ἆ"] = "Ἆ",
+ ["ἇ"] = "Ἇ",
+ ["ἐ"] = "Ἐ",
+ ["ἑ"] = "Ἑ",
+ ["ἒ"] = "Ἒ",
+ ["ἓ"] = "Ἓ",
+ ["ἔ"] = "Ἔ",
+ ["ἕ"] = "Ἕ",
+ ["ἠ"] = "Ἠ",
+ ["ἡ"] = "Ἡ",
+ ["ἢ"] = "Ἢ",
+ ["ἣ"] = "Ἣ",
+ ["ἤ"] = "Ἤ",
+ ["ἥ"] = "Ἥ",
+ ["ἦ"] = "Ἦ",
+ ["ἧ"] = "Ἧ",
+ ["ἰ"] = "Ἰ",
+ ["ἱ"] = "Ἱ",
+ ["ἲ"] = "Ἲ",
+ ["ἳ"] = "Ἳ",
+ ["ἴ"] = "Ἴ",
+ ["ἵ"] = "Ἵ",
+ ["ἶ"] = "Ἶ",
+ ["ἷ"] = "Ἷ",
+ ["ὀ"] = "Ὀ",
+ ["ὁ"] = "Ὁ",
+ ["ὂ"] = "Ὂ",
+ ["ὃ"] = "Ὃ",
+ ["ὄ"] = "Ὄ",
+ ["ὅ"] = "Ὅ",
+ ["ὑ"] = "Ὑ",
+ ["ὓ"] = "Ὓ",
+ ["ὕ"] = "Ὕ",
+ ["ὗ"] = "Ὗ",
+ ["ὠ"] = "Ὠ",
+ ["ὡ"] = "Ὡ",
+ ["ὢ"] = "Ὢ",
+ ["ὣ"] = "Ὣ",
+ ["ὤ"] = "Ὤ",
+ ["ὥ"] = "Ὥ",
+ ["ὦ"] = "Ὦ",
+ ["ὧ"] = "Ὧ",
+ ["ὰ"] = "Ὰ",
+ ["ά"] = "Ά",
+ ["ὲ"] = "Ὲ",
+ ["έ"] = "Έ",
+ ["ὴ"] = "Ὴ",
+ ["ή"] = "Ή",
+ ["ὶ"] = "Ὶ",
+ ["ί"] = "Ί",
+ ["ὸ"] = "Ὸ",
+ ["ό"] = "Ό",
+ ["ὺ"] = "Ὺ",
+ ["ύ"] = "Ύ",
+ ["ὼ"] = "Ὼ",
+ ["ώ"] = "Ώ",
+ ["ᾀ"] = "ᾈ",
+ ["ᾁ"] = "ᾉ",
+ ["ᾂ"] = "ᾊ",
+ ["ᾃ"] = "ᾋ",
+ ["ᾄ"] = "ᾌ",
+ ["ᾅ"] = "ᾍ",
+ ["ᾆ"] = "ᾎ",
+ ["ᾇ"] = "ᾏ",
+ ["ᾐ"] = "ᾘ",
+ ["ᾑ"] = "ᾙ",
+ ["ᾒ"] = "ᾚ",
+ ["ᾓ"] = "ᾛ",
+ ["ᾔ"] = "ᾜ",
+ ["ᾕ"] = "ᾝ",
+ ["ᾖ"] = "ᾞ",
+ ["ᾗ"] = "ᾟ",
+ ["ᾠ"] = "ᾨ",
+ ["ᾡ"] = "ᾩ",
+ ["ᾢ"] = "ᾪ",
+ ["ᾣ"] = "ᾫ",
+ ["ᾤ"] = "ᾬ",
+ ["ᾥ"] = "ᾭ",
+ ["ᾦ"] = "ᾮ",
+ ["ᾧ"] = "ᾯ",
+ ["ᾰ"] = "Ᾰ",
+ ["ᾱ"] = "Ᾱ",
+ ["ᾳ"] = "ᾼ",
+ ["ι"] = "Ι",
+ ["ῃ"] = "ῌ",
+ ["ῐ"] = "Ῐ",
+ ["ῑ"] = "Ῑ",
+ ["ῠ"] = "Ῠ",
+ ["ῡ"] = "Ῡ",
+ ["ῥ"] = "Ῥ",
+ ["ῳ"] = "ῼ",
+ ["ⅎ"] = "Ⅎ",
+ ["ⅰ"] = "Ⅰ",
+ ["ⅱ"] = "Ⅱ",
+ ["ⅲ"] = "Ⅲ",
+ ["ⅳ"] = "Ⅳ",
+ ["ⅴ"] = "Ⅴ",
+ ["ⅵ"] = "Ⅵ",
+ ["ⅶ"] = "Ⅶ",
+ ["ⅷ"] = "Ⅷ",
+ ["ⅸ"] = "Ⅸ",
+ ["ⅹ"] = "Ⅹ",
+ ["ⅺ"] = "Ⅺ",
+ ["ⅻ"] = "Ⅻ",
+ ["ⅼ"] = "Ⅼ",
+ ["ⅽ"] = "Ⅽ",
+ ["ⅾ"] = "Ⅾ",
+ ["ⅿ"] = "Ⅿ",
+ ["ↄ"] = "Ↄ",
+ ["ⓐ"] = "Ⓐ",
+ ["ⓑ"] = "Ⓑ",
+ ["ⓒ"] = "Ⓒ",
+ ["ⓓ"] = "Ⓓ",
+ ["ⓔ"] = "Ⓔ",
+ ["ⓕ"] = "Ⓕ",
+ ["ⓖ"] = "Ⓖ",
+ ["ⓗ"] = "Ⓗ",
+ ["ⓘ"] = "Ⓘ",
+ ["ⓙ"] = "Ⓙ",
+ ["ⓚ"] = "Ⓚ",
+ ["ⓛ"] = "Ⓛ",
+ ["ⓜ"] = "Ⓜ",
+ ["ⓝ"] = "Ⓝ",
+ ["ⓞ"] = "Ⓞ",
+ ["ⓟ"] = "Ⓟ",
+ ["ⓠ"] = "Ⓠ",
+ ["ⓡ"] = "Ⓡ",
+ ["ⓢ"] = "Ⓢ",
+ ["ⓣ"] = "Ⓣ",
+ ["ⓤ"] = "Ⓤ",
+ ["ⓥ"] = "Ⓥ",
+ ["ⓦ"] = "Ⓦ",
+ ["ⓧ"] = "Ⓧ",
+ ["ⓨ"] = "Ⓨ",
+ ["ⓩ"] = "Ⓩ",
+ ["ⰰ"] = "Ⰰ",
+ ["ⰱ"] = "Ⰱ",
+ ["ⰲ"] = "Ⰲ",
+ ["ⰳ"] = "Ⰳ",
+ ["ⰴ"] = "Ⰴ",
+ ["ⰵ"] = "Ⰵ",
+ ["ⰶ"] = "Ⰶ",
+ ["ⰷ"] = "Ⰷ",
+ ["ⰸ"] = "Ⰸ",
+ ["ⰹ"] = "Ⰹ",
+ ["ⰺ"] = "Ⰺ",
+ ["ⰻ"] = "Ⰻ",
+ ["ⰼ"] = "Ⰼ",
+ ["ⰽ"] = "Ⰽ",
+ ["ⰾ"] = "Ⰾ",
+ ["ⰿ"] = "Ⰿ",
+ ["ⱀ"] = "Ⱀ",
+ ["ⱁ"] = "Ⱁ",
+ ["ⱂ"] = "Ⱂ",
+ ["ⱃ"] = "Ⱃ",
+ ["ⱄ"] = "Ⱄ",
+ ["ⱅ"] = "Ⱅ",
+ ["ⱆ"] = "Ⱆ",
+ ["ⱇ"] = "Ⱇ",
+ ["ⱈ"] = "Ⱈ",
+ ["ⱉ"] = "Ⱉ",
+ ["ⱊ"] = "Ⱊ",
+ ["ⱋ"] = "Ⱋ",
+ ["ⱌ"] = "Ⱌ",
+ ["ⱍ"] = "Ⱍ",
+ ["ⱎ"] = "Ⱎ",
+ ["ⱏ"] = "Ⱏ",
+ ["ⱐ"] = "Ⱐ",
+ ["ⱑ"] = "Ⱑ",
+ ["ⱒ"] = "Ⱒ",
+ ["ⱓ"] = "Ⱓ",
+ ["ⱔ"] = "Ⱔ",
+ ["ⱕ"] = "Ⱕ",
+ ["ⱖ"] = "Ⱖ",
+ ["ⱗ"] = "Ⱗ",
+ ["ⱘ"] = "Ⱘ",
+ ["ⱙ"] = "Ⱙ",
+ ["ⱚ"] = "Ⱚ",
+ ["ⱛ"] = "Ⱛ",
+ ["ⱜ"] = "Ⱜ",
+ ["ⱝ"] = "Ⱝ",
+ ["ⱞ"] = "Ⱞ",
+ ["ⱡ"] = "Ⱡ",
+ ["ⱥ"] = "Ⱥ",
+ ["ⱦ"] = "Ⱦ",
+ ["ⱨ"] = "Ⱨ",
+ ["ⱪ"] = "Ⱪ",
+ ["ⱬ"] = "Ⱬ",
+ ["ⱶ"] = "Ⱶ",
+ ["ⲁ"] = "Ⲁ",
+ ["ⲃ"] = "Ⲃ",
+ ["ⲅ"] = "Ⲅ",
+ ["ⲇ"] = "Ⲇ",
+ ["ⲉ"] = "Ⲉ",
+ ["ⲋ"] = "Ⲋ",
+ ["ⲍ"] = "Ⲍ",
+ ["ⲏ"] = "Ⲏ",
+ ["ⲑ"] = "Ⲑ",
+ ["ⲓ"] = "Ⲓ",
+ ["ⲕ"] = "Ⲕ",
+ ["ⲗ"] = "Ⲗ",
+ ["ⲙ"] = "Ⲙ",
+ ["ⲛ"] = "Ⲛ",
+ ["ⲝ"] = "Ⲝ",
+ ["ⲟ"] = "Ⲟ",
+ ["ⲡ"] = "Ⲡ",
+ ["ⲣ"] = "Ⲣ",
+ ["ⲥ"] = "Ⲥ",
+ ["ⲧ"] = "Ⲧ",
+ ["ⲩ"] = "Ⲩ",
+ ["ⲫ"] = "Ⲫ",
+ ["ⲭ"] = "Ⲭ",
+ ["ⲯ"] = "Ⲯ",
+ ["ⲱ"] = "Ⲱ",
+ ["ⲳ"] = "Ⲳ",
+ ["ⲵ"] = "Ⲵ",
+ ["ⲷ"] = "Ⲷ",
+ ["ⲹ"] = "Ⲹ",
+ ["ⲻ"] = "Ⲻ",
+ ["ⲽ"] = "Ⲽ",
+ ["ⲿ"] = "Ⲿ",
+ ["ⳁ"] = "Ⳁ",
+ ["ⳃ"] = "Ⳃ",
+ ["ⳅ"] = "Ⳅ",
+ ["ⳇ"] = "Ⳇ",
+ ["ⳉ"] = "Ⳉ",
+ ["ⳋ"] = "Ⳋ",
+ ["ⳍ"] = "Ⳍ",
+ ["ⳏ"] = "Ⳏ",
+ ["ⳑ"] = "Ⳑ",
+ ["ⳓ"] = "Ⳓ",
+ ["ⳕ"] = "Ⳕ",
+ ["ⳗ"] = "Ⳗ",
+ ["ⳙ"] = "Ⳙ",
+ ["ⳛ"] = "Ⳛ",
+ ["ⳝ"] = "Ⳝ",
+ ["ⳟ"] = "Ⳟ",
+ ["ⳡ"] = "Ⳡ",
+ ["ⳣ"] = "Ⳣ",
+ ["ⴀ"] = "Ⴀ",
+ ["ⴁ"] = "Ⴁ",
+ ["ⴂ"] = "Ⴂ",
+ ["ⴃ"] = "Ⴃ",
+ ["ⴄ"] = "Ⴄ",
+ ["ⴅ"] = "Ⴅ",
+ ["ⴆ"] = "Ⴆ",
+ ["ⴇ"] = "Ⴇ",
+ ["ⴈ"] = "Ⴈ",
+ ["ⴉ"] = "Ⴉ",
+ ["ⴊ"] = "Ⴊ",
+ ["ⴋ"] = "Ⴋ",
+ ["ⴌ"] = "Ⴌ",
+ ["ⴍ"] = "Ⴍ",
+ ["ⴎ"] = "Ⴎ",
+ ["ⴏ"] = "Ⴏ",
+ ["ⴐ"] = "Ⴐ",
+ ["ⴑ"] = "Ⴑ",
+ ["ⴒ"] = "Ⴒ",
+ ["ⴓ"] = "Ⴓ",
+ ["ⴔ"] = "Ⴔ",
+ ["ⴕ"] = "Ⴕ",
+ ["ⴖ"] = "Ⴖ",
+ ["ⴗ"] = "Ⴗ",
+ ["ⴘ"] = "Ⴘ",
+ ["ⴙ"] = "Ⴙ",
+ ["ⴚ"] = "Ⴚ",
+ ["ⴛ"] = "Ⴛ",
+ ["ⴜ"] = "Ⴜ",
+ ["ⴝ"] = "Ⴝ",
+ ["ⴞ"] = "Ⴞ",
+ ["ⴟ"] = "Ⴟ",
+ ["ⴠ"] = "Ⴠ",
+ ["ⴡ"] = "Ⴡ",
+ ["ⴢ"] = "Ⴢ",
+ ["ⴣ"] = "Ⴣ",
+ ["ⴤ"] = "Ⴤ",
+ ["ⴥ"] = "Ⴥ",
+ ["a"] = "A",
+ ["b"] = "B",
+ ["c"] = "C",
+ ["d"] = "D",
+ ["e"] = "E",
+ ["f"] = "F",
+ ["g"] = "G",
+ ["h"] = "H",
+ ["i"] = "I",
+ ["j"] = "J",
+ ["k"] = "K",
+ ["l"] = "L",
+ ["m"] = "M",
+ ["n"] = "N",
+ ["o"] = "O",
+ ["p"] = "P",
+ ["q"] = "Q",
+ ["r"] = "R",
+ ["s"] = "S",
+ ["t"] = "T",
+ ["u"] = "U",
+ ["v"] = "V",
+ ["w"] = "W",
+ ["x"] = "X",
+ ["y"] = "Y",
+ ["z"] = "Z",
+ ["𐐨"] = "𐐀",
+ ["𐐩"] = "𐐁",
+ ["𐐪"] = "𐐂",
+ ["𐐫"] = "𐐃",
+ ["𐐬"] = "𐐄",
+ ["𐐭"] = "𐐅",
+ ["𐐮"] = "𐐆",
+ ["𐐯"] = "𐐇",
+ ["𐐰"] = "𐐈",
+ ["𐐱"] = "𐐉",
+ ["𐐲"] = "𐐊",
+ ["𐐳"] = "𐐋",
+ ["𐐴"] = "𐐌",
+ ["𐐵"] = "𐐍",
+ ["𐐶"] = "𐐎",
+ ["𐐷"] = "𐐏",
+ ["𐐸"] = "𐐐",
+ ["𐐹"] = "𐐑",
+ ["𐐺"] = "𐐒",
+ ["𐐻"] = "𐐓",
+ ["𐐼"] = "𐐔",
+ ["𐐽"] = "𐐕",
+ ["𐐾"] = "𐐖",
+ ["𐐿"] = "𐐗",
+ ["𐑀"] = "𐐘",
+ ["𐑁"] = "𐐙",
+ ["𐑂"] = "𐐚",
+ ["𐑃"] = "𐐛",
+ ["𐑄"] = "𐐜",
+ ["𐑅"] = "𐐝",
+ ["𐑆"] = "𐐞",
+ ["𐑇"] = "𐐟",
+ ["𐑈"] = "𐐠",
+ ["𐑉"] = "𐐡",
+ ["𐑊"] = "𐐢",
+ ["𐑋"] = "𐐣",
+ ["𐑌"] = "𐐤",
+ ["𐑍"] = "𐐥",
+ ["𐑎"] = "𐐦",
+ ["𐑏"] = "𐐧",
+}
+
+
+utf8_uc_lc = {
+ ["A"] = "a",
+ ["B"] = "b",
+ ["C"] = "c",
+ ["D"] = "d",
+ ["E"] = "e",
+ ["F"] = "f",
+ ["G"] = "g",
+ ["H"] = "h",
+ ["I"] = "i",
+ ["J"] = "j",
+ ["K"] = "k",
+ ["L"] = "l",
+ ["M"] = "m",
+ ["N"] = "n",
+ ["O"] = "o",
+ ["P"] = "p",
+ ["Q"] = "q",
+ ["R"] = "r",
+ ["S"] = "s",
+ ["T"] = "t",
+ ["U"] = "u",
+ ["V"] = "v",
+ ["W"] = "w",
+ ["X"] = "x",
+ ["Y"] = "y",
+ ["Z"] = "z",
+ ["À"] = "à",
+ ["Á"] = "á",
+ ["Â"] = "â",
+ ["Ã"] = "ã",
+ ["Ä"] = "ä",
+ ["Å"] = "å",
+ ["Æ"] = "æ",
+ ["Ç"] = "ç",
+ ["È"] = "è",
+ ["É"] = "é",
+ ["Ê"] = "ê",
+ ["Ë"] = "ë",
+ ["Ì"] = "ì",
+ ["Í"] = "í",
+ ["Î"] = "î",
+ ["Ï"] = "ï",
+ ["Ð"] = "ð",
+ ["Ñ"] = "ñ",
+ ["Ò"] = "ò",
+ ["Ó"] = "ó",
+ ["Ô"] = "ô",
+ ["Õ"] = "õ",
+ ["Ö"] = "ö",
+ ["Ø"] = "ø",
+ ["Ù"] = "ù",
+ ["Ú"] = "ú",
+ ["Û"] = "û",
+ ["Ü"] = "ü",
+ ["Ý"] = "ý",
+ ["Þ"] = "þ",
+ ["Ā"] = "ā",
+ ["Ă"] = "ă",
+ ["Ą"] = "ą",
+ ["Ć"] = "ć",
+ ["Ĉ"] = "ĉ",
+ ["Ċ"] = "ċ",
+ ["Č"] = "č",
+ ["Ď"] = "ď",
+ ["Đ"] = "đ",
+ ["Ē"] = "ē",
+ ["Ĕ"] = "ĕ",
+ ["Ė"] = "ė",
+ ["Ę"] = "ę",
+ ["Ě"] = "ě",
+ ["Ĝ"] = "ĝ",
+ ["Ğ"] = "ğ",
+ ["Ġ"] = "ġ",
+ ["Ģ"] = "ģ",
+ ["Ĥ"] = "ĥ",
+ ["Ħ"] = "ħ",
+ ["Ĩ"] = "ĩ",
+ ["Ī"] = "ī",
+ ["Ĭ"] = "ĭ",
+ ["Į"] = "į",
+ ["İ"] = "i",
+ ["IJ"] = "ij",
+ ["Ĵ"] = "ĵ",
+ ["Ķ"] = "ķ",
+ ["Ĺ"] = "ĺ",
+ ["Ļ"] = "ļ",
+ ["Ľ"] = "ľ",
+ ["Ŀ"] = "ŀ",
+ ["Ł"] = "ł",
+ ["Ń"] = "ń",
+ ["Ņ"] = "ņ",
+ ["Ň"] = "ň",
+ ["Ŋ"] = "ŋ",
+ ["Ō"] = "ō",
+ ["Ŏ"] = "ŏ",
+ ["Ő"] = "ő",
+ ["Œ"] = "œ",
+ ["Ŕ"] = "ŕ",
+ ["Ŗ"] = "ŗ",
+ ["Ř"] = "ř",
+ ["Ś"] = "ś",
+ ["Ŝ"] = "ŝ",
+ ["Ş"] = "ş",
+ ["Š"] = "š",
+ ["Ţ"] = "ţ",
+ ["Ť"] = "ť",
+ ["Ŧ"] = "ŧ",
+ ["Ũ"] = "ũ",
+ ["Ū"] = "ū",
+ ["Ŭ"] = "ŭ",
+ ["Ů"] = "ů",
+ ["Ű"] = "ű",
+ ["Ų"] = "ų",
+ ["Ŵ"] = "ŵ",
+ ["Ŷ"] = "ŷ",
+ ["Ÿ"] = "ÿ",
+ ["Ź"] = "ź",
+ ["Ż"] = "ż",
+ ["Ž"] = "ž",
+ ["Ɓ"] = "ɓ",
+ ["Ƃ"] = "ƃ",
+ ["Ƅ"] = "ƅ",
+ ["Ɔ"] = "ɔ",
+ ["Ƈ"] = "ƈ",
+ ["Ɖ"] = "ɖ",
+ ["Ɗ"] = "ɗ",
+ ["Ƌ"] = "ƌ",
+ ["Ǝ"] = "ǝ",
+ ["Ə"] = "ə",
+ ["Ɛ"] = "ɛ",
+ ["Ƒ"] = "ƒ",
+ ["Ɠ"] = "ɠ",
+ ["Ɣ"] = "ɣ",
+ ["Ɩ"] = "ɩ",
+ ["Ɨ"] = "ɨ",
+ ["Ƙ"] = "ƙ",
+ ["Ɯ"] = "ɯ",
+ ["Ɲ"] = "ɲ",
+ ["Ɵ"] = "ɵ",
+ ["Ơ"] = "ơ",
+ ["Ƣ"] = "ƣ",
+ ["Ƥ"] = "ƥ",
+ ["Ʀ"] = "ʀ",
+ ["Ƨ"] = "ƨ",
+ ["Ʃ"] = "ʃ",
+ ["Ƭ"] = "ƭ",
+ ["Ʈ"] = "ʈ",
+ ["Ư"] = "ư",
+ ["Ʊ"] = "ʊ",
+ ["Ʋ"] = "ʋ",
+ ["Ƴ"] = "ƴ",
+ ["Ƶ"] = "ƶ",
+ ["Ʒ"] = "ʒ",
+ ["Ƹ"] = "ƹ",
+ ["Ƽ"] = "ƽ",
+ ["DŽ"] = "dž",
+ ["Dž"] = "dž",
+ ["LJ"] = "lj",
+ ["Lj"] = "lj",
+ ["NJ"] = "nj",
+ ["Nj"] = "nj",
+ ["Ǎ"] = "ǎ",
+ ["Ǐ"] = "ǐ",
+ ["Ǒ"] = "ǒ",
+ ["Ǔ"] = "ǔ",
+ ["Ǖ"] = "ǖ",
+ ["Ǘ"] = "ǘ",
+ ["Ǚ"] = "ǚ",
+ ["Ǜ"] = "ǜ",
+ ["Ǟ"] = "ǟ",
+ ["Ǡ"] = "ǡ",
+ ["Ǣ"] = "ǣ",
+ ["Ǥ"] = "ǥ",
+ ["Ǧ"] = "ǧ",
+ ["Ǩ"] = "ǩ",
+ ["Ǫ"] = "ǫ",
+ ["Ǭ"] = "ǭ",
+ ["Ǯ"] = "ǯ",
+ ["DZ"] = "dz",
+ ["Dz"] = "dz",
+ ["Ǵ"] = "ǵ",
+ ["Ƕ"] = "ƕ",
+ ["Ƿ"] = "ƿ",
+ ["Ǹ"] = "ǹ",
+ ["Ǻ"] = "ǻ",
+ ["Ǽ"] = "ǽ",
+ ["Ǿ"] = "ǿ",
+ ["Ȁ"] = "ȁ",
+ ["Ȃ"] = "ȃ",
+ ["Ȅ"] = "ȅ",
+ ["Ȇ"] = "ȇ",
+ ["Ȉ"] = "ȉ",
+ ["Ȋ"] = "ȋ",
+ ["Ȍ"] = "ȍ",
+ ["Ȏ"] = "ȏ",
+ ["Ȑ"] = "ȑ",
+ ["Ȓ"] = "ȓ",
+ ["Ȕ"] = "ȕ",
+ ["Ȗ"] = "ȗ",
+ ["Ș"] = "ș",
+ ["Ț"] = "ț",
+ ["Ȝ"] = "ȝ",
+ ["Ȟ"] = "ȟ",
+ ["Ƞ"] = "ƞ",
+ ["Ȣ"] = "ȣ",
+ ["Ȥ"] = "ȥ",
+ ["Ȧ"] = "ȧ",
+ ["Ȩ"] = "ȩ",
+ ["Ȫ"] = "ȫ",
+ ["Ȭ"] = "ȭ",
+ ["Ȯ"] = "ȯ",
+ ["Ȱ"] = "ȱ",
+ ["Ȳ"] = "ȳ",
+ ["Ⱥ"] = "ⱥ",
+ ["Ȼ"] = "ȼ",
+ ["Ƚ"] = "ƚ",
+ ["Ⱦ"] = "ⱦ",
+ ["Ɂ"] = "ɂ",
+ ["Ƀ"] = "ƀ",
+ ["Ʉ"] = "ʉ",
+ ["Ʌ"] = "ʌ",
+ ["Ɇ"] = "ɇ",
+ ["Ɉ"] = "ɉ",
+ ["Ɋ"] = "ɋ",
+ ["Ɍ"] = "ɍ",
+ ["Ɏ"] = "ɏ",
+ ["Ά"] = "ά",
+ ["Έ"] = "έ",
+ ["Ή"] = "ή",
+ ["Ί"] = "ί",
+ ["Ό"] = "ό",
+ ["Ύ"] = "ύ",
+ ["Ώ"] = "ώ",
+ ["Α"] = "α",
+ ["Β"] = "β",
+ ["Γ"] = "γ",
+ ["Δ"] = "δ",
+ ["Ε"] = "ε",
+ ["Ζ"] = "ζ",
+ ["Η"] = "η",
+ ["Θ"] = "θ",
+ ["Ι"] = "ι",
+ ["Κ"] = "κ",
+ ["Λ"] = "λ",
+ ["Μ"] = "μ",
+ ["Ν"] = "ν",
+ ["Ξ"] = "ξ",
+ ["Ο"] = "ο",
+ ["Π"] = "π",
+ ["Ρ"] = "ρ",
+ ["Σ"] = "σ",
+ ["Τ"] = "τ",
+ ["Υ"] = "υ",
+ ["Φ"] = "φ",
+ ["Χ"] = "χ",
+ ["Ψ"] = "ψ",
+ ["Ω"] = "ω",
+ ["Ϊ"] = "ϊ",
+ ["Ϋ"] = "ϋ",
+ ["Ϙ"] = "ϙ",
+ ["Ϛ"] = "ϛ",
+ ["Ϝ"] = "ϝ",
+ ["Ϟ"] = "ϟ",
+ ["Ϡ"] = "ϡ",
+ ["Ϣ"] = "ϣ",
+ ["Ϥ"] = "ϥ",
+ ["Ϧ"] = "ϧ",
+ ["Ϩ"] = "ϩ",
+ ["Ϫ"] = "ϫ",
+ ["Ϭ"] = "ϭ",
+ ["Ϯ"] = "ϯ",
+ ["ϴ"] = "θ",
+ ["Ϸ"] = "ϸ",
+ ["Ϲ"] = "ϲ",
+ ["Ϻ"] = "ϻ",
+ ["Ͻ"] = "ͻ",
+ ["Ͼ"] = "ͼ",
+ ["Ͽ"] = "ͽ",
+ ["Ѐ"] = "ѐ",
+ ["Ё"] = "ё",
+ ["Ђ"] = "ђ",
+ ["Ѓ"] = "ѓ",
+ ["Є"] = "є",
+ ["Ѕ"] = "ѕ",
+ ["І"] = "і",
+ ["Ї"] = "ї",
+ ["Ј"] = "ј",
+ ["Љ"] = "љ",
+ ["Њ"] = "њ",
+ ["Ћ"] = "ћ",
+ ["Ќ"] = "ќ",
+ ["Ѝ"] = "ѝ",
+ ["Ў"] = "ў",
+ ["Џ"] = "џ",
+ ["А"] = "а",
+ ["Б"] = "б",
+ ["В"] = "в",
+ ["Г"] = "г",
+ ["Д"] = "д",
+ ["Е"] = "е",
+ ["Ж"] = "ж",
+ ["З"] = "з",
+ ["И"] = "и",
+ ["Й"] = "й",
+ ["К"] = "к",
+ ["Л"] = "л",
+ ["М"] = "м",
+ ["Н"] = "н",
+ ["О"] = "о",
+ ["П"] = "п",
+ ["Р"] = "р",
+ ["С"] = "с",
+ ["Т"] = "т",
+ ["У"] = "у",
+ ["Ф"] = "ф",
+ ["Х"] = "х",
+ ["Ц"] = "ц",
+ ["Ч"] = "ч",
+ ["Ш"] = "ш",
+ ["Щ"] = "щ",
+ ["Ъ"] = "ъ",
+ ["Ы"] = "ы",
+ ["Ь"] = "ь",
+ ["Э"] = "э",
+ ["Ю"] = "ю",
+ ["Я"] = "я",
+ ["Ѡ"] = "ѡ",
+ ["Ѣ"] = "ѣ",
+ ["Ѥ"] = "ѥ",
+ ["Ѧ"] = "ѧ",
+ ["Ѩ"] = "ѩ",
+ ["Ѫ"] = "ѫ",
+ ["Ѭ"] = "ѭ",
+ ["Ѯ"] = "ѯ",
+ ["Ѱ"] = "ѱ",
+ ["Ѳ"] = "ѳ",
+ ["Ѵ"] = "ѵ",
+ ["Ѷ"] = "ѷ",
+ ["Ѹ"] = "ѹ",
+ ["Ѻ"] = "ѻ",
+ ["Ѽ"] = "ѽ",
+ ["Ѿ"] = "ѿ",
+ ["Ҁ"] = "ҁ",
+ ["Ҋ"] = "ҋ",
+ ["Ҍ"] = "ҍ",
+ ["Ҏ"] = "ҏ",
+ ["Ґ"] = "ґ",
+ ["Ғ"] = "ғ",
+ ["Ҕ"] = "ҕ",
+ ["Җ"] = "җ",
+ ["Ҙ"] = "ҙ",
+ ["Қ"] = "қ",
+ ["Ҝ"] = "ҝ",
+ ["Ҟ"] = "ҟ",
+ ["Ҡ"] = "ҡ",
+ ["Ң"] = "ң",
+ ["Ҥ"] = "ҥ",
+ ["Ҧ"] = "ҧ",
+ ["Ҩ"] = "ҩ",
+ ["Ҫ"] = "ҫ",
+ ["Ҭ"] = "ҭ",
+ ["Ү"] = "ү",
+ ["Ұ"] = "ұ",
+ ["Ҳ"] = "ҳ",
+ ["Ҵ"] = "ҵ",
+ ["Ҷ"] = "ҷ",
+ ["Ҹ"] = "ҹ",
+ ["Һ"] = "һ",
+ ["Ҽ"] = "ҽ",
+ ["Ҿ"] = "ҿ",
+ ["Ӏ"] = "ӏ",
+ ["Ӂ"] = "ӂ",
+ ["Ӄ"] = "ӄ",
+ ["Ӆ"] = "ӆ",
+ ["Ӈ"] = "ӈ",
+ ["Ӊ"] = "ӊ",
+ ["Ӌ"] = "ӌ",
+ ["Ӎ"] = "ӎ",
+ ["Ӑ"] = "ӑ",
+ ["Ӓ"] = "ӓ",
+ ["Ӕ"] = "ӕ",
+ ["Ӗ"] = "ӗ",
+ ["Ә"] = "ә",
+ ["Ӛ"] = "ӛ",
+ ["Ӝ"] = "ӝ",
+ ["Ӟ"] = "ӟ",
+ ["Ӡ"] = "ӡ",
+ ["Ӣ"] = "ӣ",
+ ["Ӥ"] = "ӥ",
+ ["Ӧ"] = "ӧ",
+ ["Ө"] = "ө",
+ ["Ӫ"] = "ӫ",
+ ["Ӭ"] = "ӭ",
+ ["Ӯ"] = "ӯ",
+ ["Ӱ"] = "ӱ",
+ ["Ӳ"] = "ӳ",
+ ["Ӵ"] = "ӵ",
+ ["Ӷ"] = "ӷ",
+ ["Ӹ"] = "ӹ",
+ ["Ӻ"] = "ӻ",
+ ["Ӽ"] = "ӽ",
+ ["Ӿ"] = "ӿ",
+ ["Ԁ"] = "ԁ",
+ ["Ԃ"] = "ԃ",
+ ["Ԅ"] = "ԅ",
+ ["Ԇ"] = "ԇ",
+ ["Ԉ"] = "ԉ",
+ ["Ԋ"] = "ԋ",
+ ["Ԍ"] = "ԍ",
+ ["Ԏ"] = "ԏ",
+ ["Ԑ"] = "ԑ",
+ ["Ԓ"] = "ԓ",
+ ["Ա"] = "ա",
+ ["Բ"] = "բ",
+ ["Գ"] = "գ",
+ ["Դ"] = "դ",
+ ["Ե"] = "ե",
+ ["Զ"] = "զ",
+ ["Է"] = "է",
+ ["Ը"] = "ը",
+ ["Թ"] = "թ",
+ ["Ժ"] = "ժ",
+ ["Ի"] = "ի",
+ ["Լ"] = "լ",
+ ["Խ"] = "խ",
+ ["Ծ"] = "ծ",
+ ["Կ"] = "կ",
+ ["Հ"] = "հ",
+ ["Ձ"] = "ձ",
+ ["Ղ"] = "ղ",
+ ["Ճ"] = "ճ",
+ ["Մ"] = "մ",
+ ["Յ"] = "յ",
+ ["Ն"] = "ն",
+ ["Շ"] = "շ",
+ ["Ո"] = "ո",
+ ["Չ"] = "չ",
+ ["Պ"] = "պ",
+ ["Ջ"] = "ջ",
+ ["Ռ"] = "ռ",
+ ["Ս"] = "ս",
+ ["Վ"] = "վ",
+ ["Տ"] = "տ",
+ ["Ր"] = "ր",
+ ["Ց"] = "ց",
+ ["Ւ"] = "ւ",
+ ["Փ"] = "փ",
+ ["Ք"] = "ք",
+ ["Օ"] = "օ",
+ ["Ֆ"] = "ֆ",
+ ["Ⴀ"] = "ⴀ",
+ ["Ⴁ"] = "ⴁ",
+ ["Ⴂ"] = "ⴂ",
+ ["Ⴃ"] = "ⴃ",
+ ["Ⴄ"] = "ⴄ",
+ ["Ⴅ"] = "ⴅ",
+ ["Ⴆ"] = "ⴆ",
+ ["Ⴇ"] = "ⴇ",
+ ["Ⴈ"] = "ⴈ",
+ ["Ⴉ"] = "ⴉ",
+ ["Ⴊ"] = "ⴊ",
+ ["Ⴋ"] = "ⴋ",
+ ["Ⴌ"] = "ⴌ",
+ ["Ⴍ"] = "ⴍ",
+ ["Ⴎ"] = "ⴎ",
+ ["Ⴏ"] = "ⴏ",
+ ["Ⴐ"] = "ⴐ",
+ ["Ⴑ"] = "ⴑ",
+ ["Ⴒ"] = "ⴒ",
+ ["Ⴓ"] = "ⴓ",
+ ["Ⴔ"] = "ⴔ",
+ ["Ⴕ"] = "ⴕ",
+ ["Ⴖ"] = "ⴖ",
+ ["Ⴗ"] = "ⴗ",
+ ["Ⴘ"] = "ⴘ",
+ ["Ⴙ"] = "ⴙ",
+ ["Ⴚ"] = "ⴚ",
+ ["Ⴛ"] = "ⴛ",
+ ["Ⴜ"] = "ⴜ",
+ ["Ⴝ"] = "ⴝ",
+ ["Ⴞ"] = "ⴞ",
+ ["Ⴟ"] = "ⴟ",
+ ["Ⴠ"] = "ⴠ",
+ ["Ⴡ"] = "ⴡ",
+ ["Ⴢ"] = "ⴢ",
+ ["Ⴣ"] = "ⴣ",
+ ["Ⴤ"] = "ⴤ",
+ ["Ⴥ"] = "ⴥ",
+ ["Ḁ"] = "ḁ",
+ ["Ḃ"] = "ḃ",
+ ["Ḅ"] = "ḅ",
+ ["Ḇ"] = "ḇ",
+ ["Ḉ"] = "ḉ",
+ ["Ḋ"] = "ḋ",
+ ["Ḍ"] = "ḍ",
+ ["Ḏ"] = "ḏ",
+ ["Ḑ"] = "ḑ",
+ ["Ḓ"] = "ḓ",
+ ["Ḕ"] = "ḕ",
+ ["Ḗ"] = "ḗ",
+ ["Ḙ"] = "ḙ",
+ ["Ḛ"] = "ḛ",
+ ["Ḝ"] = "ḝ",
+ ["Ḟ"] = "ḟ",
+ ["Ḡ"] = "ḡ",
+ ["Ḣ"] = "ḣ",
+ ["Ḥ"] = "ḥ",
+ ["Ḧ"] = "ḧ",
+ ["Ḩ"] = "ḩ",
+ ["Ḫ"] = "ḫ",
+ ["Ḭ"] = "ḭ",
+ ["Ḯ"] = "ḯ",
+ ["Ḱ"] = "ḱ",
+ ["Ḳ"] = "ḳ",
+ ["Ḵ"] = "ḵ",
+ ["Ḷ"] = "ḷ",
+ ["Ḹ"] = "ḹ",
+ ["Ḻ"] = "ḻ",
+ ["Ḽ"] = "ḽ",
+ ["Ḿ"] = "ḿ",
+ ["Ṁ"] = "ṁ",
+ ["Ṃ"] = "ṃ",
+ ["Ṅ"] = "ṅ",
+ ["Ṇ"] = "ṇ",
+ ["Ṉ"] = "ṉ",
+ ["Ṋ"] = "ṋ",
+ ["Ṍ"] = "ṍ",
+ ["Ṏ"] = "ṏ",
+ ["Ṑ"] = "ṑ",
+ ["Ṓ"] = "ṓ",
+ ["Ṕ"] = "ṕ",
+ ["Ṗ"] = "ṗ",
+ ["Ṙ"] = "ṙ",
+ ["Ṛ"] = "ṛ",
+ ["Ṝ"] = "ṝ",
+ ["Ṟ"] = "ṟ",
+ ["Ṡ"] = "ṡ",
+ ["Ṣ"] = "ṣ",
+ ["Ṥ"] = "ṥ",
+ ["Ṧ"] = "ṧ",
+ ["Ṩ"] = "ṩ",
+ ["Ṫ"] = "ṫ",
+ ["Ṭ"] = "ṭ",
+ ["Ṯ"] = "ṯ",
+ ["Ṱ"] = "ṱ",
+ ["Ṳ"] = "ṳ",
+ ["Ṵ"] = "ṵ",
+ ["Ṷ"] = "ṷ",
+ ["Ṹ"] = "ṹ",
+ ["Ṻ"] = "ṻ",
+ ["Ṽ"] = "ṽ",
+ ["Ṿ"] = "ṿ",
+ ["Ẁ"] = "ẁ",
+ ["Ẃ"] = "ẃ",
+ ["Ẅ"] = "ẅ",
+ ["Ẇ"] = "ẇ",
+ ["Ẉ"] = "ẉ",
+ ["Ẋ"] = "ẋ",
+ ["Ẍ"] = "ẍ",
+ ["Ẏ"] = "ẏ",
+ ["Ẑ"] = "ẑ",
+ ["Ẓ"] = "ẓ",
+ ["Ẕ"] = "ẕ",
+ ["Ạ"] = "ạ",
+ ["Ả"] = "ả",
+ ["Ấ"] = "ấ",
+ ["Ầ"] = "ầ",
+ ["Ẩ"] = "ẩ",
+ ["Ẫ"] = "ẫ",
+ ["Ậ"] = "ậ",
+ ["Ắ"] = "ắ",
+ ["Ằ"] = "ằ",
+ ["Ẳ"] = "ẳ",
+ ["Ẵ"] = "ẵ",
+ ["Ặ"] = "ặ",
+ ["Ẹ"] = "ẹ",
+ ["Ẻ"] = "ẻ",
+ ["Ẽ"] = "ẽ",
+ ["Ế"] = "ế",
+ ["Ề"] = "ề",
+ ["Ể"] = "ể",
+ ["Ễ"] = "ễ",
+ ["Ệ"] = "ệ",
+ ["Ỉ"] = "ỉ",
+ ["Ị"] = "ị",
+ ["Ọ"] = "ọ",
+ ["Ỏ"] = "ỏ",
+ ["Ố"] = "ố",
+ ["Ồ"] = "ồ",
+ ["Ổ"] = "ổ",
+ ["Ỗ"] = "ỗ",
+ ["Ộ"] = "ộ",
+ ["Ớ"] = "ớ",
+ ["Ờ"] = "ờ",
+ ["Ở"] = "ở",
+ ["Ỡ"] = "ỡ",
+ ["Ợ"] = "ợ",
+ ["Ụ"] = "ụ",
+ ["Ủ"] = "ủ",
+ ["Ứ"] = "ứ",
+ ["Ừ"] = "ừ",
+ ["Ử"] = "ử",
+ ["Ữ"] = "ữ",
+ ["Ự"] = "ự",
+ ["Ỳ"] = "ỳ",
+ ["Ỵ"] = "ỵ",
+ ["Ỷ"] = "ỷ",
+ ["Ỹ"] = "ỹ",
+ ["Ἀ"] = "ἀ",
+ ["Ἁ"] = "ἁ",
+ ["Ἂ"] = "ἂ",
+ ["Ἃ"] = "ἃ",
+ ["Ἄ"] = "ἄ",
+ ["Ἅ"] = "ἅ",
+ ["Ἆ"] = "ἆ",
+ ["Ἇ"] = "ἇ",
+ ["Ἐ"] = "ἐ",
+ ["Ἑ"] = "ἑ",
+ ["Ἒ"] = "ἒ",
+ ["Ἓ"] = "ἓ",
+ ["Ἔ"] = "ἔ",
+ ["Ἕ"] = "ἕ",
+ ["Ἠ"] = "ἠ",
+ ["Ἡ"] = "ἡ",
+ ["Ἢ"] = "ἢ",
+ ["Ἣ"] = "ἣ",
+ ["Ἤ"] = "ἤ",
+ ["Ἥ"] = "ἥ",
+ ["Ἦ"] = "ἦ",
+ ["Ἧ"] = "ἧ",
+ ["Ἰ"] = "ἰ",
+ ["Ἱ"] = "ἱ",
+ ["Ἲ"] = "ἲ",
+ ["Ἳ"] = "ἳ",
+ ["Ἴ"] = "ἴ",
+ ["Ἵ"] = "ἵ",
+ ["Ἶ"] = "ἶ",
+ ["Ἷ"] = "ἷ",
+ ["Ὀ"] = "ὀ",
+ ["Ὁ"] = "ὁ",
+ ["Ὂ"] = "ὂ",
+ ["Ὃ"] = "ὃ",
+ ["Ὄ"] = "ὄ",
+ ["Ὅ"] = "ὅ",
+ ["Ὑ"] = "ὑ",
+ ["Ὓ"] = "ὓ",
+ ["Ὕ"] = "ὕ",
+ ["Ὗ"] = "ὗ",
+ ["Ὠ"] = "ὠ",
+ ["Ὡ"] = "ὡ",
+ ["Ὢ"] = "ὢ",
+ ["Ὣ"] = "ὣ",
+ ["Ὤ"] = "ὤ",
+ ["Ὥ"] = "ὥ",
+ ["Ὦ"] = "ὦ",
+ ["Ὧ"] = "ὧ",
+ ["ᾈ"] = "ᾀ",
+ ["ᾉ"] = "ᾁ",
+ ["ᾊ"] = "ᾂ",
+ ["ᾋ"] = "ᾃ",
+ ["ᾌ"] = "ᾄ",
+ ["ᾍ"] = "ᾅ",
+ ["ᾎ"] = "ᾆ",
+ ["ᾏ"] = "ᾇ",
+ ["ᾘ"] = "ᾐ",
+ ["ᾙ"] = "ᾑ",
+ ["ᾚ"] = "ᾒ",
+ ["ᾛ"] = "ᾓ",
+ ["ᾜ"] = "ᾔ",
+ ["ᾝ"] = "ᾕ",
+ ["ᾞ"] = "ᾖ",
+ ["ᾟ"] = "ᾗ",
+ ["ᾨ"] = "ᾠ",
+ ["ᾩ"] = "ᾡ",
+ ["ᾪ"] = "ᾢ",
+ ["ᾫ"] = "ᾣ",
+ ["ᾬ"] = "ᾤ",
+ ["ᾭ"] = "ᾥ",
+ ["ᾮ"] = "ᾦ",
+ ["ᾯ"] = "ᾧ",
+ ["Ᾰ"] = "ᾰ",
+ ["Ᾱ"] = "ᾱ",
+ ["Ὰ"] = "ὰ",
+ ["Ά"] = "ά",
+ ["ᾼ"] = "ᾳ",
+ ["Ὲ"] = "ὲ",
+ ["Έ"] = "έ",
+ ["Ὴ"] = "ὴ",
+ ["Ή"] = "ή",
+ ["ῌ"] = "ῃ",
+ ["Ῐ"] = "ῐ",
+ ["Ῑ"] = "ῑ",
+ ["Ὶ"] = "ὶ",
+ ["Ί"] = "ί",
+ ["Ῠ"] = "ῠ",
+ ["Ῡ"] = "ῡ",
+ ["Ὺ"] = "ὺ",
+ ["Ύ"] = "ύ",
+ ["Ῥ"] = "ῥ",
+ ["Ὸ"] = "ὸ",
+ ["Ό"] = "ό",
+ ["Ὼ"] = "ὼ",
+ ["Ώ"] = "ώ",
+ ["ῼ"] = "ῳ",
+ ["Ω"] = "ω",
+ ["K"] = "k",
+ ["Å"] = "å",
+ ["Ⅎ"] = "ⅎ",
+ ["Ⅰ"] = "ⅰ",
+ ["Ⅱ"] = "ⅱ",
+ ["Ⅲ"] = "ⅲ",
+ ["Ⅳ"] = "ⅳ",
+ ["Ⅴ"] = "ⅴ",
+ ["Ⅵ"] = "ⅵ",
+ ["Ⅶ"] = "ⅶ",
+ ["Ⅷ"] = "ⅷ",
+ ["Ⅸ"] = "ⅸ",
+ ["Ⅹ"] = "ⅹ",
+ ["Ⅺ"] = "ⅺ",
+ ["Ⅻ"] = "ⅻ",
+ ["Ⅼ"] = "ⅼ",
+ ["Ⅽ"] = "ⅽ",
+ ["Ⅾ"] = "ⅾ",
+ ["Ⅿ"] = "ⅿ",
+ ["Ↄ"] = "ↄ",
+ ["Ⓐ"] = "ⓐ",
+ ["Ⓑ"] = "ⓑ",
+ ["Ⓒ"] = "ⓒ",
+ ["Ⓓ"] = "ⓓ",
+ ["Ⓔ"] = "ⓔ",
+ ["Ⓕ"] = "ⓕ",
+ ["Ⓖ"] = "ⓖ",
+ ["Ⓗ"] = "ⓗ",
+ ["Ⓘ"] = "ⓘ",
+ ["Ⓙ"] = "ⓙ",
+ ["Ⓚ"] = "ⓚ",
+ ["Ⓛ"] = "ⓛ",
+ ["Ⓜ"] = "ⓜ",
+ ["Ⓝ"] = "ⓝ",
+ ["Ⓞ"] = "ⓞ",
+ ["Ⓟ"] = "ⓟ",
+ ["Ⓠ"] = "ⓠ",
+ ["Ⓡ"] = "ⓡ",
+ ["Ⓢ"] = "ⓢ",
+ ["Ⓣ"] = "ⓣ",
+ ["Ⓤ"] = "ⓤ",
+ ["Ⓥ"] = "ⓥ",
+ ["Ⓦ"] = "ⓦ",
+ ["Ⓧ"] = "ⓧ",
+ ["Ⓨ"] = "ⓨ",
+ ["Ⓩ"] = "ⓩ",
+ ["Ⰰ"] = "ⰰ",
+ ["Ⰱ"] = "ⰱ",
+ ["Ⰲ"] = "ⰲ",
+ ["Ⰳ"] = "ⰳ",
+ ["Ⰴ"] = "ⰴ",
+ ["Ⰵ"] = "ⰵ",
+ ["Ⰶ"] = "ⰶ",
+ ["Ⰷ"] = "ⰷ",
+ ["Ⰸ"] = "ⰸ",
+ ["Ⰹ"] = "ⰹ",
+ ["Ⰺ"] = "ⰺ",
+ ["Ⰻ"] = "ⰻ",
+ ["Ⰼ"] = "ⰼ",
+ ["Ⰽ"] = "ⰽ",
+ ["Ⰾ"] = "ⰾ",
+ ["Ⰿ"] = "ⰿ",
+ ["Ⱀ"] = "ⱀ",
+ ["Ⱁ"] = "ⱁ",
+ ["Ⱂ"] = "ⱂ",
+ ["Ⱃ"] = "ⱃ",
+ ["Ⱄ"] = "ⱄ",
+ ["Ⱅ"] = "ⱅ",
+ ["Ⱆ"] = "ⱆ",
+ ["Ⱇ"] = "ⱇ",
+ ["Ⱈ"] = "ⱈ",
+ ["Ⱉ"] = "ⱉ",
+ ["Ⱊ"] = "ⱊ",
+ ["Ⱋ"] = "ⱋ",
+ ["Ⱌ"] = "ⱌ",
+ ["Ⱍ"] = "ⱍ",
+ ["Ⱎ"] = "ⱎ",
+ ["Ⱏ"] = "ⱏ",
+ ["Ⱐ"] = "ⱐ",
+ ["Ⱑ"] = "ⱑ",
+ ["Ⱒ"] = "ⱒ",
+ ["Ⱓ"] = "ⱓ",
+ ["Ⱔ"] = "ⱔ",
+ ["Ⱕ"] = "ⱕ",
+ ["Ⱖ"] = "ⱖ",
+ ["Ⱗ"] = "ⱗ",
+ ["Ⱘ"] = "ⱘ",
+ ["Ⱙ"] = "ⱙ",
+ ["Ⱚ"] = "ⱚ",
+ ["Ⱛ"] = "ⱛ",
+ ["Ⱜ"] = "ⱜ",
+ ["Ⱝ"] = "ⱝ",
+ ["Ⱞ"] = "ⱞ",
+ ["Ⱡ"] = "ⱡ",
+ ["Ɫ"] = "ɫ",
+ ["Ᵽ"] = "ᵽ",
+ ["Ɽ"] = "ɽ",
+ ["Ⱨ"] = "ⱨ",
+ ["Ⱪ"] = "ⱪ",
+ ["Ⱬ"] = "ⱬ",
+ ["Ⱶ"] = "ⱶ",
+ ["Ⲁ"] = "ⲁ",
+ ["Ⲃ"] = "ⲃ",
+ ["Ⲅ"] = "ⲅ",
+ ["Ⲇ"] = "ⲇ",
+ ["Ⲉ"] = "ⲉ",
+ ["Ⲋ"] = "ⲋ",
+ ["Ⲍ"] = "ⲍ",
+ ["Ⲏ"] = "ⲏ",
+ ["Ⲑ"] = "ⲑ",
+ ["Ⲓ"] = "ⲓ",
+ ["Ⲕ"] = "ⲕ",
+ ["Ⲗ"] = "ⲗ",
+ ["Ⲙ"] = "ⲙ",
+ ["Ⲛ"] = "ⲛ",
+ ["Ⲝ"] = "ⲝ",
+ ["Ⲟ"] = "ⲟ",
+ ["Ⲡ"] = "ⲡ",
+ ["Ⲣ"] = "ⲣ",
+ ["Ⲥ"] = "ⲥ",
+ ["Ⲧ"] = "ⲧ",
+ ["Ⲩ"] = "ⲩ",
+ ["Ⲫ"] = "ⲫ",
+ ["Ⲭ"] = "ⲭ",
+ ["Ⲯ"] = "ⲯ",
+ ["Ⲱ"] = "ⲱ",
+ ["Ⲳ"] = "ⲳ",
+ ["Ⲵ"] = "ⲵ",
+ ["Ⲷ"] = "ⲷ",
+ ["Ⲹ"] = "ⲹ",
+ ["Ⲻ"] = "ⲻ",
+ ["Ⲽ"] = "ⲽ",
+ ["Ⲿ"] = "ⲿ",
+ ["Ⳁ"] = "ⳁ",
+ ["Ⳃ"] = "ⳃ",
+ ["Ⳅ"] = "ⳅ",
+ ["Ⳇ"] = "ⳇ",
+ ["Ⳉ"] = "ⳉ",
+ ["Ⳋ"] = "ⳋ",
+ ["Ⳍ"] = "ⳍ",
+ ["Ⳏ"] = "ⳏ",
+ ["Ⳑ"] = "ⳑ",
+ ["Ⳓ"] = "ⳓ",
+ ["Ⳕ"] = "ⳕ",
+ ["Ⳗ"] = "ⳗ",
+ ["Ⳙ"] = "ⳙ",
+ ["Ⳛ"] = "ⳛ",
+ ["Ⳝ"] = "ⳝ",
+ ["Ⳟ"] = "ⳟ",
+ ["Ⳡ"] = "ⳡ",
+ ["Ⳣ"] = "ⳣ",
+ ["A"] = "a",
+ ["B"] = "b",
+ ["C"] = "c",
+ ["D"] = "d",
+ ["E"] = "e",
+ ["F"] = "f",
+ ["G"] = "g",
+ ["H"] = "h",
+ ["I"] = "i",
+ ["J"] = "j",
+ ["K"] = "k",
+ ["L"] = "l",
+ ["M"] = "m",
+ ["N"] = "n",
+ ["O"] = "o",
+ ["P"] = "p",
+ ["Q"] = "q",
+ ["R"] = "r",
+ ["S"] = "s",
+ ["T"] = "t",
+ ["U"] = "u",
+ ["V"] = "v",
+ ["W"] = "w",
+ ["X"] = "x",
+ ["Y"] = "y",
+ ["Z"] = "z",
+ ["𐐀"] = "𐐨",
+ ["𐐁"] = "𐐩",
+ ["𐐂"] = "𐐪",
+ ["𐐃"] = "𐐫",
+ ["𐐄"] = "𐐬",
+ ["𐐅"] = "𐐭",
+ ["𐐆"] = "𐐮",
+ ["𐐇"] = "𐐯",
+ ["𐐈"] = "𐐰",
+ ["𐐉"] = "𐐱",
+ ["𐐊"] = "𐐲",
+ ["𐐋"] = "𐐳",
+ ["𐐌"] = "𐐴",
+ ["𐐍"] = "𐐵",
+ ["𐐎"] = "𐐶",
+ ["𐐏"] = "𐐷",
+ ["𐐐"] = "𐐸",
+ ["𐐑"] = "𐐹",
+ ["𐐒"] = "𐐺",
+ ["𐐓"] = "𐐻",
+ ["𐐔"] = "𐐼",
+ ["𐐕"] = "𐐽",
+ ["𐐖"] = "𐐾",
+ ["𐐗"] = "𐐿",
+ ["𐐘"] = "𐑀",
+ ["𐐙"] = "𐑁",
+ ["𐐚"] = "𐑂",
+ ["𐐛"] = "𐑃",
+ ["𐐜"] = "𐑄",
+ ["𐐝"] = "𐑅",
+ ["𐐞"] = "𐑆",
+ ["𐐟"] = "𐑇",
+ ["𐐠"] = "𐑈",
+ ["𐐡"] = "𐑉",
+ ["𐐢"] = "𐑊",
+ ["𐐣"] = "𐑋",
+ ["𐐤"] = "𐑌",
+ ["𐐥"] = "𐑍",
+ ["𐐦"] = "𐑎",
+ ["𐐧"] = "𐑏",
+}
+
diff --git a/ElvUI/Libraries/oUF/LICENSE b/ElvUI/Libraries/oUF/LICENSE
new file mode 100644
index 0000000..b8e3658
--- /dev/null
+++ b/ElvUI/Libraries/oUF/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2006-2017 Trond A Ekseth
+Copyright (c) 2016-2017 Val Voronov
+Copyright (c) 2016-2017 Adrian L Lange
+Copyright (c) 2016-2017 Rainrider
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/ElvUI/Libraries/oUF/blizzard.lua b/ElvUI/Libraries/oUF/blizzard.lua
new file mode 100644
index 0000000..01337af
--- /dev/null
+++ b/ElvUI/Libraries/oUF/blizzard.lua
@@ -0,0 +1,72 @@
+local ns = oUF
+local oUF = ns.oUF
+
+local hiddenParent = CreateFrame("Frame")
+
+-- sourced from FrameXML/PartyMemberFrame.lua
+local MAX_PARTY_MEMBERS = MAX_PARTY_MEMBERS or 4
+
+local hiddenParent = CreateFrame('Frame', nil, UIParent)
+hiddenParent:SetAllPoints()
+hiddenParent:Hide()
+
+local function handleFrame(baseName)
+ local frame
+ if(type(baseName) == 'string') then
+ frame = _G[baseName]
+ else
+ frame = baseName
+ end
+
+ if(frame) then
+ frame:UnregisterAllEvents()
+ frame:Hide()
+
+ -- Keep frame hidden without causing taint
+ frame:SetParent(hiddenParent)
+
+ local health = frame.healthBar or frame.healthbar
+ if(health) then
+ health:UnregisterAllEvents()
+ end
+
+ local power = frame.manabar
+ if(power) then
+ power:UnregisterAllEvents()
+ end
+
+ local spell = frame.castBar or frame.spellbar
+ if(spell) then
+ spell:UnregisterAllEvents()
+ end
+
+ local buffFrame = frame.BuffFrame
+ if(buffFrame) then
+ buffFrame:UnregisterAllEvents()
+ end
+ end
+end
+
+function oUF:DisableBlizzard(unit)
+ if(not unit) then return end
+
+ if(unit == 'player') then
+ handleFrame(PlayerFrame)
+ elseif(unit == 'pet') then
+ handleFrame(PetFrame)
+ elseif(unit == 'target') then
+ handleFrame(TargetFrame)
+ handleFrame(ComboFrame)
+ elseif(unit == 'targettarget') then
+ handleFrame(TargetofTargetFrame)
+ elseif(unit:match('party%d?$')) then
+ local id = unit:match('party(%d)')
+ if(id) then
+ handleFrame('PartyMemberFrame' .. id)
+ else
+ for i = 1, MAX_PARTY_MEMBERS do
+ handleFrame(string.format('PartyMemberFrame%d', i))
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/colors.lua b/ElvUI/Libraries/oUF/colors.lua
new file mode 100644
index 0000000..c7c3537
--- /dev/null
+++ b/ElvUI/Libraries/oUF/colors.lua
@@ -0,0 +1,234 @@
+local ns = oUF
+local oUF = ns.oUF
+local Private = oUF.Private
+
+local frame_metatable = Private.frame_metatable
+
+local colors = {
+ smooth = {
+ 1, 0, 0,
+ 1, 1, 0,
+ 0, 1, 0
+ },
+ health = {49 / 255, 207 / 255, 37 / 255},
+ disconnected = {.6, .6, .6},
+ tapped = {.6, .6, .6},
+ class = {},
+ reaction = {},
+ power = {},
+}
+
+-- We do this because people edit the vars directly, and changing the default
+-- globals makes SPICE FLOW!
+local function customClassColors()
+ if(CUSTOM_CLASS_COLORS) then
+ local function updateColors()
+ for classToken, color in next, CUSTOM_CLASS_COLORS do
+ colors.class[classToken] = {color.r, color.g, color.b}
+ end
+
+ for _, obj in next, oUF.objects do
+ obj:UpdateAllElements('CUSTOM_CLASS_COLORS')
+ end
+ end
+
+ updateColors()
+ CUSTOM_CLASS_COLORS:RegisterCallback(updateColors)
+
+ return true
+ end
+end
+
+if(not customClassColors()) then
+ for classToken, color in next, RAID_CLASS_COLORS do
+ colors.class[classToken] = {color.r, color.g, color.b}
+ end
+
+ local eventHandler = CreateFrame('Frame')
+ eventHandler:RegisterEvent('ADDON_LOADED')
+ eventHandler:SetScript('OnEvent', function(self)
+ if(customClassColors()) then
+ self:UnregisterEvent('ADDON_LOADED')
+ self:SetScript('OnEvent', nil)
+ end
+ end)
+end
+
+for eclass, color in next, FACTION_BAR_COLORS do
+ colors.reaction[eclass] = {color.r, color.g, color.b}
+end
+
+colors.power = {}
+colors.power[0] = {0.00, 0.00, 1.00}
+colors.power[1] = {1.00, 0.00, 0.00}
+colors.power[2] = {1.00, 0.50, 0.25}
+colors.power[3] = {1.00, 1.00, 0.00}
+colors.power[4] = {0.00, 1.00, 1.00}
+
+local function colorsAndPercent(a, b, ...)
+ if(a <= 0 or b == 0) then
+ return nil, unpack(arg)
+ elseif(a >= b) then
+ return nil, select(select('#', unpack(arg)) - 2, unpack(arg))
+ end
+
+ local num = select('#', unpack(arg)) / 3
+ local segment, relperc = math.modf((a / b) * (num - 1))
+ return relperc, select((segment * 3) + 1, unpack(arg))
+end
+
+-- http://www.wowwiki.com/ColorGradient
+--[[ Colors: oUF:RGBColorGradient(a, b, ...)
+Used to convert a percent value (the quotient of `a` and `b`) into a gradient from 2 or more RGB colors. If more than 2
+colors are passed, the gradient will be between the two colors which perc lies in an evenly divided range. A RGB color
+is a sequence of 3 consecutive RGB percent values (in the range [0-1]). If `a` is negative or `b` is zero then the first
+RGB color (the first 3 RGB values passed to the function) is returned. If `a` is bigger than or equal to `b`, then the
+last 3 RGB values are returned.
+
+* self - the global oUF object
+* a - value used as numerator to calculate the percentage (number)
+* b - value used as denominator to calculate the percentage (number)
+* ... - a list of RGB percent values. At least 6 values should be passed (number [0-1])
+--]]
+local function RGBColorGradient(...)
+ local relperc, r1, g1, b1, r2, g2, b2 = colorsAndPercent(unpack(arg))
+ if(relperc) then
+ return r1 + (r2 - r1) * relperc, g1 + (g2 - g1) * relperc, b1 + (b2 - b1) * relperc
+ else
+ return r1, g1, b1
+ end
+end
+
+-- HCY functions are based on http://www.chilliant.com/rgb2hsv.html
+local function getY(r, g, b)
+ return 0.299 * r + 0.587 * g + 0.114 * b
+end
+
+--[[ Colors: oUF:RGBToHCY(r, g, b)
+Used to convert a color from RGB to HCY color space.
+
+* self - the global oUF object
+* r - red color component (number [0-1])
+* g - green color component (number [0-1])
+* b - blue color component (number [0-1])
+--]]
+function oUF: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 = math.mod((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 math_abs = math.abs
+--[[ Colors: oUF:HCYtoRGB(hue, chroma, luma)
+Used to convert a color from HCY to RGB color space.
+
+* self - the global oUF object
+* hue - hue color component (number [0-1])
+* chroma - chroma color component (number [0-1])
+* luma - luminance color component (number [0-1])
+--]]
+function oUF:HCYtoRGB(hue, chroma, luma)
+ local r, g, b = 0, 0, 0
+ if(hue and luma > 0) then
+ local h2 = hue * 6
+ local x = chroma * (1 - math_abs(math.mod(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
+
+ local y = getY(r, g, b)
+ if(luma < y) then
+ chroma = chroma * (luma / y)
+ elseif(y < 1) then
+ chroma = chroma * (1 - luma) / (1 - y)
+ end
+
+ r = (r - y) * chroma + luma
+ g = (g - y) * chroma + luma
+ b = (b - y) * chroma + luma
+ end
+ return r, g, b
+end
+
+--[[ Colors: oUF:HCYColorGradient(a, b, ...)
+Used to convert a percent value (the quotient of `a` and `b`) into a gradient from 2 or more HCY colors. If more than 2
+colors are passed, the gradient will be between the two colors which perc lies in an evenly divided range. A HCY color
+is a sequence of 3 consecutive values in the range [0-1]. If `a` is negative or `b` is zero then the first
+HCY color (the first 3 HCY values passed to the function) is returned. If `a` is bigger than or equal to `b`, then the
+last 3 HCY values are returned.
+
+* self - the global oUF object
+* a - value used as numerator to calculate the percentage (number)
+* b - value used as denominator to calculate the percentage (number)
+* ... - a list of HCY color values. At least 6 values should be passed (number [0-1])
+--]]
+local function HCYColorGradient(...)
+ local relperc, r1, g1, b1, r2, g2, b2 = colorsAndPercent(unpack(arg))
+ if(not relperc) then
+ return r1, g1, b1
+ end
+
+ local h1, c1, y1 = self:RGBToHCY(r1, g1, b1)
+ local h2, c2, y2 = self: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 self:HCYtoRGB(math.mod(h1 + dh * relperc, 1), c, y)
+ else
+ return self:HCYtoRGB(h1 or h2, c, y)
+ end
+
+end
+
+--[[ Colors: oUF:ColorGradient(a, b, ...) or frame:ColorGradient(a, b, ...)
+Used as a proxy to call the proper gradient function depending on the user's preference. If `oUF.useHCYColorGradient` is
+set to true, `:HCYColorGradient` will be called, else `:RGBColorGradient`.
+
+* self - the global oUF object or a unit frame
+* a - value used as numerator to calculate the percentage (number)
+* b - value used as denominator to calculate the percentage (number)
+* ... - a list of color values. At least 6 values should be passed (number [0-1])
+--]]
+local function ColorGradient(...)
+ return (oUF.useHCYColorGradient and HCYColorGradient or RGBColorGradient)(unpack(arg))
+end
+
+Private.colors = colors
+
+oUF.colors = colors
+oUF.ColorGradient = ColorGradient
+oUF.RGBColorGradient = RGBColorGradient
+oUF.HCYColorGradient = HCYColorGradient
+oUF.useHCYColorGradient = false
+
+frame_metatable.__index.colors = colors
+frame_metatable.__index.ColorGradient = ColorGradient
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/assistantindicator.lua b/ElvUI/Libraries/oUF/elements/assistantindicator.lua
new file mode 100644
index 0000000..cdbda9f
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/assistantindicator.lua
@@ -0,0 +1,103 @@
+--[[
+# Element: Assistant Indicator
+
+Toggles the visibility of an indicator based on the unit's raid assistant status.
+
+## Widget
+
+AssistantIndicator - Any UI widget.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ -- Position and size
+ local AssistantIndicator = self:CreateTexture(nil, 'OVERLAY')
+ AssistantIndicator:SetSize(16, 16)
+ AssistantIndicator:SetPoint('TOP', self)
+
+ -- Register it with oUF
+ self.AssistantIndicator = AssistantIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local UnitInRaid = UnitInRaid
+local UnitIsPartyLeader = UnitIsPartyLeader
+local UnitIsRaidOfficer = UnitIsRaidOfficer
+
+local function Update(self, event)
+ local element = self.AssistantIndicator
+
+ --[[ Callback: AssistantIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the AssistantIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local unit = self.unit
+ local isAssistant = UnitInRaid(unit) and not UnitIsPartyLeader(unit)
+ if(isAssistant) then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: AssistantIndicator:PostUpdate(isAssistant)
+ Called after the element has been updated.
+
+ * self - the AssistantIndicator element
+ * isAssistant - indicates whether the unit is a raid assistant (boolean)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(isAssistant)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: AssistantIndicator.Override(self, event, ...)
+ Used to completely override the element's update process.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event (string)
+ --]]
+ return (self.AssistantIndicator.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self)
+ local element = self.AssistantIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PARTY_MEMBERS_CHANGED', Path)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\GroupFrame\UI-Group-AssistantIcon]])
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.AssistantIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('PARTY_MEMBERS_CHANGED', Path)
+ end
+end
+
+oUF:AddElement('AssistantIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/auras.lua b/ElvUI/Libraries/oUF/elements/auras.lua
new file mode 100644
index 0000000..e8f834b
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/auras.lua
@@ -0,0 +1,516 @@
+--[[
+# Element: Auras
+
+Handles creation and updating of aura icons.
+
+## Widget
+
+Auras - A Frame to hold `Button`s representing both buffs and debuffs.
+Buffs - A Frame to hold `Button`s representing buffs.
+Debuffs - A Frame to hold `Button`s representing debuffs.
+
+## Notes
+
+At least one of the above widgets must be present for the element to work.
+
+## Options
+
+.disableMouse - Disables mouse events (boolean)
+.disableCooldown - Disables the cooldown spiral (boolean)
+.size - Aura icon size. Defaults to 16 (number)
+.spacing - Spacing between each icon. Defaults to 0 (number)
+.['spacing-x'] - Horizontal spacing between each icon. Takes priority over `spacing` (number)
+.['spacing-y'] - Vertical spacing between each icon. Takes priority over `spacing` (number)
+.['growth-x'] - Horizontal growth direction. Defaults to 'RIGHT' (string)
+.['growth-y'] - Vertical growth direction. Defaults to 'UP' (string)
+.initialAnchor - Anchor point for the icons. Defaults to 'BOTTOMLEFT' (string)
+.filter - Custom filter list for auras to display. Defaults to 'HELPFUL' for buffs and 'HARMFUL' for
+ debuffs (string)
+
+## Options Auras
+
+.numBuffs - The maximum number of buffs to display. Defaults to 32 (number)
+.numDebuffs - The maximum number of debuffs to display. Defaults to 40 (number)
+.numTotal - The maximum number of auras to display. Prioritizes buffs over debuffs. Defaults to the sum of
+ .numBuffs and .numDebuffs (number)
+.gap - Controls the creation of an invisible icon between buffs and debuffs. Defaults to false (boolean)
+.buffFilter - Custom filter list for buffs to display. Takes priority over `filter` (string)
+.debuffFilter - Custom filter list for debuffs to display. Takes priority over `filter` (string)
+
+## Options Buffs
+
+.num - Number of buffs to display. Defaults to 32 (number)
+
+## Options Debuffs
+
+.num - Number of debuffs to display. Defaults to 40 (number)
+
+## Attributes
+
+button.filter - the filter list used to determine the visibility of the aura (string)
+button.isDebuff - indicates if the button holds a debuff (boolean)
+
+## Examples
+
+ -- Position and size
+ local Buffs = CreateFrame('Frame', nil, self)
+ Buffs:SetPoint('RIGHT', self, 'LEFT')
+ Buffs:SetSize(16 * 2, 16 * 16)
+
+ -- Register with oUF
+ self.Buffs = Buffs
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local tinsert = table.insert
+local floor = math.floor
+
+local CreateFrame = CreateFrame
+local GetTime = GetTime
+local UnitAura = UnitAura
+
+local VISIBLE = 1
+local HIDDEN = 0
+
+local function UpdateTooltip(self)
+ if self.filter == 'HELPFUL' then
+ GameTooltip:SetUnitBuff(self:GetParent().__owner.unit, self:GetID(), self.filter)
+ else
+ GameTooltip:SetUnitDebuff(self:GetParent().__owner.unit, self:GetID(), self.filter)
+ end
+end
+
+local function onEnter(self)
+ if(not self:IsVisible()) then return end
+
+ GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
+ self:UpdateTooltip()
+end
+
+local function onLeave()
+ GameTooltip:Hide()
+end
+
+local function createAuraIcon(element, index)
+ local button = CreateFrame('Button', '$parentButton' .. index, element)
+ button:RegisterForClicks('RightButtonUp')
+
+ local cd = CreateFrame('Cooldown', '$parentCooldown', button, 'oUF_CooldownFrameTemplate')
+ cd:SetAllPoints()
+
+ local icon = button:CreateTexture(nil, 'BORDER')
+ icon:SetAllPoints()
+
+ local count = button:CreateFontString(nil, 'OVERLAY', 'NumberFontNormal')
+ count:SetPoint('BOTTOMRIGHT', button, 'BOTTOMRIGHT', -1, 0)
+
+ local overlay = button:CreateTexture(nil, 'OVERLAY')
+ overlay:SetTexture([[Interface\Buttons\UI-Debuff-Overlays]])
+ overlay:SetAllPoints()
+ overlay:SetTexCoord(.296875, .5703125, 0, .515625)
+ button.overlay = overlay
+
+ button.UpdateTooltip = UpdateTooltip
+ button:SetScript('OnEnter', onEnter)
+ button:SetScript('OnLeave', onLeave)
+
+ button.icon = icon
+ button.count = count
+ button.cd = cd
+
+ --[[ Callback: Auras:PostCreateIcon(button)
+ Called after a new aura button has been created.
+
+ * self - the widget holding the aura buttons
+ * button - the newly created aura button (Button)
+ --]]
+ if(element.PostCreateIcon) then element:PostCreateIcon(button) end
+
+ return button
+end
+
+local function customFilter(element, unit, button, name)
+ if(name) then
+ return true
+ end
+end
+
+local function updateIcon(element, unit, index, offset, filter, isDebuff, visible)
+ local name, rank, texture, count, dispelType, duration, expiration = UnitAura(unit, index, filter)
+
+ if element.forceShow then
+ name, rank, texture = GetSpellInfo(26993)
+ count, dispelType, duration, expiration = 5, 'Magic', 0, 60
+ end
+
+ if(name) then
+ local position = visible + offset + 1
+ local button = element[position]
+ if(not button) then
+ --[[ Override: Auras:CreateIcon(position)
+ Used to create the aura button at a given position.
+
+ * self - the widget holding the aura buttons
+ * position - the position at which the aura button is to be created (number)
+
+ ## Returns
+
+ * button - the button used to represent the aura (Button)
+ --]]
+ button = (element.CreateIcon or createAuraIcon) (element, position)
+
+ tinsert(element, button)
+ element.createdIcons = element.createdIcons + 1
+ end
+
+ button.filter = filter
+ button.isDebuff = isDebuff
+
+ --[[ Override: Auras:CustomFilter(unit, button, ...)
+ Defines a custom filter that controls if the aura button should be shown.
+
+ * self - the widget holding the aura buttons
+ * unit - the unit on which the aura is cast (string)
+ * button - the button displaying the aura (Button)
+ * ... - the return values from [UnitAura](http://wowprogramming.com/docs/api/UnitAura)
+
+ ## Returns
+
+ * show - indicates whether the aura button should be shown (boolean)
+ --]]
+ local show = true
+ if not element.forceShow then
+ show = (element.CustomFilter or customFilter) (element, unit, button, name, rank, texture, count, dispelType, duration, expiration)
+ end
+
+ if(show) then
+ -- We might want to consider delaying the creation of an actual cooldown
+ -- object to this point, but I think that will just make things needlessly
+ -- complicated.
+ if(button.cd and not element.disableCooldown) then
+ if(duration and duration > 0) then
+ button.cd:SetCooldown(GetTime() - (duration - expiration), duration)
+ button.cd:Show()
+ else
+ button.cd:Hide()
+ end
+ end
+
+ if(button.overlay) then
+ if((isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType) then
+ local color = DebuffTypeColor[dispelType] or DebuffTypeColor.none
+
+ button.overlay:SetVertexColor(color.r, color.g, color.b)
+ button.overlay:Show()
+ else
+ button.overlay:Hide()
+ end
+ end
+
+ if(button.icon) then button.icon:SetTexture(texture) end
+ if(button.count) then button.count:SetText(count > 1 and count) end
+
+ local size = element.size or 16
+ button:SetSize(size, size)
+
+ button:EnableMouse(not element.disableMouse)
+ button:SetID(index)
+ button:Show()
+
+ --[[ Callback: Auras:PostUpdateIcon(unit, button, index, position)
+ Called after the aura button has been updated.
+
+ * self - the widget holding the aura buttons
+ * unit - the unit on which the aura is cast (string)
+ * button - the updated aura button (Button)
+ * index - the index of the aura (number)
+ * position - the actual position of the aura button (number)
+ --]]
+ if(element.PostUpdateIcon) then
+ element:PostUpdateIcon(unit, button, index, position)
+ end
+
+ return VISIBLE
+ else
+ return HIDDEN
+ end
+ end
+end
+
+local function SetPosition(element, from, to)
+ local sizex = (element.size or 16) + (element['spacing-x'] or element.spacing or 0)
+ local sizey = (element.size or 16) + (element['spacing-y'] or element.spacing or 0)
+ local anchor = element.initialAnchor or 'BOTTOMLEFT'
+ local growthx = (element['growth-x'] == 'LEFT' and -1) or 1
+ local growthy = (element['growth-y'] == 'DOWN' and -1) or 1
+ local cols = floor(element:GetWidth() / sizex + 0.5)
+
+ for i = from, to do
+ local button = element[i]
+
+ -- Bail out if the to range is out of scope.
+ if(not button) then break end
+ local col = (i - 1) % cols
+ local row = floor((i - 1) / cols)
+
+ button:ClearAllPoints()
+ button:SetPoint(anchor, element, anchor, col * sizex * growthx, row * sizey * growthy)
+ end
+end
+
+local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontHide)
+ if(not offset) then offset = 0 end
+ local index = 1
+ local visible = 0
+ local hidden = 0
+ while(visible < limit) do
+ local result = updateIcon(element, unit, index, offset, filter, isDebuff, visible)
+ if(not result) then
+ break
+ elseif(result == VISIBLE) then
+ visible = visible + 1
+ elseif(result == HIDDEN) then
+ hidden = hidden + 1
+ end
+
+ index = index + 1
+ end
+
+ if(not dontHide) then
+ for i = visible + offset + 1, #element do
+ element[i]:Hide()
+ end
+ end
+
+ return visible, hidden
+end
+
+local function UpdateAuras(self, event, unit)
+ if(self.unit ~= unit) then return end
+
+ local auras = self.Auras
+ if(auras) then
+ --[[ Callback: Auras:PreUpdate(unit)
+ Called before the element has been updated.
+
+ * self - the widget holding the aura buttons
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(auras.PreUpdate) then auras:PreUpdate(unit) end
+
+ local numBuffs = auras.numBuffs or 32
+ local numDebuffs = auras.numDebuffs or 40
+ local max = auras.numTotal or numBuffs + numDebuffs
+
+ local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', math.min(numBuffs, max), nil, 0, true)
+
+ local hasGap
+ if(visibleBuffs ~= 0 and auras.gap) then
+ hasGap = true
+ visibleBuffs = visibleBuffs + 1
+
+ local button = auras[visibleBuffs]
+ if(not button) then
+ button = (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs)
+ tinsert(auras, button)
+ auras.createdIcons = auras.createdIcons + 1
+ end
+
+ -- Prevent the button from displaying anything.
+ if(button.cd) then button.cd:Hide() end
+ if(button.icon) then button.icon:SetTexture() end
+ if(button.overlay) then button.overlay:Hide() end
+ if(button.stealable) then button.stealable:Hide() end
+ if(button.count) then button.count:SetText() end
+
+ button:EnableMouse(false)
+ button:Show()
+
+ --[[ Callback: Auras:PostUpdateGapIcon(unit, gapButton, visibleBuffs)
+ Called after an invisible aura button has been created. Only used by Auras when the `gap` option is enabled.
+
+ * self - the widget holding the aura buttons
+ * unit - the unit that has the invisible aura button (string)
+ * gapButton - the invisible aura button (Button)
+ * visibleBuffs - the number of currently visible aura buttons (number)
+ --]]
+ if(auras.PostUpdateGapIcon) then
+ auras:PostUpdateGapIcon(unit, button, visibleBuffs)
+ end
+ end
+
+ local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', math.min(numDebuffs, max - visibleBuffs), true, visibleBuffs)
+ auras.visibleDebuffs = visibleDebuffs
+
+ if(hasGap and visibleDebuffs == 0) then
+ auras[visibleBuffs]:Hide()
+ visibleBuffs = visibleBuffs - 1
+ end
+
+ auras.visibleBuffs = visibleBuffs
+ auras.visibleAuras = auras.visibleBuffs + auras.visibleDebuffs
+
+ local fromRange, toRange
+ --[[ Callback: Auras:PreSetPosition(max)
+ Called before the aura buttons have been (re-)anchored.
+
+ * self - the widget holding the aura buttons
+ * max - the maximum possible number of aura buttons (number)
+
+ ## Returns
+
+ * from - the offset of the first aura button to be (re-)anchored (number)
+ * to - the offset of the last aura button to be (re-)anchored (number)
+ --]]
+ if(auras.PreSetPosition) then
+ fromRange, toRange = auras:PreSetPosition(max)
+ end
+
+ if(fromRange or auras.createdIcons > auras.anchoredIcons) then
+ --[[ Override: Auras:SetPosition(from, to)
+ Used to (re-)anchor the aura buttons.
+ Called when new aura buttons have been created or if :PreSetPosition is defined.
+
+ * self - the widget that holds the aura buttons
+ * from - the offset of the first aura button to be (re-)anchored (number)
+ * to - the offset of the last aura button to be (re-)anchored (number)
+ --]]
+ (auras.SetPosition or SetPosition) (auras, fromRange or auras.anchoredIcons + 1, toRange or auras.createdIcons)
+ auras.anchoredIcons = auras.createdIcons
+ end
+
+ --[[ Callback: Auras:PostUpdate(unit)
+ Called after the element has been updated.
+
+ * self - the widget holding the aura buttons
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(auras.PostUpdate) then auras:PostUpdate(unit) end
+ end
+
+ local buffs = self.Buffs
+ if(buffs) then
+ if(buffs.PreUpdate) then buffs:PreUpdate(unit) end
+
+ local numBuffs = buffs.num or 32
+ local visibleBuffs, hiddenBuffs = filterIcons(buffs, unit, buffs.filter or 'HELPFUL', numBuffs)
+ buffs.visibleBuffs = visibleBuffs
+
+ local fromRange, toRange
+ if(buffs.PreSetPosition) then
+ fromRange, toRange = buffs:PreSetPosition(numBuffs)
+ end
+
+ if(fromRange or buffs.createdIcons > buffs.anchoredIcons) then
+ (buffs.SetPosition or SetPosition) (buffs, fromRange or buffs.anchoredIcons + 1, toRange or buffs.createdIcons)
+ buffs.anchoredIcons = buffs.createdIcons
+ end
+
+ if(buffs.PostUpdate) then buffs:PostUpdate(unit) end
+ end
+
+ local debuffs = self.Debuffs
+ if(debuffs) then
+ if(debuffs.PreUpdate) then debuffs:PreUpdate(unit) end
+
+ local numDebuffs = debuffs.num or 40
+ local visibleDebuffs, hiddenDebuffs = filterIcons(debuffs, unit, debuffs.filter or 'HARMFUL', numDebuffs, true)
+ debuffs.visibleDebuffs = visibleDebuffs
+
+ local fromRange, toRange
+ if(debuffs.PreSetPosition) then
+ fromRange, toRange = debuffs:PreSetPosition(numDebuffs)
+ end
+
+ if(fromRange or debuffs.createdIcons > debuffs.anchoredIcons) then
+ (debuffs.SetPosition or SetPosition) (debuffs, fromRange or debuffs.anchoredIcons + 1, toRange or debuffs.createdIcons)
+ debuffs.anchoredIcons = debuffs.createdIcons
+ end
+
+ if(debuffs.PostUpdate) then debuffs:PostUpdate(unit) end
+ end
+end
+
+local function Update(self, event, unit)
+ if(self.unit ~= unit) then return end
+
+ UpdateAuras(self, event, unit)
+
+ -- Assume no event means someone wants to re-anchor things. This is usually
+ -- done by UpdateAllElements and :ForceUpdate.
+ if(event == 'ForceUpdate' or not event) then
+ local buffs = self.Buffs
+ if(buffs) then
+ (buffs.SetPosition or SetPosition) (buffs, 1, buffs.createdIcons)
+ end
+
+ local debuffs = self.Debuffs
+ if(debuffs) then
+ (debuffs.SetPosition or SetPosition) (debuffs, 1, debuffs.createdIcons)
+ end
+
+ local auras = self.Auras
+ if(auras) then
+ (auras.SetPosition or SetPosition) (auras, 1, auras.createdIcons)
+ end
+ end
+end
+
+local function ForceUpdate(element)
+ return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self)
+ if(self.Buffs or self.Debuffs or self.Auras) then
+ self:RegisterEvent('UNIT_AURA', UpdateAuras)
+
+ local buffs = self.Buffs
+ if(buffs) then
+ buffs.__owner = self
+ buffs.ForceUpdate = ForceUpdate
+
+ buffs.createdIcons = buffs.createdIcons or 0
+ buffs.anchoredIcons = 0
+
+ --buffs:Show()
+ end
+
+ local debuffs = self.Debuffs
+ if(debuffs) then
+ debuffs.__owner = self
+ debuffs.ForceUpdate = ForceUpdate
+
+ debuffs.createdIcons = debuffs.createdIcons or 0
+ debuffs.anchoredIcons = 0
+
+ --debuffs:Show()
+ end
+
+ local auras = self.Auras
+ if(auras) then
+ auras.__owner = self
+ auras.ForceUpdate = ForceUpdate
+
+ auras.createdIcons = auras.createdIcons or 0
+ auras.anchoredIcons = 0
+
+ --auras:Show()
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ if(self.Buffs or self.Debuffs or self.Auras) then
+ self:UnregisterEvent('UNIT_AURA', UpdateAuras)
+
+ if(self.Buffs) then self.Buffs:Hide() end
+ if(self.Debuffs) then self.Debuffs:Hide() end
+ if(self.Auras) then self.Auras:Hide() end
+ end
+end
+
+oUF:AddElement('Auras', Update, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/castbar.lua b/ElvUI/Libraries/oUF/elements/castbar.lua
new file mode 100644
index 0000000..538e62f
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/castbar.lua
@@ -0,0 +1,585 @@
+--[[
+# Element: Castbar
+
+Handles the visibility and updating of spell castbars.
+Based upon oUF_Castbar by starlon.
+
+## Widget
+
+Castbar - A `StatusBar` to represent spell cast/channel progress.
+
+## Sub-Widgets
+
+.Text - A `FontString` to represent spell name.
+.Icon - A `Texture` to represent spell icon.
+.Time - A `FontString` to represent spell duration.
+.SafeZone - A `Texture` to represent latency.
+
+## Notes
+
+A default texture will be applied to the StatusBar and Texture widgets if they don't have a texture or a color set.
+
+## Options
+
+.timeToHold - indicates for how many seconds the castbar should be visible after a _FAILED or _INTERRUPTED
+ event. Defaults to 0 (number)
+
+## Examples
+
+ -- Position and size
+ local Castbar = CreateFrame('StatusBar', nil, self)
+ Castbar:SetSize(20, 20)
+ Castbar:SetPoint('TOP')
+ Castbar:SetPoint('LEFT')
+ Castbar:SetPoint('RIGHT')
+
+ -- Add a background
+ local Background = Castbar:CreateTexture(nil, 'BACKGROUND')
+ Background:SetAllPoints(Castbar)
+ Background:SetTexture(1, 1, 1, .5)
+
+ -- Add a spark
+ local Spark = Castbar:CreateTexture(nil, 'OVERLAY')
+ Spark:SetSize(20, 20)
+ Spark:SetBlendMode('ADD')
+
+ -- Add a timer
+ local Time = Castbar:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
+ Time:SetPoint('RIGHT', Castbar)
+
+ -- Add spell text
+ local Text = Castbar:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
+ Text:SetPoint('LEFT', Castbar)
+
+ -- Add spell icon
+ local Icon = Castbar:CreateTexture(nil, 'OVERLAY')
+ Icon:SetSize(20, 20)
+ Icon:SetPoint('TOPLEFT', Castbar, 'TOPLEFT')
+
+ -- Add safezone
+ local SafeZone = Castbar:CreateTexture(nil, 'OVERLAY')
+
+ -- Register it with oUF
+ Castbar.bg = Background
+ Castbar.Spark = Spark
+ Castbar.Time = Time
+ Castbar.Text = Text
+ Castbar.Icon = Icon
+ Castbar.SafeZone = SafeZone
+ self.Castbar = Castbar
+--]]
+local ns = oUF
+local oUF = ns.oUF
+
+local GetNetStats = GetNetStats
+local GetTime = GetTime
+local UnitCastingInfo = UnitCastingInfo
+local UnitChannelInfo = UnitChannelInfo
+local UnitIsUnit = UnitIsUnit
+
+local tradeskillCastTime, tradeskillCastDuration, tradeskillCurrent, tradeskillTotal, mergeTradeskill = 0, 0, 0, 0, false
+
+local function updateSafeZone(self)
+ local safeZone = self.SafeZone
+ local width = self:GetWidth()
+ local _, _, ms = GetNetStats()
+
+ -- Guard against GetNetStats returning latencies of 0.
+ if(ms ~= 0) then
+ local safeZoneRatio = (ms / 1e3) / self.max
+ if(safeZoneRatio > 1) then
+ safeZoneRatio = 1
+ end
+ safeZone:SetWidth(width * safeZoneRatio)
+ safeZone:Show()
+ else
+ safeZone:Hide()
+ end
+end
+
+local function UNIT_SPELLCAST_SENT(self, event, unit, spell, rank, target)
+ local element = self.Castbar
+ element.curTarget = (target and target ~= '') and target or nil
+
+ if element.isTradeSkill then
+ element.tradeSkillCastName = spell
+ end
+end
+
+local function UNIT_SPELLCAST_START(self, event, unit)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ local name, _, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(unit)
+ if(not name) then
+ return element:Hide()
+ end
+
+ endTime = endTime / 1e3
+ startTime = startTime / 1e3
+ local max = endTime - startTime
+
+ element.castName = name
+ element.duration = GetTime() - startTime
+ element.max = max
+ element.delay = 0
+ element.casting = true
+ element.holdTime = 0
+ element.isTradeSkill = isTradeSkill
+
+ if(mergeTradeskill and isTradeSkill and UnitIsUnit(unit, 'player')) then
+ element.duration = element.duration + (element.max * tradeskillCurrent)
+ element.max = max * tradeskillTotal
+
+ if(unit == 'player') then
+ tradeskillCurrent = tradeskillCurrent + 1
+ tradeskillCastDuration = element.duration
+ tradeskillCastTime = max
+ end
+
+ element:SetValue(element.duration)
+ else
+ element:SetValue(0)
+ end
+ element:SetMinMaxValues(0, element.max)
+
+ if(element.Text) then element.Text:SetText(text) end
+ if(element.Icon) then element.Icon:SetTexture(texture) end
+ if(element.Time) then element.Time:SetText() end
+
+ local sf = element.SafeZone
+ if(sf) then
+ sf:ClearAllPoints()
+ sf:SetPoint('RIGHT')
+ sf:SetPoint('TOP')
+ sf:SetPoint('BOTTOM')
+ updateSafeZone(element)
+ end
+
+ --[[ Callback: Castbar:PostCastStart(unit, name)
+ Called after the element has been updated upon a spell cast start.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the spell being cast (string)
+ --]]
+ if(element.PostCastStart) then
+ element:PostCastStart(unit, name)
+ end
+ element:Show()
+end
+
+local function UNIT_SPELLCAST_FAILED(self, event, unit, spellname)
+ if(not self.casting) then return end
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ if(spellname and (element.castName ~= spellname and element.tradeSkillCastName ~= spellname)) then
+ return
+ end
+
+ if(mergeTradeskill and UnitIsUnit(unit, 'player')) then
+ mergeTradeskill = false
+ element.tradeSkillCastName = nil
+ end
+
+ local text = element.Text
+ if(text) then
+ text:SetText(FAILED)
+ end
+
+ element.casting = nil
+ element.holdTime = element.timeToHold or 0
+
+ --[[ Callback: Castbar:PostCastFailed(unit, name)
+ Called after the element has been updated upon a failed spell cast.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the failed spell (string)
+ --]]
+ if(element.PostCastFailed) then
+ return element:PostCastFailed(unit, spellname)
+ end
+end
+
+local function UNIT_SPELLCAST_FAILED_QUIET(self, event, unit, spellname)
+ if(not self.casting) then return end
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ if(spellname and (element.castName ~= spellname and element.tradeSkillCastName ~= spellname)) then
+ return
+ end
+
+ if(mergeTradeskill and UnitIsUnit(unit, 'player')) then
+ mergeTradeskill = false
+ element.tradeSkillCastName = nil
+ end
+
+ element.casting = nil
+ element:SetValue(0)
+ element:Hide()
+end
+
+local function UNIT_SPELLCAST_INTERRUPTED(self, event, unit, spellname)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ if(spellname and element.castName ~= spellname) then
+ return
+ end
+
+ local text = element.Text
+ if(text) then
+ text:SetText(INTERRUPTED)
+ end
+
+ element.casting = nil
+ element.channeling = nil
+ element.holdTime = element.timeToHold or 0
+
+ --[[ Callback: Castbar:PostCastInterrupted(unit, name)
+ Called after the element has been updated upon an interrupted spell cast.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the interrupted spell (string)
+ --]]
+ if(element.PostCastInterrupted) then
+ return element:PostCastInterrupted(unit, spellname)
+ end
+end
+
+local function UNIT_SPELLCAST_DELAYED(self, event, unit)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ local name, _, _, _, startTime = UnitCastingInfo(unit)
+ if(not startTime or not element:IsShown()) then return end
+
+ local duration = GetTime() - (startTime / 1000)
+ if(duration < 0) then duration = 0 end
+
+ element.delay = element.delay + element.duration - duration
+ element.duration = duration
+
+ element:SetValue(duration)
+
+ --[[ Callback: Castbar:PostCastDelayed(unit, name)
+ Called after the element has been updated when a spell cast has been delayed.
+
+ * self - the Castbar widget
+ * unit - unit that the update has been triggered (string)
+ * name - name of the delayed spell (string)
+ --]]
+ if(element.PostCastDelayed) then
+ return element:PostCastDelayed(unit, name)
+ end
+end
+
+local function UNIT_SPELLCAST_STOP(self, event, unit, spellname)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ if(spellname and (element.castName ~= spellname)) then
+ return
+ end
+
+ if(mergeTradeskill and UnitIsUnit(unit, 'player')) then
+ if(tradeskillCurrent == tradeskillTotal) then
+ mergeTradeskill = false
+ end
+ else
+ element.casting = nil
+ end
+
+ --[[ Callback: Castbar:PostCastStop(unit, name)
+ Called after the element has been updated when a spell cast has finished.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the spell (string)
+ --]]
+ if(element.PostCastStop) then
+ return element:PostCastStop(unit, spellname)
+ end
+end
+
+local function UNIT_SPELLCAST_CHANNEL_START(self, event, unit)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ local name, _, _, texture, startTime, endTime = UnitChannelInfo(unit)
+ if(not name) then
+ return
+ end
+
+ endTime = endTime / 1e3
+ startTime = startTime / 1e3
+ local max = (endTime - startTime)
+ local duration = endTime - GetTime()
+
+ element.duration = duration
+ element.max = max
+ element.delay = 0
+ element.startTime = startTime
+ element.endTime = endTime
+ element.extraTickRatio = 0
+ element.channeling = true
+ element.holdTime = 0
+
+ -- We have to do this, as it's possible for spell casts to never have _STOP
+ -- executed or be fully completed by the OnUpdate handler before CHANNEL_START
+ -- is called.
+ element.casting = nil
+ element.castName = nil
+
+ element:SetMinMaxValues(0, max)
+ element:SetValue(duration)
+
+ if(element.Text) then element.Text:SetText(name) end
+ if(element.Icon) then element.Icon:SetTexture(texture) end
+ if(element.Time) then element.Time:SetText() end
+
+ local sf = element.SafeZone
+ if(sf) then
+ sf:ClearAllPoints()
+ sf:SetPoint('LEFT')
+ sf:SetPoint('TOP')
+ sf:SetPoint('BOTTOM')
+ updateSafeZone(element)
+ end
+
+ --[[ Callback: Castbar:PostChannelStart(unit, name)
+ Called after the element has been updated upon a spell channel start.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the channeled spell (string)
+ --]]
+ if(element.PostChannelStart) then
+ element:PostChannelStart(unit, name)
+ end
+ element:Show()
+end
+
+local function UNIT_SPELLCAST_CHANNEL_UPDATE(self, event, unit)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ local name, _, _, _, startTime, endTime = UnitChannelInfo(unit)
+ if(not name or not element:IsShown()) then
+ return
+ end
+
+ local duration = (endTime / 1000) - GetTime()
+ element.delay = element.delay + element.duration - duration
+ element.duration = duration
+ element.max = (endTime - startTime) / 1000
+ element.startTime = startTime / 1000
+ element.endTime = endTime / 1000
+
+ element:SetMinMaxValues(0, element.max)
+ element:SetValue(duration)
+
+ --[[ Callback: Castbar:PostChannelUpdate(unit, name)
+ Called after the element has been updated after a channeled spell has been delayed or interrupted.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the channeled spell (string)
+ --]]
+ if(element.PostChannelUpdate) then
+ return element:PostChannelUpdate(unit, name)
+ end
+end
+
+local function UNIT_SPELLCAST_CHANNEL_STOP(self, event, unit, spellname)
+ if(self.unit ~= unit and self.realUnit ~= unit) then return end
+
+ local element = self.Castbar
+ if(element:IsShown()) then
+ element.channeling = nil
+
+ --[[ Callback: Castbar:PostChannelUpdate(unit, name)
+ Called after the element has been updated after a channeled spell has been completed.
+
+ * self - the Castbar widget
+ * unit - unit for which the update has been triggered (string)
+ * name - name of the channeled spell (string)
+ --]]
+ if(element.PostChannelStop) then
+ return element:PostChannelStop(unit, spellname)
+ end
+ end
+end
+
+local function onUpdate(self, elapsed)
+ if(self.casting) then
+ local duration = self.duration + elapsed
+ if(duration >= self.max or (tradeskillTotal > 1 and duration >= (tradeskillCastDuration + tradeskillCastTime * 1.25))) then
+ self.casting = nil
+ self:Hide()
+ tradeskillTotal = 0
+
+ if(self.PostCastStop) then self:PostCastStop(self.__owner.unit) end
+ return
+ end
+
+ if(self.Time) then
+ if(self.delay ~= 0) then
+ if(self.CustomDelayText) then
+ self:CustomDelayText(duration)
+ else
+ self.Time:SetText(format('%.1f|cffff0000-%.1f|r', duration, self.delay))
+ end
+ else
+ if(self.CustomTimeText) then
+ self:CustomTimeText(duration)
+ else
+ self.Time:SetText(format('%.1f', duration))
+ end
+ end
+ end
+
+ self.duration = duration
+ self:SetValue(duration)
+
+ if(self.Spark) then
+ self.Spark:SetPoint('CENTER', self, 'LEFT', (duration / self.max) * self:GetWidth(), 0)
+ end
+ elseif(self.channeling) then
+ local duration = self.duration - elapsed
+
+ if(duration <= 0) then
+ self.channeling = nil
+ self:Hide()
+
+ if(self.PostChannelStop) then self:PostChannelStop(self.__owner.unit) end
+ return
+ end
+
+ if(self.Time) then
+ if(self.delay ~= 0) then
+ if(self.CustomDelayText) then
+ self:CustomDelayText(duration)
+ else
+ self.Time:SetText(format('%.1f|cffff0000-%.1f|r', duration, self.delay))
+ end
+ else
+ if(self.CustomTimeText) then
+ self:CustomTimeText(duration)
+ else
+ self.Time:SetText(format('%.1f', duration))
+ end
+ end
+ end
+
+ self.duration = duration
+ self:SetValue(duration)
+ if(self.Spark) then
+ self.Spark:SetPoint('CENTER', self, 'LEFT', (duration / self.max) * self:GetWidth(), 0)
+ end
+ elseif(self.holdTime > 0) then
+ self.holdTime = self.holdTime - elapsed
+ else
+ self.casting = nil
+ self.castName = nil
+ self.channeling = nil
+ tradeskillTotal = 0
+
+ self:Hide()
+ end
+end
+
+local function Update(self, ...)
+ UNIT_SPELLCAST_START(self, ...)
+ return UNIT_SPELLCAST_CHANNEL_START(self, ...)
+end
+
+local function ForceUpdate(element)
+ return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self, unit)
+ local element = self.Castbar
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ if(not (unit and unit:match('%wtarget$'))) then
+ self:RegisterEvent('UNIT_SPELLCAST_START', UNIT_SPELLCAST_START)
+ self:RegisterEvent('UNIT_SPELLCAST_FAILED', UNIT_SPELLCAST_FAILED)
+ self:RegisterEvent('UNIT_SPELLCAST_STOP', UNIT_SPELLCAST_STOP)
+ self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', UNIT_SPELLCAST_INTERRUPTED)
+ self:RegisterEvent('UNIT_SPELLCAST_DELAYED', UNIT_SPELLCAST_DELAYED)
+ self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', UNIT_SPELLCAST_CHANNEL_START)
+ self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', UNIT_SPELLCAST_CHANNEL_UPDATE)
+ self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', UNIT_SPELLCAST_CHANNEL_STOP)
+ self:RegisterEvent('UNIT_SPELLCAST_SENT', UNIT_SPELLCAST_SENT, true)
+ self:RegisterEvent('UNIT_SPELLCAST_FAILED_QUIET', UNIT_SPELLCAST_FAILED_QUIET)
+ end
+
+ element.holdTime = 0
+ element:SetScript('OnUpdate', element.OnUpdate or onUpdate)
+
+ if(self.unit == 'player') then
+ CastingBarFrame:UnregisterAllEvents()
+ CastingBarFrame.Show = CastingBarFrame.Hide
+ CastingBarFrame:Hide()
+
+ PetCastingBarFrame:UnregisterAllEvents()
+ PetCastingBarFrame.Show = PetCastingBarFrame.Hide
+ PetCastingBarFrame:Hide()
+ end
+
+ if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
+ element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
+ end
+
+ local spark = element.Spark
+ if(spark and spark:IsObjectType('Texture') and not spark:GetTexture()) then
+ spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
+ end
+
+ local safeZone = element.SafeZone
+ if(safeZone and safeZone:IsObjectType('Texture') and not safeZone:GetTexture()) then
+ safeZone:SetTexture(1, 0, 0)
+ end
+
+ element:Hide()
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.Castbar
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('UNIT_SPELLCAST_START', UNIT_SPELLCAST_START)
+ self:UnregisterEvent('UNIT_SPELLCAST_FAILED', UNIT_SPELLCAST_FAILED)
+ self:UnregisterEvent('UNIT_SPELLCAST_STOP', UNIT_SPELLCAST_STOP)
+ self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTED', UNIT_SPELLCAST_INTERRUPTED)
+ self:UnregisterEvent('UNIT_SPELLCAST_DELAYED', UNIT_SPELLCAST_DELAYED)
+ self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_START', UNIT_SPELLCAST_CHANNEL_START)
+ self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', UNIT_SPELLCAST_CHANNEL_UPDATE)
+ self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', UNIT_SPELLCAST_CHANNEL_STOP)
+ self:UnregisterEvent('UNIT_SPELLCAST_SENT', UNIT_SPELLCAST_SENT)
+ self:UnregisterEvent('UNIT_SPELLCAST_FAILED_QUIET', UNIT_SPELLCAST_FAILED_QUIET)
+
+ element:SetScript('OnUpdate', nil)
+ end
+end
+
+hooksecurefunc('DoTradeSkill', function(_, num)
+ tradeskillCastTime = 0
+ tradeskillCastDuration = 0
+ tradeskillCurrent = 0
+ tradeskillTotal = num or 1
+ mergeTradeskill = true
+end)
+
+oUF:AddElement('Castbar', Update, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/combatindicator.lua b/ElvUI/Libraries/oUF/elements/combatindicator.lua
new file mode 100644
index 0000000..51d34b1
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/combatindicator.lua
@@ -0,0 +1,102 @@
+--[[
+# Element: Combat Indicator
+
+Toggles the visibility of an indicator based on the player's combat status.
+
+## Widget
+
+CombatIndicator - Any UI widget.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ -- Position and size
+ local CombatIndicator = self:CreateTexture(nil, 'OVERLAY')
+ CombatIndicator:SetSize(16, 16)
+ CombatIndicator:SetPoint('TOP', self)
+
+ -- Register it with oUF
+ self.CombatIndicator = CombatIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local UnitAffectingCombat = UnitAffectingCombat
+
+local function Update(self, event)
+ local element = self.CombatIndicator
+
+ --[[ Callback: CombatIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the CombatIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local inCombat = UnitAffectingCombat('player')
+ if(inCombat) then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: CombatIndicator:PostUpdate(inCombat)
+ Called after the element has been updated.
+
+ * self - the CombatIndicator element
+ * inCombat - indicates if the player is affecting combat (boolean)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(inCombat)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: CombatIndicator.Override(self, event)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ --]]
+ return (self.CombatIndicator.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self, unit)
+ local element = self.CombatIndicator
+ if(element and unit == 'player') then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PLAYER_REGEN_DISABLED', Path)
+ self:RegisterEvent('PLAYER_REGEN_ENABLED', Path)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\CharacterFrame\UI-StateIcon]])
+ element:SetTexCoord(.5, 1, 0, .49)
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.CombatIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('PLAYER_REGEN_DISABLED', Path)
+ self:UnregisterEvent('PLAYER_REGEN_ENABLED', Path)
+ end
+end
+
+oUF:AddElement('CombatIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/combopoints.lua b/ElvUI/Libraries/oUF/elements/combopoints.lua
new file mode 100644
index 0000000..e8d5e55
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/combopoints.lua
@@ -0,0 +1,118 @@
+--[[
+# Element: ComboPoints
+
+Handles the visibility and updating of the player's combo points.
+
+## Widget
+
+ComboPoints - An `table` consisting of as many Textures as the theoretical maximum return of [GetComboPoints](http://wowprogramming.com/docs/api/GetComboPoints).
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ local ComboPoints = {}
+ for index = 1, 10 do
+ local Bar = CreateFrame('StatusBar', nil, self)
+
+ -- Position and size.
+ Bar:SetSize(16, 16)
+ Bar:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', (index - 1) * Bar:GetWidth(), 0)
+
+ ComboPoints[index] = Bar
+ end
+
+ -- Register with oUF
+ self.ComboPoints = ComboPoints
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local GetComboPoints = GetComboPoints
+local MAX_COMBO_POINTS = MAX_COMBO_POINTS
+
+local function Update(self, event)
+ local element = self.ComboPoints
+
+ --[[ Callback: ComboPoints:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the ComboPoints element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local cp = GetComboPoints('player', 'target')
+
+ for i = 1, MAX_COMBO_POINTS do
+ if(i <= cp) then
+ element[i]:Show()
+ else
+ element[i]:Hide()
+ end
+ end
+
+ --[[ Callback: ComboPoints:PostUpdate(role)
+ Called after the element has been updated.
+
+ * self - the ComboPoints element
+ * cpoint - the current amount of combo points (number)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(cp)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: ComboPoints.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.ComboPoints.Override or Update) (self, ...)
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self)
+ local element = self.ComboPoints
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PLAYER_COMBO_POINTS', Path, true)
+ self:RegisterEvent('PLAYER_TARGET_CHANGED', Path, true)
+
+ for index = 1, MAX_COMBO_POINTS do
+ local cp = element[index]
+ if(cp:IsObjectType('Texture') and not cp:GetTexture()) then
+ cp:SetTexture([[Interface\ComboFrame\ComboPoint]])
+ cp:SetTexCoord(0, 0.375, 0, 1)
+ end
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.ComboPoints
+ if(element) then
+ for index = 1, MAX_COMBO_POINTS do
+ element[index]:Hide()
+ end
+
+ self:UnregisterEvent('PLAYER_COMBO_POINTS', Path)
+ self:UnregisterEvent('PLAYER_TARGET_CHANGED', Path)
+ end
+end
+
+oUF:AddElement('ComboPoints', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/elements.xml b/ElvUI/Libraries/oUF/elements/elements.xml
new file mode 100644
index 0000000..91f969b
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/elements.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/happinessindicator.lua b/ElvUI/Libraries/oUF/elements/happinessindicator.lua
new file mode 100644
index 0000000..80e5f81
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/happinessindicator.lua
@@ -0,0 +1,116 @@
+--[[
+# Element: HappinessIndicator
+
+Handles the visibility and updating of player pet happiness.
+
+## Widget
+
+HappinessIndicator - A `Texture` used to display the current happiness level.
+The element works by changing the texture's vertex color.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ -- Position and size
+ local HappinessIndicator = self:CreateTexture(nil, 'OVERLAY')
+ HappinessIndicator:SetSize(16, 16)
+ HappinessIndicator:SetPoint('TOPRIGHT', self)
+
+ -- Register it with oUF
+ self.HappinessIndicator = HappinessIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local GetPetHappiness = GetPetHappiness
+local HasPetUI = HasPetUI
+
+local function Update(self, event, unit)
+ if(not unit or self.unit ~= unit) then return end
+
+ local element = self.HappinessIndicator
+
+ --[[ Callback: HappinessIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the ComboPoints element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local _, hunterPet = HasPetUI()
+ local happiness, damagePercentage = GetPetHappiness()
+
+ if(hunterPet and happiness) then
+ if(happiness == 1) then
+ element:SetTexCoord(0.375, 0.5625, 0, 0.359375)
+ elseif(happiness == 2) then
+ element:SetTexCoord(0.1875, 0.375, 0, 0.359375)
+ elseif(happiness == 3) then
+ element:SetTexCoord(0, 0.1875, 0, 0.359375)
+ end
+
+ element:Show()
+ else
+ return element:Hide()
+ end
+
+ --[[ Callback: HappinessIndicator:PostUpdate(role)
+ Called after the element has been updated.
+
+ * self - the ComboPoints element
+ * unit - the unit for which the update has been triggered (string)
+ * happiness - the numerical happiness value of the pet (1 = unhappy, 2 = content, 3 = happy) (number)
+ * damagePercentage - damage modifier, happiness affects this (unhappy = 75%, content = 100%, happy = 125%) (number)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(unit, happiness, damagePercentage)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: HappinessIndicator.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.HappinessIndicator.Override or Update) (self, ...)
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self)
+ local element = self.HappinessIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('UNIT_HAPPINESS', Path)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\PetPaperDollFrame\UI-PetHappiness]])
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.HappinessIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('UNIT_HAPPINESS', Path)
+ end
+end
+
+oUF:AddElement('HappinessIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/health.lua b/ElvUI/Libraries/oUF/elements/health.lua
new file mode 100644
index 0000000..6a9d705
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/health.lua
@@ -0,0 +1,292 @@
+--[[
+# Element: Health Bar
+
+Handles the updating of a status bar that displays the unit's health.
+
+## Widget
+
+Health - A `StatusBar` used to represent the unit's health.
+
+## Sub-Widgets
+
+.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
+
+## Notes
+
+A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
+
+## Options
+
+.frequentUpdates - Indicates whether to use OnUpdate script instead of UNIT_HEALTH to update the bar (boolean)
+.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
+
+The following options are listed by priority. The first check that returns true decides the color of the bar.
+
+.colorTapping - Use `self.colors.tapping` to color the bar if the unit isn't tapped by the player (boolean)
+.colorDisconnected - Use `self.colors.disconnected` to color the bar if the unit is offline (boolean)
+.colorHappiness - Use `self.colors.happiness` to color the bar if the unit is pet based on pet happiness (boolean)
+.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
+ second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass) (boolean)
+.colorClassNPC - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
+.colorClassPet - Use `self.colors.class[class]` to color the bar if the unit is player controlled, but not a player
+ (boolean)
+.colorReaction - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
+ unit. `reaction` is defined by the return value of
+ [UnitReaction](http://wowprogramming.com/docs/api/UnitReaction) (boolean)
+.colorSmooth - Use `smoothGradient` if present or `self.colors.smooth` to color the bar with a smooth gradient
+ based on the player's current health percentage (boolean)
+.colorHealth - Use `self.colors.health` to color the bar. This flag is used to reset the bar color back to default
+ if none of the above conditions are met (boolean)
+
+## Sub-Widgets Options
+
+.multiplier - Used to tint the background based on the main widgets R, G and B values. Defaults to 1 (number)[0-1]
+
+## Attributes
+
+.disconnected - Indicates whether the unit is disconnected (boolean)
+
+## Examples
+
+ -- Position and size
+ local Health = CreateFrame('StatusBar', nil, self)
+ Health:SetHeight(20)
+ Health:SetPoint('TOP')
+ Health:SetPoint('LEFT')
+ Health:SetPoint('RIGHT')
+
+ -- Add a background
+ local Background = Health:CreateTexture(nil, 'BACKGROUND')
+ Background:SetAllPoints(Health)
+ Background:SetTexture(1, 1, 1, .5)
+
+ -- Options
+ Health.frequentUpdates = true
+ Health.colorTapping = true
+ Health.colorDisconnected = true
+ Health.colorClass = true
+ Health.colorReaction = true
+ Health.colorHealth = true
+
+ -- Make the background darker.
+ Background.multiplier = .5
+
+ -- Register it with oUF
+ Health.bg = Background
+ self.Health = Health
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local unpack = unpack
+
+local GetPetHappiness = GetPetHappiness
+local UnitClass = UnitClass
+local UnitHealth = UnitHealth
+local UnitHealthMax = UnitHealthMax
+local UnitIsConnected = UnitIsConnected
+local UnitIsPlayer = UnitIsPlayer
+local UnitIsTapped = UnitIsTapped
+local UnitIsTappedByPlayer = UnitIsTappedByPlayer
+local UnitIsUnit = UnitIsUnit
+local UnitPlayerControlled = UnitPlayerControlled
+local UnitReaction = UnitReaction
+
+local updateFrequentUpdates
+
+local function UpdateColor(element, unit, cur, max)
+ local parent = element.__owner
+
+ if element.frequentUpdates ~= element.__frequentUpdates then
+ element.__frequentUpdates = element.frequentUpdates
+ updateFrequentUpdates(parent, unit)
+ end
+
+ local r, g, b, t
+ if(element.colorTapping and not UnitPlayerControlled(unit) and (UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit))) then
+ t = parent.colors.tapped
+ elseif(element.colorDisconnected and element.disconnected) then
+ t = parent.colors.disconnected
+ elseif(element.colorHappiness and UnitIsUnit(unit, 'pet') and GetPetHappiness()) then
+ t = parent.colors.happiness[GetPetHappiness()]
+ elseif(element.colorClass and UnitIsPlayer(unit)) or
+ (element.colorClassNPC and not UnitIsPlayer(unit)) or
+ (element.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
+ local _, class = UnitClass(unit)
+ t = parent.colors.class[class]
+ elseif(element.colorReaction and UnitReaction(unit, 'player')) then
+ t = parent.colors.reaction[UnitReaction(unit, 'player')]
+ elseif(element.colorSmooth) then
+ r, g, b = parent.ColorGradient(cur, max, unpack(element.smoothGradient or parent.colors.smooth))
+ elseif(element.colorHealth) then
+ t = parent.colors.health
+ end
+
+ if(t) then
+ r, g, b = t[1], t[2], t[3]
+ end
+
+ if(r or g or b) then
+ element:SetStatusBarColor(r, g, b)
+
+ local bg = element.bg
+ if(bg) then
+ local mu = bg.multiplier or 1
+ bg:SetVertexColor(r * mu, g * mu, b * mu)
+ end
+ end
+end
+
+local function Update(self, event, unit)
+ if(not unit or self.unit ~= unit) then return end
+ local element = self.Health
+
+ --[[ Callback: Health:PreUpdate(unit)
+ Called before the element has been updated.
+
+ * self - the Health element
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate(unit)
+ end
+
+ local cur, max = UnitHealth(unit), UnitHealthMax(unit)
+ local disconnected = not UnitIsConnected(unit)
+ element:SetMinMaxValues(0, max)
+
+ if(disconnected) then
+ element:SetValue(max)
+ else
+ element:SetValue(cur)
+ end
+
+ element.disconnected = disconnected
+
+ --[[ Override: Health:UpdateColor(unit, cur, max)
+ Used to completely override the internal function for updating the widgets' colors.
+
+ * self - the Health element
+ * unit - the unit for which the update has been triggered (string)
+ * cur - the unit's current health value (number)
+ * max - the unit's maximum possible health value (number)
+ --]]
+ element:UpdateColor(unit, cur, max)
+
+ --[[ Callback: Health:PostUpdate(unit, cur, max)
+ Called after the element has been updated.
+
+ * self - the Health element
+ * unit - the unit for which the update has been triggered (string)
+ * cur - the unit's current health value (number)
+ * max - the unit's maximum possible health value (number)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(unit, cur, max)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: Health.Override(self, event, unit)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * unit - the unit accompanying the event (string)
+ --]]
+ return (self.Health.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function onHealthUpdate()
+ if(this.disconnected) then return end
+
+ local unit = this.__owner.unit
+ local health = UnitHealth(unit)
+
+ if(health ~= this.min) then
+ this.min = health
+
+ return Path(this.__owner, 'OnHealthUpdate', unit)
+ end
+end
+
+function updateFrequentUpdates(self, unit)
+ if(not unit or string.match(unit, '%w+target$')) then return end
+
+ local element = self.Health
+ if(element.frequentUpdates and not element:GetScript('OnUpdate')) then
+ element:SetScript('OnUpdate', onHealthUpdate)
+
+ if((unit == 'party' or string.match(unit, 'party%d?$'))) then
+ self:RegisterEvent('UNIT_HEALTH', Path)
+ elseif(self:IsEventRegistered("UNIT_HEALTH")) then
+ self:UnregisterEvent('UNIT_HEALTH', Path)
+ end
+ elseif(not element.frequentUpdates and element:GetScript('OnUpdate')) then
+ element:SetScript('OnUpdate', nil)
+
+ self:RegisterEvent('UNIT_HEALTH', Path)
+ end
+end
+
+local function Enable(self, unit)
+ local element = self.Health
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+ element.__frequentUpdates = element.frequentUpdates
+ updateFrequentUpdates(self, unit)
+
+ if(element.frequentUpdates and (unit and not string.match(unit, '%w+target$'))) then
+ element:SetScript('OnUpdate', onHealthUpdate)
+
+ -- The party frames need this to handle disconnect states correctly.
+ if(unit == 'party') then
+ self:RegisterEvent('UNIT_HEALTH', Path)
+ end
+ else
+ self:RegisterEvent('UNIT_HEALTH', Path)
+ end
+
+ self:RegisterEvent('UNIT_MAXHEALTH', Path)
+ self:RegisterEvent('UNIT_CONNECTION', Path)
+ self:RegisterEvent('UNIT_FACTION', Path) -- For tapping
+ self:RegisterEvent('UNIT_HAPPINESS', Path)
+
+ if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
+ element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
+ end
+
+ if(not element.UpdateColor) then
+ element.UpdateColor = UpdateColor
+ end
+
+ element:Show()
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.Health
+ if(element) then
+ if(element:GetScript('OnUpdate')) then
+ element:SetScript('OnUpdate', nil)
+ end
+
+ element:Hide()
+
+ self:UnregisterEvent('UNIT_HEALTH', Path)
+ self:UnregisterEvent('UNIT_MAXHEALTH', Path)
+ self:UnregisterEvent('UNIT_CONNECTION', Path)
+ self:UnregisterEvent('UNIT_FACTION', Path)
+ self:UnregisterEvent('UNIT_HAPPINESS', Path)
+ end
+end
+
+oUF:AddElement('Health', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/leaderindicator.lua b/ElvUI/Libraries/oUF/elements/leaderindicator.lua
new file mode 100644
index 0000000..df5c83d
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/leaderindicator.lua
@@ -0,0 +1,107 @@
+--[[
+# Element: Leader Indicator
+
+Toggles the visibility of an indicator based on the unit's leader status.
+
+## Widget
+
+LeaderIndicator - Any UI widget.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ -- Position and size
+ local LeaderIndicator = self:CreateTexture(nil, 'OVERLAY')
+ LeaderIndicator:SetSize(16, 16)
+ LeaderIndicator:SetPoint('BOTTOM', self, 'TOP')
+
+ -- Register it with oUF
+ self.LeaderIndicator = LeaderIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local UnitInParty = UnitInParty
+local UnitInRaid = UnitInRaid
+local UnitIsPartyLeader = UnitIsPartyLeader
+
+local function Update(self, event)
+ local element = self.LeaderIndicator
+
+ --[[ Callback: LeaderIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the LeaderIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local unit = self.unit
+ local isLeader = (UnitInParty(unit) or UnitInRaid(unit)) and UnitIsPartyLeader(unit)
+ if(isLeader) then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: LeaderIndicator:PostUpdate(isLeader)
+ Called after the element has been updated.
+
+ * self - the LeaderIndicator element
+ * isLeader - indicates whether the element is shown (boolean)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(isLeader)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: LeaderIndicator.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.LeaderIndicator.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self)
+ local element = self.LeaderIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PARTY_LEADER_CHANGED', Path)
+ self:RegisterEvent('PARTY_MEMBERS_CHANGED', Path)
+ self:RegisterEvent('RAID_ROSTER_UPDATE', Path)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\GroupFrame\UI-Group-LeaderIcon]])
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.LeaderIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('PARTY_LEADER_CHANGED', Path)
+ self:UnregisterEvent('PARTY_MEMBERS_CHANGED', Path)
+ self:UnregisterEvent('RAID_ROSTER_UPDATE', Path)
+ end
+end
+
+oUF:AddElement('LeaderIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/masterlooterindicator.lua b/ElvUI/Libraries/oUF/elements/masterlooterindicator.lua
new file mode 100644
index 0000000..17e59e7
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/masterlooterindicator.lua
@@ -0,0 +1,126 @@
+--[[
+# Element: Master Looter Indicator
+
+Toggles the visibility of an indicator based on the unit's master looter status.
+
+## Widget
+
+MasterLooterIndicator - Any UI widget.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ -- Position and size
+ local MasterLooterIndicator = self:CreateTexture(nil, 'OVERLAY')
+ MasterLooterIndicator:SetSize(16, 16)
+ MasterLooterIndicator:SetPoint('TOPRIGHT', self)
+
+ -- Register it with oUF
+ self.MasterLooterIndicator = MasterLooterIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local GetLootMethod = GetLootMethod
+local UnitInParty = UnitInParty
+local UnitInRaid = UnitInRaid
+local UnitIsUnit = UnitIsUnit
+
+local function Update(self, event)
+ local unit = self.unit
+ local element = self.MasterLooterIndicator
+
+ --[[ Callback: MasterLooterIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the MasterLooterIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local isShown = false
+ if(UnitInParty(unit) or UnitInRaid(unit)) then
+ local method, partyIndex, raidIndex = GetLootMethod()
+ if(method == 'master') then
+ local mlUnit
+ if(partyIndex) then
+ if(partyIndex == 0) then
+ mlUnit = 'player'
+ else
+ mlUnit = 'party' .. partyIndex
+ end
+ elseif(raidIndex) then
+ mlUnit = 'raid' .. raidIndex
+ end
+
+ if(mlUnit and UnitIsUnit(unit, mlUnit)) then
+ isShown = true
+ end
+ end
+ end
+
+ if isShown then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: MasterLooterIndicator:PostUpdate(isShown)
+ Called after the element has been updated.
+
+ * self - the MasterLooterIndicator element
+ * isShown - indicates whether the element is shown (boolean)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(isShown)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: MasterLooterIndicator.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.MasterLooterIndicator.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self, unit)
+ local element = self.MasterLooterIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PARTY_LOOT_METHOD_CHANGED', Path, true)
+ self:RegisterEvent('PARTY_MEMBERS_CHANGED', Path, true)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\GroupFrame\UI-Group-MasterLooter]])
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.MasterLooterIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('PARTY_LOOT_METHOD_CHANGED', Path)
+ self:UnregisterEvent('PARTY_MEMBERS_CHANGED', Path)
+ end
+end
+
+oUF:AddElement('MasterLooterIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/portrait.lua b/ElvUI/Libraries/oUF/elements/portrait.lua
new file mode 100644
index 0000000..5416c29
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/portrait.lua
@@ -0,0 +1,148 @@
+--[[
+# Element: Portraits
+
+Handles the updating of the unit's portrait.
+
+## Widget
+
+Portrait - A `PlayerModel` or a `Texture` used to represent the unit's portrait.
+
+## Notes
+
+A question mark model will be used if the widget is a PlayerModel and the client doesn't have the model information for
+the unit.
+
+## Examples
+
+ -- 3D Portrait
+ -- Position and size
+ local Portrait = CreateFrame('PlayerModel', nil, self)
+ Portrait:SetSize(32, 32)
+ Portrait:SetPoint('RIGHT', self, 'LEFT')
+
+ -- Register it with oUF
+ self.Portrait = Portrait
+
+ -- 2D Portrait
+ local Portrait = self:CreateTexture(nil, 'OVERLAY')
+ Portrait:SetSize(32, 32)
+ Portrait:SetPoint('RIGHT', self, 'LEFT')
+
+ -- Register it with oUF
+ self.Portrait = Portrait
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local SetPortraitTexture = SetPortraitTexture
+local UnitExists = UnitExists
+local UnitName = UnitName
+local UnitIsConnected = UnitIsConnected
+local UnitIsUnit = UnitIsUnit
+local UnitIsVisible = UnitIsVisible
+
+local function Update(self, event, unit)
+ if(not unit or not UnitIsUnit(self.unit, unit)) then return end
+
+ local element = self.Portrait
+
+ --[[ Callback: Portrait:PreUpdate(unit)
+ Called before the element has been updated.
+
+ * self - the Portrait element
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(element.PreUpdate) then element:PreUpdate(unit) end
+
+ local name = UnitName(unit)
+ local isAvailable = UnitIsConnected(unit) and UnitIsVisible(unit)
+ if(event ~= 'OnUpdate' or element.name ~= name or element.state ~= isAvailable) then
+ if(element:IsObjectType('PlayerModel')) then
+ if(not isAvailable) then
+ element:SetModelScale(4.25)
+ element:SetCamera(0)
+ element:SetPosition(0, 0, -1.5)
+ element:SetModel([[Interface\Buttons\TalkToMeQuestionMark.m2]])
+ elseif(element.name ~= name or event == 'UNIT_MODEL_CHANGED') then
+ element:ClearModel()
+ element:SetUnit(unit)
+ element:SetModelScale(1)
+ element:SetCamera(0)
+ element:SetPosition(0, 0, 0)
+ else
+ element:SetCamera(0)
+ end
+ else
+ SetPortraitTexture(element, unit)
+ end
+
+ element.name = name
+ element.state = isAvailable
+ end
+
+ --[[ Callback: Portrait:PostUpdate(unit)
+ Called after the element has been updated.
+
+ * self - the Portrait element
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(unit)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: Portrait.Override(self, event, unit)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * unit - the unit accompanying the event (string)
+ --]]
+ return (self.Portrait.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self, unit)
+ local element = self.Portrait
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('UNIT_PORTRAIT_UPDATE', Path)
+ self:RegisterEvent('UNIT_MODEL_CHANGED', Path)
+ self:RegisterEvent('UNIT_CONNECTION', Path)
+
+ -- The quest log uses PARTY_MEMBER_{ENABLE,DISABLE} to handle updating of
+ -- party members overlapping quests. This will probably be enough to handle
+ -- model updating.
+ --
+ -- DISABLE isn't used as it fires when we most likely don't have the
+ -- information we want.
+ if(unit == 'party') then
+ self:RegisterEvent('PARTY_MEMBER_ENABLE', Path)
+ end
+
+ element:Show()
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.Portrait
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('UNIT_PORTRAIT_UPDATE', Path)
+ self:UnregisterEvent('UNIT_MODEL_CHANGED', Path)
+ self:UnregisterEvent('PARTY_MEMBER_ENABLE', Path)
+ self:UnregisterEvent('UNIT_CONNECTION', Path)
+ end
+end
+
+oUF:AddElement('Portrait', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/power.lua b/ElvUI/Libraries/oUF/elements/power.lua
new file mode 100644
index 0000000..d9489c0
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/power.lua
@@ -0,0 +1,326 @@
+--[[
+# Element: Power Bar
+
+Handles the updating of a status bar that displays the unit's power.
+
+## Widget
+
+Power - A `StatusBar` used to represent the unit's power.
+
+## Sub-Widgets
+
+.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
+
+## Notes
+
+A default texture will be applied if the widget is a StatusBar and doesn't have a texture or a color set.
+
+## Options
+
+.frequentUpdates - Indicates whether to use OnUpdate script instead of UNIT_POWER to update the bar. Only valid for the
+ player and pet units (boolean)
+.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
+
+The following options are listed by priority. The first check that returns true decides the color of the bar.
+
+.colorTapping - Use `self.colors.tapping` to color the bar if the unit isn't tapped by the player (boolean)
+.colorDisconnected - Use `self.colors.disconnected` to color the bar if the unit is offline (boolean)
+.colorHappiness - Use `self.colors.happiness` to color the bar if the unit is pet based on pet happiness (boolean)
+.colorPower - Use `self.colors.power[token]` to color the bar based on the unit's power type. This method will
+ fall-back to `:GetAlternativeColor()` if it can't find a color matching the token. If this function
+ isn't defined, then it will attempt to color based upon the alternative power colors returned by
+ [UnitPowerType](http://wowprogramming.com/docs/api/UnitPowerType). Finally, if these aren't
+ defined, then it will attempt to color the bar based upon `self.colors.power[type]` (boolean)
+.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
+ second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass) (boolean)
+.colorClassNPC - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
+.colorClassPet - Use `self.colors.class[class]` to color the bar if the unit is player controlled, but not a player
+ (boolean)
+.colorReaction - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
+ unit. `reaction` is defined by the return value of
+ [UnitReaction](http://wowprogramming.com/docs/api/UnitReaction) (boolean)
+.colorSmooth - Use `smoothGradient` if present or `self.colors.smooth` to color the bar with a smooth gradient
+ based on the player's current power percentage (boolean)
+
+## Sub-Widget Options
+
+.multiplier - A multiplier used to tint the background based on the main widgets R, G and B values. Defaults to 1
+ (number)[0-1]
+
+## Attributes
+
+.disconnected - Indicates whether the unit is disconnected (boolean)
+.tapped - Indicates whether the unit is tapped by the player (boolean)
+
+## Examples
+
+ -- Position and size
+ local Power = CreateFrame('StatusBar', nil, self)
+ Power:SetHeight(20)
+ Power:SetPoint('BOTTOM')
+ Power:SetPoint('LEFT')
+ Power:SetPoint('RIGHT')
+
+ -- Add a background
+ local Background = Power:CreateTexture(nil, 'BACKGROUND')
+ Background:SetAllPoints(Power)
+ Background:SetTexture(1, 1, 1, .5)
+
+ -- Options
+ Power.frequentUpdates = true
+ Power.colorTapping = true
+ Power.colorDisconnected = true
+ Power.colorPower = true
+ Power.colorClass = true
+ Power.colorReaction = true
+
+ -- Make the background darker.
+ Background.multiplier = .5
+
+ -- Register it with oUF
+ Power.bg = Background
+ self.Power = Power
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local unpack = unpack
+
+local GetPetHappiness = GetPetHappiness
+local UnitClass = UnitClass
+local UnitIsConnected = UnitIsConnected
+local UnitIsPlayer = UnitIsPlayer
+local UnitIsTapped = UnitIsTapped
+local UnitIsTappedByPlayer = UnitIsTappedByPlayer
+local UnitIsUnit = UnitIsUnit
+local UnitMana = UnitMana
+local UnitManaMax = UnitManaMax
+local UnitPlayerControlled = UnitPlayerControlled
+local UnitPowerType = UnitPowerType
+local UnitReaction = UnitReaction
+
+local updateFrequentUpdates
+
+local function UpdateColor(element, unit, cur, min, max)
+ local parent = element.__owner
+
+ if element.frequentUpdates ~= element.__frequentUpdates then
+ element.__frequentUpdates = element.frequentUpdates
+ updateFrequentUpdates(element, unit)
+ end
+
+ local ptype = UnitPowerType(unit)
+ local r, g, b, t
+ if(element.colorTapping and element.tapped) then
+ t = parent.colors.tapped
+ elseif(element.colorDisconnected and element.disconnected) then
+ t = parent.colors.disconnected
+ elseif(element.colorHappiness and UnitIsUnit(unit, 'pet') and GetPetHappiness()) then
+ t = parent.colors.happiness[GetPetHappiness()]
+ elseif(element.colorPower) then
+ t = parent.colors.power[ptype]
+ elseif(element.colorClass and UnitIsPlayer(unit)) or
+ (element.colorClassNPC and not UnitIsPlayer(unit)) or
+ (element.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
+ local _, class = UnitClass(unit)
+ t = parent.colors.class[class]
+ elseif(element.colorReaction and UnitReaction(unit, 'player')) then
+ t = parent.colors.reaction[UnitReaction(unit, 'player')]
+ elseif(element.colorSmooth) then
+ local adjust = 0 - (min or 0)
+ r, g, b = parent.ColorGradient(cur + adjust, max + adjust, unpack(element.smoothGradient or parent.colors.smooth))
+ end
+
+ if(t) then
+ r, g, b = t[1], t[2], t[3]
+ end
+
+ t = parent.colors.power[ptype]
+
+ element:SetStatusBarTexture(element.texture)
+
+ if(r or g or b) then
+ element:SetStatusBarColor(r, g, b)
+ end
+
+ local bg = element.bg
+ if(bg and b) then
+ local mu = bg.multiplier or 1
+ bg:SetVertexColor(r * mu, g * mu, b * mu)
+ end
+end
+
+local function Update(self, event, unit)
+ if(self.unit ~= unit) then return end
+ local element = self.Power
+
+ --[[ Callback: Power:PreUpdate(unit)
+ Called before the element has been updated.
+
+ * self - the Power element
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate(unit)
+ end
+
+ local cur, max = UnitMana(unit), UnitManaMax(unit)
+ local disconnected = not UnitIsConnected(unit)
+ local tapped = not UnitPlayerControlled(unit) and (UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit))
+ element:SetMinMaxValues(0, max)
+
+ if(disconnected) then
+ element:SetValue(max)
+ else
+ element:SetValue(cur)
+ end
+
+ element.disconnected = disconnected
+ element.tapped = tapped
+
+ --[[ Override: Power:UpdateColor(unit, cur, max)
+ Used to completely override the internal function for updating the widget's colors.
+
+ * self - the Power element
+ * unit - the unit for which the update has been triggered (string)
+ * cur - the unit's current power value (number)
+ * max - the unit's maximum possible power value (number)
+ --]]
+ element:UpdateColor(unit, cur, max)
+
+ --[[ Callback: Power:PostUpdate(unit, cur, max)
+ Called after the element has been updated.
+
+ * self - the Power element
+ * unit - the unit for which the update has been triggered (string)
+ * cur - the unit's current power value (number)
+ * max - the unit's maximum possible power value (number)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(unit, cur, max)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: Power.Override(self, event, unit, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * unit - the unit accompanying the event (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.Power.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function onPowerUpdate()
+ if(this.disconnected) then return end
+
+ local unit = this.__owner.unit
+ local power = UnitMana(unit)
+
+ if(power ~= this.min) then
+ this.min = power
+
+ return Path(this.__owner, 'OnPowerUpdate', unit)
+ end
+end
+
+function updateFrequentUpdates(self, unit)
+ if(not unit or (unit ~= 'player' and unit ~= 'pet')) then return end
+
+ local element = self.Power
+ if(element.frequentUpdates and not element:GetScript('OnUpdate')) then
+ element:SetScript('OnUpdate', onPowerUpdate)
+
+ self:UnregisterEvent('UNIT_MANA', Path)
+ self:UnregisterEvent('UNIT_RAGE', Path)
+ self:UnregisterEvent('UNIT_FOCUS', Path)
+ self:UnregisterEvent('UNIT_ENERGY', Path)
+ elseif(not element.frequentUpdates and element:GetScript('OnUpdate')) then
+ element:SetScript('OnUpdate', nil)
+
+ self:RegisterEvent('UNIT_MANA', Path)
+ self:RegisterEvent('UNIT_RAGE', Path)
+ self:RegisterEvent('UNIT_FOCUS', Path)
+ self:RegisterEvent('UNIT_ENERGY', Path)
+ end
+end
+
+local function Enable(self, unit)
+ local element = self.Power
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+ element.__frequentUpdates = element.frequentUpdates
+ updateFrequentUpdates(self, unit)
+
+ if(element.frequentUpdates and (unit == 'player' or unit == 'pet')) then
+ element:SetScript('OnUpdate', onPowerUpdate)
+ else
+ self:RegisterEvent('UNIT_MANA', Path)
+ self:RegisterEvent('UNIT_RAGE', Path)
+ self:RegisterEvent('UNIT_FOCUS', Path)
+ self:RegisterEvent('UNIT_ENERGY', Path)
+ end
+
+ self:RegisterEvent('UNIT_MAXMANA', Path)
+ self:RegisterEvent('UNIT_MAXRAGE', Path)
+ self:RegisterEvent('UNIT_MAXFOCUS', Path)
+ self:RegisterEvent('UNIT_MAXENERGY', Path)
+ self:RegisterEvent('UNIT_MAXRUNIC_POWER', Path)
+ self:RegisterEvent('UNIT_DISPLAYPOWER', Path)
+
+ self:RegisterEvent('UNIT_CONNECTION', Path)
+ self:RegisterEvent('UNIT_HAPPINESS', Path)
+ self:RegisterEvent('UNIT_FACTION', Path) -- For tapping
+
+ if(element:IsObjectType('StatusBar')) then
+ element.texture = element:GetStatusBarTexture() and element:GetStatusBarTexture():GetTexture() or [[Interface\TargetingFrame\UI-StatusBar]]
+ element:SetStatusBarTexture(element.texture)
+ end
+
+ if(not element.UpdateColor) then
+ element.UpdateColor = UpdateColor
+ end
+
+ element:Show()
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.Power
+ if(element) then
+ element:Hide()
+
+ if(element:GetScript('OnUpdate')) then
+ element:SetScript('OnUpdate', nil)
+ else
+ self:UnregisterEvent('UNIT_MANA', Path)
+ self:UnregisterEvent('UNIT_RAGE', Path)
+ self:UnregisterEvent('UNIT_FOCUS', Path)
+ self:UnregisterEvent('UNIT_ENERGY', Path)
+ self:UnregisterEvent('UNIT_RUNIC_POWER', Path)
+ end
+
+ self:UnregisterEvent('UNIT_MAXMANA', Path)
+ self:UnregisterEvent('UNIT_MAXRAGE', Path)
+ self:UnregisterEvent('UNIT_MAXFOCUS', Path)
+ self:UnregisterEvent('UNIT_MAXENERGY', Path)
+ self:UnregisterEvent('UNIT_MAXRUNIC_POWER', Path)
+ self:UnregisterEvent('UNIT_DISPLAYPOWER', Path)
+
+ self:UnregisterEvent('UNIT_CONNECTION', Path)
+ self:UnregisterEvent('UNIT_HAPPINESS', Path)
+ self:UnregisterEvent('UNIT_FACTION', Path)
+ end
+end
+
+oUF:AddElement('Power', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/pvpindicator.lua b/ElvUI/Libraries/oUF/elements/pvpindicator.lua
new file mode 100644
index 0000000..3d8c436
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/pvpindicator.lua
@@ -0,0 +1,118 @@
+--[[
+# Element: PvP Icon
+
+Handles the visibility and updating of an indicator based on the unit's PvP status.
+
+## Widget
+
+PvPIndicator - A `Texture` used to display faction, FFA PvP status icon.
+
+## Notes
+
+This element updates by changing the texture.
+
+## Examples
+
+ -- Position and size
+ local PvPIndicator = self:CreateTexture(nil, 'ARTWORK', nil, 1)
+ PvPIndicator:SetSize(30, 30)
+ PvPIndicator:SetPoint('RIGHT', self, 'LEFT')
+
+ -- Register it with oUF
+ self.PvPIndicator = PvPIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local UnitFactionGroup = UnitFactionGroup
+local UnitIsPVP = UnitIsPVP
+local UnitIsPVPFreeForAll = UnitIsPVPFreeForAll
+
+local FFA_ICON = [[Interface\TargetingFrame\UI-PVP-FFA]]
+local FACTION_ICON = [[Interface\TargetingFrame\UI-PVP-]]
+
+local function Update(self, event, unit)
+ if(unit ~= self.unit) then return end
+
+ local element = self.PvPIndicator
+
+ --[[ Callback: PvPIndicator:PreUpdate(unit)
+ Called before the element has been updated.
+
+ * self - the PvPIndicator element
+ * unit - the unit for which the update has been triggered (string)
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate(unit)
+ end
+
+ local status
+ local factionGroup = UnitFactionGroup(unit)
+
+ if(UnitIsPVPFreeForAll(unit)) then
+ element:SetTexture(FFA_ICON)
+ element:SetTexCoord(0, 0.65625, 0, 0.65625)
+ status = 'ffa'
+ elseif(factionGroup and factionGroup ~= 'Neutral' and UnitIsPVP(unit)) then
+ element:SetTexture(FACTION_ICON .. factionGroup)
+ element:SetTexCoord(0, 0.65625, 0, 0.65625)
+ status = factionGroup
+ end
+
+ if(status) then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: PvPIndicator:PostUpdate(unit, status)
+ Called after the element has been updated.
+
+ * self - the PvPIndicator element
+ * unit - the unit for which the update has been triggered (string)
+ * status - the unit's current PvP status or faction accounting for mercenary mode (string)['ffa', 'Alliance',
+ 'Horde']
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(unit, status)
+ end
+end
+
+local function Path(self, ...)
+ --[[Override: PvPIndicator.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.PvPIndicator.Override or Update) (self, ...)
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
+end
+
+local function Enable(self)
+ local element = self.PvPIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('UNIT_FACTION', Path)
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.PvPIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('UNIT_FACTION', Path)
+ end
+end
+
+oUF:AddElement('PvPIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/raidroleindicator.lua b/ElvUI/Libraries/oUF/elements/raidroleindicator.lua
new file mode 100644
index 0000000..678b9de
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/raidroleindicator.lua
@@ -0,0 +1,114 @@
+--[[
+# Element: Raid Role Indicator
+
+Handles the visibility and updating of an indicator based on the unit's raid assignment (main tank or main assist).
+
+## Widget
+
+RaidRoleIndicator - A `Texture` representing the unit's raid assignment.
+
+## Notes
+
+This element updates by changing the texture.
+
+## Examples
+
+ -- Position and size
+ local RaidRoleIndicator = self:CreateTexture(nil, 'OVERLAY')
+ RaidRoleIndicator:SetSize(16, 16)
+ RaidRoleIndicator:SetPoint('TOPLEFT')
+
+ -- Register it with oUF
+ self.RaidRoleIndicator = RaidRoleIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local GetPartyAssignment = GetPartyAssignment
+local UnitInRaid = UnitInRaid
+
+local MAINTANK_ICON = [[Interface\GROUPFRAME\UI-GROUP-MAINTANKICON]]
+local MAINASSIST_ICON = [[Interface\GROUPFRAME\UI-GROUP-MAINASSISTICON]]
+
+local function Update(self, event)
+ local unit = self.unit
+
+ local element = self.RaidRoleIndicator
+
+ --[[ Callback: RaidRoleIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the RaidRoleIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local role, isShown
+ if(UnitInRaid(unit)) then
+ if(GetPartyAssignment('MAINTANK', unit)) then
+ isShown = true
+ element:SetTexture(MAINTANK_ICON)
+ role = 'MAINTANK'
+ elseif(GetPartyAssignment('MAINASSIST', unit)) then
+ isShown = true
+ element:SetTexture(MAINASSIST_ICON)
+ role = 'MAINASSIST'
+ end
+ end
+
+ if isShown then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: RaidRoleIndicator:PostUpdate(role)
+ Called after the element has been updated.
+
+ * self - the RaidRoleIndicator element
+ * role - the unit's raid assignment (string?)['MAINTANK', 'MAINASSIST']
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(role)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: RaidRoleIndicator.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.RaidRoleIndicator.Override or Update)(self, ...)
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self)
+ local element = self.RaidRoleIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PARTY_MEMBERS_CHANGED', Path, true)
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.RaidRoleIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('PARTY_MEMBERS_CHANGED', Path)
+ end
+end
+
+oUF:AddElement('RaidRoleIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/raidtargetindicator.lua b/ElvUI/Libraries/oUF/elements/raidtargetindicator.lua
new file mode 100644
index 0000000..f97bfad
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/raidtargetindicator.lua
@@ -0,0 +1,102 @@
+--[[
+# Element: Raid Target Indicator
+
+Handles the visibility and updating of an indicator based on the unit's raid target assignment.
+
+## Widget
+
+RaidTargetIndicator - A `Texture` used to display the raid target icon.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture set.
+
+## Examples
+
+ -- Position and size
+ local RaidTargetIndicator = self:CreateTexture(nil, 'OVERLAY')
+ RaidTargetIndicator:SetSize(16, 16)
+ RaidTargetIndicator:SetPoint('TOPRIGHT', self)
+
+ -- Register it with oUF
+ self.RaidTargetIndicator = RaidTargetIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local GetRaidTargetIndex = GetRaidTargetIndex
+local SetRaidTargetIconTexture = SetRaidTargetIconTexture
+
+local function Update(self, event)
+ local element = self.RaidTargetIndicator
+
+ --[[ Callback: RaidTargetIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the RaidTargetIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local index = GetRaidTargetIndex(self.unit)
+ if(index) then
+ SetRaidTargetIconTexture(element, index)
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: RaidTargetIndicator:PostUpdate(index)
+ Called after the element has been updated.
+
+ * self - the RaidTargetIndicator element
+ * index - the index of the raid target marker (number?)[1-8]
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(index)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: RaidTargetIndicator.Override(self, event)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ --]]
+ return (self.RaidTargetIndicator.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ if(not element.__owner.unit) then return end
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self)
+ local element = self.RaidTargetIndicator
+ if(element) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('RAID_TARGET_UPDATE', Path, true)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\TargetingFrame\UI-RaidTargetingIcons]])
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.RaidTargetIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('RAID_TARGET_UPDATE', Path)
+ end
+end
+
+oUF:AddElement('RaidTargetIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/range.lua b/ElvUI/Libraries/oUF/elements/range.lua
new file mode 100644
index 0000000..f78d7a2
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/range.lua
@@ -0,0 +1,137 @@
+--[[
+# Element: Range Fader
+
+Changes the opacity of a unit frame based on whether the frame's unit is in the player's range.
+
+## Widget
+
+Range - A table containing opacity values.
+
+## Notes
+
+Offline units are handled as if they are in range.
+
+## Options
+
+.outsideAlpha - Opacity when the unit is out of range. Defaults to 0.55 (number)[0-1].
+.insideAlpha - Opacity when the unit is within range. Defaults to 1 (number)[0-1].
+
+## Examples
+
+ -- Register with oUF
+ self.Range = {
+ insideAlpha = 1,
+ outsideAlpha = 1/2,
+ }
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local _FRAMES = {}
+local OnRangeFrame
+
+local UnitInRange, UnitIsConnected = UnitInRange, UnitIsConnected
+
+local function Update(self, event)
+ local element = self.Range
+ local unit = self.unit
+
+ --[[ Callback: Range:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the Range element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local inRange
+ local connected = UnitIsConnected(unit)
+ if(connected) then
+ inRange = UnitInRange(unit)
+ if(not inRange) then
+ self:SetAlpha(element.outsideAlpha)
+ else
+ self:SetAlpha(element.insideAlpha)
+ end
+ else
+ self:SetAlpha(element.insideAlpha)
+ end
+
+ --[[ Callback: Range:PostUpdate(object, inRange, isConnected)
+ Called after the element has been updated.
+
+ * self - the Range element
+ * object - the parent object
+ * inRange - indicates if the unit was within 40 yards of the player (boolean)
+ * isConnected - indicates if the unit is online (boolean)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(self, inRange, connected)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: Range.Override(self, event)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ --]]
+ return (self.Range.Override or Update) (self, ...)
+end
+
+-- Internal updating method
+local timer = 0
+local function OnRangeUpdate(_, elapsed)
+ timer = timer + elapsed
+
+ if(timer >= .20) then
+ for _, object in next, _FRAMES do
+ if(object:IsShown()) then
+ Path(object, 'OnUpdate')
+ end
+ end
+
+ timer = 0
+ end
+end
+
+local function Enable(self)
+ local element = self.Range
+ if(element) then
+ element.__owner = self
+ element.insideAlpha = element.insideAlpha or 1
+ element.outsideAlpha = element.outsideAlpha or 0.55
+
+ if(not OnRangeFrame) then
+ OnRangeFrame = CreateFrame('Frame')
+ OnRangeFrame:SetScript('OnUpdate', OnRangeUpdate)
+ end
+
+ table.insert(_FRAMES, self)
+ OnRangeFrame:Show()
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.Range
+ if(element) then
+ for index, frame in next, _FRAMES do
+ if(frame == self) then
+ table.remove(_FRAMES, index)
+ break
+ end
+ end
+ self:SetAlpha(element.insideAlpha)
+
+ if(#_FRAMES == 0) then
+ OnRangeFrame:Hide()
+ end
+ end
+end
+
+oUF:AddElement('Range', nil, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/readycheckindicator.lua b/ElvUI/Libraries/oUF/elements/readycheckindicator.lua
new file mode 100644
index 0000000..54b8a75
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/readycheckindicator.lua
@@ -0,0 +1,150 @@
+--[[
+# Element: Ready Check Indicator
+
+Handles the visibility and updating of an indicator based on the unit's ready check status.
+
+## Widget
+
+ReadyCheckIndicator - A `Texture` representing ready check status.
+
+## Notes
+
+This element updates by changing the texture.
+Default textures will be applied if the layout does not provide custom ones. See Options.
+
+## Options
+
+.finishedTime - For how many seconds the icon should stick after a check has completed. Defaults to 10 (number).
+.fadeTime - For how many seconds the icon should fade away after the stick duration has completed. Defaults to
+ 1.5 (number).
+.readyTexture - Path to an alternate texture for the ready check 'ready' status.
+.notReadyTexture - Path to an alternate texture for the ready check 'notready' status.
+.waitingTexture - Path to an alternate texture for the ready check 'waiting' status.
+
+## Attributes
+
+.status - the unit's ready check status (string?)['ready', 'noready', 'waiting']
+
+## Examples
+
+ -- Position and size
+ local ReadyCheckIndicator = self:CreateTexture(nil, 'OVERLAY')
+ ReadyCheckIndicator:SetSize(16, 16)
+ ReadyCheckIndicator:SetPoint('TOP')
+
+ -- Register with oUF
+ self.ReadyCheckIndicator = ReadyCheckIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local GetReadyCheckStatus = GetReadyCheckStatus
+local UnitExists = UnitExists
+
+local function OnFinished(self)
+ local element = self:GetParent()
+ element:Hide()
+
+ --[[ Callback: ReadyCheckIndicator:PostUpdateFadeOut()
+ Called after the element has been faded out.
+
+ * self - the ReadyCheckIndicator element
+ --]]
+ if(element.PostUpdateFadeOut) then
+ element:PostUpdateFadeOut()
+ end
+end
+
+local function Update(self, event)
+ local element = self.ReadyCheckIndicator
+
+ --[[ Callback: ReadyCheckIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the ReadyCheckIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local unit = self.unit
+ local status = GetReadyCheckStatus(unit)
+ if(UnitExists(unit) and status) then
+ if(status == 'ready') then
+ element:SetTexture(element.readyTexture)
+ elseif(status == 'notready') then
+ element:SetTexture(element.notReadyTexture)
+ else
+ element:SetTexture(element.waitingTexture)
+ end
+
+ element.status = status
+ element:Show()
+ elseif(event ~= 'READY_CHECK_FINISHED') then
+ element.status = nil
+ element:Hide()
+ end
+
+ if(event == 'READY_CHECK_FINISHED') then
+ if(element.status == 'waiting') then
+ element:SetTexture(element.notReadyTexture)
+ end
+ end
+
+ --[[ Callback: ReadyCheckIndicator:PostUpdate(status)
+ Called after the element has been updated.
+
+ * self - the ReadyCheckIndicator element
+ * status - the unit's ready check status (string?)['ready', 'notready', 'waiting']
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(status)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: ReadyCheckIndicator.Override(self, event, ...)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ * ... - the arguments accompanying the event
+ --]]
+ return (self.ReadyCheckIndicator.Override or Update) (self, ...)
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self, unit)
+ local element = self.ReadyCheckIndicator
+ if(element and (unit and (unit:sub(1, 5) == 'party' or unit:sub(1, 4) == 'raid'))) then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ element.readyTexture = element.readyTexture or READY_CHECK_READY_TEXTURE
+ element.notReadyTexture = element.notReadyTexture or READY_CHECK_NOT_READY_TEXTURE
+ element.waitingTexture = element.waitingTexture or READY_CHECK_WAITING_TEXTURE
+
+ self:RegisterEvent('READY_CHECK', Path, true)
+ self:RegisterEvent('READY_CHECK_CONFIRM', Path, true)
+ self:RegisterEvent('READY_CHECK_FINISHED', Path, true)
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.ReadyCheckIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('READY_CHECK', Path)
+ self:UnregisterEvent('READY_CHECK_CONFIRM', Path)
+ self:UnregisterEvent('READY_CHECK_FINISHED', Path)
+ end
+end
+
+oUF:AddElement('ReadyCheckIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/restingindicator.lua b/ElvUI/Libraries/oUF/elements/restingindicator.lua
new file mode 100644
index 0000000..932be68
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/restingindicator.lua
@@ -0,0 +1,100 @@
+--[[
+# Element: Resting Indicator
+
+Toggles the visibility of an indicator based on the player's resting status.
+
+## Widget
+
+RestingIndicator - Any UI widget.
+
+## Notes
+
+A default texture will be applied if the widget is a Texture and doesn't have a texture or a color set.
+
+## Examples
+
+ -- Position and size
+ local RestingIndicator = self:CreateTexture(nil, 'OVERLAY')
+ RestingIndicator:SetSize(16, 16)
+ RestingIndicator:SetPoint('TOPLEFT', self)
+
+ -- Register it with oUF
+ self.RestingIndicator = RestingIndicator
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local IsResting = IsResting
+
+local function Update(self, event)
+ local element = self.RestingIndicator
+
+ --[[ Callback: RestingIndicator:PreUpdate()
+ Called before the element has been updated.
+
+ * self - the RestingIndicator element
+ --]]
+ if(element.PreUpdate) then
+ element:PreUpdate()
+ end
+
+ local isResting = IsResting()
+ if(isResting) then
+ element:Show()
+ else
+ element:Hide()
+ end
+
+ --[[ Callback: RestingIndicator:PostUpdate(isResting)
+ Called after the element has been updated.
+
+ * self - the RestingIndicator element
+ * isResting - indicates if the player is resting (boolean)
+ --]]
+ if(element.PostUpdate) then
+ return element:PostUpdate(isResting)
+ end
+end
+
+local function Path(self, ...)
+ --[[ Override: RestingIndicator.Override(self, event)
+ Used to completely override the internal update function.
+
+ * self - the parent object
+ * event - the event triggering the update (string)
+ --]]
+ return (self.RestingIndicator.Override or Update) (self, unpack(arg))
+end
+
+local function ForceUpdate(element)
+ return Path(element.__owner, 'ForceUpdate')
+end
+
+local function Enable(self, unit)
+ local element = self.RestingIndicator
+ if(element and unit == 'player') then
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ self:RegisterEvent('PLAYER_UPDATE_RESTING', Path, true)
+
+ if(element:IsObjectType('Texture') and not element:GetTexture()) then
+ element:SetTexture([[Interface\CharacterFrame\UI-StateIcon]])
+ element:SetTexCoord(0, 0.5, 0, 0.421875)
+ end
+
+ return true
+ end
+end
+
+local function Disable(self)
+ local element = self.RestingIndicator
+ if(element) then
+ element:Hide()
+
+ self:UnregisterEvent('PLAYER_UPDATE_RESTING', Path)
+ end
+end
+
+oUF:AddElement('RestingIndicator', Path, Enable, Disable)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/elements/tags.lua b/ElvUI/Libraries/oUF/elements/tags.lua
new file mode 100644
index 0000000..70c5fc5
--- /dev/null
+++ b/ElvUI/Libraries/oUF/elements/tags.lua
@@ -0,0 +1,828 @@
+-- Credits: Vika, Cladhaire, Tekkub
+--[[
+# Element: Tags
+
+Provides a system for text-based display of information by binding a tag string to a font string widget which in turn is
+tied to a unit frame.
+
+## Widget
+
+A FontString to hold a tag string. Unlike other elements, this widget must not have a preset name.
+
+## Notes
+
+A `Tag` is a Lua string consisting of a function name surrounded by square brackets. The tag will be replaced by the
+output of the function and displayed as text on the font string widget with that the tag has been registered. Literals
+can be pre- or appended by separating them with a `>` before or `<` after the function name. The literals will be only
+displayed when the function returns a non-nil value. I.e. `"[perhp<%]"` will display the current health as a percentage
+of the maximum health followed by the % sign.
+
+A `Tag String` is a Lua string consisting of one or multiple tags with optional literals between them. Each tag will be
+updated individually and the output will follow the tags order. Literals will be displayed in the output string
+regardless of whether the surrounding tag functions return a value. I.e. `"[curhp]/[maxhp]"` will resolve to something
+like `2453/5000`.
+
+A `Tag Function` is used to replace a single tag in a tag string by its output. A tag function receives only two
+arguments - the unit and the realUnit of the unit frame used to register the tag (see Options for further details). The
+tag function is called when the unit frame is shown or when a specified event has fired. It the tag is registered on an
+eventless frame (i.e. one holding the unit "targettarget"), then the tag function is called in a set time interval.
+
+A number of built-in tag functions exist. The layout can also define its own tag functions by adding them to the
+`oUF.Tags.Methods` table. The events upon which the function will be called are specified in a white-space separated
+list added to the `oUF.Tags.Events` table. Should an event fire without unit information, then it should also be listed
+in the `oUF.Tags.SharedEvents` table as follows: `oUF.Tags.SharedEvents.EVENT_NAME = true`.
+
+## Options
+
+.overrideUnit - if specified on the font string widget, the frame's realUnit will be passed as the second argument to
+ every tag function whose name is contained in the relevant tag string. Otherwise the second argument
+ is always nil (boolean)
+.frequentUpdates - defines how often the correspondig tag function(s) should be called. This will override the events for
+ the tag(s), if any. If the value is a number, it is taken as a time interval in seconds. If the value
+ is a boolean, the time interval is set to 0.5 seconds (number or boolean)
+
+## Attributes
+
+.parent - the unit frame on which the tag has been registered
+
+## Examples
+
+ -- define the tag function
+ oUF.Tags.Methods['mylayout:threatname'] = function(unit, realUnit)
+ local color = _TAGS['threatcolor'](unit)
+ local name = _TAGS['name'](unit, realUnit)
+ return string.format('%s%s|r', color, name)
+ end
+
+ -- add the events
+ oUF.Tags.Events['mylayout:threatname'] = 'UNIT_NAME_UPDATE UNIT_THREAT_SITUATION_UPDATE'
+
+ -- create the text widget
+ local info = self.Health:CreateFontString(nil, 'OVERLAY', 'GameFontNormal')
+ info:SetPoint('LEFT')
+
+ -- register the tag on the text widget with oUF
+ self:Tag(info, '[mylayout:threatname]')
+--]]
+
+local ns = oUF
+local oUF = ns.oUF
+
+local _G = _G
+local unpack = unpack
+local floor = math.floor
+local format = string.format
+local tinsert, tremove = table.insert, table.remove
+
+local GetComboPoints = GetComboPoints
+local GetNumRaidMembers = GetNumRaidMembers
+local GetPetHappiness = GetPetHappiness
+local GetQuestDifficultyColor = GetQuestDifficultyColor
+local GetRaidRosterInfo = GetRaidRosterInfo
+local IsResting = IsResting
+local UnitCanAttack = UnitCanAttack
+local UnitClass = UnitClass
+local UnitClassification = UnitClassification
+local UnitCreatureFamily = UnitCreatureFamily
+local UnitCreatureType = UnitCreatureType
+local UnitFactionGroup = UnitFactionGroup
+local UnitIsConnected = UnitIsConnected
+local UnitIsDead = UnitIsDead
+local UnitIsGhost = UnitIsGhost
+local UnitIsPVP = UnitIsPVP
+local UnitIsPartyLeader = UnitIsPartyLeader
+local UnitIsPlayer = UnitIsPlayer
+local UnitLevel = UnitLevel
+local UnitMana = UnitMana
+local UnitManaMax = UnitManaMax
+local UnitName = UnitName
+local UnitPowerType = UnitPowerType
+local UnitRace = UnitRace
+local UnitSex = UnitSex
+
+local _PATTERN = '%[..-%]+'
+
+local _ENV = {
+ Hex = function(r, g, b)
+ if(type(r) == 'table') then
+ if(r.r) then
+ r, g, b = r.r, r.g, r.b
+ else
+ r, g, b = unpack(r)
+ end
+ end
+ if not r or type(r) == 'string' then
+ return '|cffFFFFFF'
+ end
+ return format('|cff%02x%02x%02x', r * 255, g * 255, b * 255)
+ end,
+ ColorGradient = oUF.ColorGradient,
+}
+local _PROXY = setmetatable(_ENV, {__index = _G})
+
+local tagStrings = {
+ ['creature'] = [[function(u)
+ return UnitCreatureFamily(u) or UnitCreatureType(u)
+ end]],
+
+ ['dead'] = [[function(u)
+ if(UnitIsDead(u)) then
+ return 'Dead'
+ elseif(UnitIsGhost(u)) then
+ return 'Ghost'
+ end
+ end]],
+
+ ['difficulty'] = [[function(u)
+ if UnitCanAttack('player', u) then
+ local l = UnitLevel(u)
+ return Hex(GetQuestDifficultyColor((l > 0) and l or 999))
+ end
+ end]],
+
+ ['leader'] = [[function(u)
+ if(UnitIsPartyLeader(u)) then
+ return 'L'
+ end
+ end]],
+
+ ['leaderlong'] = [[function(u)
+ if(UnitIsPartyLeader(u)) then
+ return 'Leader'
+ end
+ end]],
+
+ ['level'] = [[function(u)
+ local l = UnitLevel(u)
+ if(l > 0) then
+ return l
+ else
+ return '??'
+ end
+ end]],
+
+ ['missinghp'] = [[function(u)
+ local current = UnitHealthMax(u) - UnitHealth(u)
+ if(current > 0) then
+ return current
+ end
+ end]],
+
+ ['missingpp'] = [[function(u)
+ local current = UnitManaMax(u) - UnitMana(u)
+ if(current > 0) then
+ return current
+ end
+ end]],
+
+ ['name'] = [[function(u, r)
+ return UnitName(r or u)
+ end]],
+
+ ['offline'] = [[function(u)
+ if(not UnitIsConnected(u)) then
+ return 'Offline'
+ end
+ end]],
+
+ ['perhp'] = [[function(u)
+ local m = UnitHealthMax(u)
+ if(m == 0) then
+ return 0
+ else
+ return floor(UnitHealth(u) / m * 100 + .5)
+ end
+ end]],
+
+ ['perpp'] = [[function(u)
+ local m = UnitManaMax(u)
+ if(m == 0) then
+ return 0
+ else
+ return floor(UnitMana(u) / m * 100 + .5)
+ end
+ end]],
+
+ ['plus'] = [[function(u)
+ local c = UnitClassification(u)
+ if(c == 'elite' or c == 'rareelite') then
+ return '+'
+ end
+ end]],
+
+ ['pvp'] = [[function(u)
+ if(UnitIsPVP(u)) then
+ return 'PvP'
+ end
+ end]],
+
+ ['raidcolor'] = [[function(u)
+ local _, x = UnitClass(u)
+ if(x) then
+ return Hex(_COLORS.class[x])
+ end
+ end]],
+
+ ['rare'] = [[function(u)
+ local c = UnitClassification(u)
+ if(c == 'rare' or c == 'rareelite') then
+ return 'Rare'
+ end
+ end]],
+
+ ['resting'] = [[function(u)
+ if(u == 'player' and IsResting()) then
+ return 'zzz'
+ end
+ end]],
+
+ ['sex'] = [[function(u)
+ local s = UnitSex(u)
+ if(s == 2) then
+ return 'Male'
+ elseif(s == 3) then
+ return 'Female'
+ end
+ end]],
+
+ ['smartclass'] = [[function(u)
+ if(UnitIsPlayer(u)) then
+ return _TAGS['class'](u)
+ end
+
+ return _TAGS['creature'](u)
+ end]],
+
+ ['status'] = [[function(u)
+ if(UnitIsDead(u)) then
+ return 'Dead'
+ elseif(UnitIsGhost(u)) then
+ return 'Ghost'
+ elseif(not UnitIsConnected(u)) then
+ return 'Offline'
+ else
+ return _TAGS['resting'](u)
+ end
+ end]],
+
+ ['cpoints'] = [[function(u)
+ local cp = GetComboPoints('player', 'target')
+ if(cp > 0) then
+ return cp
+ end
+ end]],
+
+ ['smartlevel'] = [[function(u)
+ local c = UnitClassification(u)
+ if(c == 'worldboss') then
+ return 'Boss'
+ else
+ local plus = _TAGS['plus'](u)
+ local level = _TAGS['level'](u)
+ if(plus) then
+ return level .. plus
+ else
+ return level
+ end
+ end
+ end]],
+
+ ['classification'] = [[function(u)
+ local c = UnitClassification(u)
+ if(c == 'rare') then
+ return 'Rare'
+ elseif(c == 'rareelite') then
+ return 'Rare Elite'
+ elseif(c == 'elite') then
+ return 'Elite'
+ elseif(c == 'worldboss') then
+ return 'Boss'
+ end
+ end]],
+
+ ['shortclassification'] = [[function(u)
+ local c = UnitClassification(u)
+ if(c == 'rare') then
+ return 'R'
+ elseif(c == 'rareelite') then
+ return 'R+'
+ elseif(c == 'elite') then
+ return '+'
+ elseif(c == 'worldboss') then
+ return 'B'
+ end
+ end]],
+
+ ['group'] = [[function(unit)
+ local name, server = UnitName(unit)
+ if(server and server ~= '') then
+ name = format('%s-%s', name, server)
+ end
+
+ for i=1, GetNumRaidMembers() do
+ local raidName, _, group = GetRaidRosterInfo(i)
+ if(raidName == name) then
+ return group
+ end
+ end
+ end]],
+
+ ['deficit:name'] = [[function(u)
+ local missinghp = _TAGS['missinghp'](u)
+ if(missinghp) then
+ return '-' .. missinghp
+ else
+ return _TAGS['name'](u)
+ end
+ end]],
+
+ ['curmana'] = [[function(unit)
+ return UnitMana(unit, SPELL_POWER_MANA)
+ end]],
+
+ ['maxmana'] = [[function(unit)
+ return UnitManaMax(unit, SPELL_POWER_MANA)
+ end]],
+
+ ['happiness'] = [[function(u)
+ if(UnitIsUnit(u, 'pet')) then
+ local happiness = GetPetHappiness()
+ if(happiness == 1) then
+ return ':<'
+ elseif(happiness == 2) then
+ return ':|'
+ elseif(happiness == 3) then
+ return ':D'
+ end
+ end
+ end]],
+
+ ['powercolor'] = [[function(u)
+ local pType, pToken, altR, altG, altB = UnitPowerType(u)
+ local t = _COLORS.power[pToken]
+
+ if(not t) then
+ if(altR) then
+ if(altR > 1 or altG > 1 or altB > 1) then
+ return Hex(altR / 255, altG / 255, altB / 255)
+ else
+ return Hex(altR, altG, altB)
+ end
+ else
+ return Hex(_COLORS.power[pType])
+ end
+ end
+
+ return Hex(t)
+ end]],
+}
+
+local tags = setmetatable(
+ {
+ curhp = UnitHealth,
+ curpp = UnitMana,
+ maxhp = UnitHealthMax,
+ maxpp = UnitManaMax,
+ class = UnitClass,
+ faction = UnitFactionGroup,
+ race = UnitRace,
+ },
+ {
+ __index = function(self, key)
+ local tagFunc = tagStrings[key]
+ if(tagFunc) then
+ local func, err = loadstring('return ' .. tagFunc)
+ if(func) then
+ func = func()
+
+ -- Want to trigger __newindex, so no rawset.
+ self[key] = func
+ tagStrings[key] = nil
+
+ return func
+ else
+ error(err, 3)
+ end
+ end
+ end,
+ __newindex = function(self, key, val)
+ if(type(val) == 'string') then
+ tagStrings[key] = val
+ elseif(type(val) == 'function') then
+ -- So we don't clash with any custom envs.
+ if(getfenv(val) == _G) then
+ setfenv(val, _PROXY)
+ end
+
+ rawset(self, key, val)
+ end
+ end,
+ }
+)
+
+_ENV._TAGS = tags
+
+local tagEvents = {
+ ['curhp'] = 'UNIT_HEALTH',
+ ['maxhp'] = 'UNIT_MAXHEALTH',
+ ['curpp'] = 'UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE',
+ ['maxpp'] = 'UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE',
+ ['dead'] = 'UNIT_HEALTH',
+ ['leader'] = 'PARTY_LEADER_CHANGED',
+ ['leaderlong'] = 'PARTY_LEADER_CHANGED',
+ ['level'] = 'UNIT_LEVEL PLAYER_LEVEL_UP',
+ ['missinghp'] = 'UNIT_HEALTH UNIT_MAXHEALTH',
+ ['missingpp'] = 'UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE',
+ ['name'] = 'UNIT_NAME_UPDATE',
+ ['offline'] = 'UNIT_HEALTH',
+ ['perhp'] = 'UNIT_HEALTH UNIT_MAXHEALTH',
+ ['perpp'] = 'UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE',
+ ['plus'] = 'UNIT_CLASSIFICATION_CHANGED',
+ ['pvp'] = 'UNIT_FACTION',
+ ['rare'] = 'UNIT_CLASSIFICATION_CHANGED',
+ ['resting'] = 'PLAYER_UPDATE_RESTING',
+ ['status'] = 'UNIT_HEALTH PLAYER_UPDATE_RESTING',
+ ['cpoints'] = 'PLAYER_COMBO_POINTS PLAYER_TARGET_CHANGED',
+ ['smartlevel'] = 'UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED',
+ ['classification'] = 'UNIT_CLASSIFICATION_CHANGED',
+ ['shortclassification'] = 'UNIT_CLASSIFICATION_CHANGED',
+ ['group'] = 'PARTY_MEMBERS_CHANGED RAID_ROSTER_UPDATE',
+ ['curmana'] = 'UNIT_MANA UNIT_MAXMANA',
+ ['maxmana'] = 'UNIT_MANA UNIT_MAXMANA',
+ ['happiness'] = 'UNIT_HAPPINESS',
+ ['powercolor'] = 'UNIT_DISPLAYPOWER',
+}
+
+local unitlessEvents = {
+ PLAYER_LEVEL_UP = true,
+ PLAYER_UPDATE_RESTING = true,
+ PLAYER_TARGET_CHANGED = true,
+
+ RAID_ROSTER_UPDATE = true,
+ PARTY_MEMBERS_CHANGED = true,
+ PARTY_LEADER_CHANGED = true,
+
+ PLAYER_COMBO_POINTS = true,
+}
+
+local events = {}
+local frame = CreateFrame('Frame')
+frame:SetScript('OnEvent', function()
+ local strings = events[event]
+ if(strings) then
+ for _, fontstring in next, strings do
+ if(fontstring:IsVisible() and (unitlessEvents[event] or fontstring.parent.unit == arg1)) then
+ fontstring:UpdateTag()
+ end
+ end
+ end
+end)
+
+local onUpdates = {}
+local eventlessUnits = {}
+
+local function createOnUpdate(timer)
+ local OnUpdate = onUpdates[timer]
+
+ if(not OnUpdate) then
+ local total = timer
+ local frame = CreateFrame('Frame')
+ local strings = eventlessUnits[timer]
+
+ frame:SetScript('OnUpdate', function()
+ if(total >= timer) then
+ for _, fs in next, strings do
+ if(fs.parent:IsShown() and UnitExists(fs.parent.unit)) then
+ fs:UpdateTag()
+ end
+ end
+
+ total = 0
+ end
+
+ total = total + arg1
+ end)
+
+ onUpdates[timer] = frame
+ end
+end
+
+local function onShow(self)
+ for _, fs in next, self.__tags do
+ fs:UpdateTag()
+ end
+end
+
+local function getTagName(tag)
+ local tagStart = (string.match(tag, '>+()') or 2)
+ local tagEnd = string.match(tag, '.*()<+')
+ tagEnd = (tagEnd and tagEnd - 1) or -2
+
+ return string.sub(tag, tagStart, tagEnd), tagStart, tagEnd
+end
+
+local function registerEvent(fontstr, event)
+ if(not events[event]) then events[event] = {} end
+
+ frame:RegisterEvent(event)
+ tinsert(events[event], fontstr)
+end
+
+local function registerEvents(fontstr, tagstr)
+ for tag in string.gmatch(tagstr, _PATTERN) do
+ tag = getTagName(tag)
+ local tagevents = tagEvents[tag]
+ if(tagevents) then
+ for event in string.gmatch(tagevents, '%S+') do
+ registerEvent(fontstr, event)
+ end
+ end
+ end
+end
+
+local function unregisterEvents(fontstr)
+ for event, data in next, events do
+ for i, tagfsstr in next, data do
+ if(tagfsstr == fontstr) then
+ if(getn(data) == 1) then
+ frame:UnregisterEvent(event)
+ end
+
+ tremove(data, i)
+ end
+ end
+ end
+end
+
+local OnEnter = function(self)
+ for _, fs in pairs(self.__mousetags) do
+ fs:SetAlpha(1)
+ end
+end
+
+local OnLeave = function(self)
+ for _, fs in pairs(self.__mousetags) do
+ fs:SetAlpha(0)
+ end
+end
+
+local onUpdateDelay = {}
+local tagPool = {}
+local funcPool = {}
+local tmp = {}
+local escapeSequences = {
+ ["||c"] = "|c",
+ ["||r"] = "|r",
+ ["||T"] = "|T",
+ ["||t"] = "|t",
+}
+
+--[[ Tags: frame:Tag(fs, tagstr)
+Used to register a tag on a unit frame.
+
+* self - the unit frame on which to register the tag
+* fs - the font string to display the tag (FontString)
+* tagstr - the tag string (string)
+--]]
+local function Tag(self, fs, tagstr)
+ if(not fs or not tagstr) then return end
+
+ if(not self.__tags) then
+ self.__tags = {}
+ self.__mousetags = {}
+ tinsert(self.__elements, onShow)
+ else
+ -- Since people ignore everything that's good practice - unregister the tag
+ -- if it already exists.
+ for _, tag in pairs(self.__tags) do
+ if(fs == tag) then
+ -- We don't need to remove it from the __tags table as Untag handles
+ -- that for us.
+ self:Untag(fs)
+ end
+ end
+ end
+
+ fs.parent = self
+
+ for escapeSequence, replacement in pairs(escapeSequences) do
+ while string.find(tagstr, escapeSequence) do
+ tagstr = string.gsub(tagstr, escapeSequence, replacement)
+ end
+ end
+
+ if string.find(tagstr, '%[mouseover%]') then
+ tinsert(self.__mousetags, fs)
+ fs:SetAlpha(0)
+ if not self.__HookFunc then
+ self:HookScript('OnEnter', OnEnter)
+ self:HookScript('OnLeave', OnLeave)
+ self.__HookFunc = true;
+ end
+ tagstr = string.gsub(tagstr, '%[mouseover%]', '')
+ else
+ for index, fontString in pairs(self.__mousetags) do
+ if fontString == fs then
+ self.__mousetags[index] = nil;
+ fs:SetAlpha(1)
+ end
+ end
+ end
+
+ local containsOnUpdate
+ for tag in string.gmatch(tagstr, _PATTERN) do
+ tag = getTagName(tag)
+ if not tagEvents[tag] then
+ containsOnUpdate = onUpdateDelay[tag] or 0.15;
+ end
+ end
+
+ local func = tagPool[tagstr]
+ if(not func) then
+ local format, numTags = string.gsub(string.gsub(tagstr, '%%', '%%%%'), _PATTERN, '%%s')
+ local args = {}
+
+ for bracket in string.gmatch(tagstr, _PATTERN) do
+ local tagFunc = funcPool[bracket] or tags[string.sub(bracket, 2, -2)]
+ if(not tagFunc) then
+ local tagName, tagStart, tagEnd = getTagName(bracket)
+
+ local tag = tags[tagName]
+ if(tag) then
+ tagStart = tagStart - 2
+ tagEnd = tagEnd + 2
+
+ if(tagStart ~= 0 and tagEnd ~= 0) then
+ local prefix = string.sub(bracket, 2, tagStart)
+ local suffix = string.sub(bracket, tagEnd, -2)
+
+ tagFunc = function(unit, realUnit)
+ local str = tag(unit, realUnit)
+ if(str) then
+ return prefix .. str .. suffix
+ end
+ end
+ elseif(tagStart ~= 0) then
+ local prefix = string.sub(bracket, 2, tagStart)
+
+ tagFunc = function(unit, realUnit)
+ local str = tag(unit, realUnit)
+ if(str) then
+ return prefix .. str
+ end
+ end
+ elseif(tagEnd ~= 0) then
+ local suffix = string.sub(bracket, tagEnd, -2)
+
+ tagFunc = function(unit, realUnit)
+ local str = tag(unit, realUnit)
+ if(str) then
+ return str .. suffix
+ end
+ end
+ end
+
+ funcPool[bracket] = tagFunc
+ end
+ end
+
+ if(tagFunc) then
+ tinsert(args, tagFunc)
+ else
+ numTags = -1
+ func = function(self)
+ return self:SetText(bracket)
+ end
+ end
+ end
+
+ if(numTags == 1) then
+ func = function(self)
+ local parent = self.parent
+ local realUnit
+ if(self.overrideUnit) then
+ realUnit = parent.realUnit
+ end
+
+ _ENV._COLORS = parent.colors
+ return self:SetText(string.format(
+ format,
+ args[1](parent.unit, realUnit) or ''
+ ))
+ end
+ elseif(numTags == 2) then
+ func = function(self)
+ local parent = self.parent
+ local unit = parent.unit
+ local realUnit
+ if(self.overrideUnit) then
+ realUnit = parent.realUnit
+ end
+
+ _ENV._COLORS = parent.colors
+ return self:SetText(string.format(
+ format,
+ args[1](unit, realUnit) or '',
+ args[2](unit, realUnit) or ''
+ ))
+ end
+ elseif(numTags == 3) then
+ func = function(self)
+ local parent = self.parent
+ local unit = parent.unit
+ local realUnit
+ if(self.overrideUnit) then
+ realUnit = parent.realUnit
+ end
+
+ _ENV._COLORS = parent.colors
+ return self:SetText(string.format(
+ format,
+ args[1](unit, realUnit) or '',
+ args[2](unit, realUnit) or '',
+ args[3](unit, realUnit) or ''
+ ))
+ end
+ elseif numTags ~= -1 then
+ func = function(self)
+ local parent = self.parent
+ local unit = parent.unit
+ local realUnit
+ if(self.overrideUnit) then
+ realUnit = parent.realUnit
+ end
+
+ _ENV._COLORS = parent.colors
+ for i, func in next, args do
+ tmp[i] = func(unit, realUnit) or ''
+ end
+
+ -- We do 1, numTags because tmp can hold several unneeded variables.
+ return self:SetText(string.format(format, unpack(tmp, 1, numTags)))
+ end
+ end
+
+ if numTags ~= -1 then
+ tagPool[tagstr] = func
+ end
+ end
+ fs.UpdateTag = func
+
+ local unit = self.unit
+ if(self.__eventless or fs.frequentUpdates) or containsOnUpdate then
+ local timer
+ if(type(fs.frequentUpdates) == 'number') then
+ timer = fs.frequentUpdates
+ elseif containsOnUpdate then
+ timer = containsOnUpdate
+ else
+ timer = .5
+ end
+
+ if(not eventlessUnits[timer]) then eventlessUnits[timer] = {} end
+ tinsert(eventlessUnits[timer], fs)
+
+ createOnUpdate(timer)
+ else
+ registerEvents(fs, tagstr)
+ end
+
+ tinsert(self.__tags, fs)
+end
+
+--[[ Tags: frame:Untag(fs)
+Used to unregister a tag from a unit frame.
+
+* self - the unit frame from which to unregister the tag
+* fs - the font string holding the tag (FontString)
+--]]
+local function Untag(self, fs)
+ if(not fs) then return end
+
+ unregisterEvents(fs)
+ for _, timers in next, eventlessUnits do
+ for i, fontstr in next, timers do
+ if(fs == fontstr) then
+ tremove(timers, i)
+ end
+ end
+ end
+
+ for i, fontstr in next, self.__tags do
+ if(fontstr == fs) then
+ tremove(self.__tags, i)
+ end
+ end
+
+ fs.UpdateTag = nil
+end
+
+oUF.Tags = {
+ Methods = tags,
+ Events = tagEvents,
+ SharedEvents = unitlessEvents,
+ OnUpdateThrottle = onUpdateDelay,
+}
+
+oUF:RegisterMetaFunction('Tag', Tag)
+oUF:RegisterMetaFunction('Untag', Untag)
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/events.lua b/ElvUI/Libraries/oUF/events.lua
new file mode 100644
index 0000000..9a0f9c6
--- /dev/null
+++ b/ElvUI/Libraries/oUF/events.lua
@@ -0,0 +1,137 @@
+local ns = oUF
+local oUF = ns.oUF
+local Private = oUF.Private
+
+local argcheck = Private.argcheck
+local error = Private.error
+local frame_metatable = Private.frame_metatable
+
+-- Original event methods
+local registerEvent = frame_metatable.__index.RegisterEvent
+local unregisterEvent = frame_metatable.__index.UnregisterEvent
+
+function Private.UpdateUnits(frame, unit, realUnit)
+
+ return true
+end
+
+local function onEvent()
+ if(this:IsVisible() or event == 'UNIT_COMBO_POINTS') then
+ --print(this, event, arg and unpack(arg))
+ --print(this, event, arg1, arg2, arg3, arg4, arg5)
+
+ return this[event](this, event, arg1, arg2, arg3, arg4, arg5)
+ end
+end
+
+local event_metatable = {
+ __call = function(funcs, self, ...)
+ for _, func in next, funcs do
+ func(self, unpack(arg))
+ end
+ end,
+}
+
+--[[ Events: frame:RegisterEvent(event, func, unitless)
+Used to register a frame for a game event and add an event handler. OnUpdate polled frames are prevented from
+registering events.
+
+* self - frame that will be registered for the given event.
+* event - name of the event to register (string)
+* func - function that will be executed when the event fires. If a string is passed, then a function by that name
+ must be defined on the frame. Multiple functions can be added for the same frame and event
+ (string or function)
+* unitless - indicates that the event does not fire for a specific unit, so the event arguments won't be
+ matched to the frame unit(s). Events that do not start with UNIT_ or are not known to be unit events are
+ automatically considered unitless (boolean)
+--]]
+function frame_metatable.__index:RegisterEvent(event, func)
+ -- Block OnUpdate polled frames from registering events.
+ -- UNIT_PORTRAIT_UPDATE and UNIT_MODEL_CHANGED which are used for
+ -- portrait updates.
+ if(self.__eventless and event ~= 'UNIT_PORTRAIT_UPDATE' and event ~= 'UNIT_MODEL_CHANGED') then return end
+
+ argcheck(event, 2, 'string')
+
+ if(type(func) == 'string' and type(self[func]) == 'function') then
+ func = self[func]
+ end
+
+ local curev = self[event]
+ local kind = type(curev)
+ if(curev and func) then
+ if(kind == 'function' and curev ~= func) then
+ self[event] = setmetatable({curev, func}, event_metatable)
+ elseif(kind == 'table') then
+ for _, infunc in next, curev do
+ if(infunc == func) then return end
+ end
+
+ table.insert(curev, func)
+ end
+ elseif(self:IsEventRegistered(event)) then
+ return
+ else
+ if(type(func) == 'function') then
+ self[event] = func
+ elseif(not self[event]) then
+ return error("Style [%s] attempted to register event [%s] on unit [%s] with a handler that doesn't exist.", self.style, event, self.unit or 'unknown')
+ end
+
+ if not self:GetScript('OnEvent') then
+ self:SetScript('OnEvent', onEvent)
+ end
+
+ registerEvent(self, event)
+ self.__registeredEvents[event] = true
+ end
+end
+
+--[[ Events: frame:IsEventRegistered(event, func)
+Used to determine if a game event is registered.
+
+* self - the frame registered for the event
+* event - name of the registered event (string)
+--]]
+function frame_metatable.__index:IsEventRegistered(event)
+ argcheck(event, 2, 'string')
+
+ return self.__registeredEvents[event] and true or false
+end
+
+--[[ Events: frame:UnregisterEvent(event, func)
+Used to remove a function from the event handler list for a game event.
+
+* self - the frame registered for the event
+* event - name of the registered event (string)
+* func - function to be removed from the list of event handlers. If this is the only handler for the given event, then
+ the frame will be unregistered for the event
+--]]
+function frame_metatable.__index:UnregisterEvent(event, func)
+ argcheck(event, 2, 'string')
+
+ local curev = self[event]
+ if(type(curev) == 'table' and func) then
+ for k, infunc in next, curev do
+ if(infunc == func) then
+ table.remove(curev, k)
+
+ local n = getn(curev)
+ if(n == 1) then
+ local _, handler = next(curev)
+ self[event] = handler
+ elseif(n == 0) then
+ -- This should not happen
+ unregisterEvent(self, event)
+ self.__registeredEvents[event] = nil
+ end
+
+ break
+ end
+ end
+ elseif(curev == func) then
+ self[event] = nil
+ unregisterEvent(self, event)
+ self.__registeredEvents[event] = nil
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/factory.lua b/ElvUI/Libraries/oUF/factory.lua
new file mode 100644
index 0000000..35ee6f6
--- /dev/null
+++ b/ElvUI/Libraries/oUF/factory.lua
@@ -0,0 +1,71 @@
+local ns = oUF
+local oUF = ns.oUF
+local Private = oUF.Private
+
+local argcheck = Private.argcheck
+
+local queue = {}
+local factory = CreateFrame('Frame')
+factory:SetScript('OnEvent', function()
+ return this[event](this, event, arg and unpack(arg))
+end)
+
+factory:RegisterEvent('PLAYER_LOGIN')
+factory.active = true
+
+function factory:PLAYER_LOGIN()
+ if(not self.active) then return end
+
+ for _, func in next, queue do
+ func(oUF)
+ end
+
+ -- Avoid creating dupes.
+ wipe(queue)
+end
+
+--[[ Factory: oUF:Factory(func)
+Used to call a function directly if the current character is logged in and the factory is active. Else the function is
+queued up to be executed at a later time (upon PLAYER_LOGIN by default).
+
+* self - the global oUF object
+* func - function to be executed or delayed (function)
+--]]
+function oUF:Factory(func)
+ argcheck(func, 2, 'function')
+
+ -- Call the function directly if we're active and logged in.
+ if(IsLoggedIn() and factory.active) then
+ return func(self)
+ else
+ table.insert(queue, func)
+ end
+end
+
+--[[ Factory: oUF:EnableFactory()
+Used to enable the factory.
+
+* self - the global oUF object
+--]]
+function oUF:EnableFactory()
+ factory.active = true
+end
+
+--[[ Factory: oUF:DisableFactory()
+Used to disable the factory.
+
+* self - the global oUF object
+--]]
+function oUF:DisableFactory()
+ factory.active = nil
+end
+
+--[[ Factory: oUF:RunFactoryQueue()
+Used to try to execute queued up functions. The current player must be logged in and the factory must be active for
+this to succeed.
+
+* self - the global oUF object
+--]]
+function oUF:RunFactoryQueue()
+ factory:PLAYER_LOGIN()
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/finalize.lua b/ElvUI/Libraries/oUF/finalize.lua
new file mode 100644
index 0000000..e319a5f
--- /dev/null
+++ b/ElvUI/Libraries/oUF/finalize.lua
@@ -0,0 +1,4 @@
+local ns = oUF
+
+-- It's named Private for a reason!
+ns.oUF.Private = nil
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/init.lua b/ElvUI/Libraries/oUF/init.lua
new file mode 100644
index 0000000..cad6dda
--- /dev/null
+++ b/ElvUI/Libraries/oUF/init.lua
@@ -0,0 +1,5 @@
+oUF = {}
+
+local ns = oUF
+ns.oUF = {}
+ns.oUF.Private = {}
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/oUF.xml b/ElvUI/Libraries/oUF/oUF.xml
new file mode 100644
index 0000000..f954b51
--- /dev/null
+++ b/ElvUI/Libraries/oUF/oUF.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/ouf.lua b/ElvUI/Libraries/oUF/ouf.lua
new file mode 100644
index 0000000..af24496
--- /dev/null
+++ b/ElvUI/Libraries/oUF/ouf.lua
@@ -0,0 +1,698 @@
+local ns = oUF
+
+local oUF = ns.oUF
+local Private = oUF.Private
+
+local argcheck = Private.argcheck
+
+local print = Private.print
+local error = Private.error
+
+local styles, style = {}
+local callback, units, objects, headers = {}, {}, {}, {}
+
+local elements = {}
+local activeElements = {}
+
+-- updating of "invalid" units.
+local function enableTargetUpdate(object)
+ object.onUpdateFrequency = object.onUpdateFrequency or .5
+ object.__eventless = true
+
+ local total = 0
+ object:SetScript('OnUpdate', function()
+ if not this.unit then
+ return
+ elseif total > this.onUpdateFrequency then
+ this:UpdateAllElements('OnUpdate')
+ total = 0
+ end
+
+ total = total + GetTime()
+ end)
+end
+Private.enableTargetUpdate = enableTargetUpdate
+
+local function updateActiveUnit(self, event, unit)
+ return true
+end
+
+local function iterateChildren(...)
+ for i = 1, table.getn(arg) do
+ local obj = arg[i]
+
+ if(type(obj) == 'table' and obj.isChild) then
+ updateActiveUnit(obj, 'iterateChildren')
+ end
+ end
+end
+
+local function onAttributeChanged(self, name, value)
+ if(name == 'unit' and value) then
+ if(self.hasChildren) then
+ iterateChildren(self:GetChildren())
+ end
+
+ if(not self.onlyProcessChildren) then
+ updateActiveUnit(self, 'OnAttributeChanged')
+ end
+--[[
+ if(self.unit and self.unit == value) then
+ return
+ else
+ if(self.hasChildren) then
+ iterateChildren(self:GetChildren())
+ end
+ end
+]]
+ end
+end
+
+local frame_metatable = {
+ __index = CreateFrame('Button')
+}
+Private.frame_metatable = frame_metatable
+
+for k, v in next, {
+ UpdateElement = function(self, name)
+ local unit = self.unit
+ if(not unit or not UnitExists(unit)) then return end
+
+ local element = elements[name]
+ if(not element or not self:IsElementEnabled(name) or not activeElements[self]) then return end
+ if(element.update) then
+ element.update(self, 'OnShow', unit)
+ end
+ end,
+
+ UpdateElement = function(self, name)
+ local unit = self.unit
+ if(not unit or not UnitExists(unit)) then return end
+
+ local element = elements[name]
+ if(not element or not self:IsElementEnabled(name) or not activeElements[self]) then return end
+ if(element.update) then
+ element.update(self, 'OnShow', unit)
+ end
+ end,
+
+ --[[ frame:EnableElement(name, unit)
+ Used to activate an element for the given unit frame.
+
+ * self - unit frame for which the element should be enabled
+ * name - name of the element to be enabled (string)
+ * unit - unit to be passed to the element's Enable function. Defaults to the frame's unit (string?)
+ --]]
+ EnableElement = function(self, name, unit)
+ local unit = unit or self.unit
+ if not unit then return end
+
+ argcheck(name, 2, 'string')
+ argcheck(unit or self.unit, 3, 'string', 'nil')
+
+ local element = elements[name]
+ if(not element or self:IsElementEnabled(name) or not activeElements[self]) then return end
+
+ if(element.enable(self, unit or self.unit)) then
+ activeElements[self][name] = true
+
+ if(element.update) then
+ table.insert(self.__elements, element.update)
+ end
+ end
+ end,
+
+ --[[ frame:DisableElement(name)
+ Used to deactivate an element for the given unit frame.
+
+ * self - unit frame for which the element should be disabled
+ * name - name of the element to be disabled (string)
+ --]]
+ DisableElement = function(self, name)
+ argcheck(name, 2, 'string')
+
+ local enabled = self:IsElementEnabled(name)
+ if(not enabled) then return end
+
+ local update = elements[name].update
+ for k, func in next, self.__elements do
+ if(func == update) then
+ table.remove(self.__elements, k)
+ break
+ end
+ end
+
+ activeElements[self][name] = nil
+
+ -- We need to run a new update cycle in-case we knocked ourself out of sync.
+ -- The main reason we do this is to make sure the full update is completed
+ -- if an element for some reason removes itself _during_ the update
+ -- progress.
+ self:UpdateAllElements('DisableElement')
+
+ return elements[name].disable(self)
+ end,
+
+ --[[ frame:IsElementEnabled(name)
+ Used to check if an element is enabled on the given frame.
+
+ * self - unit frame
+ * name - name of the element (string)
+ --]]
+ IsElementEnabled = function(self, name)
+ argcheck(name, 2, 'string')
+
+ local element = elements[name]
+ if(not element) then return end
+
+ local active = activeElements[self]
+ return active and active[name]
+ end,
+
+ --[[ frame:Enable(asState)
+ Used to toggle the visibility of a unit frame based on the existence of its unit. This is a reference to
+ `RegisterUnitWatch`.
+
+ * self - unit frame
+ * asState - if true, the frame's "state-unitexists" attribute will be set to a boolean value denoting whether the
+ unit exists; if false, the frame will be shown if its unit exists, and hidden if it does not (boolean)
+ --]]
+ Enable = RegisterUnitWatch,
+ --[[ frame:Disable()
+ Used to UnregisterUnitWatch for the given frame and hide it.
+
+ * self - unit frame
+ --]]
+ Disable = function(self)
+ UnregisterUnitWatch(self)
+ self:Hide()
+ end,
+
+ --[[ frame:UpdateAllElements(event)
+ Used to update all enabled elements on the given frame.
+
+ * self - unit frame
+ * event - event name to pass to the elements' update functions (string)
+ --]]
+ UpdateAllElements = function(self, event)
+ local unit = self.unit
+ if(not UnitExists(unit)) then return end
+
+ assert(type(event) == 'string', "Invalid argument 'event' in UpdateAllElements.")
+
+ if(self.PreUpdate) then
+ self:PreUpdate(event)
+ end
+
+ for _, func in next, self.__elements do
+ func(self, event, unit)
+ end
+
+ if(self.PostUpdate) then
+ self:PostUpdate(event)
+ end
+ end,
+
+ SetUnit = function(self, unit)
+ if unit ~= unit then
+ self.unit = unit
+ end
+ end,
+} do
+ frame_metatable.__index[k] = v
+end
+
+local secureDropdown
+local function InitializeSecureMenu()
+ local unit = SecureTemplatesDropdown.unit
+ if(not unit) then return end
+
+ local unitType = string.match(unit, '^([a-z]+)[0-9]+$') or unit
+
+ local menu
+ if(unitType == 'party') then
+ menu = 'PARTY'
+ elseif(UnitIsUnit(unit, 'player')) then
+ menu = 'SELF'
+ elseif(UnitIsUnit(unit, 'pet')) then
+ menu = 'PET'
+ elseif(UnitIsPlayer(unit)) then
+ if(UnitInRaid(unit) or UnitInParty(unit)) then
+ menu = 'PARTY'
+ else
+ menu = 'PLAYER'
+ end
+ elseif(UnitIsUnit(unit, 'target')) then
+ menu = 'RAID_TARGET_ICON'
+ end
+
+ if(menu) then
+ UnitPopup_ShowMenu(SecureTemplatesDropdown, menu, unit)
+ end
+end
+
+local function togglemenu(self, unit)
+ if(not secureDropdown) then
+ secureDropdown = CreateFrame('Frame', 'SecureTemplatesDropdown', nil, 'UIDropDownMenuTemplate')
+ secureDropdown:SetID(1)
+
+ table.insert(UnitPopupFrames, secureDropdown:GetName())
+ UIDropDownMenu_Initialize(secureDropdown, InitializeSecureMenu, 'MENU')
+ end
+
+ if(secureDropdown.openedFor and secureDropdown.openedFor ~= self) then
+ CloseDropDownMenus()
+ end
+
+ secureDropdown.unit = string.lower(unit)
+ secureDropdown.openedFor = self
+
+ ToggleDropDownMenu(1, nil, secureDropdown, 'cursor')
+end
+
+local function onShow()
+ return this:UpdateAllElements('OnShow')
+end
+
+local function initObject(unit, style, styleFunc, header, ...)
+ local num = table.getn(arg)
+ for i = 1, num do
+ local object = arg[i]
+ local objectUnit = object.guessUnit or unit
+ local suffix = string.match(objectUnit or unit, '%w+target')
+
+ object.__elements = {}
+ object.__registeredEvents = {}
+ object.style = style
+ object = setmetatable(object, frame_metatable)
+
+ -- Expose the frame through oUF.objects.
+ table.insert(objects, object)
+
+ -- We have to force update the frames when PEW fires.
+ object:RegisterEvent('PLAYER_ENTERING_WORLD', object.UpdateAllElements)
+
+ object:SetScript("OnClick", function()
+ if arg1 == "RightButton" then
+ togglemenu(this, object.unit)
+ else
+ TargetUnit(this.unit)
+ end
+ end)
+
+ if(not header) then
+ -- Other target units are handled by :HandleUnit().
+ if(suffix == 'target') then
+ enableTargetUpdate(object)
+ else
+ oUF:HandleUnit(object, unit)
+ end
+ else
+ -- Used to update frames when they change position in a group.
+ object:RegisterEvent('RAID_ROSTER_UPDATE', object.UpdateAllElements)
+
+ if(num > 1) then
+ if(object:GetParent() == header) then
+ object.hasChildren = true
+ else
+ object.isChild = true
+ end
+ end
+
+ if(suffix == 'target') then
+ enableTargetUpdate(object)
+ end
+ end
+
+ Private.UpdateUnits(object, objectUnit)
+
+ styleFunc(object, objectUnit, not header)
+
+ --object:SetScript('OnAttributeChanged', onAttributeChanged)
+ object:SetScript('OnShow', onShow)
+
+ activeElements[object] = {}
+ for element in next, elements do
+ object:EnableElement(element, objectUnit)
+ end
+
+ for _, func in next, callback do
+ func(object)
+ end
+
+ -- Make Clique kinda happy
+ _G.ClickCastFrames = ClickCastFrames or {}
+ ClickCastFrames[object] = true
+ end
+end
+
+local function walkObject(object, unit)
+ local parent = object:GetParent()
+ local style = parent.style or style
+ local styleFunc = styles[style]
+
+ local header = parent.headerType and parent
+
+ -- Check if we should leave the main frame blank.
+ if(object.onlyProcessChildren) then
+ object.hasChildren = true
+ --object:SetScript('OnAttributeChanged', onAttributeChanged)
+ return initObject(unit, style, styleFunc, header, object:GetChildren())
+ end
+
+ return initObject(unit, style, styleFunc, header, object, object:GetChildren())
+end
+
+--[[ oUF:RegisterInitCallback(func)
+Used to add a function to a table to be executed upon unit frame/header initialization.
+
+* self - the global oUF object
+* func - function to be added
+--]]
+function oUF:RegisterInitCallback(func)
+ table.insert(callback, func)
+end
+
+--[[ oUF:RegisterMetaFunction(name, func)
+Used to make a (table of) function(s) available to all unit frames.
+
+* self - the global oUF object
+* name - unique name of the function (string)
+* func - function or a table of functions (function or table)
+--]]
+function oUF:RegisterMetaFunction(name, func)
+ argcheck(name, 2, 'string')
+ argcheck(func, 3, 'function', 'table')
+
+ if(frame_metatable.__index[name]) then
+ return
+ end
+
+ frame_metatable.__index[name] = func
+end
+
+--[[ oUF:RegisterStyle(name, func)
+Used to register a style with oUF. This will also set the active style if it hasn't been set yet.
+
+* self - the global oUF object
+* name - name of the style
+* func - function(s) defining the style (function or table)
+--]]
+function oUF:RegisterStyle(name, func)
+ argcheck(name, 2, 'string')
+ argcheck(func, 3, 'function', 'table')
+
+ if(styles[name]) then return error('Style [%s] already registered.', name) end
+ if(not style) then style = name end
+
+ styles[name] = func
+end
+
+--[[ oUF:SetActiveStyle(name)
+Used to set the active style.
+
+* self - the global oUF object
+* name - name of the style (string)
+--]]
+function oUF:SetActiveStyle(name)
+ argcheck(name, 2, 'string')
+ if(not styles[name]) then return error('Style [%s] does not exist.', name) end
+
+ style = name
+end
+
+do
+ local function iter(_, n)
+ -- don't expose the style functions.
+ return (next(styles, n))
+ end
+
+ --[[ oUF:IterateStyles()
+ Returns an iterator over all registered styles.
+
+ * self - the global oUF object
+ --]]
+ function oUF.IterateStyles()
+ return iter, nil, nil
+ end
+end
+
+local getCondition
+do
+ local conditions = {
+ raid40 = '[target=raid26,exists] show;',
+ raid25 = '[target=raid11,exists] show;',
+ raid10 = '[target=raid6,exists] show;',
+ raid = '[group:raid] show;',
+ party = '[group:party,nogroup:raid] show;',
+ solo = '[target=player,exists,nogroup:party] show;',
+ }
+
+ function getCondition(...)
+ local cond = ''
+
+ for i = 1, select('#', arg) do
+ local short = select(i, unpack(arg))
+
+ local condition = conditions[short]
+ if(condition) then
+ cond = cond .. condition
+ end
+ end
+
+ return cond .. 'hide'
+ end
+end
+
+local function generateName(unit, ...)
+ local name = 'oUF_' .. style:gsub('^oUF_?', ''):gsub('[^%a%d_]+', '')
+
+ local raid, party, groupFilter
+ for i = 1, select('#', arg), 2 do
+ local att, val = select(i, unpack(arg))
+ if(att == 'showRaid') then
+ raid = true
+ elseif(att == 'showParty') then
+ party = true
+ elseif(att == 'groupFilter') then
+ groupFilter = val
+ end
+ end
+
+ local append
+ if(raid) then
+ if(groupFilter) then
+ if(type(groupFilter) == 'number' and groupFilter > 0) then
+ append = groupFilter
+ elseif(groupFilter:match('TANK')) then
+ append = 'MainTank'
+ elseif(groupFilter:match('ASSIST')) then
+ append = 'MainAssist'
+ else
+ local _, count = groupFilter:gsub(',', '')
+ if(count == 0) then
+ append = 'Raid' .. groupFilter
+ else
+ append = 'Raid'
+ end
+ end
+ else
+ append = 'Raid'
+ end
+ elseif(party) then
+ append = 'Party'
+ elseif(unit) then
+ append = unit:gsub('^%l', string.upper)
+ end
+
+ if(append) then
+ name = name .. append
+ end
+
+ local base = name
+ local i = 2
+ while(_G[name]) do
+ name = base .. i
+ i = i + 1
+ end
+
+ return name
+end
+
+do
+ local function styleProxy(self, frame, ...)
+ return walkObject(_G[frame])
+ end
+
+ -- There has to be an easier way to do this.
+ local initialConfigFunction = function(self)
+ local header = self:GetParent()
+
+ local unit
+ if(not self.onlyProcessChildren) then
+ local groupFilter = header:GetAttribute('groupFilter')
+
+ if(header:GetAttribute('showRaid')) then
+ unit = 'raid'
+ elseif(header:GetAttribute('showParty')) then
+ unit = 'party'
+ end
+
+ self.menu = togglemenu
+ --self:SetAttribute('type1', 'target')
+ --self:SetAttribute('type2', 'menu')
+ self.guessUnit = unit
+ self.unit = "player"
+ -- self.onlyProcessChildren =true
+ end
+
+ styleProxy(nil, self:GetName())
+ end
+
+ local setAttribute = function(self, name, value)
+ if self.attributes[name] ~= value then
+ self.attributes[name] = value
+
+ if self:IsVisible() then
+ SecureGroupHeader_Update(self)
+ end
+ end
+ end
+ local getAttribute = function(self, name)
+ return self.attributes[name]
+ end
+ --[[ oUF:SpawnHeader(overrideName, template, visibility, ...)
+ Used to create a group header and apply the currently active style to it.
+
+ * self - the global oUF object
+ * overrideName - unique global name to be used for the header. Defaults to an auto-generated name based on the name
+ of the active style and other arguments passed to `:SpawnHeader` (string?)
+ * template - name of a template to be used for creating the header. Defaults to `'oUF_GroupHeaderTemplate'`
+ (string?)
+ * visibility - macro conditional(s) which define when to display the header (string).
+ * ... - further argument pairs. Consult [Group Headers](http://wowprogramming.com/docs/secure_template/Group_Headers)
+ for possible values.
+
+ In addition to the standard group headers, oUF implements some of its own attributes. These can be supplied by the
+ layout, but are optional.
+
+ * oUF-initialConfigFunction - can contain code that will be securely run at the end of the initial secure
+ configuration (string?)
+ * oUF-onlyProcessChildren - can be used to force headers to only process children (boolean?)
+ --]]
+ function oUF:SpawnHeader(overrideName, template, visibility, ...)
+ if(not style) then return error('Unable to create frame. No styles have been registered.') end
+
+ template = (template or 'oUF_GroupHeaderTemplate')
+
+ local isPetHeader = string.match(template, 'PetHeader')
+ local name = overrideName or generateName(nil, unpack(arg))
+ local header = CreateFrame('Frame', name, UIParent, template)
+ header:Hide()
+
+ header.attributes = {}
+ header.SetAttribute = setAttribute
+ header.GetAttribute = getAttribute
+
+ --header:SetAttribute('template', 'SecureUnitButtonTemplate')
+ for i = 1, getn(arg), 2 do
+ local att, val = select(i, unpack(arg))
+ if(not att) then break end
+
+ header:SetAttribute(att, val)
+ end
+
+ header.style = style
+ header.styleFunction = styleProxy
+ header.visibility = visibility
+
+ -- Expose the header through oUF.headers.
+ table.insert(headers, header)
+
+ header.initialConfigFunction = initialConfigFunction
+ header.headerType = isPetHeader and 'pet' or 'group'
+
+ if(header:GetAttribute('showParty')) then
+ self:DisableBlizzard('party')
+ end
+
+
+ --[[if(visibility) then
+ local type, list = string.split(' ', visibility, 2)
+ if(list and type == 'custom') then
+ RegisterStateDriver(header, 'visibility', list)
+ header.visibility = list
+ else
+ local condition = getCondition(string.split(',', visibility))
+ RegisterStateDriver(header, 'visibility', condition)
+ header.visibility = condition
+ end
+ end]]
+
+ return header
+ end
+end
+
+--[[ oUF:Spawn(unit, overrideName)
+Used to create a single unit frame and apply the currently active style to it.
+
+* self - the global oUF object
+* unit - the frame's unit (string)
+* overrideName - unique global name to use for the unit frame. Defaults to an auto-generated name based on the unit
+ (string?)
+--]]
+function oUF:Spawn(unit, overrideName)
+ argcheck(unit, 2, 'string')
+ if(not style) then return error('Unable to create frame. No styles have been registered.') end
+
+ unit = string.lower(unit)
+
+ local name = overrideName or generateName(unit)
+ local object = CreateFrame('Button', name, UIParent)
+ object:Hide()
+ Private.UpdateUnits(object, unit)
+
+ self:DisableBlizzard(unit)
+ units[unit] = object
+ walkObject(object, unit)
+
+ object.unit = unit
+
+ return object
+end
+
+--[[ oUF:AddElement(name, update, enable, disable)
+Used to register an element with oUF.
+
+* self - the global oUF object
+* name - unique name of the element (string)
+* update - used to update the element (function?)
+* enable - used to enable the element for a given unit frame and unit (function?)
+* disable - used to disable the element for a given unit frame (function?)
+--]]
+function oUF:AddElement(name, update, enable, disable)
+ argcheck(name, 2, 'string')
+ argcheck(update, 3, 'function', 'nil')
+ argcheck(enable, 4, 'function', 'nil')
+ argcheck(disable, 5, 'function', 'nil')
+
+ if(elements[name]) then return error('Element [%s] is already registered.', name) end
+ elements[name] = {
+ update = update;
+ enable = enable;
+ disable = disable;
+ }
+end
+
+--[[ oUF.units
+Array containing all unit frames with existing units created by oUF:Spawn.
+--]]
+oUF.units = units
+--[[ oUF.objects
+Array containing all unit frames created by `oUF:Spawn`.
+--]]
+oUF.objects = objects
+--[[ oUF.headers
+Array containing all group headers created by `oUF:SpawnHeader`.
+--]]
+oUF.headers = headers
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/private.lua b/ElvUI/Libraries/oUF/private.lua
new file mode 100644
index 0000000..c481ad4
--- /dev/null
+++ b/ElvUI/Libraries/oUF/private.lua
@@ -0,0 +1,22 @@
+local ns = oUF
+local Private = ns.oUF.Private
+
+function Private.argcheck(value, num, ...)
+ assert(type(num) == 'number', "Bad argument #2 to 'argcheck' (number expected, got " .. type(num) .. ')')
+
+ for i = 1, select('#', arg) do
+ if(type(value) == select(i, unpack(arg))) then return end
+ end
+
+ local types = strjoin(', ', unpack(arg))
+ local name = string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
+ error(string.format("Bad argument #%d to '%s' (%s expected, got %s)", num, name, types, type(value)), 3)
+end
+
+function Private.print(...)
+ print('|cff33ff99oUF:|r', unpack(arg))
+end
+
+function Private.error(...)
+ Private.print('|cffff0000Error:|r ' .. string.format(unpack(arg)))
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/templates.lua b/ElvUI/Libraries/oUF/templates.lua
new file mode 100644
index 0000000..6a03772
--- /dev/null
+++ b/ElvUI/Libraries/oUF/templates.lua
@@ -0,0 +1,445 @@
+local pairs = pairs
+local ipairs = ipairs
+
+local unitExistsWatchers = {}
+local unitExistsCache = setmetatable({},{
+ __index = function(t, k)
+ local v = UnitExists(k) or false
+ t[k] = v
+ return v
+ end
+})
+
+local function updateUnitWatch(frame)
+ local unit = frame.unit
+ local exists = (unit and unitExistsCache[unit])
+ if exists then
+ if not frame:IsShown() then
+ frame:Show()
+ end
+ elseif frame:IsShown() then
+ frame:Hide()
+ end
+end
+
+local unitWatch = CreateFrame("Frame")
+unitWatch:Hide()
+
+local timer = 0
+unitWatch:SetScript("OnUpdate", function()
+ timer = timer - arg1
+ if timer <= 0 then
+ timer = 0.2
+
+ for k in pairs(unitExistsCache) do
+ unitExistsCache[k] = nil
+ end
+ for frame in pairs(unitExistsWatchers) do
+ updateUnitWatch(frame)
+ end
+ end
+end)
+unitWatch:SetScript("OnEvent", function() timer = 0 end)
+
+unitWatch:RegisterEvent("PLAYER_TARGET_CHANGED")
+unitWatch:RegisterEvent("PLAYER_REGEN_DISABLED")
+unitWatch:RegisterEvent("PLAYER_REGEN_ENABLED")
+unitWatch:RegisterEvent("UNIT_PET")
+unitWatch:RegisterEvent("RAID_ROSTER_UPDATE")
+unitWatch:RegisterEvent("PARTY_MEMBERS_CHANGED")
+
+function RegisterUnitWatch(frame)
+ unitExistsWatchers[frame] = true
+ unitWatch:Show()
+ updateUnitWatch(frame)
+end
+
+function UnregisterUnitWatch(frame)
+ unitExistsWatchers[frame] = nil
+end
+
+--[[
+List of the various configuration attributes
+======================================================
+showRaid = [BOOLEAN] -- true if the header should be shown while in a raid
+showParty = [BOOLEAN] -- true if the header should be shown while in a party and not in a raid
+showPlayer = [BOOLEAN] -- true if the header should show the player when not in a raid
+showSolo = [BOOLEAN] -- true if the header should be shown while not in a group (implies showPlayer)
+nameList = [STRING] -- a comma separated list of player names (not used if 'groupFilter' is set)
+groupFilter = [1-8, STRING] -- a comma seperated list of raid group numbers and/or uppercase class names and/or uppercase roles
+strictFiltering = [BOOLEAN] - if true, then characters must match both a group and a class from the groupFilter list
+point = [STRING] -- a valid XML anchoring point (Default: "TOP")
+xOffset = [NUMBER] -- the x-Offset to use when anchoring the unit buttons (Default: 0)
+yOffset = [NUMBER] -- the y-Offset to use when anchoring the unit buttons (Default: 0)
+sortMethod = ["INDEX", "NAME"] -- defines how the group is sorted (Default: "INDEX")
+sortDir = ["ASC", "DESC"] -- defines the sort order (Default: "ASC")
+template = [STRING] -- the XML template to use for the unit buttons
+templateType = [STRING] - specifies the frame type of the managed subframes (Default: "Button")
+groupBy = [nil, "GROUP", "CLASS", "ROLE"] - specifies a "grouping" type to apply before regular sorting (Default: nil)
+groupingOrder = [STRING] - specifies the order of the groupings (ie. "1,2,3,4,5,6,7,8")
+maxColumns = [NUMBER] - maximum number of columns the header will create (Default: 1)
+unitsPerColumn = [NUMBER or nil] - maximum units that will be displayed in a singe column, nil is infinate (Default: nil)
+startingIndex = [NUMBER] - the index in the final sorted unit list at which to start displaying units (Default: 1)
+columnSpacing = [NUMBER] - the ammount of space between the rows/columns (Default: 0)
+columnAnchorPoint = [STRING] - the anchor point of each new column (ie. use LEFT for the columns to grow to the right)
+--]]
+
+function SecureGroupHeader_OnEvent()
+ if (event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE") and this:IsVisible() then
+ SecureGroupHeader_Update(this)
+ end
+end
+
+-- relativePoint, xMultiplier, yMultiplier = getRelativePointAnchor(point)
+-- Given a point return the opposite point and which axes the point
+-- depends on.
+local function getRelativePointAnchor(point)
+ point = strupper(point)
+ if point == "TOP" then
+ return "BOTTOM", 0, -1
+ elseif point == "BOTTOM" then
+ return "TOP", 0, 1
+ elseif point == "LEFT" then
+ return "RIGHT", 1, 0
+ elseif point == "RIGHT" then
+ return "LEFT", -1, 0
+ elseif point == "TOPLEFT" then
+ return "BOTTOMRIGHT", 1, -1
+ elseif point == "TOPRIGHT" then
+ return "BOTTOMLEFT", -1, -1
+ elseif point == "BOTTOMLEFT" then
+ return "TOPRIGHT", 1, 1
+ elseif point == "BOTTOMRIGHT" then
+ return "TOPLEFT", -1, 1
+ else
+ return "CENTER", 0, 0
+ end
+end
+
+function ApplyUnitButtonConfiguration(frame)
+ RegisterUnitWatch(frame)
+end
+
+local function ApplyConfig(header, newChild, defaultConfigFunction)
+ local configFunction = header.initialConfigFunction or defaultConfigFunction
+ if type(configFunction) == "function" then
+ configFunction(newChild)
+ return true
+ end
+end
+
+function SetupUnitButtonConfiguration(header, newChild, defaultConfigFunction)
+ if ApplyConfig(header, newChild, defaultConfigFunction) then
+ ApplyUnitButtonConfiguration(newChild)
+ end
+end
+
+-- empties tbl and assigns the value true to each key passed as part of ...
+local function fillTable(tbl, ...)
+ for key in pairs(tbl) do
+ tbl[key] = nil
+ end
+ for i = 1, getn(arg), 1 do
+ local key = arg[i]
+ key = tonumber(key) or key
+ tbl[key] = true
+ end
+end
+
+-- same as fillTable() except that each key is also stored in
+-- the array portion of the table in order
+local function doubleFillTable(tbl, ...)
+ fillTable(tbl, unpack(arg))
+ for i = 1, getn(arg), 1 do
+ tbl[i] = arg[i]
+ end
+end
+
+--working tables
+local tokenTable = {}
+local sortingTable = {}
+local groupingTable = {}
+local tempTable = {}
+
+-- creates child frames and finished configuring them
+local function configureChildren(self)
+ local point = self:GetAttribute("point") or "TOP" --default anchor point of "TOP"
+ local relativePoint, xOffsetMult, yOffsetMult = getRelativePointAnchor(point)
+ local xMultiplier, yMultiplier = abs(xOffsetMult), abs(yOffsetMult)
+ local xOffset = self:GetAttribute("xOffset") or 0 --default of 0
+ local yOffset = self:GetAttribute("yOffset") or 0 --default of 0
+ local sortDir = self:GetAttribute("sortDir") or "ASC" --sort ascending by default
+ local columnSpacing = self:GetAttribute("columnSpacing") or 0
+ local startingIndex = self:GetAttribute("startingIndex") or 1
+
+ local unitCount = getn(sortingTable)
+ local numDisplayed = unitCount - (startingIndex - 1)
+ local unitsPerColumn = self:GetAttribute("unitsPerColumn")
+ local numColumns
+ if unitsPerColumn and numDisplayed > unitsPerColumn then
+ numColumns = min(ceil(numDisplayed / unitsPerColumn), (self:GetAttribute("maxColumns") or 1))
+ else
+ unitsPerColumn = numDisplayed
+ numColumns = 1
+ end
+ local loopStart = startingIndex
+ local loopFinish = min((startingIndex - 1) + unitsPerColumn * numColumns, unitCount)
+ local step = 1
+
+ numDisplayed = loopFinish - (loopStart - 1)
+
+ if sortDir == "DESC" then
+ loopStart = unitCount - (startingIndex - 1)
+ loopFinish = loopStart - (numDisplayed - 1)
+ step = -1
+ end
+
+ -- ensure there are enough buttons
+ local needButtons = max(1, numDisplayed)
+ if not self:GetAttribute("child"..needButtons) then
+ local name = self:GetName()
+ if not name then
+ self:Hide()
+ return
+ end
+ for i = 1, needButtons, 1 do
+ local childAttr = "child"..i
+ if not self:GetAttribute(childAttr) then
+ local newButton = CreateFrame("Button", name.."UnitButton"..i, self)
+ newButton:SetFrameStrata("LOW")
+ SetupUnitButtonConfiguration(self, newButton)
+ self:SetAttribute(childAttr, newButton)
+ end
+ end
+ end
+
+ local columnAnchorPoint, columnRelPoint, colxMulti, colyMulti
+ if numColumns > 1 then
+ columnAnchorPoint = self:GetAttribute("columnAnchorPoint")
+ columnRelPoint, colxMulti, colyMulti = getRelativePointAnchor(columnAnchorPoint)
+ end
+
+ local buttonNum = 0
+ local columnNum = 1
+ local columnUnitCount = 0
+ local currentAnchor = self
+
+ for i = loopStart, loopFinish, step do
+ buttonNum = buttonNum + 1
+ columnUnitCount = columnUnitCount + 1
+ if columnUnitCount > unitsPerColumn then
+ columnUnitCount = 1
+ columnNum = columnNum + 1
+ end
+
+ local unitButton = self:GetAttribute("child"..buttonNum)
+ unitButton:Hide()
+ unitButton:ClearAllPoints()
+ if buttonNum == 1 then
+ unitButton:SetPoint(point, currentAnchor, point, 0, 0)
+ if columnAnchorPoint then
+ unitButton:SetPoint(columnAnchorPoint, currentAnchor, columnAnchorPoint, 0, 0)
+ end
+ elseif columnUnitCount == 1 then
+ local columnAnchor = self:GetAttribute("child"..(buttonNum - unitsPerColumn))
+ unitButton:SetPoint(columnAnchorPoint, columnAnchor, columnRelPoint, colxMulti * columnSpacing, colyMulti * columnSpacing)
+ else
+ unitButton:SetPoint(point, currentAnchor, relativePoint, xMultiplier * xOffset, yMultiplier * yOffset)
+ end
+ unitButton.unit = sortingTable[sortingTable[i]]
+ unitButton:Show()
+
+ currentAnchor = unitButton
+ end
+ repeat
+ buttonNum = buttonNum + 1
+ local unitButton = self:GetAttribute("child"..buttonNum)
+ if unitButton then
+ unitButton:Hide()
+ unitButton.unit = nil
+ end
+ until not unitButton
+
+ local unitButton = self:GetAttribute("child1")
+ local unitButtonWidth = unitButton:GetWidth()
+ local unitButtonHeight = unitButton:GetHeight()
+ if numDisplayed > 0 then
+ local width = xMultiplier * (unitsPerColumn - 1) * unitButtonWidth + ((unitsPerColumn - 1) * (xOffset * xOffsetMult)) + unitButtonWidth
+ local height = yMultiplier * (unitsPerColumn - 1) * unitButtonHeight + ((unitsPerColumn - 1) * (yOffset * yOffsetMult)) + unitButtonHeight
+
+ if numColumns > 1 then
+ width = width + ((numColumns -1) * abs(colxMulti) * (width + columnSpacing))
+ height = height + ((numColumns -1) * abs(colyMulti) * (height + columnSpacing))
+ end
+
+ self:SetWidth(width)
+ self:SetHeight(height)
+ else
+ local minWidth = self:GetAttribute("minWidth") or (yMultiplier * unitButtonWidth)
+ local minHeight = self:GetAttribute("minHeight") or (xMultiplier * unitButtonHeight)
+ self:SetWidth(max(minWidth, 0.1))
+ self:SetHeight(max(minHeight, 0.1))
+ end
+end
+
+local function GetGroupHeaderType(self)
+ local type, start, stop
+
+ local nRaid = GetNumRaidMembers()
+ local nParty = GetNumPartyMembers()
+ if nRaid > 0 and self:GetAttribute("showRaid") then
+ type = "RAID"
+ elseif (nRaid > 0 or nParty > 0) and self:GetAttribute("showParty") then
+ type = "PARTY"
+ elseif self:GetAttribute("showSolo") then
+ type = "SOLO"
+ end
+ if type then
+ if type == "RAID" then
+ start = 1
+ stop = nRaid
+ else
+ if type == "SOLO" or self:GetAttribute("showPlayer") then
+ start = 0
+ else
+ start = 1
+ end
+ stop = nParty
+ end
+ end
+
+ return type, start, stop
+end
+
+local function GetGroupRosterInfo(type, index)
+ local _, unit, name, subgroup, className
+ if type == "RAID" then
+ unit = "raid"..index
+ name, _, subgroup, _, _, className = GetRaidRosterInfo(index)
+ else
+ if index > 0 then
+ unit = "party"..index
+ else
+ unit = "player"
+ end
+ if UnitExists(unit) then
+ name = UnitName(unit)
+ _, className = UnitClass(unit)
+ end
+ subgroup = 1
+ end
+ return unit, name, subgroup, className
+end
+
+function SecureGroupHeader_Update(self)
+ local nameList = self:GetAttribute("nameList")
+ local groupFilter = self:GetAttribute("groupFilter")
+ local sortMethod = self:GetAttribute("sortMethod")
+ local groupBy = self:GetAttribute("groupBy")
+
+ for key in pairs(sortingTable) do
+ sortingTable[key] = nil
+ end
+ table.setn(sortingTable, 0)
+
+ -- See if this header should be shown
+ local type, start, stop = GetGroupHeaderType(self)
+ if not type then
+ configureChildren(self)
+ return
+ end
+
+ if not groupFilter and not nameList then
+ groupFilter = "1,2,3,4,5,6,7,8"
+ end
+
+ if groupFilter then
+ -- filtering by a list of group numbers and/or classes
+ fillTable(tokenTable, strsplit(",", groupFilter))
+ local strictFiltering = self:GetAttribute("strictFiltering") -- non-strict by default
+ for i = start, stop, 1 do
+ local unit, name, subgroup, className = GetGroupRosterInfo(type, i)
+ if name and ((not strictFiltering) and (tokenTable[subgroup] or tokenTable[className])) or (tokenTable[subgroup] and tokenTable[className]) then
+ tinsert(sortingTable, name)
+ sortingTable[name] = unit
+ if groupBy == "GROUP" then
+ groupingTable[name] = subgroup
+ elseif groupBy == "CLASS" then
+ groupingTable[name] = className
+ end
+ end
+ end
+
+ if groupBy then
+ local groupingOrder = self:GetAttribute("groupingOrder")
+ doubleFillTable(tokenTable, strsplit(",", groupingOrder))
+ for k in pairs(tempTable) do
+ tempTable[k] = nil
+ end
+ for _, grouping in ipairs(tokenTable) do
+ grouping = tonumber(grouping) or grouping
+ for k in ipairs(groupingTable) do
+ groupingTable[k] = nil
+ end
+ table.setn(groupingTable, 0)
+ for index, name in ipairs(sortingTable) do
+ if groupingTable[name] == grouping then
+ tinsert(groupingTable, name)
+ tempTable[name] = true
+ end
+ end
+ if sortMethod == "NAME" then -- sort by ID by default
+ table.sort(groupingTable)
+ end
+ for _, name in ipairs(groupingTable) do
+ tinsert(tempTable, name)
+ end
+ end
+ -- handle units whose group didn't appear in groupingOrder
+ for k in ipairs(groupingTable) do
+ groupingTable[k] = nil
+ end
+ table.setn(groupingTable, 0)
+
+ for index, name in ipairs(sortingTable) do
+ if not tempTable[name] then
+ tinsert(groupingTable, name)
+ end
+ end
+ if sortMethod == "NAME" then -- sort by ID by default
+ table.sort(groupingTable)
+ end
+ for _, name in ipairs(groupingTable) do
+ tinsert(tempTable, name)
+ end
+
+ --copy the names back to sortingTable
+ for index, name in ipairs(tempTable) do
+ sortingTable[index] = name
+ end
+
+ elseif sortMethod == "NAME" then -- sort by ID by default
+ table.sort(sortingTable)
+ end
+ else
+ -- filtering via a list of names
+ doubleFillTable(sortingTable, strsplit(",", nameList))
+ for i = start, stop, 1 do
+ local unit, name = GetGroupRosterInfo(type, i)
+ if sortingTable[name] then
+ sortingTable[name] = unit
+ end
+ end
+ for i = getn(sortingTable), 1, -1 do
+ local name = sortingTable[i]
+ if sortingTable[name] == true then
+ tremove(sortingTable, i)
+ end
+ end
+ if sortMethod == "NAME" then
+ table.sort(sortingTable)
+ end
+ end
+
+ configureChildren(self)
+end
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/templates.xml b/ElvUI/Libraries/oUF/templates.xml
new file mode 100644
index 0000000..2fd459d
--- /dev/null
+++ b/ElvUI/Libraries/oUF/templates.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ this:RegisterEvent("PARTY_MEMBERS_CHANGED")
+ this:RegisterEvent("RAID_ROSTER_UPDATE")
+
+
+ SecureGroupHeader_OnEvent(this, event)
+
+
+ SecureGroupHeader_Update(this)
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/units.lua b/ElvUI/Libraries/oUF/units.lua
new file mode 100644
index 0000000..55f216d
--- /dev/null
+++ b/ElvUI/Libraries/oUF/units.lua
@@ -0,0 +1,18 @@
+local ns = oUF
+local oUF = ns.oUF
+local Private = oUF.Private
+
+local enableTargetUpdate = Private.enableTargetUpdate
+
+-- Handles unit specific actions.
+function oUF:HandleUnit(object, unit)
+ local unit = object.unit or unit
+
+ if(unit == 'target') then
+ object:RegisterEvent('PLAYER_TARGET_CHANGED', object.UpdateAllElements)
+ elseif(unit == 'mouseover') then
+ object:RegisterEvent('UPDATE_MOUSEOVER_UNIT', object.UpdateAllElements)
+ elseif(string.match(unit, '%w+target')) then
+ enableTargetUpdate(object)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Locales/Chinese_UI.lua b/ElvUI/Locales/Chinese_UI.lua
new file mode 100644
index 0000000..629eb60
--- /dev/null
+++ b/ElvUI/Locales/Chinese_UI.lua
@@ -0,0 +1,347 @@
+-- Chinese localization file for zhCN.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "zhCN")
+if not L then return end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "插件 %s 不相容于 ElvUI 的 %s 模组, 请停用不相容的插件, 或停用模组."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "欢迎使用 %sElvUI|r %s%s|r 版, 请输入/ec进入设定介面. 如需技术支持,请至至 https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "绑定"
+L["Key"] = "键"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "无绑定设定"
+L["Remove Bar %d Action Page"] = "移除第%d动作条"
+L["Trigger"] = "触发器"
+
+--Bags
+L["Bank"] = "银行"
+L["Hold Control + Right Click:"] = "按住 Ctrl 并按鼠标右键:"
+L["Hold Shift + Drag:"] = "按住 Shift 并拖动:"
+L["Purchase Bags"] = "购买背包"
+L["Reset Position"] = "重设位置"
+L["Sort Bags"] = "背包整理"
+L["Temporary Move"] = "移动背包"
+L["Toggle Bags"] = "背包开关"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "出售灰色物品"
+
+--Chat
+L["AFK"] = "离开" --Also used in datatexts and tooltip
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "忙碌" --Also used in datatexts and tooltip
+L["G"] = "公会"
+L["Invalid Target"] = "无效的目标"
+L["O"] = "干部"
+L["P"] = "队伍"
+L["PL"] = "队长"
+L["R"] = "团队"
+L["RL"] = "团队队长"
+L["RW"] = "团队警告"
+L["says"] = "说"
+L["whispers"] = "密语"
+L["yells"] = "大喊"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(按住Shift) 内存占用"
+L["Avoidance Breakdown"] = "免伤统计"
+L["Character: "] = "角色: "
+L["Chest"] = "胸"
+L["Combat"] = "战斗"
+L["Combat Time"] = true;
+L["Coords"] = "坐标"
+L["copperabbrev"] = "|cffeda55f铜|r"
+L["Deficit:"] = "赤字:"
+L["DPS"] = "伤害输出"
+L["Earned:"] = "赚取:"
+L["Friends List"] = "好友列表"
+L["Friends"] = "好友" --Also in Skins
+L["Gold"] = "金"
+L["goldabbrev"] = "|cffffd700金|r"
+L["Hit"] = "命中"
+L["Hold Shift + Right Click:"] = "按住Shift + 右键点击"
+L["Home Latency:"] = "本机延迟:"
+L["HP"] = "生命值"
+L["HPS"] = "治疗输出"
+L["lvl"] = "等级"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "等级减伤: "
+L["No Guild"] = "没有公会"
+L["Profit:"] = "利润:"
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "重置数据: 按住 Shift + 右键点击"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "已有进度的副本"
+L["Server: "] = "服务器: "
+L["Session:"] = "本次登陆:"
+L["silverabbrev"] = "|cffc7c7cf银|r"
+L["SP"] = "法术强度"
+L["Spell/Heal Power"] = "法术/治疗强度"
+L["Spent:"] = "花费:"
+L["Stats For:"] = "统计:"
+L["System"] = "系统信息"
+L["Total CPU:"] = "CPU占用"
+L["Total Memory:"] = "总内存:"
+L["Total: "] = "合计: "
+L["Unhittable:"] = "未命中:"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s 尝试调用保护函数 '%s'."
+L["No locals to dump"] = "没有本地文件"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s 试图与你分享过滤器配置. 你是否接受?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s 试图与你分享配置文件 %s. 你是否接受?"
+L["Data From: %s"] = "数据来源: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "过滤器配置下载于 %s, 你是否现在变更?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "天啊! 太奇葩了! 下载消失了! 就像在风中放了一个屁... 再试一次吧!"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "配置文件从 %s 下载完成, 但是配置文件 %s 已存在. 请更改名称, 否则它会覆盖你的现有配置文件."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "配置文件从 %s 下载完成, 你是否加载配置文件 %s?"
+L["Profile request sent. Waiting for response from player."] = "已发送文件请求. 等待对方响应."
+L["Request was denied by user."] = "请求被对方拒绝."
+L["Your profile was successfully recieved by the player."] = "你的配置文件已被其他玩家成功接收."
+
+--Install
+L["Aura Bars & Icons"] = "光环条与图标"
+L["Auras Set"] = "光环样式设置"
+L["Auras"] = "光环"
+L["Caster DPS"] = "法系输出"
+L["Chat Set"] = "对话设定"
+L["Chat"] = "聊天框"
+L["Choose a theme layout you wish to use for your initial setup."] = "为你的个人设置选择一个你喜欢的皮肤主题."
+L["Classic"] = "经典"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "点击下面的按钮调整聊天框、单位框架的尺寸, 以及移动动作条位置"
+L["Config Mode:"] = "设置模式:"
+L["CVars Set"] = "参数设定"
+L["CVars"] = "参数"
+L["Dark"] = "黑暗"
+L["Disable"] = "禁用"
+L["ElvUI Installation"] = "安装 ElvUI"
+L["Finished"] = "完成"
+L["Grid Size:"] = "网格尺寸:"
+L["Healer"] = "治疗"
+L["High Resolution"] = "高分辨率"
+L["high"] = "高"
+L["Icons Only"] = "图标"
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "如果你有不想显示的图标或光环条, 你可以简单的通过按住Shift右键点击使它隐藏."
+L["Importance: |cff07D400High|r"] = "重要度: |cff07D400高|r"
+L["Importance: |cffD3CF00Medium|r"] = "重要性: |cffD3CF00中|r"
+L["Importance: |cffFF0000Low|r"] = "重要性:|cffFF0000低|r"
+L["Installation Complete"] = "安装完成"
+L["Layout Set"] = "界面布局设置"
+L["Layout"] = "界面布局"
+L["Lock"] = "锁定"
+L["Low Resolution"] = "低分辨率"
+L["low"] = "低"
+L["Nudge"] = "微调"
+L["Physical DPS"] = "物理输出"
+L["Please click the button below so you can setup variables and ReloadUI."] = "请按下方按钮设定变数并重载介面."
+L["Please click the button below to setup your CVars."] = "请按下方按钮设定参数."
+L["Please press the continue button to go onto the next step."] = "请按继续按钮到下一步"
+L["Resolution Style Set"] = "分辨率样式设置"
+L["Resolution"] = "分辨率"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "选择你想要在ElvUI的单位框体里使用何种光环系统. 选择光环条和图标将同时使用光环条和图标, 选择图标来仅仅显示图标."
+L["Setup Chat"] = "设定聊天框"
+L["Setup CVars"] = "设定参数"
+L["Skip Process"] = "略过"
+L["Sticky Frames"] = "框架依附"
+L["Tank"] = "坦克"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "对话窗口与 WOW 原始对话窗口的操作方式相同, 你可以拖拉、移动分页或重新命名分页.请按下方按钮以设定对话窗口."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "若要进入内建设定选单, 请输入 /ec, 或者按一下小地图旁的 C 按钮.若要略过安装程序, 请按下方按钮."
+L["Theme Set"] = "主题设置"
+L["Theme Setup"] = "主题安装"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "此安装程序有助你了解 ElvUI 部份功能, 并可协助你预先设定 UI."
+L["This is completely optional."] = "这是可选项."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "此安装步骤将会设定聊天框的名称、位置和颜色."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "此安装步骤将会设定 WOW 预设选项, 建议你执行此步骤, 以确保功能均可正常运作."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "这个分辨率不需要你改动任何设置以适应你的屏幕."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "这个分辨率需要你改变一些设置才能适应你的屏幕."
+L["This will change the layout of your unitframes and actionbars."] = "这将会改变你单位框架和动作条的构架."
+L["Trade"] = "拾取/交易"
+L["Welcome to ElvUI version %s!"] = "欢迎使用 ElvUI 版本 %s!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "你已经完成安装过程. 如果你需要技术支持请访问 https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "你可以在游戏内的设定选项内更改ElvUI的字体、颜色等设定."
+L["You can now choose what layout you wish to use based on your combat role."] = "你现在可以根据你的战斗角色选择合适的布局."
+L["You may need to further alter these settings depending how low you resolution is."] = "根据你的分辨率你可能需要改动这些设置."
+L["Your current resolution is %s, this is considered a %s resolution."] = "你当前的分辨率是 %s, 这被认为是个 %s 分辨率."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% 以上 |cff%02x%02x%02x%s|r]"
+L["Bars"] = "条"
+L["Calendar"] = "日历"
+L["Can't Roll"] = "无法需求此装备"
+L["Disband Group"] = "解散队伍"
+L["Empty Slot"] = "空拾取位"
+L["Enable"] = "启用"
+L["Experience"] = "经验/声望条"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "贪婪"
+L["Left Click:"] = "鼠标左键:"
+L["Mouse"] = "老鼠"
+L["Raid Menu"] = "团队菜单"
+L["Remaining:"] = "剩余:"
+L["Rested:"] = "休息:"
+L["Right Click:"] = "鼠标右键:"
+L["Show BG Texts"] = "显示战场资讯文字"
+L["Toggle Chat Frame"] = "开关聊天框架"
+L["Toggle Configuration"] = "设置开关"
+L["XP:"] = "经验:"
+L["You don't have permission to mark targets."] = "你没有标记目标的权限"
+
+--Movers
+L["Arena Frames"] = "竞技场框架"
+L["Bag Mover (Grow Down)"] = "背包框架(向下)"
+L["Bag Mover (Grow Up)"] = "背包框架(向上)"
+L["Bag Mover"] = "背包框架"
+L["Bags"] = "背包" --Also in DataTexts
+L["Bank Mover (Grow Down)"] = "银行框架(向下)"
+L["Bank Mover (Grow Up)"] = "银行框架(向上)"
+L["Bar "] = "动作条 " --Also in ActionBars
+L["BNet Frame"] = "战网提示信息"
+L["Boss Frames"] = "首领框架"
+L["Classbar"] = "职业特有条"
+L["Experience Bar"] = "经验条"
+L["Focus Castbar"] = "焦点目标施法条"
+L["Focus Frame"] = "焦点目标框架"
+L["FocusTarget Frame"] = "焦点目标的目标框架"
+L["GM Ticket Frame"] = "GM对话框"
+L["Left Chat"] = "左侧对话框"
+L["Loot / Alert Frames"] = "拾取/提醒框"
+L["Loot Frame"] = "拾取框架"
+L["MA Frames"] = "主助理框"
+L["Micro Bar"] = "微型系统菜单" --Also in ActionBars
+L["Minimap"] = "小地图"
+L["MirrorTimer"] = "镜像计时器"
+L["MT Frames"] = "主坦克框"
+L["Party Frames"] = "队伍框架"
+L["Pet Bar"] = "宠物动作条" --Also in ActionBars
+L["Pet Castbar"] = "宠物施法条"
+L["Pet Frame"] = "宠物框架"
+L["PetTarget Frame"] = "宠物目标框架"
+L["Player Buffs"] = "玩家增益"
+L["Player Castbar"] = "玩家施法条"
+L["Player Debuffs"] = "玩家减益"
+L["Player Frame"] = "玩家框架"
+L["Player Powerbar"] = "玩家能量条"
+L["PvP"] = true;
+L["Raid Frames"] = "团队框架"
+L["Raid Pet Frames"] = "团队宠物框架"
+L["Raid-40 Frames"] = "40人团队框架"
+L["Reputation Bar"] = "声望条"
+L["Right Chat"] = "右侧对话框"
+L["Stance Bar"] = "姿态条" --Also in ActionBars
+L["Target Castbar"] = "目标施法条"
+L["Target Frame"] = "目标框架"
+L["Target Powerbar"] = "目标能量条"
+L["TargetTarget Frame"] = "目标的目标框架"
+L["TargetTargetTarget Frame"] = "目标的目标的目标框架"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "鼠标提示"
+L["Vehicle Seat Frame"] = "载具座位框"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = "ElvUI插件安装"
+L["In Progress"] = "正在进行中"
+L["List of installations in queue:"] = "即将安装的列表:"
+L["Pending"] = "等待中"
+L["Steps"] = "步骤"
+
+--Prints
+L[" |cff00ff00bound to |r"] = " |cff00ff00绑定到 |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "%s 个框架锚点冲突, 请移动buff或者debuff锚点让他们彼此不依附.暂时强制debuff依附到主框架."
+L["All keybindings cleared for |cff00ff00%s|r."] = "取消 |cff00ff00%s|r 所有绑定的快捷键."
+L["Already Running.. Bailing Out!"] = "正在运行!"
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "战场信息暂时隐藏, 你可以通过输入/bgstats 或右键点击小地图旁「C」按钮显示."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "当你处于战场时战场信息将再次显示."
+L["Binds Discarded"] = "取消绑定"
+L["Binds Saved"] = "储存绑定"
+L["Confused.. Try Again!"] = "请再试一次!"
+L["No gray items to delete."] = "没有要删除的灰色物品"
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "法术'%s'已经被添加到单位框架的光环过滤器中."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "这个设置引起一个互相矛盾的锚点, '%s' 被依附于他自身. 请检查你的锚点设置. 设置 '%s' 依附到 '%s'."
+L["Vendored gray items for:"] = "已出售灰色物品:"
+L["You don't have enough money to repair."] = "没有足够的资金来修复."
+L["You must be at a vendor."] = "你必需以商人为目标."
+L["Your items have been repaired for: "] = "装备已修复: "
+L["Your items have been repaired using guild bank funds for: "] = "物品已使用公会银行资金修复: "
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000LUA错误已接收, 你可以在脱离战斗后检查.|r"
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "你所做的改动只会影响到使用这个插件的本角色, 你需要重新加载界面才能使改动生效."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
+L["Are you sure you want to apply this font to all ElvUI elements?"] = "确定要对所有ElvUI元素使用这个字体?"
+L["Are you sure you want to delete all your gray items?"] = "确定需要摧毁你的灰色物品?"
+L["Are you sure you want to disband the group?"] = "确定要解散队伍?"
+L["Are you sure you want to reset all the settings on this profile?"] = "确定需要重置这个配置文件中的所有设置?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "确定需要重置所有框架至默认位置?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "由于大量的改动导致光环系统需要一个新的安装过程. 这是可选的, 最后一步将设置你的光环样式. 点击「完成」将不再提示. 如果由于某些原因反复提示, 请重新开启游戏."
+L["Can't buy anymore slots!"] = "银行背包栏位已达最大值"
+L["Disable Warning"] = "停用警告"
+L["Discard"] = "取消"
+L["Do you enjoy the new ElvUI?"] = "你喜欢新的ElvUI么?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "你发誓在你没停用其他插件前不会到技术支持询问某些功能失效吗?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI已过期5个或者更多的版本。你可以在 https://github.com/ElvUI-Vanilla/ElvUI/ 下载到最新的版本"
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = true;
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI需要进行数据库优化, 请耐性等待."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "移动鼠标到动作条或技能书按钮上绑定快捷键. 按ESC或鼠标右键取消目前快捷键"
+L["I Swear"] = "我承诺"
+L["No, Revert Changes!"] = "不, 撤销修改!"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "你不能同时使用Elvui和Tukui, 请选择一个禁用."
+L["One or more of the changes you have made require a ReloadUI."] = "已变更一或多个设定, 需重载界面."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "你所做的改动可能会影响到使用这个插件的所有角色, 你需要重新加载界面才能使改动生效."
+L["Save"] = "储存"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "你尝试导入的配置文件已经存在.请选择一个新的名字或者确认覆盖存在的配置文件."
+L["Type /hellokitty to revert to old settings."] = "输入/hellokitty以撤销到原来的设定"
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "使用治疗布局时建议你下载 Clique 插件,从而拥有点击施法功能"
+L["Yes, Keep Changes!"] = "是的, 保存修改!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "你选择了细边框主题选项,你必须完成安装程序来移除任何图像错误"
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "你改变了界面缩放比例, 然而ElvUI的自动缩放选项是开启的.点击接受以关闭ElvUI的自动缩放."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "你导入的设置可能需要重载界面才能生效.确认重载?"
+L["You must purchase a bank slot first!"] = "你必需购买一个银行背包栏位"
+
+--Tooltip
+L["Count"] = "计数"
+L["Item Level:"] = "物品等级:"
+L["Talent Specialization:"] = "天赋专精:"
+L["Targeted By:"] = "同目标的有:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "你可以通过按ESC键 -> 按键设置, 滚动到ElvUI设置下方设置一个快速标记的快捷键."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI可以根据你所使用的天赋自动套用不同的设置档. 你可以在配置文件中使用此功能."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "如需技术支援请至 https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "如果你不慎移除了对话框, 你可以重新安装一次重置他们."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "如果你遇到问题, ElvUI会尝试禁用你除了ElvUI之外的插件. 请记住你不能用不同的插件实现同一功能."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "你可以通过 /focus 命令设置焦点目标."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "你可以通过按住Shift拖动技能条中的按键. 你可以在 Blizzard 的动作条设置中更改按键."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "你可以通过右键点击对话框标签栏设置你需要在对话框内显示的频道."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "你可以通过鼠标滑过对话框右上角点击复制图标打开对话复制窗口."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "你可以通过按住Shift并将鼠标滑过目标看到目标的装备等级, 这将显示在你的鼠标提示框内."
+L["You can set your keybinds quickly by typing /kb."] = "你可以通过输入 /kb 快速绑定按键."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "你可以通过鼠标中键点击小地图或在动作条设置内选择打开微型系统栏."
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "使用 /resetui 命令可以重置你的所有框架位置. 你也可以通过命令 /resetui <框架名称> 单独重置某个框架.\n例如: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = "死亡"
+L["Ghost"] = "鬼魂"
+L["Offline"] = "离线"
diff --git a/ElvUI/Locales/English_UI.lua b/ElvUI/Locales/English_UI.lua
new file mode 100644
index 0000000..aff03f0
--- /dev/null
+++ b/ElvUI/Locales/English_UI.lua
@@ -0,0 +1,347 @@
+-- English localization file for enUS and enGB.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0");
+local L = AceLocale:NewLocale("ElvUI", "enUS", true, true);
+if not L then return; end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "The addon %s is not compatible with ElvUI's %s module. Please select either the addon or the ElvUI module to disable."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "Welcome to %sElvUI|r version %s%s|r, type /ec to access the in-game configuration menu. If you are in need of technical support you can visit us at https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = true;
+L["Key"] = true;
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = true;
+L["Remove Bar %d Action Page"] = true;
+L["Trigger"] = true;
+
+--Bags
+L["Bank"] = true;
+L["Hold Control + Right Click:"] = true;
+L["Hold Shift + Drag:"] = true;
+L["Purchase Bags"] = true;
+L["Reset Position"] = true;
+L["Sort Bags"] = true;
+L["Temporary Move"] = true;
+L["Toggle Bags"] = true;
+L["Toggle Key"] = true;
+L["Vendor Grays"] = true;
+
+--Chat
+L["AFK"] = true; --Also used in datatexts
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = true; --Also used in datatexts
+L["G"] = true;
+L["Invalid Target"] = true;
+L["O"] = true;
+L["P"] = true;
+L["PL"] = true;
+L["R"] = true;
+L["RL"] = true;
+L["RW"] = true;
+L["says"] = true;
+L["whispers"] = true;
+L["yells"] = true;
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = true;
+L["Avoidance Breakdown"] = true;
+L["Character: "] = true;
+L["Chest"] = true;
+L["Combat"] = true;
+L["Combat Time"] = true;
+L["Coords"] = true;
+L["copperabbrev"] = "|cffeda55fc|r" --Also used in Bags
+L["Deficit:"] = true;
+L["DPS"] = true;
+L["Earned:"] = true;
+L["Friends List"] = true;
+L["Friends"] = true; --Also in Skins
+L["Gold"] = true;
+L["goldabbrev"] = "|cffffd700g|r" --Also used in Bags
+L["Hit"] = true;
+L["Hold Shift + Right Click:"] = true;
+L["Home Latency:"] = true;
+L["HP"] = true;
+L["HPS"] = true;
+L["lvl"] = true;
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = true;
+L["No Guild"] = true;
+L["Profit:"] = true;
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = true;
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = true;
+L["Server: "] = true;
+L["Session:"] = true;
+L["silverabbrev"] = "|cffc7c7cfs|r" --Also used in Bags
+L["SP"] = true;
+L["Spell/Heal Power"] = true;
+L["Spent:"] = true;
+L["Stats For:"] = true;
+L["System"] = true;
+L["Total CPU:"] = true;
+L["Total Memory:"] = true;
+L["Total: "] = true;
+L["Unhittable:"] = true;
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = true;
+L["No locals to dump"] = true;
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = true;
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = true;
+L["Data From: %s"] = true;
+L["Filter download complete from %s, would you like to apply changes now?"] = true;
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = true;
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = true;
+L["Profile download complete from %s, would you like to load the profile %s now?"] = true;
+L["Profile request sent. Waiting for response from player."] = true;
+L["Request was denied by user."] = true;
+L["Your profile was successfully recieved by the player."] = true;
+
+--Install
+L["Aura Bars & Icons"] = true;
+L["Auras Set"] = true;
+L["Auras"] = true;
+L["Caster DPS"] = true;
+L["Chat Set"] = true;
+L["Chat"] = true;
+L["Choose a theme layout you wish to use for your initial setup."] = true;
+L["Classic"] = true;
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = true;
+L["Config Mode:"] = true;
+L["CVars Set"] = true;
+L["CVars"] = true;
+L["Dark"] = true;
+L["Disable"] = true;
+L["ElvUI Installation"] = true;
+L["Finished"] = true;
+L["Grid Size:"] = true;
+L["Healer"] = true;
+L["High Resolution"] = true;
+L["high"] = true;
+L["Icons Only"] = true; --Also used in Bags
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = true;
+L["Importance: |cff07D400High|r"] = true;
+L["Importance: |cffD3CF00Medium|r"] = true;
+L["Importance: |cffFF0000Low|r"] = true;
+L["Installation Complete"] = true;
+L["Layout Set"] = true;
+L["Layout"] = true;
+L["Lock"] = true;
+L["Low Resolution"] = true;
+L["low"] = true;
+L["Nudge"] = true;
+L["Physical DPS"] = true;
+L["Please click the button below so you can setup variables and ReloadUI."] = true;
+L["Please click the button below to setup your CVars."] = true;
+L["Please press the continue button to go onto the next step."] = true;
+L["Resolution Style Set"] = true;
+L["Resolution"] = true;
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = true;
+L["Setup Chat"] = true;
+L["Setup CVars"] = true;
+L["Skip Process"] = true;
+L["Sticky Frames"] = true;
+L["Tank"] = true;
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = true;
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = true;
+L["Theme Set"] = true;
+L["Theme Setup"] = true;
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = true;
+L["This is completely optional."] = true;
+L["This part of the installation process sets up your chat windows names, positions and colors."] = true;
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = true;
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = true;
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = true;
+L["This will change the layout of your unitframes and actionbars."] = true;
+L["Trade"] = true;
+L["Welcome to ElvUI version %s!"] = true;
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = true;
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = true;
+L["You can now choose what layout you wish to use based on your combat role."] = true;
+L["You may need to further alter these settings depending how low you resolution is."] = true;
+L["Your current resolution is %s, this is considered a %s resolution."] = true;
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
+L["Bars"] = true; --Also used in UnitFrames
+L["Calendar"] = true;
+L["Can't Roll"] = true;
+L["Disband Group"] = true;
+L["Empty Slot"] = true;
+L["Enable"] = true; --Doesn't fit a section since it's used a lot of places
+L["Experience"] = true;
+L["Farm Mode"] = true;
+L["Fishy Loot"] = true;
+L["Left Click:"] = true; --layout\layout.lua
+L["Mouse"] = true;
+L["Raid Menu"] = true;
+L["Remaining:"] = true;
+L["Rested:"] = true;
+L["Right Click:"] = true; --layout\layout.lua
+L["Show BG Texts"] = true; --layout\layout.lua
+L["Toggle Chat Frame"] = true; --layout\layout.lua
+L["Toggle Configuration"] = true; --layout\layout.lua
+L["XP:"] = true;
+L["You don't have permission to mark targets."] = true;
+
+--Movers
+L["Arena Frames"] = true; --Also used in UnitFrames
+L["Bag Mover (Grow Down)"] = true;
+L["Bag Mover (Grow Up)"] = true;
+L["Bag Mover"] = true;
+L["Bags"] = true; --Also in DataTexts
+L["Bank Mover (Grow Down)"] = true;
+L["Bank Mover (Grow Up)"] = true;
+L["Bar "] = true; --Also in ActionBars
+L["BNet Frame"] = true;
+L["Boss Frames"] = true; --Also used in UnitFrames
+L["Classbar"] = true; --Also used in UnitFrames
+L["Experience Bar"] = true;
+L["Focus Castbar"] = true;
+L["Focus Frame"] = true; --Also used in UnitFrames
+L["FocusTarget Frame"] = true; --Also used in UnitFrames
+L["GM Ticket Frame"] = true;
+L["Left Chat"] = true;
+L["Loot / Alert Frames"] = true;
+L["Loot Frame"] = true;
+L["MA Frames"] = true;
+L["Micro Bar"] = true; --Also in ActionBars
+L["Minimap"] = true;
+L["MirrorTimer"] = true;
+L["MT Frames"] = true;
+L["Party Frames"] = true; --Also used in UnitFrames
+L["Pet Bar"] = true; --Also in ActionBars
+L["Pet Castbar"] = true;
+L["Pet Frame"] = true; --Also used in UnitFrames
+L["PetTarget Frame"] = true; --Also used in UnitFrames
+L["Player Buffs"] = true;
+L["Player Castbar"] = true;
+L["Player Debuffs"] = true;
+L["Player Frame"] = true; --Also used in UnitFrames
+L["Player Powerbar"] = true;
+L["PvP"] = true;
+L["Raid Frames"] = true;
+L["Raid Pet Frames"] = true;
+L["Raid-40 Frames"] = true;
+L["Reputation Bar"] = true;
+L["Right Chat"] = true;
+L["Stance Bar"] = true; --Also in ActionBars
+L["Target Castbar"] = true;
+L["Target Frame"] = true; --Also used in UnitFrames
+L["Target Powerbar"] = true;
+L["TargetTarget Frame"] = true; --Also used in UnitFrames
+L["TargetTargetTarget Frame"] = true; --Also used in UnitFrames
+L["Time Manager Frame"] = true;
+L["Tooltip"] = true;
+L["Vehicle Seat Frame"] = true;
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = true;
+L["In Progress"] = true;
+L["List of installations in queue:"] = true;
+L["Pending"] = true;
+L["Steps"] = true;
+
+--Prints
+L[" |cff00ff00bound to |r"] = true;
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = true;
+L["All keybindings cleared for |cff00ff00%s|r."] = true;
+L["Already Running.. Bailing Out!"] = true;
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = true;
+L["Battleground datatexts will now show again if you are inside a battleground."] = true;
+L["Binds Discarded"] = true;
+L["Binds Saved"] = true;
+L["Confused.. Try Again!"] = true;
+L["No gray items to delete."] = true;
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = true;
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
+L["Vendored gray items for:"] = true;
+L["You don't have enough money to repair."] = true;
+L["You must be at a vendor."] = true;
+L["Your items have been repaired for: "] = true;
+L["Your items have been repaired using guild bank funds for: "] = true;
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = true;
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = true;
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
+L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
+L["Are you sure you want to delete all your gray items?"] = true;
+L["Are you sure you want to disband the group?"] = true;
+L["Are you sure you want to reset all the settings on this profile?"] = true;
+L["Are you sure you want to reset every mover back to it's default position?"] = true;
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = true;
+L["Can't buy anymore slots!"] = true;
+L["Disable Warning"] = true;
+L["Discard"] = true;
+L["Do you enjoy the new ElvUI?"] = true;
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = true;
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = true;
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = true;
+L["ElvUI needs to perform database optimizations please be patient."] = true;
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = true;
+L["I Swear"] = true;
+L["No, Revert Changes!"] = true;
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = true;
+L["One or more of the changes you have made require a ReloadUI."] = true;
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = true;
+L["Save"] = true;
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = true;
+L["Type /hellokitty to revert to old settings."] = true;
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = true;
+L["Yes, Keep Changes!"] = true;
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = true;
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = true;
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = true;
+L["You must purchase a bank slot first!"] = true;
+
+--Tooltip
+L["Count"] = true;
+L["Item Level:"] = true;
+L["Talent Specialization:"] = true;
+L["Targeted By:"] = true;
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = true;
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = true;
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = true;
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = true;
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = true;
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = true;
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = true;
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = true;
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = true;
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = true;
+L["You can set your keybinds quickly by typing /kb."] = true;
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = true;
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = true;
+
+--UnitFrames
+L["Dead"] = true;
+L["Ghost"] = true;
+L["Offline"] = true;
diff --git a/ElvUI/Locales/French_UI.lua b/ElvUI/Locales/French_UI.lua
new file mode 100644
index 0000000..ec23230
--- /dev/null
+++ b/ElvUI/Locales/French_UI.lua
@@ -0,0 +1,347 @@
+-- French localization file for frFR.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0");
+local L = AceLocale:NewLocale("ElvUI", "frFR");
+if not L then return; end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "L'addon %s n'est pas compatible avec le module %s d'ElvUI. Merci de sélectionner soit l'addon ou le module d'ElvUI pour le désactiver."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "Bienvenue sur %sElvUI|r version %s%s|r, tapez /ec afin d'accéder au menu de configuration en jeu. Si vous avez besoin d'un support technique, vous pouvez nous rejoindre sur https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "Raccourcis"
+L["Key"] = "Touche"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Suppr"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "Aucune assignation"
+L["Remove Bar %d Action Page"] = "Retirer la pagination de la barre d'action"
+L["Trigger"] = "Déclencheur"
+
+--Bags
+L["Bank"] = "Banque"
+L["Hold Control + Right Click:"] = "Contrôle enfoncé + Clique droit"
+L["Hold Shift + Drag:"] = "Majuscule enfoncée + Déplacer"
+L["Purchase Bags"] = "Acheter des sacs"
+L["Reset Position"] = "Réinitialiser la position"
+L["Sort Bags"] = "Trier les sacs"
+L["Temporary Move"] = "Déplacer temporairement"
+L["Toggle Bags"] = "Afficher les sacs"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "Vendre les objets gris"
+
+--Chat
+L["AFK"] = "ABS" --Also used in datatexts and tooltip
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "NPD" --Also used in datatexts and tooltip
+L["G"] = "G"
+L["Invalid Target"] = "Cible incorrecte"
+L["O"] = "O"
+L["P"] = "Gr"
+L["PL"] = "CdG"
+L["R"] = "R"
+L["RL"] = "RL"
+L["RW"] = "RW"
+L["says"] = "dit"
+L["whispers"] = "chuchote"
+L["yells"] = "crie"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(Maintenir MAJ) Utilisation de la Mémoire."
+L["Avoidance Breakdown"] = "Répartition de l'évitement"
+L["Character: "] = "Personnage: "
+L["Chest"] = "Torse"
+L["Combat"] = "Combat"
+L["Combat Time"] = true;
+L["Coords"] = true;
+L["copperabbrev"] = "|cffeda55fc|r" --Also used in Bags
+L["Deficit:"] = "Déficit:"
+L["DPS"] = "DPS"
+L["Earned:"] = "Gagné:"
+L["Friends List"] = "Liste d'amis"
+L["Friends"] = "Amis" --Also in Skins
+L["Gold"] = true;
+L["goldabbrev"] = "|cffffd700g|r" --Also used in Bags
+L["Hit"] = "Toucher"
+L["Hold Shift + Right Click:"] = "Maintenir Majuscule + Clic droit"
+L["Home Latency:"] = "Latence du Domicile:"
+L["HP"] = "PdS"
+L["HPS"] = "HPS"
+L["lvl"] = "niveau"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "Réduction par niveau: "
+L["No Guild"] = "Pas de Guilde"
+L["Profit:"] = "Profit:"
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "RAZ des données: MAJ + Clic droit"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "Raid(s) Sauvegardé(s)"
+L["Server: "] = "Serveur: "
+L["Session:"] = "Session:"
+L["silverabbrev"] = "|cffc7c7cfs|r" --Also used in Bags
+L["SP"] = "PdS"
+L["Spell/Heal Power"] = true;
+L["Spent:"] = "Dépensé: "
+L["Stats For:"] = "Stats pour:"
+L["System"] = true;
+L["Total CPU:"] = "Charge du CPU:"
+L["Total Memory:"] = "Mémoire totale:"
+L["Total: "] = "Total: "
+L["Unhittable:"] = "Intouchable:"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s a essayé d'appeler la fonction protégée '%s'."
+L["No locals to dump"] = "Aucunes données à vider"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s tente de partager ses filtres avec vous. Voulez-vous accepter la demande?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s tente de partager le profil %s avec vous. Voulez-vous accepter la demande?"
+L["Data From: %s"] = "Donnée de: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "Téléchargement du filtre de %s complet, voulez-vous appliquer les changements maintenant ?" --Need review
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Seigneur ! C'est un miracle ! Le téléchargement s'est envolé et a disparu comme un pet dans le vent! Essayez encore !"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Téléchargement du profil de %s complet, mais le profil de % existe déjà. Changez le nom ou il écrasera le profil existant."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "Téléchargement du profil de %s complet, voulez-vous charger le profil %s maintenant?"
+L["Profile request sent. Waiting for response from player."] = "Requête du profil envoyé. En attente de la réponse du joueur."
+L["Request was denied by user."] = "La requête a été refusée par l'utilisateur."
+L["Your profile was successfully recieved by the player."] = "Votre profil a été reçu avec succès par le joueur."
+
+--Install
+L["Aura Bars & Icons"] = "Barres d'Auras & Icônes"
+L["Auras Set"] = "Configuration des Auras"
+L["Auras"] = "Auras"
+L["Caster DPS"] = "DPS Distance"
+L["Chat Set"] = "Chat configuré"
+L["Chat"] = "Discussion"
+L["Choose a theme layout you wish to use for your initial setup."] = "Choisissez un modèle de thème que vous souhaitez utiliser pour votre configuration initiale."
+L["Classic"] = "Classique"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Cliquez sur le bouton ci-dessous pour redimensionner vos fenêtres de chat, vos cadres d'unités et repositionner vos barres d'actions."
+L["Config Mode:"] = "Mode Configuration:"
+L["CVars Set"] = "CVars configurés"
+L["CVars"] = "CVars"
+L["Dark"] = "Sombre"
+L["Disable"] = "Désactiver"
+L["ElvUI Installation"] = "Installation d'ElvUI"
+L["Finished"] = "Terminé"
+L["Grid Size:"] = "Taille de la Grille:"
+L["Healer"] = "Soigneur"
+L["High Resolution"] = "Haute Résolution"
+L["high"] = "Haute"
+L["Icons Only"] = "Icônes seulement" --Also used in Bags
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Si vous avez une icône ou une barre d'aura que vous ne souhaitez pas afficher il suffit de maintenir la touche MAJ enfoncée et d'effectuer un clic droit sur l'icône correspondante pour la faire disparaitre."
+L["Importance: |cff07D400High|r"] = "Importance: |cff07D400Haute|r"
+L["Importance: |cffD3CF00Medium|r"] = "Importance: |cffD3CF00Moyenne|r"
+L["Importance: |cffFF0000Low|r"] = "Importance: |cffFF0000Faible|r"
+L["Installation Complete"] = "Installation terminée"
+L["Layout Set"] = "Disposition configurée"
+L["Layout"] = "Disposition"
+L["Lock"] = "Verrouiller"
+L["Low Resolution"] = "Basse résolution"
+L["low"] = "Faible"
+L["Nudge"] = "Pousser"
+L["Physical DPS"] = "DPS Physique"
+L["Please click the button below so you can setup variables and ReloadUI."] = "Pour configurer les variables et recharger l'interface, cliquez sur le bouton ci-dessous."
+L["Please click the button below to setup your CVars."] = "Pour configurer les CVars, cliquez sur le bouton ci-dessous."
+L["Please press the continue button to go onto the next step."] = "Pour passer à l'étape suivante, cliquez sur le bouton Continuer."
+L["Resolution Style Set"] = "Paramètre de résolution configuré"
+L["Resolution"] = "Résolution"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Sélectionnez le système d`auras que vous voulez utiliser avec les cadres d`unités ElvUI. Sélectionnez Barres d'Auras & Icônes pour utiliser à la fois les barres et les icônes, choisissez Icônes pour voir seulement les icônes."
+L["Setup Chat"] = "Configurer le Chat."
+L["Setup CVars"] = "Configurer les CVars"
+L["Skip Process"] = "Passer cette étape"
+L["Sticky Frames"] = "Cadres aimantés"
+L["Tank"] = "Tank"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "La fenêtre de chat ElvUI utilise les même fonctions que celle de Blizzard, vous pouvez faire un clique droit sur un onglet pour le déplacer, le renommer, etc."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "Le menu de configuration est accessible en tapant la commande /ec ou en cliquant sur le bouton 'C' sur la Mini-carte. Cliquez sur le bouton ci-dessous si vous voulez passer le processus d'installation."
+L["Theme Set"] = "Thème configuré"
+L["Theme Setup"] = "Configuration du thème"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Ce programme d'installation vous aidera à découvrir quelques fonctionnalités qu'ElvUI offre et préparera également votre interface à son utilisation."
+L["This is completely optional."] = "Ceci est totalement optionnel."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "Cette partie du processus d'installation configure les noms, positions et couleurs de vos fenêtres de chat."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Cette partie du processus d'installation paramètrera vos options par défaut de World of Warcraft. Il est recommandé d'effectuer cette étape afin que tout fonctionne correctement."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Cette résolution ne nécessite pas que vous modifiez les paramètres de l'interface utilisateur pour s'adapter à votre écran."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Cette résolution nécessite que vous modifiez les paramètres de l'interface utilisateur pour s'adapter à votre écran."
+L["This will change the layout of your unitframes and actionbars."] = "Ceci changera la disposition des cadres d'unités et des barres d'actions."
+L["Trade"] = "Échanger"
+L["Welcome to ElvUI version %s!"] = "Bienvenue sur la version %s d'ElvUI!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Vous avez maintenant terminé le processus d'installation. Si vous avez besoin d'un support technique, merci de vous rendre sur https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Vous pouvez toujours modifier les polices et les couleurs de n'importe quel élément d'Elvui dans la configuration du jeu."
+L["You can now choose what layout you wish to use based on your combat role."] = "Vous pouvez maintenant choisir quelle disposition vous souhaitez utiliser en fonction de votre rôle en combat."
+L["You may need to further alter these settings depending how low you resolution is."] = "Vous devrez peut-être encore modifier ces paramètres en fonction d'un changement de résolution."
+L["Your current resolution is %s, this is considered a %s resolution."] = "Votre résolution actuelle est %s, elle est donc considérée comme une %s Résolution."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% excès |cff%02x%02x%02x%s|r]"
+L["Bars"] = "Barres" --Also used in UnitFrames
+L["Calendar"] = "Calendrier"
+L["Can't Roll"] = "Ne peut pas jeter les dés"
+L["Disband Group"] = "Dissoudre le groupe"
+L["Empty Slot"] = true;
+L["Enable"] = "Activer" --Doesn't fit a section since it's used a lot of places
+L["Experience"] = "Expérience"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "Butin de pêche"
+L["Left Click:"] = "Clique Gauche:" --layout\layout.lua
+L["Mouse"] = "Souris"
+L["Raid Menu"] = "Menu Raid"
+L["Remaining:"] = "Restant:"
+L["Rested:"] = "Reposé:"
+L["Right Click:"] = "Clique Droit:" --layout\layout.lua
+L["Show BG Texts"] = "Voir les textes de BG" --layout\layout.lua
+L["Toggle Chat Frame"] = "Activer la fenêtre de discussion" --layout\layout.lua
+L["Toggle Configuration"] = "Afficher la Configuration" --layout\layout.lua
+L["XP:"] = "XP:"
+L["You don't have permission to mark targets."] = "Vous n'avez pas la permission de marquer les cibles."
+
+--Movers
+L["Arena Frames"] = "Cadre d'arène" --Also used in UnitFrames
+L["Bag Mover (Grow Down)"] = true;
+L["Bag Mover (Grow Up)"] = true;
+L["Bag Mover"] = true;
+L["Bags"] = "Sacs" --Also in DataTexts
+L["Bank Mover (Grow Down)"] = true;
+L["Bank Mover (Grow Up)"] = true;
+L["Bar "] = "Barre " --Also in ActionBars
+L["BNet Frame"] = "Cadre BNet"
+L["Boss Frames"] = "Cadre du Boss" --Also used in UnitFrames
+L["Classbar"] = "Barre de Classe"
+L["Experience Bar"] = "Barre d'expérience"
+L["Focus Castbar"] = "Barre d'incantation du Focus"
+L["Focus Frame"] = "Cadre Focus" --Also used in UnitFrames
+L["FocusTarget Frame"] = "Cadre de la cible de votre Focus" --Also used in UnitFrames
+L["GM Ticket Frame"] = "Cadre du ticket MJ"
+L["Left Chat"] = "Chat gauche"
+L["Loot / Alert Frames"] = "Cadres de butin / Alerte"
+L["Loot Frame"] = "Cadre de butin"
+L["MA Frames"] = "Cadres de l`assistant principal"
+L["Micro Bar"] = "Micro Barre" --Also in ActionBars
+L["Minimap"] = "Mini-carte"
+L["MirrorTimer"] = "Timer mirroir"
+L["MT Frames"] = "Cadres du Tank principal"
+L["Party Frames"] = "Cadres de groupe" --Also used in UnitFrames
+L["Pet Bar"] = "Barre du familier" --Also in ActionBars
+L["Pet Castbar"] = "Barre d'incantation du familier"
+L["Pet Frame"] = "Cadre du familier" --Also used in UnitFrames
+L["PetTarget Frame"] = "Cadre de la cible du familier" --Also used in UnitFrames
+L["Player Buffs"] = "Améliorations du joueur"
+L["Player Castbar"] = "Barre d'incantation du joueur"
+L["Player Debuffs"] = "Affaiblissements du joueur"
+L["Player Frame"] = "Cadre du joueur" --Also used in UnitFrames
+L["Player Powerbar"] = "Barre de pouvoir du joueur" -- need review.
+L["PvP"] = true;
+L["Raid Frames"] = "Cadres de Raid"
+L["Raid Pet Frames"] = "Cadres de Raid des Familiers"
+L["Raid-40 Frames"] = "Cadres de Raid 40"
+L["Reputation Bar"] = "Barre de réputation"
+L["Right Chat"] = "Chat de droite"
+L["Stance Bar"] = "Barre de posture" --Also in ActionBars
+L["Target Castbar"] = "Barre d'incantation de la cible"
+L["Target Frame"] = "Cadre de la cible" --Also used in UnitFrames
+L["Target Powerbar"] = "Barre de pouvoir de la cible" -- need review.
+L["TargetTarget Frame"] = "Cadre de la cible de votre cible" --Also used in UnitFrames
+L["TargetTargetTarget Frame"] = "Cadre de la cible de la cible de la cible"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "Infobulle"
+L["Vehicle Seat Frame"] = "Cadre de siège du véhicule"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = true;
+L["In Progress"] = true;
+L["List of installations in queue:"] = true;
+L["Pending"] = true;
+L["Steps"] = true;
+
+--Prints
+L[" |cff00ff00bound to |r"] = "|cff00ff00assigné à |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "% du (des) cadre(s) à un point d'ancrage contradictoire(s), merci de changer le point d'ancrage des améliorations ou des affaiblissements de sorte qu'ils ne soient pas attachés les uns aux autres. Forcer les affaiblissements à être attachés au cadre d'unité principale jusqu'à ce qu'ils soient fixés."
+L["All keybindings cleared for |cff00ff00%s|r."] = "Tous les raccourcis ont été effacés pour |cff00ff00%s|r."
+L["Already Running.. Bailing Out!"] = "Déjà en cours d'exécution, arrêt du processus..."
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Textes d'informations du champ de bataille temporairement masqués, pour les afficher tapez /bgstats ou cliquez droit sur le 'C' près de la mini-carte."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "Les textes d'informations du champ de bataille seront à nouveau affichés si vous êtes dans un champ de bataille."
+L["Binds Discarded"] = "Raccourcis annulés"
+L["Binds Saved"] = "Raccourcis sauvegardés"
+L["Confused.. Try Again!"] = "Confus...Essayez à nouveau!"
+L["No gray items to delete."] = "Aucun objet gris à détruire."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "Le sort '%s' a bien été ajouté à la liste noire des filtres des cadres d'unités."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
+L["Vendored gray items for:"] = "Objets gris vendus pour:"
+L["You don't have enough money to repair."] = "Vous n'avez pas assez d'argent pour réparer votre équipement."
+L["You must be at a vendor."] = "Vous devez être chez un marchand."
+L["Your items have been repaired for: "] = "Votre équipement a été réparé pour: "
+L["Your items have been repaired using guild bank funds for: "] = "Votre équipement a été réparé avec l'argent de la banque de guilde pour: "
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Erreur Lua reçue. Vous pouvez voir ce message d'erreur quand vous sortirez de combat."
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "Un réglage que vous avez modifié ne s'appliquera que pour ce personnage. La modification de ce réglage ne sera pas affecté par un changement de profil. Changer ce réglage requiert de relancer l'interface."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = "En acceptant, votre liste de priorités des filtres sera réinitialisée pour les auras des cadres d'unités. Êtes-vous sûr ?"
+L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
+L["Are you sure you want to delete all your gray items?"] = "Êtes-vous sûr de vouloir détruire tous vos Objets Gris ?"
+L["Are you sure you want to disband the group?"] = "Êtes-vous sûr de vouloir dissoudre le groupe ? "
+L["Are you sure you want to reset all the settings on this profile?"] = "Êtes-vous sûr de vouloir réinitialiser tous les réglages sur ce profile?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "Êtes-vous sûr de vouloir réinitialiser tous les cadres à leur position par défaut ?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "En raison de la confusion générale provoquée par le nouveau système d'aura, j'ai mis en place une nouvelle étape dans le processus d'installation. Cette option est facultative. Si vous aimez la façon dont vos auras sont configurés allez à la dernière étape et cliquez sur Terminé pour ne pas être averti à nouveau. Si, pour une raison quelconque, vous êtes averti de nouveau, relancez complètement le jeu."
+L["Can't buy anymore slots!"] = "Impossible d'acheter plus emplacements !"
+L["Disable Warning"] = "Désactiver l'alerte"
+L["Discard"] = "Annuler"
+L["Do you enjoy the new ElvUI?"] = "Aimez-vous le nouveau ElvUI?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Jurez-vous de ne pas poster sur le support technique du forum sur quelque chose qui ne fonctionne pas sans avoir désactivé en premier la combinaison Addon/Module?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI est périmé d'au moins 5 versions. Vous pouvez télécharger la nouvelle version sur https://github.com/ElvUI-Vanilla/ElvUI/"
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI est périmé. Vous pouvez télécharger la nouvelle version sur https://github.com/ElvUI-Vanilla/ElvUI/"
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI a besoin d'effectuer des optimisations de la base de données, merci de patienter."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Passez votre souris sur n'importe quel bouton d'action ou bouton du grimoire pour lui attribuer un raccourcis. Appuyez sur la touche Échap ou le clique droit pour effacer le raccourci en cours."
+L["I Swear"] = "Je le jure"
+L["No, Revert Changes!"] = "Non, annuler les changements!"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh seigneur, vous avez ElvUI et Tukui d'activé en même temps. Sélectionnez un addon à désactiver."
+L["One or more of the changes you have made require a ReloadUI."] = "Une ou plusieurs modifications que vous avez effectuées nécessitent un rechargement de l'interface."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Un ou plusieurs changement(s) que vous avez effectué a une incidence sur tous les personnages qui utilisent cet Addon. Vous devriez recharger l'interface utilisateur pour voir le(s) changement(s) apporté(s)."
+L["Save"] = "Sauvegarder"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "Le profil que vous essayez d'importer existe déjà. Choisissez un nouveau nom ou acceptez d'écraser le profil existant."
+L["Type /hellokitty to revert to old settings."] = "Tapez /hellokitty pour recharger les anciennes configurations"
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Si vous utilisez l'agencement Soigneur, il est hautement recommandé de télécharger l'Addon Clique si vous souhaitez avoir la fonction cliquer-pour-soigner."
+L["Yes, Keep Changes!"] = "Oui, garder les changements!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = true;
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Vous venez de changer l'échelle de votre interface, alors que votre option d'échelle automatique est encore activée dans ElvUI. Cliquer sur accepter si vous voulez désactiver l'option d'échelle automatique."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Vous avez importé des paramètes qui requierent un rechargement de l'interface. Recharger maintenant ?"
+L["You must purchase a bank slot first!"] = "Vous devez d'abord acheter un emplacement de banque!"
+
+--Tooltip
+L["Count"] = "Nombre:"
+L["Item Level:"] = "Niveau d'équipement"
+L["Talent Specialization:"] = "Spécialisation des talents"
+L["Targeted By:"] = "Ciblé par:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "Une fonction marqueur de raid est disponible en appuyant sur Échap -> Raccourcis, défilez en bas d'ElvUI et paramétrez le raccourcis pour le marqueur de raid."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI dispose d'une fonction double spécialisation qui vous permet de charger à la volée des profils différents en fonction de votre spécialisation actuelle."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Pour tout support technique, merci de nous visiter à https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Si vous supprimez accidentellement un cadre de discussion, vous pouvez toujours aller dans le menu de configuration d'ElvUI. Cliquez ensuite sur Installation puis passez à l'étape concernant les fenêtres de discussion pour remettre à zéro les paramètres."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Si vous rencontrez des problèmes avec ElvUI, essayez de désactiver tous vos addons sauf ElvUI. Rappelez-vous que'ElvUi est une interface utilisateur complète et que vous ne pouvez pas exécuter deux addons qui font la même chose."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "Le cadre de focus peut être défini en tapant /focus quand vous êtes en train de cibler une unité que vous voulez focus. Il est recommandé de faire une macro pour cela."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Pour déplacer par défaut les capacités des barres d'actions, maintenez MAJ + déplacer. Vous pouvez modifier la touche de modification dans le menu des barres d'actions."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Pour configurer quels canaux de discussions doivent apparaitre dans les fenêtres de Chat, faites un clic droit sur l'onglet de Chat et allez dans les paramètres."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Vous pouvez accéder à une copie du Chat et des fonctions du Chat en survolant avec votre souris le coin haut droit de la fenêtre de discussion. Cliquez ensuite sur le bouton."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Vous pouvez voir le niveau d'objet moyen de n'importe qui en maintenant la touche MAJ enfoncée puis en passant votre souris sur un joueur. Le score apparaitra dans la bulle d'information."
+L["You can set your keybinds quickly by typing /kb."] = "Vous pouvez assignez rapidement vos raccourcis en tapant /kb."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Vous pouvez afficher la microbarre en utilisant le bouton central de votre souris sur la minicarte. Vous pouvez aussi l'afficher via les réglages des Barres d'actions"
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "Vous pouvez utiliser la commande /resetui pour réinitialiser l'ensemble de vos cadres. Vous pouvez aussi utiliser la commande /resetui pour réinitialiser un cadre spécifique.\nExemple: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = "Mort"
+L["Ghost"] = "Fantôme"
+L["Offline"] = "Déconnecté"
diff --git a/ElvUI/Locales/German_UI.lua b/ElvUI/Locales/German_UI.lua
new file mode 100644
index 0000000..e4f1af4
--- /dev/null
+++ b/ElvUI/Locales/German_UI.lua
@@ -0,0 +1,347 @@
+-- German localization file for deDE.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "deDE")
+if not L then return end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "Das Addon %s ist nicht mit dem ElvUI %s Modul kompatibel. Bitte deaktiviere entweder das Addon oder deaktiviere das ElvUI Modul."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "Willkommen zu %sElvUI|r Version %s%s|r, Tippe /ec um das Konfigurationsmenü aufzurufen. Für technische Hilfe, besuche das Supportforum unter https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "Belegung"
+L["Key"] = "Taste"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "Keine Belegungen gesetzt."
+L["Remove Bar %d Action Page"] = "Entferne Leiste %d Aktion Seite"
+L["Trigger"] = "Auslöser"
+
+--Bags
+L["Bank"] = true;
+L["Hold Control + Right Click:"] = "Halte Steuerung + Rechtsklick:"
+L["Hold Shift + Drag:"] = "Halte Shift + Ziehen:"
+L["Purchase Bags"] = "Taschen kaufen"
+L["Reset Position"] = "Position zurücksetzen"
+L["Sort Bags"] = "Taschen sortieren"
+L["Temporary Move"] = "Temporäres Bewegen"
+L["Toggle Bags"] = "Taschen umschalten"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "Graue Gegenstände verkaufen"
+
+--Chat
+L["AFK"] = "AFK" --Also used in datatexts and tooltip
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "DND" --Also used in datatexts and tooltip
+L["G"] = "G"
+L["Invalid Target"] = "Ungültiges Ziel"
+L["O"] = "O"
+L["P"] = "P"
+L["PL"] = "PL"
+L["R"] = "R"
+L["RL"] = "RL"
+L["RW"] = "RW"
+L["says"] = "sagen"
+L["whispers"] = "flüstern"
+L["yells"] = "schreien"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(Shift gedrückt) Speichernutzung"
+L["Avoidance Breakdown"] = "Vermeidung Aufgliederung"
+L["Character: "] = "Charakter: "
+L["Chest"] = "Brust"
+L["Combat"] = "Kampf"
+L["Combat Time"] = "Kampf Zeit"
+L["Coords"] = true;
+L["copperabbrev"] = "|cffeda55fc|r" --Also used in Bags
+L["Deficit:"] = "Defizit:"
+L["DPS"] = "DPS"
+L["Earned:"] = "Verdient:"
+L["Friends List"] = "Freundesliste"
+L["Friends"] = "Freunde" --Also in Skins
+L["Gold"] = true;
+L["goldabbrev"] = "|cffffd700g|r" --Also used in gold datatext
+L["Hit"] = "Hit"
+L["Hold Shift + Right Click:"] = "Halte Umschalt + Rechts Klick:"
+L["Home Latency:"] = "Standort Latenz"
+L["HP"] = "HP"
+L["HPS"] = "HPS"
+L["lvl"] = "lvl"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "Milderung durch Stufe:"
+L["No Guild"] = "Keine Gilde"
+L["Profit:"] = "Gewinn:"
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "Daten zurücksetzen: Halte Shift + Rechtsklick"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "Gespeicherte Schlachtzüge"
+L["Server: "] = "Server: "
+L["Session:"] = "Sitzung:"
+L["silverabbrev"] = "|cffc7c7cfs|r" --Also used in Bags
+L["SP"] = "SP"
+L["Spell/Heal Power"] = true;
+L["Spent:"] = "Ausgegeben:"
+L["Stats For:"] = "Stats Für:"
+L["System"] = true;
+L["Total CPU:"] = "Gesamt CPU:"
+L["Total Memory:"] = "Gesamte Speichernutzung:"
+L["Total: "] = "Gesamt: "
+L["Unhittable:"] = "Unhittable:"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s versucht die geschützte Funktion aufrufen '%s'."
+L["No locals to dump"] = "Keine Lokalisierung zum verwerfen"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s möchte seine Filter Einstellungen mit dir teilen. Möchtest du die Anfrage annehmen?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s versucht das Profil %s mit dir zu teilen. Möchtest du die Anfrage annehmen?"
+L["Data From: %s"] = "Datei von: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "Filter komplett heruntergeladen von %s, möchtest du die Änderungen nun vornehmen?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Herr! Es ist ein Wunder! Der Download verschwand wie ein Furz im Wind! Versuche es nochmal!"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Profil komplett heruntergeladen von %s, allerdings ist das Profil %s bereits vorhanden. Ändere den Namen oder das bereits existierende Profil wird überschrieben."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "Profil komplett heruntergeladen von %s, möchtest du das Profil %s nun laden?"
+L["Profile request sent. Waiting for response from player."] = "Profil Anfrage gesendet. Warte auf die Antwort des Spielers."
+L["Request was denied by user."] = "Die Anfrage wurde vom Benutzer abgelehnt."
+L["Your profile was successfully recieved by the player."] = "Dein Profil wurde erfolgreich von dem Spieler empfangen."
+
+--Install
+L["Aura Bars & Icons"] = "Aurenleiste & Symbole"
+L["Auras Set"] = "Auren gesetzt"
+L["Auras"] = "Auren"
+L["Caster DPS"] = "Fernkampf DD"
+L["Chat Set"] = "Chat gesetzt"
+L["Chat"] = "Chat"
+L["Choose a theme layout you wish to use for your initial setup."] = "Wähle ein Layout, welches du bei deinem ersten Setup verwenden möchtest."
+L["Classic"] = "Klassisch"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Klicke auf die Taste unten um die Größe deiner Chatfenster, Einheitenfenster und die Umpositionierung deiner Aktionsleisten durchzuführen."
+L["Config Mode:"] = "Konfigurationsmodus:"
+L["CVars Set"] = "CVars gesetzt"
+L["CVars"] = "CVars"
+L["Dark"] = "Dunkel"
+L["Disable"] = "Deaktivieren"
+L["ElvUI Installation"] = "ElvUI Installation"
+L["Finished"] = "Beendet"
+L["Grid Size:"] = "Rastergröße:"
+L["Healer"] = "Heiler"
+L["High Resolution"] = "Hohe Auflösung"
+L["high"] = "hoch"
+L["Icons Only"] = "Nur Symbole" --Also used in Bags
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Wenn du ein Symbol oder eine Aurenleiste nicht angezeigt haben möchtest, dann halte Shift gedrückt und klicke mit Rechtsklick auf das Symbol um es auszublenden."
+L["Importance: |cff07D400High|r"] = "Bedeutung: |cff07D400Hoch|r"
+L["Importance: |cffD3CF00Medium|r"] = "Bedeutung: |cffD3CF00Mittel|r"
+L["Importance: |cffFF0000Low|r"] = "Bedeutung: |cffD3CF00Niedrig|r"
+L["Installation Complete"] = "Installation komplett"
+L["Layout Set"] = "Layout gesetzt"
+L["Layout"] = "Layout"
+L["Lock"] = "Sperren"
+L["Low Resolution"] = "Niedrige Auflösung"
+L["low"] = "niedrig"
+L["Nudge"] = "Stoß"
+L["Physical DPS"] = "Physische DPS"
+L["Please click the button below so you can setup variables and ReloadUI."] = "Bitte klicke die Taste unten um den Installationsprozess abzuschließen und das Benutzerinterface neu zu laden."
+L["Please click the button below to setup your CVars."] = "Klicke 'Installiere CVars' um die CVars einzurichten."
+L["Please press the continue button to go onto the next step."] = "Bitte drücke die Weiter-Taste um zum nächsten Schritt zu gelangen."
+L["Resolution Style Set"] = "Auflösungsart gesetzt"
+L["Resolution"] = "Auflösung"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Wähle für die ElvUI Einheitenfenster ob das Auren-System Aurenleisten und Symbole, oder nur Symbole anzeigt."
+L["Setup Chat"] = "Chateinstellungen"
+L["Setup CVars"] = "Installiere CVars"
+L["Skip Process"] = "Schritt überspringen"
+L["Sticky Frames"] = "Anheftende Fenster"
+L["Tank"] = "Tank"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "Die Chatfensterfunktionen sind die gleichen, wie die Chatfenster von Blizzard. Du kannst auf die Tabs rechtsklicken und sie z.B. neu zu positionieren, umzubenennen, etc. Bitte klicke den Button unten um das Chatfenster einzurichten."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "Das ElvUI-Konfigurationsmenü kannst du entweder mit /ec oder durch das Anklicken der 'C' Taste an der Minimap aufrufen. Drücke 'Schritt überspringen' um zum nächsten Schritt zu gelangen."
+L["Theme Set"] = "Thema gesetzt"
+L["Theme Setup"] = "Thema Setup"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Dieser Installationsprozess wird dir helfen, die Funktionen von ElvUI für deine Benutzeroberfläche besser kennenzulernen."
+L["This is completely optional."] = "Das ist komplett Optional."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "Dieser Abschnitt der Installation stellt die Chat Fenster Namen, Positionen und Farben ein."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Dieser Installationsprozess richtet alle wichtigen Cvars deines World of Warcrafts ein, um eine problemlose Nutzung zu ermöglichen."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Diese Auflösung benötigt keine Änderungen um mit der Benutzeroberfläche zu funktionieren."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Diese Auflösung benötigt Änderungen um mit der Benutzeroberfläche zu funktionieren."
+L["This will change the layout of your unitframes and actionbars."] = "Dies wird das Layout der Einheitenfenster und Aktionsleisten ändern."
+L["Trade"] = "Handel"
+L["Welcome to ElvUI version %s!"] = "Willkommen bei ElvUI Version %s!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Du hast den Installationsprozess abgeschlossen. Solltest du technische Hilfe benötigen, besuche uns auf https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Du kannst jederzeit in der Ingame-Konfiguration Schriften und Farben von jedem Element des Interfaces ändern."
+L["You can now choose what layout you wish to use based on your combat role."] = "Du kannst nun auf Basis deiner Rolle im Kampf ein Layout wählen."
+L["You may need to further alter these settings depending how low you resolution is."] = "Unter Umständen musst du, je nachdem wie niedrig deine Auflösung ist, diese Einstellungen ändern."
+L["Your current resolution is %s, this is considered a %s resolution."] = "Deine Aktuelle Auflösung ist %s, diese wird als eine %s Auflösung angesehen."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
+L["Bars"] = "Leisten" --Also used in UnitFrames
+L["Calendar"] = "Kalender"
+L["Can't Roll"] = "Es kann nicht gewürfelt werden."
+L["Disband Group"] = "Gruppe auflösen"
+L["Empty Slot"] = "Leerer Platz"
+L["Enable"] = "Eingeschaltet" --Doesn't fit a section since it's used a lot of places
+L["Experience"] = "Erfahrung"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "Faule Beute"
+L["Left Click:"] = "Linksklick:" --layout\layout.lua
+L["Mouse"] = "Maus"
+L["Raid Menu"] = "Schlachtzugsmenü"
+L["Remaining:"] = "Verbleibend:"
+L["Rested:"] = "Ausgeruht:"
+L["Right Click:"] = "Rechtsklick:" --layout\layout.lua
+L["Show BG Texts"] = "Zeige Schlachtfeldtexte" --layout\layout.lua
+L["Toggle Chat Frame"] = "Chatfenster an-/ausschalten" --layout\layout.lua
+L["Toggle Configuration"] = "Konfiguration umschalten" --layout\layout.lua
+L["XP:"] = "EP:"
+L["You don't have permission to mark targets."] = "Du hast keine Rechte um ein Ziel zu markieren."
+
+--Movers
+L["Arena Frames"] = "Arena Fenster" --Also used in UnitFrames
+L["Bag Mover (Grow Down)"] = "Taschen Anker (Nach unten wachsen)"
+L["Bag Mover (Grow Up)"] = "Taschen Anker (Nach oben wachsen)"
+L["Bag Mover"] = "Taschen Anker"
+L["Bags"] = "Taschen" --Also in DataTexts
+L["Bank Mover (Grow Down)"] = "Bank Anker (Nach unten wachsen)"
+L["Bank Mover (Grow Up)"] = "Bank Anker (Nach oben wachsen)"
+L["Bar "] = "Leiste " --Also in ActionBars
+L["BNet Frame"] = "BNet-Fenster"
+L["Boss Frames"] = "Boss Fenster" --Also used in UnitFrames
+L["Classbar"] = "Klassenleiste"
+L["Experience Bar"] = "Erfahrungsleiste"
+L["Focus Castbar"] = "Fokus Zauberbalken"
+L["Focus Frame"] = "Fokusfenster" --Also used in UnitFrames
+L["FocusTarget Frame"] = "Fokus-Ziel Fenster" --Also used in UnitFrames
+L["GM Ticket Frame"] = "GM-Ticket-Fenster"
+L["Left Chat"] = "Linker Chat"
+L["Loot / Alert Frames"] = "Beute-/Alarmfenster"
+L["Loot Frame"] = "Beute-Fenster"
+L["MA Frames"] = "MA-Fenster"
+L["Micro Bar"] = "Mikroleiste" --Also in ActionBars
+L["Minimap"] = "Minimap"
+L["MirrorTimer"] = "Spiegel Zeitgeber"
+L["MT Frames"] = "MT-Fenster"
+L["Party Frames"] = "Gruppenfenster" --Also used in UnitFrames
+L["Pet Bar"] = "Begleisterleiste" --Also in ActionBars
+L["Pet Castbar"] = "Begleiter Zauberleiste"
+L["Pet Frame"] = "Begleiterfenster" --Also used in UnitFrames
+L["PetTarget Frame"] = "Begleiter-Ziel Fenster" --Also used in UnitFrames
+L["Player Buffs"] = "Spieler Buffs"
+L["Player Castbar"] = "Spieler Zauberbalken"
+L["Player Debuffs"] = "Spieler Debuffs"
+L["Player Frame"] = "Spielerfenster" --Also used in UnitFrames
+L["Player Powerbar"] = "Spieler Kraftleiste"
+L["PvP"] = true;
+L["Raid Frames"] = "Schlachtzugsfenster" --Also used in UnitFrames
+L["Raid Pet Frames"] = "Schlachtzugspets-Fenster"
+L["Raid-40 Frames"] = "40er Schlachtzugsfenster" --Also used in UnitFrames
+L["Reputation Bar"] = "Rufleiste"
+L["Right Chat"] = "Rechter Chat"
+L["Stance Bar"] = "Haltungsleiste" --Also in ActionBars
+L["Target Castbar"] = "Ziel Zauberbalken"
+L["Target Frame"] = "Zielfenster" --Also used in UnitFrames
+L["Target Powerbar"] = "Ziel Kraftleiste"
+L["TargetTarget Frame"] = "Ziel des Ziels Fenster" --Also used in UnitFrames
+L["TargetTargetTarget Frame"] = "Ziel des Ziels des Ziels Fenster"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "Tooltip"
+L["Vehicle Seat Frame"] = "Fahrzeugfenster"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = true;
+L["In Progress"] = "In Bearbeitung"
+L["List of installations in queue:"] = "Liste von Installationen in Warteschlange:"
+L["Pending"] = "Ausstehend"
+L["Steps"] = "Schritte"
+
+--Prints
+L[" |cff00ff00bound to |r"] = " |cff00ff00gebunden zu |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "Es liegt ein Konflikt bei den Ankerpunkten des Rahmens %s vor. Bitte ändere entweder den Ankerpunkt des Stärkungs- oder Schwächungszaubers, damit diese nicht länger mit einander verbunden sind. Verbinde die Schwächungszauber mit dem Hauptrahmen, damit dieses Problem behoben wird."
+L["All keybindings cleared for |cff00ff00%s|r."] = "Alle Tastaturbelegungen gelöscht für |cff00ff00%s|r."
+L["Already Running.. Bailing Out!"] = "Bereits ausgeführt.. Warte ab!"
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Schlachtfeld-Infotexte sind kurzzeitig versteckt, um sie wieder anzuzeigen tippe /bgstats oder rechtsklicke auf das 'C' Symbol nahe der Minimap."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "Schlachtfeld-Infotexte werden wieder angezeigt, solange du dich in einem Schlachtfeld befindest."
+L["Binds Discarded"] = "Tastaturbelegungen verworfen"
+L["Binds Saved"] = "Tastaturbelegungen gespeichert"
+L["Confused.. Try Again!"] = "Verwirrt.. Versuche es erneut!"
+L["No gray items to delete."] = "Es sind keine grauen Gegenstände zum Löschen vorhanden."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "Der Zauber '%s' wurde zur schwarzen Liste der Einheitenfenster hinzugefügt."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "Diese Einstellungen haben einen Konflikt mit einem Ankerpunkt, wo '%s' an sich selbst angehaftet sein soll. Bitte kontrolliere deine Ankerpunkte. Einstellung '%s' angehaftet an '%s'."
+L["Vendored gray items for:"] = "Graue Gegenstände verkauft für:"
+L["You don't have enough money to repair."] = "Du hast nicht genügend Gold für die Reparatur."
+L["You must be at a vendor."] = "Du musst bei einem Händler sein."
+L["Your items have been repaired for: "] = "Deine Gegenstände wurden repariert für: "
+L["Your items have been repaired using guild bank funds for: "] = "Deine Gegenstände wurden repariert. Die Gildenbank kostete das: "
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Lua Fehler erhalten. Du kannst die Fehlermeldung ansehen, wenn du den Kampf verlässt."
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "Eine Einstellung, die du geändert hast, betrifft nur einen Charakter. Diese Einstellung, die du verändert hast, wird die Benutzerprofile unbeeinflusst lassen. Eine Änderung dieser Einstellung erfordert, dass du dein Interface neu laden musst."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = "Wenn du aktzeptierst wird die Filter Priorität für alle Einheitenfenster auf Standard zurückgesetzt. Bist du sicher?"
+L["Are you sure you want to apply this font to all ElvUI elements?"] = "Bist du sicher, dass du diese Schrifart auf alle ElvUI Elemente anwenden möchtest?"
+L["Are you sure you want to delete all your gray items?"] = "Bist du sicher, dass du alle grauen Gegenstände löschen willst?"
+L["Are you sure you want to disband the group?"] = "Bist du dir sicher, dass du die Gruppe auflösen willst?"
+L["Are you sure you want to reset all the settings on this profile?"] = "Bist du dir sicher dass du alle Einstellungen dieses Profils zurücksetzen willst?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "Bist du dir sicher, dass du jeden Beweger an die Standard-Position zurücksetzen möchtest?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Aufgrund der großen Verwirrung, die durch das neue Auren-System verursacht wurde, habe ich einen neuen Schritt zum Installationsprozess hinzugefügt. Dieser ist optional. Wenn du deine Auren so eingestellt lassen willst, wie sie sind, gehe einfach zum letzten Schritt und klicke auf fertig um nicht erneut aufgefordert zu werden. Wirst du, aus welchen Grund auch immer, öfter aufgefordert, starte bitte dein Spiel neu"
+L["Can't buy anymore slots!"] = "Kann keine Slots mehr kaufen"
+L["Disable Warning"] = "Deaktiviere Warnung"
+L["Discard"] = "Verwerfen"
+L["Do you enjoy the new ElvUI?"] = "Gefällt dir das neue ElvUI?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Schwörst du, dass du keinen Beitrag im Supportforum posten wirst, ohne vorher alle anderen Addons/Module zu deaktivieren?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI ist seit fünf oder mehr Revisionen nicht aktuell. Du kannst die neuste Version bei https://github.com/ElvUI-Vanilla/ElvUI/ herunterladen."
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI ist nicht aktuell. Du kannst die neuste Version bei https://github.com/ElvUI-Vanilla/ElvUI/ herunterladen."
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI muss eine Datenbank Optimierung durchführen. Bitte warte eine Moment."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Bewege deine Maus über einen Aktionsbutton oder dein Zauberbuch um ihn mit einem Hotkey zu belegen. Drücke Escape oder rechte Maustaste um die aktuelle Tastenbelegung des Buttons zu löschen."
+L["I Swear"] = "Ich schwöre"
+L["No, Revert Changes!"] = "Nein, Änderungen verwerfen!"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh Gott, du hast ElvUI und Tukui zur gleichen Zeit aktiviert. Wähle ein Addon um es zu deaktivieren."
+L["One or more of the changes you have made require a ReloadUI."] = "Eine oder mehrere Einstellungen, die du vorgenommen hast, benötigen ein Neuladen des Benutzerinterfaces um in Effekt zu treten."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Eine oder mehrere Änderungen, die du getroffen hast, betrifft alle Charaktere die dieses Addon benutzen. Du musst das Benutzerinterface neu laden um die Änderungen, die du durchgeführt hast, zu sehen."
+L["Save"] = "Speichern"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "Das Profil, dass du versuchst zu importieren existiert bereits. Wähle einen neuen Namen oder aktzeptiere dass das vorhandene Profile überschrieben wird."
+L["Type /hellokitty to revert to old settings."] = "Tippe /hellokitty um die alten Einstellungen zu verwenden."
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Wenn du das Heiler Layout benutzt ist es sehr empfohlen das Addon Clique zu downloaden wenn du die Klick-zum-Heilen Funktion haben willst."
+L["Yes, Keep Changes!"] = "Ja, Änderungen behalten!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Du hast die Dünnen Rahmen Einstellungen geändert. Du musst die Installation komplett abschließen um grafische Fehler zu vermeiden."
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Du hast die Skalierung des benutzerinterfaces geändert, während du die automatische Skalierung in ElvUI aktiv hast. Drücke Annehmen um die automatische Skalierung zu deaktivieren."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Du hast Einstellungen importiert die wahrscheinlich ein Neuladen des UI erfordern. Jetzt neu laden?"
+L["You must purchase a bank slot first!"] = "Du musst erst ein Bankfach kaufen!"
+
+--Tooltip
+L["Count"] = "Zähler"
+L["Item Level:"] = "Itemlevel"
+L["Talent Specialization:"] = "Talentspezialisierung"
+L["Targeted By:"] = "Ziel von:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "Ein Feature für Schlachtzugsmarkierung ist verfügbar, wenn du Escape drückst und Tastaturbelegung wählst, scrolle anschließend bis unter die Kategorie ElvUI und wähle eine Tastenbelegung für die Schlachtzugsmarkierung."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI hat ein Feature für Dualspezialisierungen, welches dich abhängig von deiner momentanen Spezialisierung verschiedene Profile laden lässt. Dieses Feature kannst du im Abschnitt Profil aktivieren."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Für technische Hilfe besuche uns unter https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Wenn du ausversehen das Chatfenster entfernen solltest, kannst du ganz einfach in die Ingame-Konfiguration gehen und den Installationsprozess erneut aufrufen. Drücke Installieren und gehe zu den Chateinstellungen und setze diese zurück."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Wenn du Probleme mit ElvUI hast, deaktiviere alle Addons außer ElvUI. Denke auch daran, dass ElvUI die komplette Benutzeroberfläche ersetzt, d.h. du kannst kein Addon verwenden, welches die gleichen Funktionen wie ElvUI nutzt."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "Du kannst, während du ein Ziel hast, das Fokusfenster durch die Eingabe von /fokus setzen. Es wird empfohlen ein Makro dafür zu nutzen."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Um Fähigkeiten auf der Aktionsleiste zu verschieben nutze Shift und bewege zeitgleich die Maus. Du kannst die Modifier-Taste im Aktionsleistenmenü umstellen."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Um einzustellen welcher Kanal im welchem Chatfenster angezeigt werden soll, klicke rechts auf das Chattab und gehe auf Einstellungen."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Du kannst die Funktionen Chat Kopieren und Chatmenü aufrufen, wenn du die Maus in die obere rechte Ecke des Chatfensters bewegst und links-/rechtsklickst."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Du kannst die durchschnittliche Gegenstandsstufe von jemanden sehen, wenn du bei gedrückter Shift-Taste mit der Maus über ihn fährst. Die Gegenstandsstufe wird dann im Tooltip angezeigt."
+L["You can set your keybinds quickly by typing /kb."] = "Du kannst deine Tastaturbelegung schnell ändern, wenn du /kb eintippst."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Du kannst die Mikroleiste durch mittleren Mausklick auf der Minimap aufrufen oder auch die tatsächliche Mikroleiste in den Aktionsleisten Optionen aktivieren."
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "Du kannst durch benutzen von /resetui alle Ankerpunkte zurücksetzen. Du kannst das Kommando auch benutzen um spezielle Anker zurückzusetzen, /resetui .\nBeispiel: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = "Tot"
+L["Ghost"] = "Geist"
+L["Offline"] = "Offline"
diff --git a/ElvUI/Locales/Korean_UI.lua b/ElvUI/Locales/Korean_UI.lua
new file mode 100644
index 0000000..72af59b
--- /dev/null
+++ b/ElvUI/Locales/Korean_UI.lua
@@ -0,0 +1,347 @@
+-- Korean localization file for koKR.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "koKR")
+if not L then return end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "%s 애드온의 기능이 ElvUI의 %s 모듈과 상충됩니다. 그 애드온을 쓰지 않거나 ElvUI의 기능을 사용해제하세요."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "%sElvUI|r 버전 %s%s|r 을 사용해 주셔서 감사합니다. /ec 를 입력하면 설정창을 열 수 있습니다. 궁금한 점이나 기술지원은 https://github.com/ElvUI-Vanilla/ElvUI 에서 해결하세요"
+
+--ActionBars
+L["Binding"] = " "
+L["Key"] = "단축키"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "W▼"
+L["KEY_MOUSEWHEELUP"] = "W▲"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "P▼"
+L["KEY_PAGEUP"] = "P▲"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "Spc"
+L["No bindings set."] = "설정한 단축키가 없습니다."
+L["Remove Bar %d Action Page"] = "Blizzard %d번 행동단축바 숨기기"
+L["Trigger"] = "묶음을 펼치고 각 주문에 지정하세요."
+
+--Bags
+L["Bank"] = "은행"
+L["Hold Control + Right Click:"] = "Shift 우클릭:"
+L["Hold Shift + Drag:"] = "Shift 드래그:"
+L["Purchase Bags"] = "가방 슬롯 구입"
+L["Reset Position"] = "위치 초기화"
+L["Sort Bags"] = "가방 정렬"
+L["Temporary Move"] = "임시 이동"
+L["Toggle Bags"] = "가방슬롯 보기"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "잡동사니 자동판매"
+
+--Chat
+L["AFK"] = "자리비움"
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "다른 용무중"
+L["G"] = "길드"
+L["Invalid Target"] = "잘못된 대상"
+L["O"] = "관리자"
+L["P"] = "파티"
+L["PL"] = "파장"
+L["R"] = "공대"
+L["RL"] = "공장"
+L["RW"] = "경보"
+L["says"] = "일반"
+L["whispers"] = "귓"
+L["yells"] = "외침"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "Shift: 메모리 사용량"
+L["Avoidance Breakdown"] = "방어율 목록"
+L["Character: "] = "캐릭터:"
+L["Chest"] = "가슴"
+L["Combat"] = "전투"
+L["Combat Time"] = true;
+L["Coords"] = true;
+L["copperabbrev"] = "|TInterface\\MoneyFrame\\UI-MoneyIcons:0:0:1:0:64:16:33:48:1:16|t" --"|cffeda55f●|r"
+L["Deficit:"] = "손해:"
+L["DPS"] = "DPS"
+L["Earned:"] = "수입:"
+L["Friends List"] = "친구 목록"
+L["Friends"] = "친구"
+L["Gold"] = true;
+L["goldabbrev"] = "|TInterface\\MoneyFrame\\UI-MoneyIcons:0:0:1:0:64:16:1:16:1:16|t" --"|cffffd700●|r"
+L["Hit"] = "적중도"
+L["Hold Shift + Right Click:"] = true;
+L["Home Latency:"] = "지연 시간:"
+L["HP"] = "주문력"
+L["HPS"] = "HPS"
+L["lvl"] = "레벨"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "레벨별 데미지 경감률"
+L["No Guild"] = "길드 없음"
+L["Profit:"] = "이익:"
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "기록 리셋: Shift + 우클릭"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "귀속된 던전"
+L["Server: "] = "서버:"
+L["Session:"] = "현재 접속:"
+L["silverabbrev"] = "|TInterface\\MoneyFrame\\UI-MoneyIcons:0:0:1:0:64:16:17:32:1:16|t" --"|cffc7c7cf●|r"
+L["SP"] = "주문력"
+L["Spell/Heal Power"] = true;
+L["Spent:"] = "지출:"
+L["Stats For:"] = "점수:"
+L["System"] = true;
+L["Total CPU:"] = "전체 CPU 사용량:"
+L["Total Memory:"] = "전체 메모리:"
+L["Total: "] = "합계:"
+L["Unhittable:"] = "100% 방어행동까지"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s 기능이 사용할 수 없는 %s 함수를 사용하려 합니다."
+L["No locals to dump"] = true; --Currently not used
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s 유저가 필터설정을 전송하려 합니다. 받으시겠습니까?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s 유저가 ElvUI 설정을 전송하려 합니다. 받으시겠습니까?"
+L["Data From: %s"] = "%s 유저에게서 데이터 받는중..."
+L["Filter download complete from %s, would you like to apply changes now?"] = "%s 유저에게서 필터 설정 다운로드가 완료되었습니다. 변경사항을 적용할까요?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "데이터를 받는 중 혼선이 생겼습니다. 다시 시도해주세요."
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "%s 유저에게서 ElvUI 설정 다운로드가 완료되었습니다. 하지만 건네받은 프로필 이름이 이미 존재합니다. 프로필이름을 바꾸지 않으면 기존의 것에 덮어씌웁니다."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "%s 유저에게서 ElvUI 설정 다운로드가 완료되었습니다. 건네받은 설정을 지금 불러올까요?"
+L["Profile request sent. Waiting for response from player."] = "상대에게서 전송여부를 확인받고 있습니다."
+L["Request was denied by user."] = "상대방이 전송을 거절했습니다."
+L["Your profile was successfully recieved by the player."] = "상대에게 데이터를 성공적으로 전송했습니다."
+
+--Install
+L["Aura Bars & Icons"] = "바 & 아이콘 표시"
+L["Auras Set"] = "오라설정 적용"
+L["Auras"] = "오라 설정"
+L["Caster DPS"] = "원거리 딜러"
+L["Chat Set"] = "대화창 설정"
+L["Chat"] = "대화창"
+L["Choose a theme layout you wish to use for your initial setup."] = "UI의 전체적인 분위기를 선택하세요."
+L["Classic"] = "클래식"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "원하는 해상도로 설정을 강제 적용하고자 한다면 아래에서 원하는 해상도를 선택하세요."
+L["Config Mode:"] = "표시할 프레임 계열:"
+L["CVars Set"] = "CVars 설정"
+L["CVars"] = "게임 인터페이스 설정(CVars)"
+L["Dark"] = "어두운 느낌"
+L["Disable"] = "비활성화"
+L["ElvUI Installation"] = "ElvUI 설치"
+L["Finished"] = "마침"
+L["Grid Size:"] = "격자 크기 :"
+L["Healer"] = "힐러"
+L["High Resolution"] = "고해상도 세팅"
+L["high"] = "고"
+L["Icons Only"] = "아이콘만 표시"
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "표시하고 싶지 않은 버프/디버프가 보이면 아이콘을 Shift 우클릭하세요. 차단 목록에 등록되어 보이지 않게 됩니다."
+L["Importance: |cff07D400High|r"] = "중요도: |cff07D400높음|r"
+L["Importance: |cffD3CF00Medium|r"] = "중요도: |cffD3CF00보통|r"
+L["Importance: |cffFF0000Low|r"] = "중요도 : |cffFF0000낮음|r"
+L["Installation Complete"] = "설치 완료"
+L["Layout Set"] = "레이아웃 설정"
+L["Layout"] = "레이아웃"
+L["Lock"] = "잠금"
+L["Low Resolution"] = "저해상도 세팅"
+L["low"] = "저"
+L["Nudge"] = "미세조정"
+L["Physical DPS"] = "근접 딜러"
+L["Please click the button below so you can setup variables and ReloadUI."] = "아래 버튼을 누르면 설치를 마무리하고 UI를 재시작합니다."
+L["Please click the button below to setup your CVars."] = "ElvUI의 게임 인터페이스 설정을 적용하려면 아래 버튼을 클릭하세요."
+L["Please press the continue button to go onto the next step."] = "|cff2eb7e4[계속]|r 버튼으로 설치를 진행하세요."
+L["Resolution Style Set"] = "해상도 스타일 설정"
+L["Resolution"] = "해상도"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "ElvUI 유닛프레임에서 표시할 오라(버프,디버프)의 형태를 선택하세요."
+L["Setup Chat"] = "대화창 설치"
+L["Setup CVars"] = "인터페이스 설정 적용"
+L["Skip Process"] = "건너뛰기"
+L["Sticky Frames"] = "자석"
+L["Tank"] = "탱커"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "보편적인 설정을 적용할 뿐이므로, 마음대로 채널표시나 색상을 변경할 수 있습니다.|n아래 버튼을 클릭하면 채팅창 설정을 적용합니다."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "게임 내 설정창은 채팅창에 /ec를 입력하시거나 미니맵 옆의 C버튼을 클릭하면 열립니다. 그냥 사용하고자 한다면 아래의 |cff2eb7e4[건너뛰기]|r 버튼을 누르세요."
+L["Theme Set"] = "테마 적용"
+L["Theme Setup"] = "테마 설정"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "이 설치과정을 통해 ElvUI를 좀 더 자신에게 맞게 설정하고|n몇가지 기능에 대해 알 수 있습니다."
+L["This is completely optional."] = "이것은 선택 사항입니다."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "채팅창 설정을 변경합니다. 간단한 채널설정, 색상설정 등이 포함되어 있습니다.|n자신만의 채널 설정, 색상 등을 유지하고 싶으면 설치하지 마세요."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "WoW의 기본 인터페이스 설정을 ElvUI에 적합하게 변경합니다. 애드온 사용에 있어 유용하니 적용할 것을 추천합니다."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "현재 해상도에 알맞게 UI가 배치될 것이니 설정을 변경할 필요는 없습니다."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "해상도에 알맞는 UI 배치를 적용하려면 몇가지 설정을 변경할 필요가 있습니다."
+L["This will change the layout of your unitframes and actionbars."] = "역할에 따라서 유닛프레임과 행동단축바의 레이아웃이 알맞게 바뀝니다."
+L["Trade"] = "거래"
+L["Welcome to ElvUI version %s!"] = "ElvUI 버전 %s에 오신 것을 환영합니다!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "설치 과정이 끝났습니다.|n궁금한 점 해결이나 기술지원이 필요하면 |cff2eb7e4https://github.com/ElvUI-Vanilla/ElvUI|r 를 방문하세요."
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "ElvUI에서 표시하는 폰트나 색상은 설정에서 언제든지 바꿀 수 있습니다."
+L["You can now choose what layout you wish to use based on your combat role."] = "게임 안에서 주로 플레이하는 전문화 역할을 선택하세요."
+L["You may need to further alter these settings depending how low you resolution is."] = "당신의 해상도가 얼마나 낮은지에 따라 설정을 더 조절해야할 수도 있습니다."
+L["Your current resolution is %s, this is considered a %s resolution."] = "현재 사용중인 해상도는 |cff2eb7e4%s|r 이며, |cff2eb7e4%s해상도|r 입니다."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% 정도 |cff%02x%02x%02x%s|r보다 많음]"
+L["Bars"] = "바"
+L["Calendar"] = "달력"
+L["Can't Roll"] = "주사위를 굴릴 수 없습니다."
+L["Disband Group"] = "그룹 해산"
+L["Empty Slot"] = true;
+L["Enable"] = "사용"
+L["Experience"] = "경험치"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "낚시 전리품"
+L["Left Click:"] = "왼 클릭 :"
+L["Mouse"] = "쥐"
+L["Raid Menu"] = "공대 도구"
+L["Remaining:"] = "다음 레벨까지: "
+L["Rested:"] = "휴식 경험치:"
+L["Right Click:"] = "우클릭:"
+L["Show BG Texts"] = "전장전용 정보문자 표시"
+L["Toggle Chat Frame"] = "패널 표시 전환"
+L["Toggle Configuration"] = "ElvUI 설정창 열기"
+L["XP:"] = "경험치:"
+L["You don't have permission to mark targets."] = "레이드 아이콘을 지정할 권한이 없습니다."
+
+--Movers
+L["Arena Frames"] = "투기장 프레임"
+L["Bag Mover (Grow Down)"] = true;
+L["Bag Mover (Grow Up)"] = true;
+L["Bag Mover"] = true;
+L["Bags"] = "가방"
+L["Bank Mover (Grow Down)"] = true;
+L["Bank Mover (Grow Up)"] = true;
+L["Bar "] = "바 "
+L["BNet Frame"] = "배틀넷 알림"
+L["Boss Frames"] = "보스 프레임"
+L["Classbar"] = "직업바"
+L["Experience Bar"] = "경험치 바"
+L["Focus Castbar"] = "주시대상 시전바"
+L["Focus Frame"] = "주시대상 프레임"
+L["FocusTarget Frame"] = "주시대상의 대상 프레임"
+L["GM Ticket Frame"] = "GM요청 번호표"
+L["Left Chat"] = "좌측 패널"
+L["Loot / Alert Frames"] = "획득/알림 창"
+L["Loot Frame"] = "전리품 프레임"
+L["MA Frames"] = "지원공격 전담 프레임"
+L["Micro Bar"] = "메뉴모음 바"
+L["Minimap"] = "미니맵"
+L["MirrorTimer"] = true;
+L["MT Frames"] = "방어전담 프레임"
+L["Party Frames"] = "파티 프레임"
+L["Pet Bar"] = "소환수 바"
+L["Pet Castbar"] = "소환수 시전바"
+L["Pet Frame"] = "소환수 프레임"
+L["PetTarget Frame"] = "소환수 대상 프레임"
+L["Player Buffs"] = "플레이어 버프"
+L["Player Castbar"] = "플레이어 시전바"
+L["Player Debuffs"] = "플레이어 디버프"
+L["Player Frame"] = "플레이어 프레임"
+L["Player Powerbar"] = true;
+L["PvP"] = true;
+L["Raid Frames"] = "레이드 프레임"
+L["Raid Pet Frames"] = "레이드 소환수 프레임"
+L["Raid-40 Frames"] = "레이드 프레임(40인)"
+L["Reputation Bar"] = "평판 바"
+L["Right Chat"] = "우측 패널"
+L["Stance Bar"] = "태세 바"
+L["Target Castbar"] = "대상 시전바"
+L["Target Frame"] = "대상 프레임"
+L["Target Powerbar"] = true;
+L["TargetTarget Frame"] = "대상의대상 프레임"
+L["TargetTargetTarget Frame"] = "대상의대상의대상 프레임"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "툴팁"
+L["Vehicle Seat Frame"] = "차량 좌석 프레임"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = true;
+L["In Progress"] = true;
+L["List of installations in queue:"] = true;
+L["Pending"] = true;
+L["Steps"] = true;
+
+--Prints
+L[" |cff00ff00bound to |r"] = " 키로 다음의 행동을 실행합니다: |cff2eb7e4"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "%s 의 위치 기준 프레임이 상충되고 있습니다. 서로가 서로의 위치를 참조하지 않게 버프나 디버프 중 하나의 위치를 바꿔주세요. 수정되기 전까지 강제로 유닛프레임이 기준으로 됩니다. "
+L["All keybindings cleared for |cff00ff00%s|r."] = "|cff00ff00%s|r 버튼에 설정된 모든 단축키 설정이 해제되었습니다."
+L["Already Running.. Bailing Out!"] = "이미 실행중입니다. 잠시만 기다려 주세요."
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "전장전용 정보문자를 일시적으로 표시하지 않습니다. 다시 보고 싶으면 |cffceff00/bgstats|r 나 미니맵에 있는 C 버튼을 우클릭하세요."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "전장전용 정보문자를 다시 표시합니다."
+L["Binds Discarded"] = "방금 한 단축키 지정 작업을 저장하지 않고 취소했습니다."
+L["Binds Saved"] = "단축키가 저장되었습니다."
+L["Confused.. Try Again!"] = "작업에 혼선이 있었습니다. 다시 시도해 주세요."
+L["No gray items to delete."] = "잡동사니가 없습니다."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "%s 주문이 차단 목록에 등록되었습니다."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
+L["Vendored gray items for:"] = "모든 잡동사니를 팔았습니다:"
+L["You don't have enough money to repair."] = "수리 비용이 부족합니다."
+L["You must be at a vendor."] = "상인을 만나야 가능합니다."
+L["Your items have been repaired for: "] = "자동으로 수리하고 비용을 지불했습니다:"
+L["Your items have been repaired using guild bank funds for: "] = "길드자금으로 수리하고 비용을 지불했습니다:"
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "Lua 에러가 발생하였습니다. 전투가 끝난 후에 내역을 표시하겠습니다."
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "이 설정은 캐릭터별로 따로 저장되므로|n프로필에 영향을 주지도, 받지도 않습니다.|n|n설정 적용을 위해 리로드 하시겠습니까?"
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
+L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
+L["Are you sure you want to delete all your gray items?"] = "모든 잡동사니를 버리겠습니까?"
+L["Are you sure you want to disband the group?"] = "현재 그룹을 해산하시겠습니까?"
+L["Are you sure you want to reset all the settings on this profile?"] = "현재 사용중인 프로필을 초기화 하시겠습니까?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "모든 프레임을 기본 위치로 초기화 하시겠습니까?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "새로운 오라시스템을 혼란스러워 하는 분들이 많아 설치과정에 관련 페이지를 추가했습니다. 해도 되고 안해도 됩니다. 이미 스스로 오라시스템을 구축했으면 그냥 설치를 마지막까지 넘겨 종료하세요."
+L["Can't buy anymore slots!"] = "더 이상 가방 칸을 늘릴 수 없습니다."
+L["Disable Warning"] = "비활성화 경고"
+L["Discard"] = "작업 취소"
+L["Do you enjoy the new ElvUI?"] = "만우절 기능이었습니다! 이대로 쓰실래요?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "두 애드온을 병행하여 생기는 문제를 스스로 감수하며 관련 질문글을 올리지 마세요."
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "현재 사용하는 ElvUI가 5버전 이상 뒤쳐진 버전입니다. https://github.com/ElvUI-Vanilla/ElvUI/ 에서 새 버전을 다운로드 받으세요."
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI가 오래된 버전입니다. https://github.com/ElvUI-Vanilla/ElvUI/ 에서 새 버전을 다운로드 받으세요."
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI의 데이터베이스를 조정할 필요가 있습니다. 잠시 기다려주세요."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "행동단축바나 주문책의 스킬에 마우스오버 후 키를 누르면 단축키로 지정합니다. 단축키를 지정한 곳을 우클릭 하거나 ESC를 누르면 해제합니다."
+L["I Swear"] = "알겠습니다."
+L["No, Revert Changes!"] = "예전으로 돌려주세요"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "ElvUI 와 TukUI 를 동시에 사용하려 하고 있습니다. 하나만 선택해 주세요."
+L["One or more of the changes you have made require a ReloadUI."] = "변경 사항을 적용하려면 애드온을 리로드 해야합니다."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "이 설정은 모든 캐릭터에게 동일하게 적용됩니다.|n|n설정 적용을 위해 리로드 하시겠습니까?"
+L["Save"] = "저장"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = true;
+L["Type /hellokitty to revert to old settings."] = "/hellokitty 를 입력해서 예전 세팅으로 돌릴 수 있습니다."
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "힐러 레이아웃을 사용할 거라면 Clique 애드온을 같이 써 클릭캐스팅 기능을 이용할 것을 강력히 추천합니다."
+L["Yes, Keep Changes!"] = "네! 이대로 할래요!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Thin Border Theme 선택을 바꾸었습니다. 설치과정을 끝까지 밟아 그래픽 관련 버그를 미연에 방지하는 걸 추천합니다."
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "UI 배율이 변경되었지만 ElvUI의 UI크기 자동조절 기능이 켜져있습니다. UI크기 자동조절 기능을 끄고 싶다면 '수락'을 누르세요."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = true;
+L["You must purchase a bank slot first!"] = "우선 은행가방 칸을 구입해야됩니다!"
+
+--Tooltip
+L["Count"] = "갯수"
+L["Item Level:"] = "템렙:"
+L["Talent Specialization:"] = "특성:"
+L["Targeted By:"] = "선택됨:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "단축키 설정의 맨 아래에 있는 ElvUI 부분에서 |cff2eb7e4[Raid Marker]|r 기능을 사용하면 대상에게 징표를 간단히 찍을 수 있습니다."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "각 전문화별로 ElvUI 설정을 따로 지정할 수 있습니다. 설정의 프로필 항목에 |cff2eb7e4[이중 프로필 사용]|r 기능을 확인하세요."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "궁금한 사항이나 기술지원은 |cff2eb7e4https://github.com/ElvUI-Vanilla/ElvUI|r에서 해결하세요."
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "ElvUI 에서 지원하는 대부분의 기능은 |cff2eb7e4/ec|r 에서 조정이 가능합니다. 하고 싶은 조절 기능이 없다면 직접 lua수정으로 고쳐야 합니다."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "ElvUI에서 지원하는 기능과 겹치는 다른 애드온을 쓰고 싶으면 ElvUI 설정에서 해당 기능을 사용 체크해제 해야합니다. (예: Bartender, Dominos)"
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "ElvUI의 특정 기능만 따로 독립애드온으로 분리하는 것은 불가능합니다."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "기본적으로 단축바에서 스킬을 뺄려면 |cff2eb7e4Shift 키를 누른 상태에서 드래그|r해야 합니다. 수정키는 /ec -> 행동단축바 항목에서 바꿀 수 있습니다."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "채팅창에 표시할 채널은 채팅탭을 우클릭하면 뜨는 메뉴의 설정에서 변경할 수 있습니다."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "채팅창 우측상단의 문서 아이콘을 클릭하면 대화 내역을 복사할 수 있습니다. 우클릭하면 채팅에 관련된 메뉴가 나옵니다."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "/ec -> 툴팁 항목에서 |cff2eb7e4[특성/아이템레벨 표시]|r 기능을 체크하고 Shift를 누른 상태로 마우스를 대면 그 유저의 템렙과 특성을 툴팁에 표시합니다."
+L["You can set your keybinds quickly by typing /kb."] = "|cff2eb7e4/kb|r 를 입력하면 간편하게 단축키를 설정할 수 있는 기능이 실행됩니다."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "미니맵을 휠버튼클릭 하거나 행동단축바 설정으로 각종 메뉴버튼을 볼 수 있습니다."
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "|cff2eb7e4/resetui|r 입력으로 움직였던 모든 프레임의 위치를 초기화할 수 있습니다. |cff2eb7e4 /resetui 프레임이름|r 으로 특정 프레임만 초기화도 가능합니다."
+
+--UnitFrames
+L["Dead"] = true;
+L["Ghost"] = "유령"
+L["Offline"] = "오프라인"
diff --git a/ElvUI/Locales/Load_Locales.xml b/ElvUI/Locales/Load_Locales.xml
new file mode 100644
index 0000000..d3686e8
--- /dev/null
+++ b/ElvUI/Locales/Load_Locales.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Locales/Portuguese_UI.lua b/ElvUI/Locales/Portuguese_UI.lua
new file mode 100644
index 0000000..98d20d7
--- /dev/null
+++ b/ElvUI/Locales/Portuguese_UI.lua
@@ -0,0 +1,347 @@
+-- Portuguese localization file for ptBR.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "ptBR")
+if not L then return end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "The addon %s is not compatible with ElvUI's %s module. Please select either the addon or the ElvUI module to disable."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "Bem vindo à versão %s%s|r da %sElvUI|r, escreva /ec para acessar o menu de configuração em jogo. Se precisar de suporte técnico visite-nos no site https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "Ligações"
+L["Key"] = "Tecla"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "Sem atalhos definidos"
+L["Remove Bar %d Action Page"] = "Remover paginação de ação da barra %d."
+L["Trigger"] = "Gatilho"
+
+--Bags
+L["Bank"] = true;
+L["Hold Control + Right Click:"] = "Segurar Control + Clique Direito:"
+L["Hold Shift + Drag:"] = "Segurar Shift + Arrastar:"
+L["Purchase Bags"] = true;
+L["Reset Position"] = "Redefinir Posição"
+L["Sort Bags"] = "Organizar Bolsas"
+L["Temporary Move"] = "Mover Temporariamente"
+L["Toggle Bags"] = "Mostrar/Ocultar Bolsas"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "Vender Itens Cinzentos"
+
+--Chat
+L["AFK"] = "LDT"
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "NP"
+L["G"] = "G"
+L["Invalid Target"] = "Alvo inválido"
+L["O"] = "O"
+L["P"] = "P"
+L["PL"] = "PL"
+L["R"] = "R"
+L["RL"] = "RL"
+L["RW"] = "AR"
+L["says"] = "diz"
+L["whispers"] = "sussurra"
+L["yells"] = "grita"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(Segurar Shift) Memória em Uso"
+L["Avoidance Breakdown"] = "Separação de Anulação"
+L["Character: "] = "Personagem: "
+L["Chest"] = "Torso"
+L["Combat"] = true;
+L["Combat Time"] = true;
+L["Coords"] = true;
+L["copperabbrev"] = "|cffeda55fc|r"
+L["Deficit:"] = "Défice:"
+L["DPS"] = "DPS"
+L["Earned:"] = "Ganho:"
+L["Friends List"] = "Lista de Amigos"
+L["Friends"] = "Amigos"
+L["Gold"] = true;
+L["goldabbrev"] = "|cffffd700g|r"
+L["Hit"] = "Acerto"
+L["Hold Shift + Right Click:"] = true;
+L["Home Latency:"] = "Latência de Casa:"
+L["HP"] = "PV"
+L["HPS"] = "PVS"
+L["lvl"] = "nível"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "Mitigação por nível"
+L["No Guild"] = "Sem Guilda"
+L["Profit:"] = "Lucro:"
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "Redefinir Dados: Segurar Shifr + Clique Direito"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "Raide(s) Salva(s)"
+L["Server: "] = "Servidor: "
+L["Session:"] = "Sessão:"
+L["silverabbrev"] = "|cffc7c7cfs|r"
+L["SP"] = "PM"
+L["Spell/Heal Power"] = true;
+L["Spent:"] = "Gasto:"
+L["Stats For:"] = "Estatísticas para:"
+L["System"] = true;
+L["Total CPU:"] = "CPU Total:"
+L["Total Memory:"] = "Memória Total:"
+L["Total: "] = "Total: "
+L["Unhittable:"] = "Inacertável"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s tentou chamar a função protegida '%s'."
+L["No locals to dump"] = "Sem locais para despejar"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s está tentando compartilhar os filtros dele com você. Gostaria de aceitar o pedido?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s está tentando compartilhar o perfil %s com você. Gostaria de aceitar o pedido?"
+L["Data From: %s"] = "Dados De: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "Baixa de filtros de %s completada, gostaria de aplicar as alterações agora?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Senhor! É um milagre! O Download sumiu como um peido no vento! Tente novamente!"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Baixa de perfil completada de %s, mas o perfil %s já existe. Altere o nome ou ele irá sobrescrever o perfil existente."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "Baixa de perfil completada de %s, gostaria de carregar o perfil %s agora?"
+L["Profile request sent. Waiting for response from player."] = "Pedido de perfil enviado. Aguardando a resposta do jogador."
+L["Request was denied by user."] = "Pedido negado pelo usuário."
+L["Your profile was successfully recieved by the player."] = "Seu perfil foi recebido com sucesso pelo jogador."
+
+--Install
+L["Aura Bars & Icons"] = true;
+L["Auras Set"] = "Auras configuradas"
+L["Auras"] = true;
+L["Caster DPS"] = "DPS Lançador"
+L["Chat Set"] = "Bate-Papo configurado"
+L["Chat"] = "Bate-papo"
+L["Choose a theme layout you wish to use for your initial setup."] = "Escolha o tema de layout que deseje usar inicialmente."
+L["Classic"] = "Clássico"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Clique no botão abaixo para redimensionar os seus quadros de bate-papo, quadros de unidades, e reposicionar as suas barras de ações."
+L["Config Mode:"] = "Modo de configuração"
+L["CVars Set"] = "CVars configuradas"
+L["CVars"] = "CVars"
+L["Dark"] = "Escuro"
+L["Disable"] = "Desativar"
+L["ElvUI Installation"] = "Instalação do ElvUI"
+L["Finished"] = "Terminado"
+L["Grid Size:"] = "Tamanho da Grade"
+L["Healer"] = "Curandeiro"
+L["High Resolution"] = "Alta Resolução"
+L["high"] = "alto"
+L["Icons Only"] = "Apenas Ícones"
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Se existir um ícone ou uma barra de aura que você não queira ver exibida simplesmente mantenha pressionada a tecla Shift e clique no ícone com o botão direito para que o ícone/barra de aura desapareça."
+L["Importance: |cff07D400High|r"] = "Importância: |cff07D400Alta|r"
+L["Importance: |cffD3CF00Medium|r"] = "Importância: |cffD3CF00Média|r"
+L["Importance: |cffFF0000Low|r"] = "Importância: |cffFF0000Baixa|r"
+L["Installation Complete"] = "Instalação Completa"
+L["Layout Set"] = "Definições do Layout"
+L["Layout"] = "Layout"
+L["Lock"] = "Travar"
+L["Low Resolution"] = "Baixa Resolução"
+L["low"] = "baixo"
+L["Nudge"] = "Ajuste fino"
+L["Physical DPS"] = "DPS Físico"
+L["Please click the button below so you can setup variables and ReloadUI."] = "Por favor, clique no botão abaixo para que possa configurar as variáveis e Recarregar a IU."
+L["Please click the button below to setup your CVars."] = "Por favor, clique no botão abaixo para configurar as suas Cvars."
+L["Please press the continue button to go onto the next step."] = "Por favor, pressione o botão Continuar para passar à próxima etapa."
+L["Resolution Style Set"] = "Estilo de Resolução defenido"
+L["Resolution"] = "Resolução"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = true;
+L["Setup Chat"] = "Configurar Bate-papo"
+L["Setup CVars"] = "Configurar CVars"
+L["Skip Process"] = "Pular Processo"
+L["Sticky Frames"] = "Quadros Pegadiços"
+L["Tank"] = "Tanque"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "As janelas de bate-papo funcionam da mesma forma das da Blizzard, você pode usar o botão direito nas guias para os arrastar, mudar o nome, etc. Por favor clique no botão abaixo para configurar as suas janelas de bate-papo"
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "O modo configuração em jogo pode ser acessado escrevendo o comando /ec ou clicando no botão 'C' no minimapa. Pressione o botão abaixo se desejar pular o processo de instalação"
+L["Theme Set"] = "Tema configurado"
+L["Theme Setup"] = "Configuração do Tema"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Este processo de instalação vai mostrar-lhe algumas das opções que a ElvUI tem para oferecer e também vai preparar a sua interface para ser usada."
+L["This is completely optional."] = "Isto é completamente opcional."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "Esta parte da instalação é para definir os nomes, posições e cores das suas janelas de bate-papo."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Esta parte da instalação serve para definir as suas opcões padrão do WoW, é recomendado fazer isto para que tudo funcione corretamente."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Esta resolução não exige que altere as definições para que a interface caiba no seu ecrã (monitor)."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Esta resolução requer que altere algumas definições para que tudo caiba no seu ecrã (monitor)."
+L["This will change the layout of your unitframes and actionbars."] = true;
+L["Trade"] = "Comércio"
+L["Welcome to ElvUI version %s!"] = "Bem-vindo à versão %s da ElvUI!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "O processo de instalação está agora terminado. Se precisar de suporte técnico por favor visite-nos no site https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "As cores e fontes da ElvUI podem ser mudadas em qualquer momento no modo de configuração demtro do jogo."
+L["You can now choose what layout you wish to use based on your combat role."] = "Pode agora escolher o layout que pretende usar baseado no seu papel."
+L["You may need to further alter these settings depending how low you resolution is."] = "Poderá ter de alterar estas definições dependendo de quão baixa for a sua resolução."
+L["Your current resolution is %s, this is considered a %s resolution."] = "A sua resolução actual é %s, esta é considerada uma resolução %s."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
+L["Bars"] = "Barras"
+L["Calendar"] = "Calendário"
+L["Can't Roll"] = "Não pode rolar"
+L["Disband Group"] = "Dissolver Grupo"
+L["Empty Slot"] = true;
+L["Enable"] = "Ativar"
+L["Experience"] = "Experiência"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "Saque de Peixes"
+L["Left Click:"] = "Clique Esquerdo:"
+L["Mouse"] = "rato"
+L["Raid Menu"] = "Menu de Raide"
+L["Remaining:"] = "Restante:"
+L["Rested:"] = "Descansado:"
+L["Right Click:"] = "Clique Direito:"
+L["Show BG Texts"] = "Mostrar Textos do CB"
+L["Toggle Chat Frame"] = "Mostrar/Ocultar Bat-papo"
+L["Toggle Configuration"] = "Mostrar/Ocultar Modo de Configuração"
+L["XP:"] = "XP:"
+L["You don't have permission to mark targets."] = "Você não tem permissão para marcar alvos."
+
+--Movers
+L["Arena Frames"] = "Quadros de Arenas"
+L["Bag Mover (Grow Down)"] = true;
+L["Bag Mover (Grow Up)"] = true;
+L["Bag Mover"] = true;
+L["Bags"] = "Bolsas"
+L["Bank Mover (Grow Down)"] = true;
+L["Bank Mover (Grow Up)"] = true;
+L["Bar "] = "Barra "
+L["BNet Frame"] = "Quadro do Bnet"
+L["Boss Frames"] = "Quadros dos Chefes"
+L["Classbar"] = "Barra da Classe"
+L["Experience Bar"] = "Barra de Experiência"
+L["Focus Castbar"] = "Barra de Lançamento do Foco"
+L["Focus Frame"] = "Quadro do Foco"
+L["FocusTarget Frame"] = "Quadro do Alvo do Foco"
+L["GM Ticket Frame"] = "Quadro de Consulta com GM"
+L["Left Chat"] = "Bate-papo esquerdo"
+L["Loot / Alert Frames"] = "Quadro de Saque / Alerta"
+L["Loot Frame"] = true;
+L["MA Frames"] = "Quadro do Assistente Principal"
+L["Micro Bar"] = "Micro Barra"
+L["Minimap"] = "Minimapa"
+L["MirrorTimer"] = true;
+L["MT Frames"] = "Quadro do Tank Principal"
+L["Party Frames"] = "Quadros de Grupo"
+L["Pet Bar"] = "Barra do Ajudante"
+L["Pet Castbar"] = true;
+L["Pet Frame"] = "Quadro do Ajudante"
+L["PetTarget Frame"] = "Quadro do Alvo do Ajudante"
+L["Player Buffs"] = true;
+L["Player Castbar"] = "Barra de lançamento do Jogador"
+L["Player Debuffs"] = true;
+L["Player Frame"] = "Quadro do Jogador"
+L["Player Powerbar"] = true;
+L["PvP"] = true;
+L["Raid Frames"] = true;
+L["Raid Pet Frames"] = true;
+L["Raid-40 Frames"] = true;
+L["Reputation Bar"] = "Barra de Reputação"
+L["Right Chat"] = "Bate-papo direito"
+L["Stance Bar"] = "Barra de Postura"
+L["Target Castbar"] = "Barra de lançamento do Alvo"
+L["Target Frame"] = "Quadro do Alvo"
+L["Target Powerbar"] = true;
+L["TargetTarget Frame"] = "Quadro do Alvo do Alvo"
+L["TargetTargetTarget Frame"] = true;
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "Tooltip"
+L["Vehicle Seat Frame"] = "Quadro de Assento de Veículo"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = true;
+L["In Progress"] = true;
+L["List of installations in queue:"] = true;
+L["Pending"] = true;
+L["Steps"] = true;
+
+--Prints
+L[" |cff00ff00bound to |r"] = " |cff00ff00Ligado a |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "%s quadro(s) tem um ponto de fixação em conflito, por favor mude o ponto de fixação do quadro de bônus ou de penalidades para que eles não fiquem ligados uns aos outros. Forçando as penalidades a ficarem anexadas ao quadro principal até que sejam consertados."
+L["All keybindings cleared for |cff00ff00%s|r."] = "Todos os atalhos livres para"
+L["Already Running.. Bailing Out!"] = "Já está executando... Cancelando a ordenação!"
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Os textos Informativos dos Campos de Batalha estão temporáriamente ocultos, para serem mostrados digite /bgstats ou clique direito no ícone 'C' perto do minimapa."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "Os textos Informativos irão agora ser mostrados se estiver dentro de um Campo de Batalha."
+L["Binds Discarded"] = "Ligações Descartadas"
+L["Binds Saved"] = "Ligações Salvas"
+L["Confused.. Try Again!"] = "Confuso... Tente novamente!"
+L["No gray items to delete."] = "Nenhum item cinzento para destruir."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "O feitiço '%s' foi adicionado à Lista Negra dos filtros das auras de unidades."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
+L["Vendored gray items for:"] = "Vendeu os itens cinzentos por:"
+L["You don't have enough money to repair."] = "Você não tem dinheiro suficiente para reparar."
+L["You must be at a vendor."] = "Tem de estar num vendedor."
+L["Your items have been repaired for: "] = "Seus itens foram reparadas por: "
+L["Your items have been repaired using guild bank funds for: "] = "Seus itens foram reparados usando fundos do banco da guilda por: "
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Erro Lua recebido. Pode ver a mensagem de erro quando sair de combate"
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "A definição que você alterou afetará apenas este personagem. Esta definição que você alterou não será afetada por mudanças de perfil. Alterar esta difinição requer que você recarregue a sua interface."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
+L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
+L["Are you sure you want to delete all your gray items?"] = "Tem a certeza de que deseja destruir todos os seus itens cinzentos?"
+L["Are you sure you want to disband the group?"] = "Tem a certeza de que quer dissolver o grupo?"
+L["Are you sure you want to reset all the settings on this profile?"] = "Tem certeza que quer redefinir todas as configurações desse perfil?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "Tem a certeza de que deseja restaurar todos os movedores de volta para a sua posição padrão?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Devido à grande confusão causada pelo novo sistema de auras foi implementado um novo passo no processo de instalação. Este passo é opcional, se você gosta da maneira que as suas auras estão configuradas vá para o último passo e clique em Terminado para não ser solicitado a configurar este passo novamente. Se por algum motivo for repetidamente solicitado a fazê-lo, por favor reinicie o seu jogo."
+L["Can't buy anymore slots!"] = "Não é possível comprar mais espaços!"
+L["Disable Warning"] = "Desativar Aviso"
+L["Discard"] = "Descartar"
+L["Do you enjoy the new ElvUI?"] = true;
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Você jura não postar no suporte técnico sobre alguma coisa não funcionando sem antes desabilitar a combinação addon/módulo?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = true;
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = true;
+L["ElvUI needs to perform database optimizations please be patient."] = true;
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Paire com o seu rato (mouse) sobre qualquer botão de ação ou botão do grimório para fazer uma Ligação. Pressione a tecla Escape ou clique com o botão direito para limpar o atalho atual."
+L["I Swear"] = "Eu Juro"
+L["No, Revert Changes!"] = true;
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh senhor, você está com os addons ElvUI e Tuki ativos ao mesmo tempo. Selecione um para desativar."
+L["One or more of the changes you have made require a ReloadUI."] = "Uma ou mais das alterações que fez requerem que recarregue a IU."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Uma ou mais das alterações que fez afetará todos os personagens que usam este addon. Você terá que recarregar a interface para ver as alterações que fez."
+L["Save"] = "Salvar"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = true;
+L["Type /hellokitty to revert to old settings."] = true;
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Ao usar o leioute de curandeiro é altamente recomendado que você baixe o addon Clique se quiser ter a função de clicar-para-curar."
+L["Yes, Keep Changes!"] = true;
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = true;
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Você mudou a Escala da sua IU, no entanto ainda tem a opção de dimensionamento automático ativa na ElvUI. Pressione Aceitar se gostaria de desativar a opção de dimensionamento automático."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = true;
+L["You must purchase a bank slot first!"] = "Você deve comprar um espaço no banco primeiro!"
+
+--Tooltip
+L["Count"] = "Contar"
+L["Item Level:"] = true;
+L["Talent Specialization:"] = true;
+L["Targeted By:"] = "Sendo Alvo de:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "A opção Marcas de Raide está disponivel pressionando Escape -> Teclas de Atalho, rolando tudo para o fundo debaixo de ElvUI e definindo uma tecla de atalho para o Raid Marker."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "A ElvUI contém o modo de duas especializações, que permite que carregue perfis diferentes baseado na sua especialização atual rapidamente. Você pode ativar esta opção na guia Perfis."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Para suporte técnico visite-nos no site https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Se acidentalmente remover um quadro de conversação você pode sempre ir ao menu de configuração em jogo, pressionar instalar, ir até a etapa de bate-papo e os restaurar."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Se estiver a ter problemas com a ElvUI tente desativar todos os addons exceto a ElvUI, lembre-se que a ElvUI é um addon de substituição de interface completo, e não se consegue executar dois addons que fazem a mesma coisa."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "A unidade de Foco pode ser definida escrevendo /focus quando voce tem no alvo a unidade que quer tal. É recomendado que faça uma macro para este efeito."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Para mover habilidades nas barras de ação (modo padrão) mantenha pressionado Shift enquanto arrasta. Você pode mudar a tecla no menu de opções das barras de ações."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Para configurar que canais aparecem em cada quadro de conversação, clique com o botão direito no guia do bate-papo e vá a configurações."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Você pode acessar ao 'copiar bate-papo' e ao menu de funções do bate-papo passando com o rato (mouse) no canto superior direito do painel e clicando botão esquerdo/direito no botão que irá aparecer."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Você pode ver o nivel médio de itens que outra pessoa tem mantendo shift pressionado e passando com o rato (mouse) por cima deles. Deverá aparecer na tooltip."
+L["You can set your keybinds quickly by typing /kb."] = "Você pode definir os seus atalhos rapidamente escrevendo /kb."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Você pode ativar a micro barra clicando no minimapa com o seu botão do meio do rato (mouse), pode também conseguir isto ativando a verdadeira micro barra nas definições das barras de ações."
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "Você pode usar o comando /resetui para restaurar todos os movedores. Pode usar este comando também para restaurar um movedor especifico escrevendo /resetui \nExemplo: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = true;
+L["Ghost"] = "Fantasma"
+L["Offline"] = "Desconectado"
diff --git a/ElvUI/Locales/Russian_UI.lua b/ElvUI/Locales/Russian_UI.lua
new file mode 100644
index 0000000..563b549
--- /dev/null
+++ b/ElvUI/Locales/Russian_UI.lua
@@ -0,0 +1,347 @@
+-- Russian localization file for ruRU.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "ruRU")
+if not L then return; end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "Аддон %s не совместим с модулем %s ElvUI. Пожалуйста, выберите отключить ли несовместимый аддон или модуль."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "Добро пожаловать в %sElvUI|r версии %s%s|r, наберите /ec для доступа в меню настроек. Если Вам нужна техническая поддержка, посетите https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "Назначение"
+L["Key"] = "Клавиша"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "Нет назначений"
+L["Remove Bar %d Action Page"] = "Удалить панель %d из списка переключаемых"
+L["Trigger"] = "Триггер"
+
+--Bags
+L["Bank"] = "Банк"
+L["Hold Control + Right Click:"] = "Зажать Control + ПКМ:"
+L["Hold Shift + Drag:"] = "Зажать shift и перетаскивать:"
+L["Purchase Bags"] = "Приобрести слот"
+L["Reset Position"] = "Сбросить позицию"
+L["Sort Bags"] = "Сортировать"
+L["Temporary Move"] = "Временное перемещение"
+L["Toggle Bags"] = "Показать сумки"
+L["Toggle Key"] = "Показать ключи"
+L["Vendor Grays"] = "Продавать серые предметы"
+
+--Chat
+L["AFK"] = "АФК" --Also used in datatexts and tooltip
+L["BG"] = "ПБ"
+L["BGL"] = "Лидер ПБ"
+L["DND"] = "ДНД" --Also used in datatexts and tooltip
+L["G"] = "Г"
+L["Invalid Target"] = "Неверная цель"
+L["O"] = "Оф"
+L["P"] = "Гр"
+L["PL"] = "Лидер гр."
+L["R"] = "Р"
+L["RL"] = "РЛ"
+L["RW"] = "Объявление"
+L["says"] = "говорит"
+L["whispers"] = "шепчет"
+L["yells"] = "кричит"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(Зажать Shift) Использование памяти"
+L["Avoidance Breakdown"] = "Распределение защиты"
+L["Character: "] = "Персонаж: "
+L["Chest"] = "Грудь"
+L["Combat"] = "Бой"
+L["Combat Time"] = "В бою"
+L["Coords"] = "Коорд."
+L["copperabbrev"] = "|cffeda55fм|r" --Also used in Bags
+L["Deficit:"] = "Убыток:"
+L["DPS"] = "УВС"
+L["Earned:"] = "Заработано"
+L["Friends List"] = "Список друзей"
+L["Friends"] = "Друзья" --Also in Skins
+L["Gold"] = "Золото"
+L["goldabbrev"] = "|cffffd700з|r" --Also used in Bags
+L["Hit"] = "Метк."
+L["Hold Shift + Right Click:"] = "Shift + ПКМ:"
+L["Home Latency:"] = "Локальная задержка: "
+L["HP"] = "+ Исцел."
+L["HPS"] = "ИВС"
+L["lvl"] = "ур."
+L["Miss Chance"] = "Вероятность промаха"
+L["Mitigation By Level: "] = "Снижение на уровне: "
+L["No Guild"] = "Нет гильдии"
+L["Profit:"] = "Прибыль:"
+L["Reload UI"] = "Перезагрузка"
+L["Reset Data: Hold Shift + Right Click"] = "Сбросить данные: Shift + ПКМ"
+L["Right Click: Reset CPU Usage"] = "ПКМ: Сбросить использование процессора"
+L["Saved Raid(s)"] = "Сохраненные рейды"
+L["Server: "] = "На сервере:"
+L["Session:"] = "За сеанс:"
+L["silverabbrev"] = "|cffc7c7cfс|r" --Also used in Bags
+L["SP"] = "+ Закл."
+L["Spell/Heal Power"] = "Сила заклинаний"
+L["Spent:"] = "Потрачено:"
+L["Stats For:"] = "Статистика для:"
+L["System"] = "Система"
+L["Total CPU:"] = "Использование процессора:"
+L["Total Memory:"] = "Всего памяти:"
+L["Total: "] = "Всего: "
+L["Unhittable:"] = "Полная защита от ударов"
+L["Wintergrasp"] = "Озеро Ледяных Оков"
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s tried to call the protected function '%s'."
+L["No locals to dump"] = "No locals to dump"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s хочет передать Вам свои фильтры. Желаете ли Вы принять их?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s хочет передать Вам профиль %s. Желаете ли Вы принять его?"
+L["Data From: %s"] = "Данные от: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "Завершена загрузка фильтров от %s. Желаете применить изменения сейчас?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Чтоб его! Загрузка была... да всплыла. Попробуйте еще раз!"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Загрузка профиля от %s завершена, но профиль %s уже существует. Измените его название или он перезапишет уже существующий профиль."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "Загрузка профиля от %s завершена, хотите загрузить профиль %s сейчас?"
+L["Profile request sent. Waiting for response from player."] = "Запрос на передачу профиля отправлен. Ждите, пожалуйста, ответа."
+L["Request was denied by user."] = "Запрос отклонен пользователем."
+L["Your profile was successfully recieved by the player."] = "Ваш профиль успешно получен целью. Ура, товарищи!"
+
+--Install
+L["Aura Bars & Icons"] = "Полосы аур и иконки"
+L["Auras Set"] = "Ауры установлены"
+L["Auras"] = "Ауры"
+L["Caster DPS"] = "Заклинатель"
+L["Chat Set"] = "Чат настроен"
+L["Chat"] = "Чат"
+L["Choose a theme layout you wish to use for your initial setup."] = "Выберите тему, которую Вы хотите использовать."
+L["Classic"] = "Классическая"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Нажмите кнопку ниже для изменения размеров вашего чата, рамок юнитов и перемещения ваших панелей действий."
+L["Config Mode:"] = "Режим настройки:"
+L["CVars Set"] = "Настройки сброшены"
+L["CVars"] = "Настройки игры"
+L["Dark"] = "Темная"
+L["Disable"] = "Выключить"
+L["ElvUI Installation"] = "Установка ElvUI"
+L["Finished"] = "Завершить"
+L["Grid Size:"] = "Размер сетки"
+L["Healer"] = "Лекарь"
+L["High Resolution"] = "Высокое разрешение"
+L["high"] = "высоким"
+L["Icons Only"] = "Только иконки" --Also used in Bags
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Если Вы видите иконку или полосу аур, которую Вы не хотите отображать, просто зажмите shift и кликните на иконке правой кнопкой, чтобы она исчезла."
+L["Importance: |cff07D400High|r"] = "Важность: |cff07D400Высокая|r"
+L["Importance: |cffD3CF00Medium|r"] = "Важность: |cffD3CF00Средняя|r"
+L["Importance: |cffFF0000Low|r"] = "Важность: |cffFF0000Низкая|r"
+L["Installation Complete"] = "Установка завершена"
+L["Layout Set"] = "Расположение установлено"
+L["Layout"] = "Расположение"
+L["Lock"] = "Закрепить"
+L["Low Resolution"] = "Низкое разрешение"
+L["low"] = "низким"
+L["Nudge"] = "Сдвиг"
+L["Physical DPS"] = "Физический урон"
+L["Please click the button below so you can setup variables and ReloadUI."] = "Пожалуйста, нажмите кнопку ниже для установки переменных и перезагрузки интерфейса."
+L["Please click the button below to setup your CVars."] = "Пожалуйста, нажмите кнопку ниже для сброса настроек."
+L["Please press the continue button to go onto the next step."] = "Пожалуйста, нажмите кнопку 'Продолжить' для перехода к следующему шагу"
+L["Resolution Style Set"] = "Разрешение установлено"
+L["Resolution"] = "Разрешение"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Выберите тип системы аур, который Вы хотите использовать на рамках юнитов ElvUI. 'Полосы аур и иконки' включит и полосы и иконки, выберите 'Только иконки', чтобы видеть только их."
+L["Setup Chat"] = "Настроить чат"
+L["Setup CVars"] = "Сбросить настройки"
+L["Skip Process"] = "Пропустить установку"
+L["Sticky Frames"] = "Клейкие фреймы"
+L["Tank"] = "Танк"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "Окна чата работают так же, как и в стандартном чате Blizzard. Вы можете нажать правую кнопку мыши на вкладках для перемещения, переименования и тд. Пожалуйста, нажмите кнопку ниже для настройки чата."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "Меню настроек можно вызвать командой /ес или кнопкой 'С' на миникарте. Нажмите кнопку ниже, если Вы хотите прервать процесс установки."
+L["Theme Set"] = "Тема установлена"
+L["Theme Setup"] = "Тема"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Этот процесс установки поможет Вам узнать о некоторых функциях ElvUI и подготовить Ваш интерфейс к использованию."
+L["This is completely optional."] = "Это действие абсолютно не обязательно."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "Эта часть установки настроит названия, позиции и цвета вкладок чата."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Эта часть установки сбросит настройки World of Warcraft на конфигурацию по умолчанию. Рекомендуется выполнить этот шаг для надлежащей работы интерфейса."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Для соответствия интерфейса вашему экрану не требуется изменения настроек."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Для соответствия интерфейса вашему экрану требуется изменение некоторых настроек."
+L["This will change the layout of your unitframes and actionbars."] = "Это изменит расположение ваших рамок юнитов, рейда и панелей команд."
+L["Trade"] = "Торговля"
+L["Welcome to ElvUI version %s!"] = "Добро пожаловать в ElvUI версии %s!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Вы завершили процесс установки. Если Вам требуется техническая поддержка, посетите https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Вы всегда можете изменить шрифты и цвета любого элемента ElvUI из меню конфигурации. Классическая и пиксельная темы не отличаются для русского клиента."
+L["You can now choose what layout you wish to use based on your combat role."] = "Вы можете выбрать используемое расположение, основываясь на Вашей роли."
+L["You may need to further alter these settings depending how low you resolution is."] = "Вам может понадобиться дальнейшее изменение этих настроек в зависимости от того, насколько низким является ваше разрешение."
+L["Your current resolution is %s, this is considered a %s resolution."] = "Ваше текущее разрешение - %s, это считается %s разрешением."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [на %.0f%% опережаем |cff%02x%02x%02x%s|r]"
+L["Bars"] = "Полосы" --Also used in UnitFrames
+L["Calendar"] = "Календарь"
+L["Can't Roll"] = "Не могу бросить кости"
+L["Disband Group"] = "Распустить группу"
+L["Empty Slot"] = "Пустой слот"
+L["Enable"] = "Включить" --Doesn't fit a section since it's used a lot of places
+L["Experience"] = "Опыт"
+L["Farm Mode"] = "Режим фарма"
+L["Fishy Loot"] = "Улов"
+L["Left Click:"] = "ЛКМ:" --layout\layout.lua
+L["Mouse"] = "мышь"
+L["Raid Menu"] = "Рейдовое меню"
+L["Remaining:"] = "Осталось:"
+L["Rested:"] = "Бодрость:"
+L["Right Click:"] = "ПКМ:" --layout\layout.lua
+L["Show BG Texts"] = "Показать текст ПБ" --layout\layout.lua
+L["Toggle Chat Frame"] = "Показать/скрыть чат" --layout\layout.lua
+L["Toggle Configuration"] = "Конфигурация" --layout\layout.lua
+L["XP:"] = "Опыт:"
+L["You don't have permission to mark targets."] = "У вас нет разрешения на установку меток"
+
+--Movers
+L["Arena Frames"] = "Арена" --Also used in UnitFrames
+L["Bag Mover (Grow Down)"] = "Сумки (Рост вниз)"
+L["Bag Mover (Grow Up)"] = "Сумки (Рост вверх)"
+L["Bag Mover"] = "Фиксатор сумок"
+L["Bags"] = "Сумки" --Also in DataTexts
+L["Bank Mover (Grow Down)"] = "Банк (Рост вниз)"
+L["Bank Mover (Grow Up)"] = "Банк (Рост вверх)"
+L["Bar "] = "Панель " --Also in ActionBars
+L["BNet Frame"] = "Оповещения BNet"
+L["Boss Frames"] = "Боссы" --Also used in UnitFrames
+L["Classbar"] = "Полоса класса"
+L["Experience Bar"] = "Полоса опыта"
+L["Focus Castbar"] = "Полоса заклинаний фокуса"
+L["Focus Frame"] = "Фокус" --Also used in UnitFrames
+L["FocusTarget Frame"] = "Цель фокуса" --Also used in UnitFrames
+L["GM Ticket Frame"] = "Запрос ГМу"
+L["Left Chat"] = "Левый чат"
+L["Loot / Alert Frames"] = "Розыгрыш/оповещения"
+L["Loot Frame"] = "Окно добычи"
+L["MA Frames"] = "Помощники"
+L["Micro Bar"] = "Микроменю" --Also in ActionBars
+L["Minimap"] = "Миникарта"
+L["MirrorTimer"] = "Таймер"
+L["MT Frames"] = "Танки"
+L["Party Frames"] = "Группа" --Also used in UnitFrames
+L["Pet Bar"] = "Панель питомца" --Also in ActionBars
+L["Pet Castbar"] = "Полоса заклинаний питомца"
+L["Pet Frame"] = "Питомец" --Also used in UnitFrames
+L["PetTarget Frame"] = "Цель питомца" --Also used in UnitFrames
+L["Player Buffs"] = "Баффы игрока"
+L["Player Castbar"] = "Полоса заклинаний игрока"
+L["Player Debuffs"] = "Дебаффы игрока"
+L["Player Frame"] = "Игрок" --Also used in UnitFrames
+L["Player Powerbar"] = "Полоса ресурса игрока"
+L["PvP"] = true;
+L["Raid Frames"] = "Рейд"
+L["Raid Pet Frames"] = "Питомцы рейда"
+L["Raid-40 Frames"] = "Рейд 40"
+L["Reputation Bar"] = "Полоса репутации"
+L["Right Chat"] = "Правый чат"
+L["Stance Bar"] = "Панель стоек" --Also in ActionBars
+L["Target Castbar"] = "Полоса заклинаний цели"
+L["Target Frame"] = "Цель" --Also used in UnitFrames
+L["Target Powerbar"] = "Полоса ресурса цели"
+L["TargetTarget Frame"] = "Цель цели" --Also used in UnitFrames
+L["TargetTargetTarget Frame"] = "Цель цели цели"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "Подсказка"
+L["Vehicle Seat Frame"] = "Техника"
+L["Watch Frame"] = "Задания"
+L["Weapons"] = "Оружие"
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = "Установка плагина ElvUI"
+L["In Progress"] = "В процессе"
+L["List of installations in queue:"] = "Очередь установки:"
+L["Pending"] = "Ожидает"
+L["Steps"] = "Шаги"
+
+--Prints
+L[" |cff00ff00bound to |r"] = " |cff00ff00назначено для |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "Обнаружен конфликт точек фиксирования во фрейме(ах) %s. Пожалуйста, переназначьте фиксирование баффов и дебаффов так, чтобы они не крепились друг к другу. Установлено принудительное крепление дебаффов к фрейму."
+L["All keybindings cleared for |cff00ff00%s|r."] = "Сброшены все назначения для |cff00ff00%s|r."
+L["Already Running.. Bailing Out!"] = "Уже выполняется.. Бобер, выдыхай!"
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Информация поля боя временно скрыта. Для отображения введите /bgstat или ПКМ на иконке 'С' у миникарты."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "Информация поля боя снова будет отображаться, если Вы находитесь на них."
+L["Binds Discarded"] = "Назначения отменены"
+L["Binds Saved"] = "Назначения сохранены"
+L["Confused.. Try Again!"] = "Что за?.. Попробуйте еще раз!"
+L["No gray items to delete."] = "Нет предметов серого качества для удаления."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "Заклинание '%s' было добавлено в фильтр 'Blacklist' аур рамок юнитов."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "Эта опция вызвала конфликт точек фиксации, в результате которого \"%s\" крепится к самому себе. Пожалуйста, проверье настройки точек фиксации. \"%s\" будет прикреплено к \"%s\"."
+L["Vendored gray items for:"] = "Проданы серые предметы на сумму:"
+L["You don't have enough money to repair."] = "У вас недостаточно денег для ремонта."
+L["You must be at a vendor."] = "Вы должны находиться у торговца"
+L["Your items have been repaired for: "] = "Ремонт обошелся в "
+L["Your items have been repaired using guild bank funds for: "] = "Ремонт обошелся гильдии в "
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Обнаружена ошибка lua. Вы получите отчет о ней после завершения боя."
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "Настройка, которую Вы только что изменили, будет влиять только на этого персонажа. Она не будет изменяться при смене профиля. Также это изменение требует перезагрузки интерфейса для вступления в силу."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = "Приняв это вы сбросите ваши списки приоритетов для всех аур на индикаторах здоровья. Вы уверены?"
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = "Приняв это вы сбросите ваши списки приоритетов для всех аур на рамках юнитов. Вы уверены?"
+L["Are you sure you want to apply this font to all ElvUI elements?"] = "Вы уверены, что хоттите применить этот шрифт ко всем элементам ElvUI?"
+L["Are you sure you want to delete all your gray items?"] = "Вы уверены, что хотите удалить все предметы серого качества?"
+L["Are you sure you want to disband the group?"] = "Вы уверены, что хотите распустить группу?"
+L["Are you sure you want to reset all the settings on this profile?"] = "Вы уверены, что хотите сбросить все настройки для этого профиля?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "Вы уверены, что хотите сбросить все фиксаторы на позиции по умолчанию?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Из-за массового непонимания новой системы аур, я добавил новый шаг в установку. Он опционален. Если Вам нравится, как сейчас настроены Ваши ауры, перейдите до последнюю страницу установки и нажмите \"Завершить\", чтобы это сообщение больше не появлялось. Если же оно появится снова, пожалуйста, перезапустите игру."
+L["Can't buy anymore slots!"] = "Невозможно приобрести больше слотов!"
+L["Disable Warning"] = "Отключить предупреждение"
+L["Discard"] = "Отменить"
+L["Do you enjoy the new ElvUI?"] = "Вам нравится ElvUI?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Клянетесь ли Вы не постить на форуме технической поддержки, что что-то не работает, до того, как отключите другие аддоны/модули?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "Ваш ElvUI устарел более, чем на 5 версий. Вы можете скачать последнюю версию с https://github.com/ElvUI-Vanilla/ElvUI/"
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI устарел. Вы можете скачать последнюю версию с https://github.com/ElvUI-Vanilla/ElvUI/"
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI нужно провести оптимизацию базы данных. Подождите, пожалуйста."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Наведите курсор на любую кнопку на панели или в книге заклинаний, чтобы назначит ей клавишу. Нажмите правую кнопку мыши или 'Escape', чтобы сбросить назначение для этой кнопки."
+L["I Swear"] = "Я клянусь!"
+L["No, Revert Changes!"] = "Нет, обратить изменения!"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Японский городовой... у Вас одновременно включены ElvUi и Tukui. Выберите аддон для отключения."
+L["One or more of the changes you have made require a ReloadUI."] = "Одно или несколько изменений требуют перезагрузки интерфейса"
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Одно или несколько изменений повлияют на всех персонажей, использующих этот аддон. Вы должны перезагрузить интерфейс для отображения этих изменений."
+L["Save"] = "Сохранить"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "Профиль, который вы хотите импортировать, уже существует. Задайте новой имя или примите для перезаписи существующего профиля."
+L["Type /hellokitty to revert to old settings."] = "Напишите /hellokitty для возврата к предыдущим настройкам."
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Для использования расположения для лекаря крайне рекомендуется установить аддон Clique, если вы хотите иметь возможность лечить по клику мышью."
+L["Yes, Keep Changes!"] = "Да, сохранить изменения!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Вы переключились в режим тонких границ. Вы должны завершить установку для исправления графических багов."
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Вы изменили масштаб интерфейса, однако у вас все еще активирована опция автоматического масштабирования в настройках ElvUI. Нажмите 'Принять', если Вы хотите отключить эту опцию."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Вы импортировали настройки, которые могут потребовать перезагрузки для вступления в силу. Перезагрузить?"
+L["You must purchase a bank slot first!"] = "Сперва Вы должны приобрести дополнительный слот в банке!"
+
+--Tooltip
+L["Count"] = "Кол-во"
+L["Item Level:"] = "Уровень предметов:"
+L["Talent Specialization:"] = "Специализация:"
+L["Targeted By:"] = "Является целью:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "Функция рейдовых меток доступна в Escape -> Назначение клавиш. Прокрутите вниз до раздела ElvUI и назначьте клавишу для рейдовых меток."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "В ElvUI присутствует функция двойной специализации, которая позволит Вам использовать разные профили для разных наборов талантов. Вы можете включить эту функцию в разделе профилей."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "За технической поддержкой обращайтесь на https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Если Вы случайно удалили вкладку чата, всегда можно сделать следующее: зайти в конфигурацию, запустить установку, дойти до шага настроек чата и сбросить их."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Если Вы испытываете проблемы с ElvUI, попробуйте отключить все аддоны, кроме самого ElvUI. Помните, ElvUI это аддон, полностью заменяющий интерфейс, Вы не можете одновременно использовать два аддона, выполняющих одинаковые функции."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "Запомненную цель (фокус) можно установить командой /focus при взятии нужного врага в цель. Для этого рекомендуется сделать макрос."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Для перемещения способностей по панелям команд нужно перемещать их с зажатой клавишей shift. Вы можете поменять модификатор в опциях панелей команд."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Для настройки отображения каналов в чате кликните правой кнопкой мыши на закладке нужного чата и выберите пункт 'параметры'."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Вы можете получить доступ к функциям копирования чата и меню чата, наведя курсор на верхний правый угол панели чата и кликнув левой/правой кнопкой мыши на появившейся кнопке."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Вы можете узнать средний уровень предметов игрока, зажав shift и наведя на них курсор. Информация будет отражена в подсказке."
+L["You can set your keybinds quickly by typing /kb."] = "Вы можете быстро назначать клавиши, введя команду /kb."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Вы можете получить доступ к микроменю, кликнув средней кнопкой мыши на миникарте. Также Вы можете включить обычное микроменю в настройках панелей команд"
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "Вы можете использовать команду /resetui чтобы сбросить положения всех фиксаторов. Вы также можете использовать команду /resetui <имя фиксатора> для сброса определенного фиксатора.\nПример: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = "Труп"
+L["Ghost"] = "Призрак"
+L["Offline"] = "Не в сети"
diff --git a/ElvUI/Locales/Spanish_UI.lua b/ElvUI/Locales/Spanish_UI.lua
new file mode 100644
index 0000000..0a364bc
--- /dev/null
+++ b/ElvUI/Locales/Spanish_UI.lua
@@ -0,0 +1,347 @@
+-- Spanish localization file for esES and esMX.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "esES") or AceLocale:NewLocale("ElvUI", "esMX")
+if not L then return end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "The addon %s is not compatible with ElvUI's %s module. Please select either the addon or the ElvUI module to disable."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "Bienvenido a %sElvUI|r versión %s%s|r, escribe /ec para acceder al menú de configuración. Si necesitas ayuda o soporte técnico puedes visitarnos en https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "Controles"
+L["Key"] = "Tecla"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "No hay teclas establecidas."
+L["Remove Bar %d Action Page"] = "Quitar Barra %d de la paginación"
+L["Trigger"] = "Disparador"
+
+--Bags
+L["Bank"] = "Banco"
+L["Hold Control + Right Click:"] = "Mantén Control y Haz Clic Derecho:"
+L["Hold Shift + Drag:"] = "Mantén Shift y Arrastra:"
+L["Purchase Bags"] = "Comprar Bolsas"
+L["Reset Position"] = "Reestablecer Posición"
+L["Sort Bags"] = "Ordenar Bolsas"
+L["Temporary Move"] = "Movimiento Temporal"
+L["Toggle Bags"] = "Mostrar/Ocultar Bolsas"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "Vender Objetos Grises"
+
+--Chat
+L["AFK"] = "Ausente"
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "Oc"
+L["G"] = "H"
+L["Invalid Target"] = "Objetivo Inválido"
+L["O"] = "O"
+L["P"] = "G"
+L["PL"] = "LG"
+L["R"] = "B"
+L["RL"] = "LB"
+L["RW"] = "AB"
+L["says"] = "dice"
+L["whispers"] = "susurra"
+L["yells"] = "grita"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(Mantén Shift) Uso de Memoria"
+L["Avoidance Breakdown"] = "Desglose de Evasión"
+L["Character: "] = "Personaje: "
+L["Chest"] = "Pecho"
+L["Combat"] = "Combate"
+L["Combat Time"] = true;
+L["Coords"] = true;
+L["copperabbrev"] = "|cffeda55fc|r"
+L["Deficit:"] = "Déficit:"
+L["DPS"] = "DPS"
+L["Earned:"] = "Ganada:"
+L["Friends List"] = "Lista de Amigos"
+L["Friends"] = "Amigos"
+L["Gold"] = "Oro"
+L["goldabbrev"] = "|cffffd700g|r"
+L["Hit"] = "Golpe"
+L["Hold Shift + Right Click:"] = true;
+L["Home Latency:"] = "Latencia Local:"
+L["HP"] = "Salud"
+L["HPS"] = "VPS"
+L["lvl"] = "Niv"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "Mitigación Por Nivel: "
+L["No Guild"] = "Sin Hermandad"
+L["Profit:"] = "Ganancia:"
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "Restablecer Datos: Mantén Shift + Clic Derecho"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "Banda(s) Guardada(s)"
+L["Server: "] = "Servidor: "
+L["Session:"] = "Sesión:"
+L["silverabbrev"] = "|cffc7c7cfs|r"
+L["SP"] = "PH"
+L["Spell/Heal Power"] = true;
+L["Spent:"] = "Gastada:"
+L["Stats For:"] = "Estadísticas para:"
+L["System"] = true;
+L["Total CPU:"] = "CPU Total:"
+L["Total Memory:"] = "Memoria Total:"
+L["Total: "] = "Total: "
+L["Unhittable:"] = "Imbatible:"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s intentó llamar a la función protegida '%s'."
+L["No locals to dump"] = "No hay locales para volcar"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s quiere compartir sus filtros contigo. ¿Aceptas la petición?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s quiere compartir el perfil %s contigo. ¿Aceptas la petición?"
+L["Data From: %s"] = "Datos De: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "Se completó la descarga de los filtros de %s. ¿Quieres aplicar los cambios ahora?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "¡Milagro! ¡La descarga se desvaneció como pedo! Intenta de nuevo"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Descarga de perfil de %s completa, pero el perfil %s ya existe. Cámbiale el nombre o se reemplazará el perfil existente."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "Descarga de perfil de %s completa ¿Quieres cargar el perfil %s ahora?"
+L["Profile request sent. Waiting for response from player."] = "Petición de perfil enviada. Esperando respuesta del jugador."
+L["Request was denied by user."] = "Petición denegada por el jugador."
+L["Your profile was successfully recieved by the player."] = "Tu perfil ha sido recibido exitosamente por el jugador."
+
+--Install
+L["Aura Bars & Icons"] = "Barras de Auras e Iconos"
+L["Auras Set"] = "Auras Configuradas"
+L["Auras"] = true;
+L["Caster DPS"] = "DPS Hechizos"
+L["Chat Set"] = "Chat Configurado"
+L["Chat"] = "Chat"
+L["Choose a theme layout you wish to use for your initial setup."] = "Elige un tema de distribución para usar en tu configuración inicial."
+L["Classic"] = "Clásico"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Haz clic en el botón de abajo para cambiar el tamaño de los marcos de chat y de unidad, y reubicar tus barras de acción."
+L["Config Mode:"] = "Modo de Configuración"
+L["CVars Set"] = "CVars Configuradas"
+L["CVars"] = "CVars"
+L["Dark"] = "Oscuro"
+L["Disable"] = "Desactivar"
+L["ElvUI Installation"] = "Instalación de ElvUI"
+L["Finished"] = "Terminado"
+L["Grid Size:"] = "Tamaño de la Rejilla:"
+L["Healer"] = "Sanador"
+L["High Resolution"] = "Alta Resolución"
+L["high"] = "alta"
+L["Icons Only"] = "Sólo Iconos"
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Si tienes un icono o una barra de aura que no quieres ver simplemente mantén pulsado la tecla Shift y haz clic con el botón izquierdo del ratón en el icono para que desaparezca."
+L["Importance: |cff07D400High|r"] = "Importancia: |cff07D400Alta|r"
+L["Importance: |cffD3CF00Medium|r"] = "Importancia: |cffD3CF00Media|r"
+L["Importance: |cffFF0000Low|r"] = "Importancia: |cffFF0000Baja|r"
+L["Installation Complete"] = "Instalación Completa"
+L["Layout Set"] = "Distribución Establecida"
+L["Layout"] = "Distribución"
+L["Lock"] = "Bloquear"
+L["Low Resolution"] = "Baja Resolución"
+L["low"] = "baja"
+L["Nudge"] = "Ajuste Fino"
+L["Physical DPS"] = "DPS Físico"
+L["Please click the button below so you can setup variables and ReloadUI."] = "Haz clic en el botón de abajo para configurar variables y recargar la interfaz."
+L["Please click the button below to setup your CVars."] = "Haz clic en el botón de abajo para configurar las CVars"
+L["Please press the continue button to go onto the next step."] = "Presiona el botón de continuar para ir al siguiente paso"
+L["Resolution Style Set"] = "Estilo de Resolución Establecido"
+L["Resolution"] = "Resolución"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Selecciona el tipo de sistema de de auras que deseas utilizar con los marcos de unidad de ElvUI. Establécelo a Barras de Auras e Iconos para usar a la vez la barra de auras y los iconos, establécelo en Sólo Iconos para ver solo los iconos."
+L["Setup Chat"] = "Configurar Chat"
+L["Setup CVars"] = "Configurar CVars"
+L["Skip Process"] = "Saltar Proceso"
+L["Sticky Frames"] = "Marcos Adhesivos"
+L["Tank"] = "Tanque"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "Las ventanas de chat funcionan igual que sus contrapartes estándar de Blizzard. Puedes hacer clic derecho en las pestañas y arrastrarlas, cambiarles el nombre, etc. Haz clic en el botón de abajo para configurar las ventanas de chat."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "El menú de configuración puede ser accedido mediante el comando /ec o haciendo clic en el botón 'C' del minimapa. Presiona el botón de abajo si deseas saltarte la instalación."
+L["Theme Set"] = "Establecer Tema"
+L["Theme Setup"] = "Configurar Tema"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "El proceso de instalación te ayudará a aprender algunas de las características de ElvUI y preparará la interfaz para su uso."
+L["This is completely optional."] = "Esto es completamente opcional."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "Esta parte de la instalación configura los nombres, posiciones y colores de las ventanas de chat."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Esta parte de la instalación configura las opciones predeterminadas de World of Warcraft. Se recomienda hacer este paso para que todo funcione apropiadamente."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Esta resolución no necesita que cambies los ajustes para que quepa la interfaz en tu pantalla."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Esta resolución requiere que cambies algunos ajustes para que todo quepa en tu pantalla."
+L["This will change the layout of your unitframes and actionbars."] = "Ésto cambiará el diseño de los marcos de unidades y barras de acción."
+L["Trade"] = "Intercambio"
+L["Welcome to ElvUI version %s!"] = "Bienvenido(a) a ElvUI versión %s!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Ya has terminado con el proceso de instalación. Si necesitas ayuda o soporte técnico por favor visítanos en https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Siempre puedes cambiar las fuentes y colores de cualquier elemento de ElvUI desde la configuración."
+L["You can now choose what layout you wish to use based on your combat role."] = "Ahora puedes elegir qué distribución quieres basándote en tu rol de combate."
+L["You may need to further alter these settings depending how low you resolution is."] = "Puede que necesites cambiar estos ajutes dependiendo de qué tan baja sea tu resolución."
+L["Your current resolution is %s, this is considered a %s resolution."] = "Tu resolución actual es %s, esto se considera una resolución %s."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
+L["Bars"] = "Barras"
+L["Calendar"] = "Calendario"
+L["Can't Roll"] = "No puede tirar dados"
+L["Disband Group"] = "Disolver Grupo"
+L["Empty Slot"] = true;
+L["Enable"] = "Habilitar"
+L["Experience"] = "Experiencia"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "Botín Sospechoso"
+L["Left Click:"] = "Click Izquierdo"
+L["Mouse"] = "Ratón"
+L["Raid Menu"] = "Menú de Banda"
+L["Remaining:"] = "Restante"
+L["Rested:"] = "Descansado:"
+L["Right Click:"] = "Click Derecho"
+L["Show BG Texts"] = "Mostrar Textos de CB"
+L["Toggle Chat Frame"] = "Mostrar/Ocultar Marco de Chat"
+L["Toggle Configuration"] = "Mostrar/Ocultar Configuración"
+L["XP:"] = "XP:"
+L["You don't have permission to mark targets."] = "No tienes permiso para marcar objetivos."
+
+--Movers
+L["Arena Frames"] = "Marcos de Arena"
+L["Bag Mover (Grow Down)"] = "Fijador de Bolsa (Crecer hacia abajo)"
+L["Bag Mover (Grow Up)"] = "Fijador de Bolsa (Crecer hacia arriba)"
+L["Bag Mover"] = "Fijador de Bolsa"
+L["Bags"] = "Bolsas"
+L["Bank Mover (Grow Down)"] = "Fijador de Banco (Crecer hacia abajo)"
+L["Bank Mover (Grow Up)"] = "Fijador de Banco (Crecer hacia arriba)"
+L["Bar "] = "Barra "
+L["BNet Frame"] = "Marco BNet"
+L["Boss Frames"] = "Marco de Jefe"
+L["Classbar"] = "Barra de Clase"
+L["Experience Bar"] = "Barra de Experiencia"
+L["Focus Castbar"] = "Barra de Lanzamiento del Foco"
+L["Focus Frame"] = "Marco de Foco"
+L["FocusTarget Frame"] = "Marco de Objetivo del Foco"
+L["GM Ticket Frame"] = "Marco de Consultas para el MJ"
+L["Left Chat"] = "Chat Izquierdo"
+L["Loot / Alert Frames"] = "Marcos de Botín / Alerta"
+L["Loot Frame"] = "Marco de Botín"
+L["MA Frames"] = "Marcos de AP"
+L["Micro Bar"] = "Micro Barra"
+L["Minimap"] = "Minimapa"
+L["MirrorTimer"] = true;
+L["MT Frames"] = "Marcos de TP"
+L["Party Frames"] = "Marco de Grupo"
+L["Pet Bar"] = "Barra de Mascota"
+L["Pet Castbar"] = "Barra de Lanzamiento de Mascota"
+L["Pet Frame"] = "Marco de Mascota"
+L["PetTarget Frame"] = "Marco de Objetivo de Mascota"
+L["Player Buffs"] = "Ventajas de Jugador"
+L["Player Castbar"] = "Barra de Lanzamiento del Jugador"
+L["Player Debuffs"] = "Perjuicios de Jugador"
+L["Player Frame"] = "Marco de Jugador"
+L["Player Powerbar"] = "Barra de Poder del Jugador"
+L["PvP"] = true;
+L["Raid Frames"] = "Marcos de Banda"
+L["Raid Pet Frames"] = "Marcos de Banda con Mascotas"
+L["Raid-40 Frames"] = "Marcos de Banda de 40"
+L["Reputation Bar"] = "Barra de Reputación"
+L["Right Chat"] = "Chat Derecho"
+L["Stance Bar"] = "Barra de Forma"
+L["Target Castbar"] = "Barra de Lanzamiento del Objetivo"
+L["Target Frame"] = "Marco de Objetivo"
+L["Target Powerbar"] = "Barra de Poder del Objetivo"
+L["TargetTarget Frame"] = "Marco de Objetivo de Objetivo"
+L["TargetTargetTarget Frame"] = "Marco del Objetivo del Objetivo del Objetivo"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "Descripción Emergente"
+L["Vehicle Seat Frame"] = "Marco del Asiento del Vehículo"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = "Instalación del plugin de ElvUI"
+L["In Progress"] = "En Progreso"
+L["List of installations in queue:"] = "Lista de Instalaciones en cola:"
+L["Pending"] = "Pendiente"
+L["Steps"] = "Pasos"
+
+--Prints
+L[" |cff00ff00bound to |r"] = " |cff00ff00ligado(a) a |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "El marco(s) %s tiene un punto de fijación en conflicto, por favor cambia el punto de fijación de los beneficios o los perjuicios para que no estén adjuntos entre ellos. Se forzará a los perjuicios para que se adjunten al marco de unidad principal hasta que se corrija."
+L["All keybindings cleared for |cff00ff00%s|r."] = "Todos los atajos borrados para |cff00ff00%s|r."
+L["Already Running.. Bailing Out!"] = "Ya está en ejecución... ¡Cancelando!"
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Textos de datos de los campos de batalla temporalmente ocultos, para mostrarlos escribe /bgstats o click derecho en 'C' donde el minimapa."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "Los textos de datos de los campos de batalla serán visibles de nuevo si estás en un campo de batalla."
+L["Binds Discarded"] = "Teclas Descartadas"
+L["Binds Saved"] = "Teclas Guardadas"
+L["Confused.. Try Again!"] = "Confundido... ¡Intenta de Nuevo!"
+L["No gray items to delete."] = "No hay objetos grises para eliminar."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "El hechizo '%s' ha sido añadido a la Lista Negra del filtro de auras del marco de unidad."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "Esta opción causó un punto de fijación en conflicto, donde '%s' estaría adjunto a sí mismo. Por favor comprueba tus puntos de fijación. Opción '%s' a ser fijado a '%s'"
+L["Vendored gray items for:"] = "Objetos grises vendidos por:"
+L["You don't have enough money to repair."] = "No tienes suficiente dinero para reparaciones."
+L["You must be at a vendor."] = "Debes estar cerca de un vendedor."
+L["Your items have been repaired for: "] = "Tus objetos han sido reparados por:"
+L["Your items have been repaired using guild bank funds for: "] = "Tus objetos han sido reparados con fondos del banco de hermandad por:"
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Error de Lua recibido. Podrás ver el error cuando salgas de combate."
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "La opción que has cambiado se aplicará sólo para este personaje. Esta opción no se verá alterada al cambiar el perfil de usuario. Cambiar esta opción requiere que recargues tu Interfaz de Usuario."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
+L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
+L["Are you sure you want to delete all your gray items?"] = "¿Estás seguro que quieres eliminar todos tus objetos grises?"
+L["Are you sure you want to disband the group?"] = "¿Estás seguro que quieres deshacer el grupo?"
+L["Are you sure you want to reset all the settings on this profile?"] = "¿Estás seguro que deseas restablecer todos los ajustes de este perfil?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "¿Estás seguro que quieres resetear cada fijador a su posición por defecto?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Debido a la gran confusión causada por el nuevo sistema de auras he implementado un nuevo paso en el proceso de instalación, esto es opcional. Si quieres conservar la configuración actual de tus auras ve al último paso de la instalación y haz clic en terminar para que este mensaje no vuelva a ser mostrado. Si por alguna razón se vuelve a mostrar por favor reinicia el juego."
+L["Can't buy anymore slots!"] = "¡No puedes comprar más huecos!"
+L["Disable Warning"] = "Deshabilitar Advertencia"
+L["Discard"] = "Descartar"
+L["Do you enjoy the new ElvUI?"] = "¿Disfrutas del nuevo ElvUI?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "¿Juras no escribir a Soporte Técnico acerca de algo que no funciona sin antes deshabilitar la combinación addon/módulo primero?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI está cinco o mas revisiones desactualizado. Puedes descargar la versión más nueva de https://github.com/ElvUI-Vanilla/ElvUI/"
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI está desactualizado. Puedes descargar la versión más nueva de https://github.com/ElvUI-Vanilla/ElvUI/"
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI necesita realizar optimizaciones de base de datos por favor se paciente."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Pasa tu ratón por encima de un botón de acción o de un botón del libro de hechizos para ligarlo. Pulsa escape o botón derecho para limpiar la asignación actual del botón de acción."
+L["I Swear"] = "Lo Juro"
+L["No, Revert Changes!"] = "¡No, Revierte los Cambios!"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh cielos, tienes ElvUI y Tukui habilitados al mismo tiempo. Elige un addon a deshabilitar"
+L["One or more of the changes you have made require a ReloadUI."] = "Uno o más de los cambios que has hecho requieren una recarga de la interfaz."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Uno o más de los cambios que has hecho afectaran a todos los personajes que usen este addon. Tendrás que recargar la intefaz de usuario para ver el cambio que has realizado."
+L["Save"] = "Guardar"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "El perfil que has intentado importar ya existe. Elige un nuevo nombre o acepta sobreescribir el perfil existente."
+L["Type /hellokitty to revert to old settings."] = "Escribe /hellokitty para revertir a las opciones antiguas."
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Utilizando el diseño de sanador es altamente recomendado bajar el addon Clique si deseas tener la función de hacer clic para curar."
+L["Yes, Keep Changes!"] = "¡Sí, Mantén los cambios!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Has cambiado la opción de Tema de Border Ligero. Tendrás que completar el proceso de instalación para quitar cualquier bug gráfico."
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Has cambiado la escala de tu interfaz, sin embargo aún tienes el AutoEscalado activado en ElvUI. Pulsa aceptar si te gustaría desactivar el AutoEscalado."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Has importado opciones que pueden requerir una recarga de la interfaz para tomar efecto. ¿Recargar ahora?"
+L["You must purchase a bank slot first!"] = "¡Debes comprar un hueco del banco primero!"
+
+--Tooltip
+L["Count"] = "Contador"
+L["Item Level:"] = "Nivel de Objeto:"
+L["Talent Specialization:"] = "Especialización de Talentos:"
+L["Targeted By:"] = "Objetivo De:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "La opción de marcador de banda está disponible pulsando Escape -> Asignar teclas -> Recorrer hacia abajo hasta ElvUI y establecer la tecla para el marcador de banda."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI tiene la posibilidad de cargar diferentes perfiles automáticamente al cambiar de especialización de talentos. Puedes activar esta función en la pestaña de perfiles."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "Para soporte técnico visítanos en https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Si eliminas un marco de chat accidentalmente, siempre puedes ir a la configuración, pulsar instalar, ir a la parte del chat, y restaurarlo."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Si has experimentado errores con ElvUI prueba a desactivar todos tus addons excepto ElvUI, recuerda que ElvUI remplaza por completo la interfaz, no puede haber addons que hagan lo mismo."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "El foco puede establecerse escribiendo /enfoque cuando tienes seleccionado al objetivo al cual quieres hacer foco. Es recomendable que hagas una macro para esto."
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Para mover habilidades a las barras de acción mantener shift + arrastrar. Puedes cambiar la tecla de modificación desde el menú de opciones de la barra de acción."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Para configurar que canales aparecen en el chat, haz clic con el botón derecho en la pestaña del chat y elige opciones."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Puedes acceder a copiar y a las opciones del chat pasando el ratón sobre la esquina superior derecha del panel del chat y haciendo click en el botón que aparece."
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Puedes ver la media de nivel de objeto de un objetivo manteniendo pulsado shift mientras pasas el ratón por encima de él. El iNvl aparecerá en la descripción emergente."
+L["You can set your keybinds quickly by typing /kb."] = "Puedes establecer tus atajos rapidamente escribiendo /kb."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Puedes acceder a la microbarra usando tu botón central del ratón sobre el minimapa. También puedes activarla desde las opciones de las barras de acción."
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "Puedes usar el commando /resetui para restablecer todos tus fijadores. También puedes usar el comando para restablecer alguno en específico, /resetui . PE: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = true;
+L["Ghost"] = "Fantasma"
+L["Offline"] = "Fuera de Línea"
diff --git a/ElvUI/Locales/Taiwanese_UI.lua b/ElvUI/Locales/Taiwanese_UI.lua
new file mode 100644
index 0000000..cc7c9d2
--- /dev/null
+++ b/ElvUI/Locales/Taiwanese_UI.lua
@@ -0,0 +1,347 @@
+-- Taiwanese localization file for zhTW.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "zhTW")
+if not L then return end
+
+--*_ADDON locales
+L["INCOMPATIBLE_ADDON"] = "插件 %s 與 ElvUI 的 %s 模組不相容。請停用不相容的插件,或停用相關的模組."
+
+--*_MSG locales
+L["LOGIN_MSG"] = "歡迎使用%sElvUI |r %s%s|r 版, 請輸入/ec 進入設定介面. 如需技術支援請至 https://github.com/ElvUI-Vanilla/ElvUI"
+
+--ActionBars
+L["Binding"] = "綁定"
+L["Key"] = "鍵"
+L["KEY_ALT"] = "A"
+L["KEY_CTRL"] = "C"
+L["KEY_DELETE"] = "Del"
+L["KEY_HOME"] = "Hm"
+L["KEY_INSERT"] = "Ins"
+L["KEY_MOUSEBUTTON"] = "M"
+L["KEY_MOUSEWHEELDOWN"] = "MwD"
+L["KEY_MOUSEWHEELUP"] = "MwU"
+L["KEY_NUMPAD"] = "N"
+L["KEY_PAGEDOWN"] = "PD"
+L["KEY_PAGEUP"] = "PU"
+L["KEY_SHIFT"] = "S"
+L["KEY_SPACE"] = "SpB"
+L["No bindings set."] = "未設定快捷綁定."
+L["Remove Bar %d Action Page"] = "移除第 %d 快捷列"
+L["Trigger"] = "觸發器"
+
+--Bags
+L["Bank"] = "銀行"
+L["Hold Control + Right Click:"] = "按住 Ctrl 並按滑鼠右鍵:"
+L["Hold Shift + Drag:"] = "按住 Shift 並拖曳:"
+L["Purchase Bags"] = "購買背包"
+L["Reset Position"] = "重設位置"
+L["Sort Bags"] = "整理背包"
+L["Temporary Move"] = "移動背包"
+L["Toggle Bags"] = "開啟/關閉背包"
+L["Toggle Key"] = true;
+L["Vendor Grays"] = "出售灰色物品"
+
+--Chat
+L["AFK"] = "暫離" --Also used in datatexts and tooltip
+L["BG"] = true;
+L["BGL"] = true;
+L["DND"] = "忙碌" --Also used in datatexts and tooltip
+L["G"] = "公會"
+L["Invalid Target"] = "無效的目標"
+L["O"] = "幹部"
+L["P"] = "隊伍"
+L["PL"] = "隊長"
+L["R"] = "團隊"
+L["RL"] = "團隊隊長"
+L["RW"] = "團隊警告"
+L["says"] = "說"
+L["whispers"] = "密語"
+L["yells"] = "大喊"
+
+--DataTexts
+L["(Hold Shift) Memory Usage"] = "(按住Shift) 記憶體使用量"
+L["Avoidance Breakdown"] = "免傷統計"
+L["Character: "] = "角色: "
+L["Chest"] = "胸部"
+L["Combat"] = "戰鬥"
+L["Combat Time"] = true;
+L["Coords"] = true;
+L["copperabbrev"] = "|cffeda55f銅|r" --Also used in Bags
+L["Deficit:"] = "赤字:"
+L["DPS"] = "傷害輸出"
+L["Earned:"] = "賺取:"
+L["Friends List"] = "好友列表"
+L["Friends"] = "好友" --Also in Skins
+L["Gold"] = "金錢"
+L["goldabbrev"] = "|cffffd700金|r" --Also used in Bags
+L["Hit"] = "命中"
+L["Hold Shift + Right Click:"] = "按住 Shift 並按滑鼠右鍵"
+L["Home Latency:"] = "本機延遲:"
+L["HP"] = "生命值"
+L["HPS"] = "治療輸出"
+L["lvl"] = "等級"
+L["Miss Chance"] = true;
+L["Mitigation By Level: "] = "等級減傷: "
+L["No Guild"] = "沒有公會"
+L["Profit:"] = "利潤: "
+L["Reload UI"] = true;
+L["Reset Data: Hold Shift + Right Click"] = "重置數據: 按住 Shift + 右鍵點擊"
+L["Right Click: Reset CPU Usage"] = true;
+L["Saved Raid(s)"] = "已有進度的副本"
+L["Server: "] = "伺服器: "
+L["Session:"] = "本次登入:"
+L["silverabbrev"] = "|cffc7c7cf銀|r" --Also used in Bags
+L["SP"] = "法術能量"
+L["Spell/Heal Power"] = true;
+L["Spent:"] = "花費:"
+L["Stats For:"] = "統計:"
+L["System"] = true;
+L["Total CPU:"] = "CPU佔用"
+L["Total Memory:"] = "總記憶體:"
+L["Total: "] = "合計: "
+L["Unhittable:"] = "未命中:"
+L["Wintergrasp"] = true;
+
+--DebugTools
+L["%s: %s tried to call the protected function '%s'."] = "%s: %s 嘗試調用保護函數'%s'."
+L["No locals to dump"] = "沒有本地檔案"
+
+--Distributor
+L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s 試圖與你分享過濾器設定. 你是否接受?"
+L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s 試圖與你分享設定檔 %s. 你是否接受?"
+L["Data From: %s"] = "數據來源: %s"
+L["Filter download complete from %s, would you like to apply changes now?"] = "過濾器設定下載於 %s, 你是否現在變更?"
+L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "天啊! 太奇葩啦! 下載消失了! 就像是在風中放了個屁... 再試一次吧!"
+L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "設定文件從 %s 下載完成, 但是設定文件 %s 已存在. 請更改名稱, 否則它會覆蓋你的現有設定檔."
+L["Profile download complete from %s, would you like to load the profile %s now?"] = "設定檔從 %s 下載完成, 你是否要加載設定檔 %s?"
+L["Profile request sent. Waiting for response from player."] = "已發送設定檔請求. 等待對方回應"
+L["Request was denied by user."] = "請求被對方拒絕."
+L["Your profile was successfully recieved by the player."] = "你的設定檔已被其他玩家成功接收."
+
+--Install
+L["Aura Bars & Icons"] = "光環條和圖示"
+L["Auras Set"] = "光環樣式設定"
+L["Auras"] = "光環"
+L["Caster DPS"] = "法系輸出"
+L["Chat Set"] = "對話设置"
+L["Chat"] = "對話"
+L["Choose a theme layout you wish to use for your initial setup."] = "為你的個人設定選擇一個你喜歡的皮膚主題."
+L["Classic"] = "經典"
+L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "點選下面的按鈕調整對話框、單位框架的尺寸, 以及移動快捷列位置."
+L["Config Mode:"] = "設定模式:"
+L["CVars Set"] = "參數設定"
+L["CVars"] = "參數"
+L["Dark"] = "黑暗"
+L["Disable"] = "停用"
+L["ElvUI Installation"] = "安裝 ElvUI"
+L["Finished"] = "設定完畢"
+L["Grid Size:"] = "網格尺寸:"
+L["Healer"] = "補師"
+L["High Resolution"] = "高解析度"
+L["high"] = "高"
+L["Icons Only"] = "圖示" --Also used in Bags
+L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "如果你有不想顯示的圖示或光環條, 你可以簡單的通過按住Shift + 右鍵點擊使它隱藏."
+L["Importance: |cff07D400High|r"] = "重要性: |cff07D400高|r"
+L["Importance: |cffD3CF00Medium|r"] = "重要性: |cffD3CF00中|r"
+L["Importance: |cffFF0000Low|r"] = "重要性: |cffFF0000低|r"
+L["Installation Complete"] = "安裝完畢"
+L["Layout Set"] = "版面配置設定"
+L["Layout"] = "介面佈局"
+L["Lock"] = "鎖定"
+L["Low Resolution"] = "低解析度"
+L["low"] = "低"
+L["Nudge"] = "微調"
+L["Physical DPS"] = "物理輸出"
+L["Please click the button below so you can setup variables and ReloadUI."] = "請按下方按鈕設定變數並重載介面."
+L["Please click the button below to setup your CVars."] = "請按下方按鈕設定參數."
+L["Please press the continue button to go onto the next step."] = "請按「繼續」按鈕,執行下一個步驟."
+L["Resolution Style Set"] = "解析度樣式設定"
+L["Resolution"] = "解析度"
+L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "選擇在 ElvUI 單位框架中要使用的光環系統. 選擇光環條和圖示來同時使用兩者, 選擇圖示來僅使用圖示"
+L["Setup Chat"] = "設定對話視窗"
+L["Setup CVars"] = "設定參數"
+L["Skip Process"] = "略過"
+L["Sticky Frames"] = "框架依附"
+L["Tank"] = "坦克"
+L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "對話視窗與WOW 原始對話視窗的操作方式相同, 你可以拖拉、移動分頁或重新命名分頁. 請按下方按鈕以設定對話視窗."
+L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "若要進入內建設定選單, 請輸入/ec, 或者按一下小地圖旁的「C」按鈕.若要略過安裝程序, 請按下方按鈕."
+L["Theme Set"] = "主題設定"
+L["Theme Setup"] = "主題安裝"
+L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "此安裝程序有助你瞭解ElvUI 部份功能, 並可協助你預先設定UI."
+L["This is completely optional."] = "此為選擇性功能."
+L["This part of the installation process sets up your chat windows names, positions and colors."] = "此安裝步驟將會設定對話視窗的名稱、位置和顏色."
+L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "此安裝步驟將會設定 WOW 預設選項, 建議你執行此步驟, 以確保功能均可正常運作."
+L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "這個解析度不需要你改動任何設定以適應你的螢幕."
+L["This resolution requires that you change some settings to get everything to fit on your screen."] = "這個解析度需要你改變一些設定才能適應你的螢幕."
+L["This will change the layout of your unitframes and actionbars."] = "這將會改變你的單位框架和動作條的佈局"
+L["Trade"] = "拾取/交易"
+L["Welcome to ElvUI version %s!"] = "歡迎使用 ElvUI %s 版!"
+L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "已完成安裝程序. 小提示: 若想開啟微型選單, 請在小地圖按滑鼠中鍵. 如果沒有中鍵按鈕, 請按住Shift鍵, 並在小地圖按滑鼠右鍵. 如需技術支援請至 https://github.com/ElvUI-Vanilla/ElvUI"
+L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "你可以在遊戲內的設定選項內更改ElvUI的字體、顏色等設定."
+L["You can now choose what layout you wish to use based on your combat role."] = "你現在可以根據你的戰鬥角色選擇合適的佈局."
+L["You may need to further alter these settings depending how low you resolution is."] = "根據你的解析度你可能需要改動這些設定."
+L["Your current resolution is %s, this is considered a %s resolution."] = "你當前的解析度是%s, 這被認為是個%s 解析度."
+
+--Misc
+L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% 以上 |cff%02x%02x%02x%s|r]"
+L["Bars"] = "條" --Also used in UnitFrames
+L["Calendar"] = "日曆"
+L["Can't Roll"] = "無法需求此裝備"
+L["Disband Group"] = "解散隊伍"
+L["Empty Slot"] = true;
+L["Enable"] = "啟用" --Doesn't fit a section since it's used a lot of places
+L["Experience"] = "經驗/聲望條"
+L["Farm Mode"] = true;
+L["Fishy Loot"] = "貪婪"
+L["Left Click:"] = "滑鼠左鍵:" --layout\layout.lua
+L["Mouse"] = "滑鼠"
+L["Raid Menu"] = "團隊選單"
+L["Remaining:"] = "剩餘:"
+L["Rested:"] = "休息:"
+L["Right Click:"] = "滑鼠右鍵:" --layout\layout.lua
+L["Show BG Texts"] = "顯示戰場資訊文字" --layout\layout.lua
+L["Toggle Chat Frame"] = "開關對話框架" --layout\layout.lua
+L["Toggle Configuration"] = "開啟/關閉設定" --layout\layout.lua
+L["XP:"] = "經驗:"
+L["You don't have permission to mark targets."] = "你沒有標記目標的權限."
+
+--Movers
+L["Arena Frames"] = "競技場框架" --Also used in UnitFrames
+L["Bag Mover (Grow Down)"] = "背包錨點 (向下增長)"
+L["Bag Mover (Grow Up)"] = "背包錨點 (向上增長)"
+L["Bag Mover"] = "背包錨點"
+L["Bags"] = "背包" --Also in DataTexts
+L["Bank Mover (Grow Down)"] = "銀行錨點 (向下增長)"
+L["Bank Mover (Grow Up)"] = "銀行錨點 (向上增長)"
+L["Bar "] = "快捷列 " --Also in ActionBars
+L["BNet Frame"] = "戰網提示資訊"
+L["Boss Frames"] = "首領框架" --Also used in UnitFrames
+L["Classbar"] = "職業特有條"
+L["Experience Bar"] = "經驗條"
+L["Focus Castbar"] = "焦點目標施法條"
+L["Focus Frame"] = "焦點目標框架" --Also used in UnitFrames
+L["FocusTarget Frame"] = "焦點目標的目標框架" --Also used in UnitFrames
+L["GM Ticket Frame"] = "GM 對話框"
+L["Left Chat"] = "左側對話框"
+L["Loot / Alert Frames"] = "拾取 / 提醒框架"
+L["Loot Frame"] = "拾取框架"
+L["MA Frames"] = "主助理框架"
+L["Micro Bar"] = "微型系統菜單" --Also in ActionBars
+L["Minimap"] = "小地圖"
+L["MirrorTimer"] = "鏡像計時器"
+L["MT Frames"] = "主坦克框架"
+L["Party Frames"] = "隊伍框架" --Also used in UnitFrames
+L["Pet Bar"] = "寵物快捷列" --Also in ActionBars
+L["Pet Castbar"] = "寵物施法條"
+L["Pet Frame"] = "寵物框架" --Also used in UnitFrames
+L["PetTarget Frame"] = "寵物目標框架" --Also used in UnitFrames
+L["Player Buffs"] = "玩家增益"
+L["Player Castbar"] = "玩家施法條"
+L["Player Debuffs"] = "玩家減益"
+L["Player Frame"] = "玩家框架" --Also used in UnitFrames
+L["Player Powerbar"] = "玩家能量條"
+L["PvP"] = true;
+L["Raid Frames"] = "團隊框架"
+L["Raid Pet Frames"] = "團隊寵物框架"
+L["Raid-40 Frames"] = "40人團隊框架"
+L["Reputation Bar"] = "聲望條"
+L["Right Chat"] = "右側對話框"
+L["Stance Bar"] = "姿態列" --Also in ActionBars
+L["Target Castbar"] = "目標施法條"
+L["Target Frame"] = "目標框架" --Also used in UnitFrames
+L["Target Powerbar"] = "目標能量條"
+L["TargetTarget Frame"] = "目標的目標框架" --Also used in UnitFrames
+L["TargetTargetTarget Frame"] = "目標的目標的目標框架"
+L["Time Manager Frame"] = true;
+L["Tooltip"] = "浮動提示"
+L["Vehicle Seat Frame"] = "載具座位框"
+L["Watch Frame"] = true;
+L["Weapons"] = true;
+L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
+
+--Plugin Installer
+L["ElvUI Plugin Installation"] = "ElvUI 插件安裝"
+L["In Progress"] = "進行中"
+L["List of installations in queue:"] = "即將安裝的列表"
+L["Pending"] = "等待中"
+L["Steps"] = "步驟"
+
+--Prints
+L[" |cff00ff00bound to |r"] = " |cff00ff00綁定到 |r"
+L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = " %s 個框架錨點衝突, 請移動buff或者debuff錨點讓他們彼此不依附. 暫時強制debuff依附到主框架."
+L["All keybindings cleared for |cff00ff00%s|r."] = "取消|cff00ff00%s|r 所有綁定的快捷鍵."
+L["Already Running.. Bailing Out!"] = "正在運行"
+L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "戰場資訊暫時隱藏, 你可以通過輸入/bgstats 或右鍵點擊小地圖旁「C」按鈕顯示."
+L["Battleground datatexts will now show again if you are inside a battleground."] = "當你處於戰場時戰場資訊將再次顯示."
+L["Binds Discarded"] = "取消綁定"
+L["Binds Saved"] = "儲存綁定"
+L["Confused.. Try Again!"] = "請再試一次!"
+L["No gray items to delete."] = "沒有可刪除的灰色物品."
+L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "法術'%s'已經被添加到單位框架的光環過濾器中."
+L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "此設定造成了錨點衝突, '%s' 框架會依附於自己, 請檢查你的錨點. 將 '%s' 依附於 '%s'."
+L["Vendored gray items for:"] = "已售出灰色物品,共得:"
+L["You don't have enough money to repair."] = "沒有足夠的資金來修復."
+L["You must be at a vendor."] = "你必須與商人對話."
+L["Your items have been repaired for: "] = "裝備已修復,共支出:"
+L["Your items have been repaired using guild bank funds for: "] = "已使用公會資金修復裝備,共支出:"
+L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000LUA錯誤已接收, 你可以在脫離戰鬥後檢查.|r"
+
+--Static Popups
+L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "你所做的改動只會影響到使用這個插件的本角色, 你需要重新加載介面才能使改動生效."
+L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
+L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
+L["Are you sure you want to apply this font to all ElvUI elements?"] = "你確定要將此字型應用到所有 ElvUI 元素嗎?"
+L["Are you sure you want to delete all your gray items?"] = "是否確定要刪除所有灰色物品?"
+L["Are you sure you want to disband the group?"] = "確定要解散隊伍?"
+L["Are you sure you want to reset all the settings on this profile?"] = "確定需要重置這個設定檔中的所有設定?"
+L["Are you sure you want to reset every mover back to it's default position?"] = "確定需要重置所有框架至預設位置?"
+L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "因為新的光環系統造成了大量的混亂因此我導入了一個新的步驟到安裝過程中. 這是可選的, 如果你喜歡你現在的設定請跳到最後一個步驟並點擊「完成」將不會再提示. 如果由於某些原因反復提示, 請重新開啟遊戲."
+L["Can't buy anymore slots!"] = "無法再購買更多銀行欄位!"
+L["Disable Warning"] = "停用警告"
+L["Discard"] = "取消"
+L["Do you enjoy the new ElvUI?"] = "你享受新版的 ElvUI嗎?"
+L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "你發誓在你沒停用其他插件或是模組前不會到技術支援發文詢問某些功能失效嗎?"
+L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI 以過期超過5個版本. 你可以在 https://github.com/ElvUI-Vanilla/ElvUI/ 下載到最新的版本."
+L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"] = "ElvUI 以過期. 你可以在 https://github.com/ElvUI-Vanilla/ElvUI/ 下載到最新的版本."
+L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI 需要進行資料庫優化, 請稍待."
+L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "移動滑鼠到快捷列或技能書按鈕上綁定快捷鍵.按ESC或滑鼠右鍵取消目前快捷鍵."
+L["I Swear"] = "我承諾"
+L["No, Revert Changes!"] = "不, 回復修改!"
+L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "喔 拜託,你不能同時使用 Elvui 和 Tukui, 請選擇一個停用."
+L["One or more of the changes you have made require a ReloadUI."] = "已變更一或多個設定, 需重載介面."
+L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "你所做的改動可能會影響到使用這個插件的所有角色, 你需要重新加載介面才能使改動生效."
+L["Save"] = "儲存"
+L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "你嘗試導入的設定檔已存在. 選擇一個新名稱或是允許覆蓋原有設定檔"
+L["Type /hellokitty to revert to old settings."] = "輸入 /hellokitty 來回復舊設定"
+L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "使用治療者佈局時建議你下載 Clique 插件, 以擁有點擊血條治療的功能"
+L["Yes, Keep Changes!"] = "是的, 保留變更!"
+L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "你選擇了細邊框主題選項. 你必須完成安裝程序來移除任何圖像錯誤"
+L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "你改變了介面縮放比例, 然而ElvUI的自動縮放選項是開啟的. 點擊接受以關閉ElvUI的自動縮放."
+L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "你導入的設定可能需要重新載入UI才能生效. 現在重新載入嗎?"
+L["You must purchase a bank slot first!"] = "你必需先購買一個銀行背包欄位!"
+
+--Tooltip
+L["Count"] = "計數"
+L["Item Level:"] = "物品等級:"
+L["Talent Specialization:"] = "天賦專精:"
+L["Targeted By:"] = "同目標的有:"
+
+--Tutorials
+L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "你可以通過按ESC鍵-> 按鍵設定, 滾動到ElvUI設定下方設定一個快速標記的快捷鍵."
+L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI 可以根據你所使用的天賦自動套用不同的裝備組. 你可以在設定檔中啟用此功能."
+L["For technical support visit us at https://github.com/ElvUI-Vanilla/ElvUI"] = "如需技術支援請至 https://github.com/ElvUI-Vanilla/ElvUI"
+L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "如果你不慎移除了對話框, 你可以重新安裝一次重置他們."
+L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "如果你使用 ElvUI 時遇到問題, 請嘗試停用除了ElvUI之外的插件. 請記住 ElvUI 是一套全套的 UI 替換插件, 你不能同時使用不同的插件來完成同一件事."
+L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "你可以使用 /focus 指令設定目前目標為焦點目標. 建議你可以寫一個聚集來做這件事"
+L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "你可以通過按住Shift拖動技能條中的按鍵. 你可以在Blizzard的快捷列設定中更改按鍵."
+L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "你可以通過右鍵點擊對話框標籤欄設定你需要在對話框內顯示的頻道."
+L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "你可以將滑鼠滑到對話框右上角並且點擊左鍵或右鍵來開啟對話複製或是對話指令視窗"
+L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "你可以透過按住Shift並將滑鼠滑過目標來看到目標的平均裝等, 結果將顯示在你的滑鼠提示框內."
+L["You can set your keybinds quickly by typing /kb."] = "你可以通過輸入/kb 快速綁定按鍵."
+L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "你可以通過滑鼠中鍵點擊小地圖或在快捷列設定內選擇打開微型系統欄."
+L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui .\nExample: /resetui Player Frame"] = "你可以使用 /resetui 命令來重置所有框架的位置. 你也可以通過命令 /resetui <框架名稱> 單獨重置某個框架.\n例如: /resetui Player Frame"
+
+--UnitFrames
+L["Dead"] = "死亡"
+L["Ghost"] = "鬼魂"
+L["Offline"] = "離線"
diff --git a/ElvUI/Media/Fonts/Action_Man.ttf b/ElvUI/Media/Fonts/Action_Man.ttf
new file mode 100644
index 0000000..4663bf9
Binary files /dev/null and b/ElvUI/Media/Fonts/Action_Man.ttf differ
diff --git a/ElvUI/Media/Fonts/Continuum_Medium.ttf b/ElvUI/Media/Fonts/Continuum_Medium.ttf
new file mode 100644
index 0000000..08c8df8
Binary files /dev/null and b/ElvUI/Media/Fonts/Continuum_Medium.ttf differ
diff --git a/ElvUI/Media/Fonts/DieDieDie.ttf b/ElvUI/Media/Fonts/DieDieDie.ttf
new file mode 100644
index 0000000..ba2936e
Binary files /dev/null and b/ElvUI/Media/Fonts/DieDieDie.ttf differ
diff --git a/ElvUI/Media/Fonts/Expressway.ttf b/ElvUI/Media/Fonts/Expressway.ttf
new file mode 100644
index 0000000..d295ee2
Binary files /dev/null and b/ElvUI/Media/Fonts/Expressway.ttf differ
diff --git a/ElvUI/Media/Fonts/Homespun.ttf b/ElvUI/Media/Fonts/Homespun.ttf
new file mode 100644
index 0000000..2f3eb9e
Binary files /dev/null and b/ElvUI/Media/Fonts/Homespun.ttf differ
diff --git a/ElvUI/Media/Fonts/Invisible.ttf b/ElvUI/Media/Fonts/Invisible.ttf
new file mode 100644
index 0000000..39748bc
Binary files /dev/null and b/ElvUI/Media/Fonts/Invisible.ttf differ
diff --git a/ElvUI/Media/Fonts/PT_Sans_Narrow.ttf b/ElvUI/Media/Fonts/PT_Sans_Narrow.ttf
new file mode 100644
index 0000000..fab582b
Binary files /dev/null and b/ElvUI/Media/Fonts/PT_Sans_Narrow.ttf differ
diff --git a/ElvUI/Media/Load_Media.xml b/ElvUI/Media/Load_Media.xml
new file mode 100644
index 0000000..1b200e5
--- /dev/null
+++ b/ElvUI/Media/Load_Media.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Media/SharedMedia.lua b/ElvUI/Media/SharedMedia.lua
new file mode 100644
index 0000000..422f10e
--- /dev/null
+++ b/ElvUI/Media/SharedMedia.lua
@@ -0,0 +1,26 @@
+local LSM = LibStub("LibSharedMedia-3.0")
+
+if LSM == nil then return end
+
+LSM:Register("statusbar", "ElvUI Gloss", "Interface\\AddOns\\ElvUI\\Media\\Textures\\normTex.tga")
+LSM:Register("statusbar", "ElvUI Norm", "Interface\\AddOns\\ElvUI\\Media\\Textures\\normTex2.tga")
+LSM:Register("statusbar", "Minimalist", "Interface\\AddOns\\ElvUI\\Media\\Textures\\Minimalist.tga")
+LSM:Register("statusbar", "ElvUI Blank", "Interface\\BUTTONS\\WHITE8X8")
+LSM:Register("background", "ElvUI Blank", "Interface\\BUTTONS\\WHITE8X8")
+LSM:Register("border", "ElvUI GlowBorder", "Interface\\AddOns\\ElvUI\\Media\\Textures\\glowTex.tga")
+LSM:Register("font", "Continuum Medium", "Interface\\AddOns\\ElvUI\\Media\\Fonts\\Continuum_Medium.ttf")
+LSM:Register("font", "Die Die Die!", "Interface\\AddOns\\ElvUI\\Media\\Fonts\\DieDieDie.ttf", LSM.LOCALE_BIT_ruRU + LSM.LOCALE_BIT_western)
+LSM:Register("font", "Action Man", "Interface\\AddOns\\ElvUI\\Media\\Fonts\\Action_Man.ttf")
+LSM:Register("font", "Expressway", "Interface\\AddOns\\ElvUI\\Media\\Fonts\\Expressway.ttf", LSM.LOCALE_BIT_ruRU + LSM.LOCALE_BIT_western)
+LSM:Register("font", "PT Sans Narrow", "Interface\\AddOns\\ElvUI\\Media\\Fonts\\PT_Sans_Narrow.ttf", LSM.LOCALE_BIT_ruRU + LSM.LOCALE_BIT_western)
+LSM:Register("font", "Homespun", "Interface\\AddOns\\ElvUI\\Media\\Fonts\\Homespun.ttf",LSM.LOCALE_BIT_ruRU + LSM.LOCALE_BIT_western)
+LSM:Register("sound", "ElvUI Aska", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\sndIncMsg.ogg")
+LSM:Register("sound", "Awww Crap", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\awwcrap.ogg")
+LSM:Register("sound", "BBQ Ass", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\bbqass.ogg")
+LSM:Register("sound", "Big Yankie Devil", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\yankiebangbang.ogg")
+LSM:Register("sound", "Dumb Shit", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\dumbshit.ogg")
+LSM:Register("sound", "Mama Weekends", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\mamaweekends.ogg")
+LSM:Register("sound", "Runaway Fast", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\runfast.ogg")
+LSM:Register("sound", "Stop Running", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\stoprunningslimball.ogg")
+LSM:Register("sound", "Warning", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\warning.ogg")
+LSM:Register("sound", "Whisper Alert", "Interface\\AddOns\\ElvUI\\Media\\Sounds\\whisper.ogg")
\ No newline at end of file
diff --git a/ElvUI/Media/Sounds/awwcrap.ogg b/ElvUI/Media/Sounds/awwcrap.ogg
new file mode 100644
index 0000000..91a9136
Binary files /dev/null and b/ElvUI/Media/Sounds/awwcrap.ogg differ
diff --git a/ElvUI/Media/Sounds/bbqass.ogg b/ElvUI/Media/Sounds/bbqass.ogg
new file mode 100644
index 0000000..ed28e17
Binary files /dev/null and b/ElvUI/Media/Sounds/bbqass.ogg differ
diff --git a/ElvUI/Media/Sounds/dumbshit.ogg b/ElvUI/Media/Sounds/dumbshit.ogg
new file mode 100644
index 0000000..5d1f2e7
Binary files /dev/null and b/ElvUI/Media/Sounds/dumbshit.ogg differ
diff --git a/ElvUI/Media/Sounds/harlemshake.ogg b/ElvUI/Media/Sounds/harlemshake.ogg
new file mode 100644
index 0000000..ebe4fd6
Binary files /dev/null and b/ElvUI/Media/Sounds/harlemshake.ogg differ
diff --git a/ElvUI/Media/Sounds/helloKitty.ogg b/ElvUI/Media/Sounds/helloKitty.ogg
new file mode 100644
index 0000000..9d3a2f8
Binary files /dev/null and b/ElvUI/Media/Sounds/helloKitty.ogg differ
diff --git a/ElvUI/Media/Sounds/mamaweekends.ogg b/ElvUI/Media/Sounds/mamaweekends.ogg
new file mode 100644
index 0000000..8c8995b
Binary files /dev/null and b/ElvUI/Media/Sounds/mamaweekends.ogg differ
diff --git a/ElvUI/Media/Sounds/runfast.ogg b/ElvUI/Media/Sounds/runfast.ogg
new file mode 100644
index 0000000..715f4c1
Binary files /dev/null and b/ElvUI/Media/Sounds/runfast.ogg differ
diff --git a/ElvUI/Media/Sounds/sndIncMsg.ogg b/ElvUI/Media/Sounds/sndIncMsg.ogg
new file mode 100644
index 0000000..f105002
Binary files /dev/null and b/ElvUI/Media/Sounds/sndIncMsg.ogg differ
diff --git a/ElvUI/Media/Sounds/stoprunningslimball.ogg b/ElvUI/Media/Sounds/stoprunningslimball.ogg
new file mode 100644
index 0000000..2d9d670
Binary files /dev/null and b/ElvUI/Media/Sounds/stoprunningslimball.ogg differ
diff --git a/ElvUI/Media/Sounds/warning.ogg b/ElvUI/Media/Sounds/warning.ogg
new file mode 100644
index 0000000..1d07d8b
Binary files /dev/null and b/ElvUI/Media/Sounds/warning.ogg differ
diff --git a/ElvUI/Media/Sounds/whisper.ogg b/ElvUI/Media/Sounds/whisper.ogg
new file mode 100644
index 0000000..2079476
Binary files /dev/null and b/ElvUI/Media/Sounds/whisper.ogg differ
diff --git a/ElvUI/Media/Sounds/yankiebangbang.ogg b/ElvUI/Media/Sounds/yankiebangbang.ogg
new file mode 100644
index 0000000..7392204
Binary files /dev/null and b/ElvUI/Media/Sounds/yankiebangbang.ogg differ
diff --git a/ElvUI/Media/Textures/Alliance-Logo.blp b/ElvUI/Media/Textures/Alliance-Logo.blp
new file mode 100644
index 0000000..e6218ff
Binary files /dev/null and b/ElvUI/Media/Textures/Alliance-Logo.blp differ
diff --git a/ElvUI/Media/Textures/Bathrobe_Chat_Logo.blp b/ElvUI/Media/Textures/Bathrobe_Chat_Logo.blp
new file mode 100644
index 0000000..aaf4bb9
Binary files /dev/null and b/ElvUI/Media/Textures/Bathrobe_Chat_Logo.blp differ
diff --git a/ElvUI/Media/Textures/ElvUI_Chat_Logo.blp b/ElvUI/Media/Textures/ElvUI_Chat_Logo.blp
new file mode 100644
index 0000000..5b94f30
Binary files /dev/null and b/ElvUI/Media/Textures/ElvUI_Chat_Logo.blp differ
diff --git a/ElvUI/Media/Textures/Horde-Logo.blp b/ElvUI/Media/Textures/Horde-Logo.blp
new file mode 100644
index 0000000..2c489da
Binary files /dev/null and b/ElvUI/Media/Textures/Horde-Logo.blp differ
diff --git a/ElvUI/Media/Textures/INV_Pet_RatCage.blp b/ElvUI/Media/Textures/INV_Pet_RatCage.blp
new file mode 100644
index 0000000..cd16708
Binary files /dev/null and b/ElvUI/Media/Textures/INV_Pet_RatCage.blp differ
diff --git a/ElvUI/Media/Textures/Icons-Classes.blp b/ElvUI/Media/Textures/Icons-Classes.blp
new file mode 100644
index 0000000..c379794
Binary files /dev/null and b/ElvUI/Media/Textures/Icons-Classes.blp differ
diff --git a/ElvUI/Media/Textures/Minimalist.tga b/ElvUI/Media/Textures/Minimalist.tga
new file mode 100644
index 0000000..030bc83
Binary files /dev/null and b/ElvUI/Media/Textures/Minimalist.tga differ
diff --git a/ElvUI/Media/Textures/Smileys/angry.blp b/ElvUI/Media/Textures/Smileys/angry.blp
new file mode 100644
index 0000000..3c07ef6
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/angry.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/broken_heart.blp b/ElvUI/Media/Textures/Smileys/broken_heart.blp
new file mode 100644
index 0000000..9b70c89
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/broken_heart.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/grin.blp b/ElvUI/Media/Textures/Smileys/grin.blp
new file mode 100644
index 0000000..ec1d943
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/grin.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/happy.blp b/ElvUI/Media/Textures/Smileys/happy.blp
new file mode 100644
index 0000000..7d0b2c2
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/happy.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/heart.blp b/ElvUI/Media/Textures/Smileys/heart.blp
new file mode 100644
index 0000000..031c081
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/heart.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/hmm.blp b/ElvUI/Media/Textures/Smileys/hmm.blp
new file mode 100644
index 0000000..02c4f64
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/hmm.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/middle_finger.blp b/ElvUI/Media/Textures/Smileys/middle_finger.blp
new file mode 100644
index 0000000..6e85a4e
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/middle_finger.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/sad.blp b/ElvUI/Media/Textures/Smileys/sad.blp
new file mode 100644
index 0000000..d41b00b
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/sad.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/surprise.blp b/ElvUI/Media/Textures/Smileys/surprise.blp
new file mode 100644
index 0000000..4e8f222
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/surprise.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/tongue.blp b/ElvUI/Media/Textures/Smileys/tongue.blp
new file mode 100644
index 0000000..5377bf7
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/tongue.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/weepy.blp b/ElvUI/Media/Textures/Smileys/weepy.blp
new file mode 100644
index 0000000..77a1dbc
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/weepy.blp differ
diff --git a/ElvUI/Media/Textures/Smileys/winky.blp b/ElvUI/Media/Textures/Smileys/winky.blp
new file mode 100644
index 0000000..e7ba977
Binary files /dev/null and b/ElvUI/Media/Textures/Smileys/winky.blp differ
diff --git a/ElvUI/Media/Textures/SquareButtonTextures.blp b/ElvUI/Media/Textures/SquareButtonTextures.blp
new file mode 100644
index 0000000..210c1a3
Binary files /dev/null and b/ElvUI/Media/Textures/SquareButtonTextures.blp differ
diff --git a/ElvUI/Media/Textures/UI-Searchbox-Icon.blp b/ElvUI/Media/Textures/UI-Searchbox-Icon.blp
new file mode 100644
index 0000000..751c71e
Binary files /dev/null and b/ElvUI/Media/Textures/UI-Searchbox-Icon.blp differ
diff --git a/ElvUI/Media/Textures/arrow.tga b/ElvUI/Media/Textures/arrow.tga
new file mode 100644
index 0000000..ea33603
Binary files /dev/null and b/ElvUI/Media/Textures/arrow.tga differ
diff --git a/ElvUI/Media/Textures/arrowdown.tga b/ElvUI/Media/Textures/arrowdown.tga
new file mode 100644
index 0000000..1bf565a
Binary files /dev/null and b/ElvUI/Media/Textures/arrowdown.tga differ
diff --git a/ElvUI/Media/Textures/arrowup.tga b/ElvUI/Media/Textures/arrowup.tga
new file mode 100644
index 0000000..109547c
Binary files /dev/null and b/ElvUI/Media/Textures/arrowup.tga differ
diff --git a/ElvUI/Media/Textures/bubbleTex.tga b/ElvUI/Media/Textures/bubbleTex.tga
new file mode 100644
index 0000000..88eb623
Binary files /dev/null and b/ElvUI/Media/Textures/bubbleTex.tga differ
diff --git a/ElvUI/Media/Textures/copy.tga b/ElvUI/Media/Textures/copy.tga
new file mode 100644
index 0000000..9a9c66a
Binary files /dev/null and b/ElvUI/Media/Textures/copy.tga differ
diff --git a/ElvUI/Media/Textures/cross.tga b/ElvUI/Media/Textures/cross.tga
new file mode 100644
index 0000000..3894f16
Binary files /dev/null and b/ElvUI/Media/Textures/cross.tga differ
diff --git a/ElvUI/Media/Textures/dps.tga b/ElvUI/Media/Textures/dps.tga
new file mode 100644
index 0000000..41ddf63
Binary files /dev/null and b/ElvUI/Media/Textures/dps.tga differ
diff --git a/ElvUI/Media/Textures/glowTex.tga b/ElvUI/Media/Textures/glowTex.tga
new file mode 100644
index 0000000..62905cc
Binary files /dev/null and b/ElvUI/Media/Textures/glowTex.tga differ
diff --git a/ElvUI/Media/Textures/healer.tga b/ElvUI/Media/Textures/healer.tga
new file mode 100644
index 0000000..0a46f0d
Binary files /dev/null and b/ElvUI/Media/Textures/healer.tga differ
diff --git a/ElvUI/Media/Textures/helloKittyChat1.tga b/ElvUI/Media/Textures/helloKittyChat1.tga
new file mode 100644
index 0000000..23b9a17
Binary files /dev/null and b/ElvUI/Media/Textures/helloKittyChat1.tga differ
diff --git a/ElvUI/Media/Textures/hello_kitty.tga b/ElvUI/Media/Textures/hello_kitty.tga
new file mode 100644
index 0000000..e9c6fe6
Binary files /dev/null and b/ElvUI/Media/Textures/hello_kitty.tga differ
diff --git a/ElvUI/Media/Textures/logo.tga b/ElvUI/Media/Textures/logo.tga
new file mode 100644
index 0000000..8d7efad
Binary files /dev/null and b/ElvUI/Media/Textures/logo.tga differ
diff --git a/ElvUI/Media/Textures/mail.tga b/ElvUI/Media/Textures/mail.tga
new file mode 100644
index 0000000..e154114
Binary files /dev/null and b/ElvUI/Media/Textures/mail.tga differ
diff --git a/ElvUI/Media/Textures/nameplateTargetIndicator.tga b/ElvUI/Media/Textures/nameplateTargetIndicator.tga
new file mode 100644
index 0000000..eaf3962
Binary files /dev/null and b/ElvUI/Media/Textures/nameplateTargetIndicator.tga differ
diff --git a/ElvUI/Media/Textures/nameplateTargetIndicatorLeft.tga b/ElvUI/Media/Textures/nameplateTargetIndicatorLeft.tga
new file mode 100644
index 0000000..f13c31f
Binary files /dev/null and b/ElvUI/Media/Textures/nameplateTargetIndicatorLeft.tga differ
diff --git a/ElvUI/Media/Textures/nameplateTargetIndicatorRight.tga b/ElvUI/Media/Textures/nameplateTargetIndicatorRight.tga
new file mode 100644
index 0000000..1958084
Binary files /dev/null and b/ElvUI/Media/Textures/nameplateTargetIndicatorRight.tga differ
diff --git a/ElvUI/Media/Textures/nameplates.BLP b/ElvUI/Media/Textures/nameplates.BLP
new file mode 100644
index 0000000..2079d3b
Binary files /dev/null and b/ElvUI/Media/Textures/nameplates.BLP differ
diff --git a/ElvUI/Media/Textures/normTex.tga b/ElvUI/Media/Textures/normTex.tga
new file mode 100644
index 0000000..996b269
Binary files /dev/null and b/ElvUI/Media/Textures/normTex.tga differ
diff --git a/ElvUI/Media/Textures/normTex2.tga b/ElvUI/Media/Textures/normTex2.tga
new file mode 100644
index 0000000..2d99837
Binary files /dev/null and b/ElvUI/Media/Textures/normTex2.tga differ
diff --git a/ElvUI/Media/Textures/pause.blp b/ElvUI/Media/Textures/pause.blp
new file mode 100644
index 0000000..7cd74fd
Binary files /dev/null and b/ElvUI/Media/Textures/pause.blp differ
diff --git a/ElvUI/Media/Textures/play.blp b/ElvUI/Media/Textures/play.blp
new file mode 100644
index 0000000..6ac0f93
Binary files /dev/null and b/ElvUI/Media/Textures/play.blp differ
diff --git a/ElvUI/Media/Textures/raidicons.blp b/ElvUI/Media/Textures/raidicons.blp
new file mode 100644
index 0000000..81c7f7c
Binary files /dev/null and b/ElvUI/Media/Textures/raidicons.blp differ
diff --git a/ElvUI/Media/Textures/reset.blp b/ElvUI/Media/Textures/reset.blp
new file mode 100644
index 0000000..827e05a
Binary files /dev/null and b/ElvUI/Media/Textures/reset.blp differ
diff --git a/ElvUI/Media/Textures/spark.tga b/ElvUI/Media/Textures/spark.tga
new file mode 100644
index 0000000..273ace5
Binary files /dev/null and b/ElvUI/Media/Textures/spark.tga differ
diff --git a/ElvUI/Media/Textures/tank.tga b/ElvUI/Media/Textures/tank.tga
new file mode 100644
index 0000000..3752091
Binary files /dev/null and b/ElvUI/Media/Textures/tank.tga differ
diff --git a/ElvUI/Media/Textures/tukui_logo.blp b/ElvUI/Media/Textures/tukui_logo.blp
new file mode 100644
index 0000000..9c418a7
Binary files /dev/null and b/ElvUI/Media/Textures/tukui_logo.blp differ
diff --git a/ElvUI/Media/Textures/vehicleexit.tga b/ElvUI/Media/Textures/vehicleexit.tga
new file mode 100644
index 0000000..caa6282
Binary files /dev/null and b/ElvUI/Media/Textures/vehicleexit.tga differ
diff --git a/ElvUI/Modules/ActionBars/ActionBars.lua b/ElvUI/Modules/ActionBars/ActionBars.lua
new file mode 100644
index 0000000..a574fe3
--- /dev/null
+++ b/ElvUI/Modules/ActionBars/ActionBars.lua
@@ -0,0 +1,500 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local AB = E:NewModule("ActionBars", "AceHook-3.0", "AceEvent-3.0");
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local gsub, split = string.gsub, string.split
+local ceil = math.ceil
+local mod = math.mod
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local UIFrameFadeIn = UIFrameFadeIn
+local UIFrameFadeOut = UIFrameFadeOut
+
+E.ActionBars = AB
+
+AB["handledBars"] = {}
+AB["handledButtons"] = {}
+AB["barDefaults"] = {
+ ["bar1"] = {
+ ["name"] = "Action",
+ ["position"] = "BOTTOM,ElvUIParent,BOTTOM,0,4",
+ },
+ ["bar2"] = {
+ ["name"] = "MultiBarBottomRight",
+ ["position"] = "BOTTOM,ElvUI_Bar1,TOP,0,2"
+ },
+ ["bar3"] = {
+ ["name"] = "MultiBarRight",
+ ["position"] = "LEFT,ElvUI_Bar1,RIGHT,4,0"
+ },
+ ["bar4"] = {
+ ["name"] = "MultiBarLeft",
+ ["position"] = "RIGHT,ElvUIParent,RIGHT,-4,0"
+ },
+ ["bar5"] = {
+ ["name"] = "MultiBarBottomLeft",
+ ["position"] = "RIGHT,ElvUI_Bar1,LEFT,-4,0"
+ }
+}
+
+function AB:PositionAndSizeBar(barName)
+ local buttonSpacing = E:Scale(self.db[barName].buttonspacing)
+ local backdropSpacing = E:Scale((self.db[barName].backdropSpacing or self.db[barName].buttonspacing))
+ local buttonsPerRow = self.db[barName].buttonsPerRow
+ local numButtons = self.db[barName].buttons
+ local size = E:Scale(self.db[barName].buttonsize)
+ local point = self.db[barName].point
+ local numColumns = ceil(numButtons / buttonsPerRow)
+ local widthMult = self.db[barName].widthMult
+ local heightMult = self.db[barName].heightMult
+ local bar = self["handledBars"][barName]
+
+ bar.db = self.db[barName]
+
+ if numButtons < buttonsPerRow then
+ buttonsPerRow = numButtons
+ end
+
+ if numColumns < 1 then
+ numColumns = 1
+ end
+
+ if self.db[barName].backdrop then
+ bar.backdrop:Show()
+ else
+ bar.backdrop:Hide()
+
+ widthMult = 1
+ heightMult = 1
+ end
+
+ local barWidth = (size * (buttonsPerRow * widthMult)) + ((buttonSpacing * (buttonsPerRow - 1)) * widthMult) + (buttonSpacing * (widthMult-1)) + ((self.db[barName].backdrop and (E.Border + backdropSpacing) or E.Spacing)*2)
+ local barHeight = (size * (numColumns * heightMult)) + ((buttonSpacing * (numColumns - 1)) * heightMult) + (buttonSpacing * (heightMult-1)) + ((self.db[barName].backdrop and (E.Border + backdropSpacing) or E.Spacing)*2)
+ bar:SetWidth(barWidth)
+ bar:SetHeight(barHeight)
+
+ bar.mouseover = self.db[barName].mouseover
+
+ local horizontalGrowth, verticalGrowth
+ if point == "TOPLEFT" or point == "TOPRIGHT" then
+ verticalGrowth = "DOWN"
+ else
+ verticalGrowth = "UP"
+ end
+
+ if point == "BOTTOMLEFT" or point == "TOPLEFT" then
+ horizontalGrowth = "RIGHT"
+ else
+ horizontalGrowth = "LEFT"
+ end
+
+ if self.db[barName].mouseover then
+ bar:SetAlpha(0)
+ else
+ bar:SetAlpha(self.db[barName].alpha)
+ end
+
+ local button, lastButton, lastColumnButton, x, y
+ local firstButtonSpacing = (self.db[barName].backdrop and (E.Border + backdropSpacing) or E.Spacing)
+ for i = 1, NUM_ACTIONBAR_BUTTONS do
+ button = bar.buttons[i]
+ lastButton = bar.buttons[i-1]
+ lastColumnButton = bar.buttons[i-buttonsPerRow]
+ button:ClearAllPoints()
+
+ button:SetParent(bar)
+
+ button:SetWidth(size)
+ button:SetHeight(size)
+ ActionButton_ShowGrid(button)
+
+ if i == 1 then
+ if point == "BOTTOMLEFT" then
+ x, y = firstButtonSpacing, firstButtonSpacing
+ elseif point == "TOPRIGHT" then
+ x, y = -firstButtonSpacing, -firstButtonSpacing
+ elseif point == "TOPLEFT" then
+ x, y = firstButtonSpacing, -firstButtonSpacing
+ else
+ x, y = -firstButtonSpacing, firstButtonSpacing
+ end
+ button:SetPoint(point, bar, point, x, y)
+ elseif mod((i - 1), buttonsPerRow) == 0 then
+ x = 0
+ y = -buttonSpacing
+ local buttonPoint, anchorPoint = "TOP", "BOTTOM"
+ if verticalGrowth == "UP" then
+ y = buttonSpacing
+ buttonPoint = "BOTTOM"
+ anchorPoint = "TOP"
+ end
+ button:SetPoint(buttonPoint, lastColumnButton, anchorPoint, x, y)
+ else
+ x = buttonSpacing
+ y = 0
+ local buttonPoint, anchorPoint = "LEFT", "RIGHT"
+ if horizontalGrowth == "LEFT" then
+ x = -buttonSpacing
+ buttonPoint = "RIGHT"
+ anchorPoint = "LEFT"
+ end
+ button:SetPoint(buttonPoint, lastButton, anchorPoint, x, y)
+ end
+
+ if i > numButtons then
+ button:SetScale(0.000001)
+ button:SetAlpha(0)
+ else
+ button:SetScale(1)
+ button:SetAlpha(1)
+ end
+
+ if self.db[barName].mouseover then
+ button:SetAlpha(0)
+ else
+ button:SetAlpha(self.db[barName].alpha)
+ end
+ end
+
+ if self.db[barName].enabled or not bar.initialized then
+ if not self.db[barName].mouseover then
+ bar:SetAlpha(self.db[barName].alpha)
+ end
+
+ bar:Show()
+
+ if not bar.initialized then
+ bar.initialized = true
+ self:PositionAndSizeBar(barName)
+ return
+ end
+ else
+ bar:Hide()
+ end
+
+ E:SetMoverSnapOffset("ElvAB_"..bar.id, bar.db.buttonspacing / 2)
+end
+
+function AB:CreateBar(id)
+ local bar = CreateFrame("Button", "ElvUI_Bar"..id, E.UIParent)
+ local point, anchor, attachTo, x, y = split(",", self["barDefaults"]["bar"..id].position)
+ bar:SetPoint(point, anchor, attachTo, x, y)
+ bar.id = id
+ E:CreateBackdrop(bar, "Default")
+ bar:SetFrameStrata("LOW")
+ local offset = E.Spacing
+ bar.backdrop:SetPoint("TOPLEFT", bar, "TOPLEFT", offset, -offset)
+ bar.backdrop:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", -offset, offset)
+ bar.buttons = {}
+ self:HookScript(bar, "OnEnter", "Bar_OnEnter")
+ self:HookScript(bar, "OnLeave", "Bar_OnLeave")
+
+ if id == 1 then
+ bar.actionButtons = {}
+ bar.bonusButtons = {}
+
+ local button
+ for i = 1, NUM_ACTIONBAR_BUTTONS do
+ button = _G["ActionButton"..i]
+ button:SetParent(bar)
+ bar.actionButtons[i] = button
+ self:HookScript(button, "OnEnter", "Button_OnEnter")
+ self:HookScript(button, "OnLeave", "Button_OnLeave")
+
+ button = _G["BonusActionButton"..i]
+ button:SetParent(bar)
+ bar.bonusButtons[i] = button
+ self:HookScript(button, "OnEnter", "Button_OnEnter")
+ self:HookScript(button, "OnLeave", "Button_OnLeave")
+ end
+
+ bar.buttons = bar.actionButtons
+
+ bar:RegisterEvent("UPDATE_BONUS_ACTIONBAR")
+ bar:SetScript("OnEvent", function()
+ if GetBonusBarOffset() > 0 then
+ bar.lastBonusBar = GetBonusBarOffset()
+
+ for i = 1, NUM_ACTIONBAR_BUTTONS do
+ bar.buttons[i]:SetParent(E.HiddenFrame)
+ end
+
+ bar.buttons = bar.bonusButtons
+ else
+ for i = 1, NUM_ACTIONBAR_BUTTONS do
+ bar.buttons[i]:SetParent(E.HiddenFrame)
+ end
+
+ bar.buttons = bar.actionButtons
+ end
+
+ AB:PositionAndSizeBar("bar1")
+ end)
+ else
+ for i = 1, NUM_ACTIONBAR_BUTTONS do
+ local button = _G[self["barDefaults"]["bar"..id].name.."Button"..i]
+ bar.buttons[i] = button
+
+ self:HookScript(button, "OnEnter", "Button_OnEnter")
+ self:HookScript(button, "OnLeave", "Button_OnLeave")
+ end
+ end
+
+ self["handledBars"]["bar"..id] = bar
+ self:PositionAndSizeBar("bar"..id)
+ E:CreateMover(bar, "ElvAB_"..id, L["Bar "]..id, nil, nil, nil,"ALL,ACTIONBARS")
+
+ return bar
+end
+
+function AB:UpdateButtonSettings()
+ for button, _ in pairs(self["handledButtons"]) do
+ if button then
+ self:StyleButton(button, button.noBackdrop)
+ else
+ self["handledButtons"][button] = nil
+ end
+ end
+
+ for i = 1, 5 do
+ self:PositionAndSizeBar("bar"..i)
+ end
+
+ --self:PositionAndSizeBarPet()
+ --self:PositionAndSizeBarShapeShift()
+end
+
+function AB:StyleButton(button, noBackdrop)
+ local name = button:GetName()
+ local icon = _G[name.."Icon"]
+ local count = _G[name.."Count"]
+ local flash = _G[name.."Flash"]
+ local hotkey = _G[name.."HotKey"]
+ local border = _G[name.."Border"]
+ local macroName = _G[name.."Name"]
+ local normal = _G[name.."NormalTexture"]
+ local normal2 = button:GetNormalTexture()
+ local buttonCooldown = _G[name.."Cooldown"]
+ local color = self.db.fontColor
+
+ if flash then flash:SetTexture(nil) end
+ if normal then normal:SetTexture(nil) normal:Hide() normal:SetAlpha(0) end
+ if normal2 then normal2:SetTexture(nil) normal2:Hide() normal2:SetAlpha(0) end
+ if border then E:Kill(border) end
+
+ if not button.noBackdrop then
+ button.noBackdrop = noBackdrop
+ end
+
+ if count then
+ count:ClearAllPoints()
+ count:SetPoint("BOTTOMRIGHT", 0, 2)
+ E:FontTemplate(count, LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+ count:SetTextColor(color.r, color.g, color.b)
+ end
+
+ if macroName then
+ if self.db.macrotext then
+ macroName:Show()
+ E:FontTemplate(macroName, LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+ macroName:ClearAllPoints()
+ E:Point(macroName, "BOTTOM", 2, 2)
+ macroName:SetJustifyH("CENTER")
+ else
+ macroName:Hide()
+ end
+ end
+
+ if not button.noBackdrop and not button.backdrop then
+ E:CreateBackdrop(button, "Default", true)
+ button.backdrop:SetAllPoints()
+ end
+
+ if icon then
+ icon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(icon)
+ end
+
+ if self.db.hotkeytext then
+ E:FontTemplate(hotkey, LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+ hotkey:SetTextColor(color.r, color.g, color.b)
+ end
+
+ self:FixKeybindText(button)
+ E:StyleButton(button)
+
+ if(not self.handledButtons[button]) then
+ E:RegisterCooldown(buttonCooldown)
+
+ self.handledButtons[button] = true
+ end
+end
+
+function AB:Bar_OnEnter()
+ if this.mouseover then
+ UIFrameFadeIn(this, 0.2, this:GetAlpha(), this.db.alpha)
+ end
+end
+
+function AB:Bar_OnLeave()
+ if this.mouseover then
+ UIFrameFadeOut(this, 0.2, this:GetAlpha(), 0)
+ end
+end
+
+function AB:Button_OnEnter()
+ local bar = (this:GetParent() == BonusActionBarFrame or this:GetParent() == MainMenuBarArtFrame) and ElvUI_Bar1 or this:GetParent()
+ if bar.mouseover then
+ UIFrameFadeIn(bar, 0.2, bar:GetAlpha(), bar.db.alpha)
+ end
+end
+
+function AB:Button_OnLeave()
+ local bar = (this:GetParent() == BonusActionBarFrame or this:GetParent() == MainMenuBarArtFrame) and ElvUI_Bar1 or this:GetParent()
+ if bar.mouseover then
+ UIFrameFadeOut(bar, 0.2, bar:GetAlpha(), 0)
+ end
+end
+
+function AB:DisableBlizzard()
+ MainMenuBar:EnableMouse(false)
+ PetActionBarFrame:EnableMouse(false)
+ ShapeshiftBarFrame:EnableMouse(false)
+
+ local elements = {
+ MainMenuBar,
+ MainMenuBarArtFrame,
+ MainMenuExpBar,
+ BonusActionBarFrame,
+ PetActionBarFrame,
+ ReputationWatchBar,
+ ShapeshiftBarFrame,
+ ShapeshiftBarLeft,
+ ShapeshiftBarMiddle,
+ ShapeshiftBarRight,
+ }
+ for _, element in pairs(elements) do
+ if element:GetObjectType() == "Frame" then
+ element:UnregisterAllEvents()
+
+ if element == MainMenuBarArtFrame then
+ element:RegisterEvent("CURRENCY_DISPLAY_UPDATE")
+ end
+ end
+
+ if element ~= MainMenuBar then
+ element:Hide()
+ end
+ element:SetAlpha(0)
+ end
+ elements = nil
+
+ local uiManagedFrames = {
+ "MultiBarLeft",
+ "MultiBarRight",
+ "MultiBarBottomLeft",
+ "MultiBarBottomRight",
+ "ShapeshiftBarFrame",
+ "PETACTIONBAR_YPOS",
+ }
+ for _, frame in pairs(uiManagedFrames) do
+ UIPARENT_MANAGED_FRAME_POSITIONS[frame] = nil
+ end
+ uiManagedFrames = nil
+end
+
+function AB:FixKeybindText(button)
+ local hotkey = _G[button:GetName().."HotKey"]
+ local text = hotkey:GetText()
+
+ if text then
+ text = gsub(text, "SHIFT%-", L["KEY_SHIFT"])
+ text = gsub(text, "ALT%-", L["KEY_ALT"])
+ text = gsub(text, "CTRL%-", L["KEY_CTRL"])
+ text = gsub(text, "BUTTON", L["KEY_MOUSEBUTTON"])
+ text = gsub(text, "MOUSEWHEELUP", L["KEY_MOUSEWHEELUP"])
+ text = gsub(text, "MOUSEWHEELDOWN", L["KEY_MOUSEWHEELDOWN"])
+ text = gsub(text, "NUMPAD", L["KEY_NUMPAD"])
+ text = gsub(text, "PAGEUP", L["KEY_PAGEUP"])
+ text = gsub(text, "PAGEDOWN", L["KEY_PAGEDOWN"])
+ text = gsub(text, "SPACE", L["KEY_SPACE"])
+ text = gsub(text, "INSERT", L["KEY_INSERT"])
+ text = gsub(text, "HOME", L["KEY_HOME"])
+ text = gsub(text, "DELETE", L["KEY_DELETE"])
+ text = gsub(text, "NMULTIPLY", "*")
+ text = gsub(text, "NMINUS", "N-")
+ text = gsub(text, "NPLUS", "N+")
+
+ if hotkey:GetText() == _G["RANGE_INDICATOR"] then
+ hotkey:SetText("")
+ else
+ hotkey:SetText(text)
+ end
+ end
+
+ if self.db.hotkeytext == true then
+ hotkey:Show()
+ else
+ hotkey:Hide()
+ end
+
+ hotkey:ClearAllPoints()
+ hotkey:SetPoint("TOPRIGHT", 0, -3)
+end
+
+function AB:ActionButton_Update()
+ self:StyleButton(this)
+end
+
+function AB:ActionButton_GetPagedID(button)
+ if button.isBonus and CURRENT_ACTIONBAR_PAGE == 1 then
+ local offset = GetBonusBarOffset()
+ if offset == 0 and ElvUI_Bar1 and ElvUI_Bar1.lastBonusBar then
+ offset = ElvUI_Bar1.lastBonusBar
+ end
+ return button:GetID() + ((NUM_ACTIONBAR_PAGES + offset - 1) * NUM_ACTIONBAR_BUTTONS)
+ end
+
+ local parentName = button:GetParent():GetName()
+ if parentName == "ElvUI_Bar5" then
+ return button:GetID() + ((BOTTOMLEFT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS)
+ elseif parentName == "ElvUI_Bar2" then
+ return button:GetID() + ((BOTTOMRIGHT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS)
+ elseif parentName == "ElvUI_Bar4" then
+ return button:GetID() + ((LEFT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS)
+ elseif parentName == "ElvUI_Bar3" then
+ return button:GetID() + ((RIGHT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS)
+ else
+ return button:GetID() + ((CURRENT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS)
+ end
+end
+
+function AB:Initialize()
+ self.db = E.db.actionbar
+
+ if E.private.actionbar.enable ~= true then return end
+
+ self:DisableBlizzard()
+
+ self:SetupMicroBar()
+
+ for i = 1, 5 do
+ self:CreateBar(i)
+ end
+
+ self:UpdateButtonSettings()
+ --self:LoadKeyBinder()
+
+ self:SecureHook("ActionButton_Update")
+ self:RawHook("ActionButton_GetPagedID")
+ -- self:SecureHook("PetActionBar_Update", "UpdatePet")
+end
+
+local function InitializeCallback()
+ AB:Initialize()
+end
+
+E:RegisterModule(AB:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/ActionBars/ButtonColoring.lua b/ElvUI/Modules/ActionBars/ButtonColoring.lua
new file mode 100644
index 0000000..6311d71
--- /dev/null
+++ b/ElvUI/Modules/ActionBars/ButtonColoring.lua
@@ -0,0 +1,187 @@
+--[[
+ tullaRange
+ Adds out of range coloring to action buttons
+ Derived from RedRange with negligable improvements to CPU usage
+--]]
+
+local E, L, V, P, G = unpack(ElvUI)
+
+local _G = _G
+local UPDATE_DELAY = 0.1
+
+local ActionHasRange = ActionHasRange
+local IsActionInRange = IsActionInRange
+local IsUsableAction = IsUsableAction
+local HasAction = HasAction
+
+local tullaRange = CreateFrame("Frame", "tullaRange", UIParent)
+
+function tullaRange:Load()
+ self:SetScript("OnUpdate", self.OnUpdate)
+ self:SetScript("OnHide", self.OnHide)
+ self:SetScript("OnEvent", self.OnEvent)
+ self.elapsed = 0
+
+ self:RegisterEvent("PLAYER_LOGIN")
+end
+
+function tullaRange:OnEvent()
+ local action = this[event]
+ if action then
+ action(this, event)
+ end
+end
+
+function tullaRange:OnUpdate()
+ if this.elapsed < UPDATE_DELAY then
+ this.elapsed = this.elapsed + arg1
+ else
+ this:Update()
+ end
+end
+
+function tullaRange:OnHide()
+ this.elapsed = 0
+end
+
+function tullaRange:PLAYER_LOGIN()
+ if not TULLARANGE_COLORS then
+ self:LoadDefaults()
+ end
+ self.colors = TULLARANGE_COLORS
+
+ self.buttonsToUpdate = {}
+
+ hooksecurefunc("ActionButton_OnUpdate", self.RegisterButton)
+ hooksecurefunc("ActionButton_UpdateUsable", self.OnUpdateButtonUsable)
+ hooksecurefunc("ActionButton_Update", self.OnButtonUpdate)
+end
+
+function tullaRange:Update()
+ self:UpdateButtons(self.elapsed)
+ self.elapsed = 0
+end
+
+function tullaRange:ForceColorUpdate()
+ for button in pairs(self.buttonsToUpdate) do
+ tullaRange.OnUpdateButtonUsable(button)
+ end
+end
+
+function tullaRange:UpdateShown()
+ if next(self.buttonsToUpdate) then
+ self:Show()
+ else
+ self:Hide()
+ end
+end
+
+function tullaRange:UpdateButtons(elapsed)
+ if not next(self.buttonsToUpdate) then
+ self:Hide()
+ return
+ end
+
+ for button in pairs(self.buttonsToUpdate) do
+ self:UpdateButton(button, elapsed)
+ end
+end
+
+function tullaRange:UpdateButton(button, elapsed)
+ tullaRange:UpdateButtonUsable(button)
+end
+
+function tullaRange:UpdateButtonStatus()
+ local action = ActionButton_GetPagedID(this)
+ if not(this:IsVisible() and action and HasAction(action) and ActionHasRange(action)) then
+ self.buttonsToUpdate[this] = nil
+ else
+ self.buttonsToUpdate[this] = true
+ end
+ self:UpdateShown()
+end
+
+function tullaRange.RegisterButton()
+ this:SetScript("OnShow", tullaRange.OnButtonShow)
+ this:SetScript("OnHide", tullaRange.OnButtonHide)
+ this:SetScript("OnUpdate", nil)
+
+ tullaRange:UpdateButtonStatus(this)
+end
+
+function tullaRange.OnButtonShow()
+ tullaRange:UpdateButtonStatus(this)
+end
+
+function tullaRange.OnButtonHide()
+ tullaRange:UpdateButtonStatus(this)
+end
+
+function tullaRange:OnUpdateButtonUsable()
+ this.tullaRangeColor = nil
+ tullaRange:UpdateButtonUsable(this)
+end
+
+function tullaRange.OnButtonUpdate()
+ tullaRange:UpdateButtonStatus(this)
+end
+
+function tullaRange:UpdateButtonUsable(button)
+ local action = ActionButton_GetPagedID(button)
+ local isUsable, notEnoughMana = IsUsableAction(action)
+
+ if isUsable then
+ if IsActionInRange(action) == 0 then
+ tullaRange.SetButtonColor(button, "OOR")
+ else
+ tullaRange.SetButtonColor(button, "NORMAL")
+ end
+ elseif notEnoughMana then
+ tullaRange.SetButtonColor(button, "OOM")
+ else
+ tullaRange.SetButtonColor(button, "UNUSABLE")
+ end
+end
+
+function tullaRange.SetButtonColor(button, colorType)
+ if button.tullaRangeColor ~= colorType then
+ button.tullaRangeColor = colorType
+
+ local r, g, b = tullaRange:GetColor(colorType)
+
+ local icon = _G[button:GetName() .. "Icon"]
+ icon:SetVertexColor(r, g, b)
+ end
+end
+
+function tullaRange:LoadDefaults()
+ TULLARANGE_COLORS = {
+ ["OOR"] = E:GetColorTable(E.db.actionbar.noRangeColor),
+ ["OOM"] = E:GetColorTable(E.db.actionbar.noPowerColor),
+ ["NORMAL"] = E:GetColorTable(E.db.actionbar.usableColor),
+ ["UNUSABLE"] = E:GetColorTable(E.db.actionbar.notUsableColor)
+ };
+end
+
+function tullaRange:Reset()
+ self:LoadDefaults()
+ self.colors = TULLARANGE_COLORS
+
+ self:ForceColorUpdate()
+end
+
+function tullaRange:SetColor(index, r, g, b)
+ local color = self.colors[index]
+ color[1] = r
+ color[2] = g
+ color[3] = b
+
+ self:ForceColorUpdate()
+end
+
+function tullaRange:GetColor(index)
+ local color = self.colors[index]
+ return color[1], color[2], color[3]
+end
+
+tullaRange:Load()
\ No newline at end of file
diff --git a/ElvUI/Modules/ActionBars/Load_ActionBars.xml b/ElvUI/Modules/ActionBars/Load_ActionBars.xml
new file mode 100644
index 0000000..e0aafda
--- /dev/null
+++ b/ElvUI/Modules/ActionBars/Load_ActionBars.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/ActionBars/Microbar.lua b/ElvUI/Modules/ActionBars/Microbar.lua
new file mode 100644
index 0000000..d8a9737
--- /dev/null
+++ b/ElvUI/Modules/ActionBars/Microbar.lua
@@ -0,0 +1,126 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local AB = E:GetModule("ActionBars");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local getn = table.getn
+local mod = math.mod
+--WoW API / Variables
+local CreateFrame = CreateFrame
+
+local microBar = CreateFrame("Frame", "microBar", E.UIParent)
+microBar:SetFrameStrata("BACKGROUND")
+
+local MICRO_BUTTONS = {
+ "CharacterMicroButton",
+ "SpellbookMicroButton",
+ "TalentMicroButton",
+ "QuestLogMicroButton",
+ "SocialsMicroButton",
+ "WorldMapMicroButton",
+ "MainMenuMicroButton",
+ "HelpMicroButton"
+}
+
+local function Button_OnEnter()
+ if AB.db.microbar.mouseover then
+ UIFrameFadeIn(microBar, .2, microBar:GetAlpha(), AB.db.microbar.alpha)
+ end
+end
+
+local function Button_OnLeave()
+ if AB.db.microbar.mouseover then
+ UIFrameFadeOut(microBar, .2, microBar:GetAlpha(), 0)
+ end
+end
+
+function AB:HandleMicroButton(button)
+ local pushed = button:GetPushedTexture()
+ local normal = button:GetNormalTexture()
+ local disabled = button:GetDisabledTexture()
+
+ button:SetParent(microBar)
+ button:Show()
+ button:SetAlpha(self.db.microbar.alpha)
+
+ E:Kill(button:GetHighlightTexture())
+ HookScript(button, "OnEnter", Button_OnEnter)
+ HookScript(button, "OnLeave", Button_OnLeave)
+
+ local f = CreateFrame("Frame", nil, button)
+ f:SetFrameLevel(1)
+ f:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 2, 0)
+ f:SetPoint("TOPRIGHT", button, "TOPRIGHT", -2, -28)
+ E:SetTemplate(f, "Default", true)
+ button.backdrop = f
+
+ pushed:SetTexCoord(0.17, 0.87, 0.5, 0.908)
+ E:SetInside(pushed, f)
+
+ normal:SetTexCoord(0.17, 0.87, 0.5, 0.908)
+ E:SetInside(normal, f)
+
+ if disabled then
+ disabled:SetTexCoord(0.17, 0.87, 0.5, 0.908)
+ E:SetInside(disabled, f)
+ end
+end
+
+function AB:UpdateMicroPositionDimensions()
+ if not microBar then return end
+
+ local numRows = 1
+ local button, prevButton, lastColumnButton
+ for i = 1, getn(MICRO_BUTTONS) do
+ button = _G[MICRO_BUTTONS[i]]
+ prevButton = _G[MICRO_BUTTONS[i-1]] or microBar
+ lastColumnButton = _G[MICRO_BUTTONS[i-self.db.microbar.buttonsPerRow]]
+
+ button:ClearAllPoints()
+
+ if prevButton == microBar then
+ button:SetPoint("TOPLEFT", prevButton, "TOPLEFT", -2 + E.Border, 28 - E.Border)
+ elseif mod((i - 1), self.db.microbar.buttonsPerRow) == 0 then
+ button:SetPoint("TOP", lastColumnButton, "BOTTOM", 0, 28 - self.db.microbar.yOffset)
+ numRows = numRows + 1
+ else
+ button:SetPoint("LEFT", prevButton, "RIGHT", - 4 + self.db.microbar.xOffset, 0)
+ end
+ end
+
+ if self.db.microbar.mouseover then
+ microBar:SetAlpha(0)
+ else
+ microBar:SetAlpha(self.db.microbar.alpha)
+ end
+
+ microBar:SetWidth(((CharacterMicroButton:GetWidth() - 4) * self.db.microbar.buttonsPerRow) + (self.db.microbar.xOffset * (self.db.microbar.buttonsPerRow - 1)) + E.Border * 2)
+ microBar:SetHeight(((CharacterMicroButton:GetHeight() - 28) * numRows) + (self.db.microbar.yOffset * (numRows - 1)) + E.Border * 2)
+
+ if self.db.microbar.enabled then
+ microBar:Show()
+ if microBar.mover then
+ E:EnableMover(microBar.mover:GetName())
+ end
+ else
+ microBar:Hide()
+ if microBar.mover then
+ E:DisableMover(microBar.mover:GetName())
+ end
+ end
+end
+
+function AB:SetupMicroBar()
+ microBar:SetPoint("TOPLEFT", 4, -48)
+
+ for i = 1, getn(MICRO_BUTTONS) do
+ self:HandleMicroButton(_G[MICRO_BUTTONS[i]])
+ end
+
+ E:SetInside(MicroButtonPortrait, CharacterMicroButton.backdrop)
+
+ self:UpdateMicroPositionDimensions()
+
+ E:CreateMover(microBar, "MicrobarMover", L["Micro Bar"], nil, nil, nil, "ALL,ACTIONBARS")
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Auras/Auras.lua b/ElvUI/Modules/Auras/Auras.lua
new file mode 100644
index 0000000..2bef35c
--- /dev/null
+++ b/ElvUI/Modules/Auras/Auras.lua
@@ -0,0 +1,502 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local A = E:NewModule("Auras", "AceEvent-3.0");
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local GetTime = GetTime
+local _G = _G
+local unpack, select, pairs, ipairs = unpack, select, pairs, ipairs
+local floor, min, max, huge = math.floor, math.min, math.max, math.huge
+local format = string.format
+local wipe, tinsert, tsort, tremove = table.wipe, table.insert, table.sort, table.remove
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local UnitAura = UnitAura
+local CancelItemTempEnchantment = CancelItemTempEnchantment
+local CancelUnitBuff = CancelUnitBuff
+local GetInventoryItemQuality = GetInventoryItemQuality
+local GetItemQualityColor = GetItemQualityColor
+local GetWeaponEnchantInfo = GetWeaponEnchantInfo
+local GetInventoryItemTexture = GetInventoryItemTexture
+
+local DIRECTION_TO_POINT = {
+ DOWN_RIGHT = "TOPLEFT",
+ DOWN_LEFT = "TOPRIGHT",
+ UP_RIGHT = "BOTTOMLEFT",
+ UP_LEFT = "BOTTOMRIGHT",
+ RIGHT_DOWN = "TOPLEFT",
+ RIGHT_UP = "BOTTOMLEFT",
+ LEFT_DOWN = "TOPRIGHT",
+ LEFT_UP = "BOTTOMRIGHT"
+}
+
+local DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER = {
+ DOWN_RIGHT = 1,
+ DOWN_LEFT = -1,
+ UP_RIGHT = 1,
+ UP_LEFT = -1,
+ RIGHT_DOWN = 1,
+ RIGHT_UP = 1,
+ LEFT_DOWN = -1,
+ LEFT_UP = -1
+}
+
+local DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER = {
+ DOWN_RIGHT = -1,
+ DOWN_LEFT = -1,
+ UP_RIGHT = 1,
+ UP_LEFT = 1,
+ RIGHT_DOWN = -1,
+ RIGHT_UP = 1,
+ LEFT_DOWN = -1,
+ LEFT_UP = 1
+}
+
+local IS_HORIZONTAL_GROWTH = {
+ RIGHT_DOWN = true,
+ RIGHT_UP = true,
+ LEFT_DOWN = true,
+ LEFT_UP = true
+}
+
+function A:UpdateTime(elapsed)
+ if self.offset then
+ local expiration = select(self.offset, GetWeaponEnchantInfo())
+ if expiration then
+ self.timeLeft = expiration / 1e3
+ else
+ self.timeLeft = 0
+ end
+ else
+ self.timeLeft = GetPlayerBuffTimeLeft(self.index)
+ end
+
+ if self.nextUpdate > 0 then
+ self.nextUpdate = not self.offset and self.nextUpdate - elapsed or 1
+ return
+ end
+
+ local timerValue, formatID
+ timerValue, formatID, self.nextUpdate = E:GetTimeInfo(self.timeLeft, A.db.fadeThreshold)
+ self.time:SetText(format("%s%s|r", E.TimeColors[formatID], format(E.TimeFormats[formatID][2], timerValue)))
+
+ if self.timeLeft > E.db.auras.fadeThreshold then
+ -- E:StopFlash(self)
+ else
+ -- E:Flash(self, 1)
+ end
+end
+
+local function UpdateTooltip()
+ if this.offset then
+ GameTooltip:SetInventoryItem("player", this.offset == 2 and 16 or 17)
+ else
+ GameTooltip:SetPlayerBuff(this.index)
+ end
+end
+
+local function OnEnter()
+ if not this:IsVisible() then return end
+
+ GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT", -5, -5)
+ this:UpdateTooltip()
+end
+
+local function OnLeave()
+ GameTooltip:Hide()
+end
+
+local function OnClick()
+ if this.index and this.index > 0 then
+ CancelPlayerBuff(this.index)
+ end
+end
+
+function A:CreateIcon(button)
+ local font = LSM:Fetch("font", self.db.font)
+ button:RegisterForClicks("RightButtonUp")
+
+ button.texture = button:CreateTexture(nil, "BORDER")
+ E:SetInside(button.texture)
+ button.texture:SetTexCoord(unpack(E.TexCoords))
+
+ button.count = button:CreateFontString(nil, "ARTWORK")
+ button.count:SetPoint("BOTTOMRIGHT", -1 + self.db.countXOffset, 1 + self.db.countYOffset)
+ E:FontTemplate(button.count, font, self.db.fontSize, self.db.fontOutline)
+
+ button.time = button:CreateFontString(nil, "ARTWORK")
+ button.time:SetPoint("TOP", button, "BOTTOM", 1 + self.db.timeXOffset, 0 + self.db.timeYOffset)
+ E:FontTemplate(button.time, font, self.db.fontSize, self.db.fontOutline)
+
+ button.highlight = button:CreateTexture(nil, "HIGHLIGHT")
+ button.highlight:SetTexture(1, 1, 1, 0.45)
+ E:SetInside(button.highlight)
+
+ button.UpdateTooltip = UpdateTooltip
+ button:SetScript("OnEnter", OnEnter)
+ button:SetScript("OnLeave", OnLeave)
+ button:SetScript("OnClick", OnClick)
+
+ E:SetTemplate(button, "Default")
+end
+
+local enchantableSlots = {
+ [1] = 16,
+ [2] = 17
+}
+
+local buttons = {}
+function A:ConfigureAuras(header, auraTable, weaponPosition)
+ local headerName = header:GetName()
+
+ local db = self.db.debuffs
+ if header.filter == "HELPFUL" then
+ db = self.db.buffs
+ end
+
+ local size = db.size
+ local point = DIRECTION_TO_POINT[db.growthDirection]
+ local xOffset = 0
+ local yOffset = 0
+ local wrapXOffset = 0
+ local wrapYOffset = 0
+ local wrapAfter = db.wrapAfter
+ local maxWraps = db.maxWraps
+ local minWidth = 0
+ local minHeight = 0
+
+ if IS_HORIZONTAL_GROWTH[db.growthDirection] then
+ minWidth = ((wrapAfter == 1 and 0 or db.horizontalSpacing) + size) * wrapAfter
+ minHeight = (db.verticalSpacing + size) * maxWraps
+ xOffset = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + size)
+ yOffset = 0
+ wrapXOffset = 0
+ wrapYOffset = DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + size)
+ else
+ minWidth = (db.horizontalSpacing + size) * maxWraps
+ minHeight = ((wrapAfter == 1 and 0 or db.verticalSpacing) + size) * wrapAfter
+ xOffset = 0
+ yOffset = DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + size)
+ wrapXOffset = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + size)
+ wrapYOffset = 0
+ end
+
+ wipe(buttons)
+ local button
+ local numWeapon = 0
+ if weaponPosition then
+ local hasMainHandEnchant, mainHandExpiration, _, hasOffHandEnchant, offHandExpiration = GetWeaponEnchantInfo()
+ for weapon = 2, 1, -1 do
+ button = _G["ElvUIPlayerBuffsTempEnchant"..weapon]
+ if select(weapon, hasMainHandEnchant, hasOffHandEnchant) then
+ numWeapon = numWeapon + 1
+ if not button then
+ button = CreateFrame("Button", "$parentTempEnchant"..weapon, header)
+ self:CreateIcon(button)
+ end
+ if button then
+ if button:IsShown() then button:Hide() end
+
+ local index = enchantableSlots[weapon]
+ local quality = GetInventoryItemQuality("player", index)
+ button.texture:SetTexture(GetInventoryItemTexture("player", index))
+
+ if quality then
+ button:SetBackdropBorderColor(GetItemQualityColor(quality))
+ end
+
+ local expirationTime = select(weapon, mainHandExpiration, offHandExpiration)
+ if expirationTime then
+ button.offset = select(weapon, 2, 5)
+ button:SetScript("OnUpdate", function() self.UpdateTime(this, arg1) end)
+ button.nextUpdate = -1
+ A.UpdateTime(button, 0)
+ else
+ button.timeLeft = nil
+ button.offset = nil
+ button:SetScript("OnUpdate", nil)
+ button.time:SetText("")
+ end
+ buttons[weapon] = button
+ end
+ else
+ if button and type(button.Hide) == "function" then
+ button.offset = nil
+ button:Hide()
+ end
+ end
+ end
+ end
+
+ for i = 1, getn(auraTable) do
+ button = _G[headerName.."AuraButton"..i]
+ if button then
+ if button:IsShown() then button:Hide() end
+ else
+ button = CreateFrame("Button", "$parentAuraButton"..i, header)
+ self:CreateIcon(button)
+ end
+ local buffInfo = auraTable[i]
+ button.index = buffInfo.index
+
+ if buffInfo.expires and buffInfo.expires > 0 then
+ local timeLeft = buffInfo.expires
+ if not button.timeLeft then
+ button.timeLeft = timeLeft
+ button:SetScript("OnUpdate", function() self.UpdateTime(this, arg1) end)
+ else
+ button.timeLeft = timeLeft
+ end
+
+ button.nextUpdate = -1
+ self.UpdateTime(button, 0)
+ else
+ button.timeLeft = nil
+ button.time:SetText("")
+ button:SetScript("OnUpdate", nil)
+ end
+
+ if buffInfo.count > 1 then
+ button.count:SetText(buffInfo.count)
+ else
+ button.count:SetText("")
+ end
+
+ if buffInfo.filter == "HARMFUL" then
+ local color = DebuffTypeColor[buffInfo.dispelType or ""]
+ button:SetBackdropBorderColor(color.r, color.g, color.b)
+ else
+ button:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end
+
+ button.texture:SetTexture(buffInfo.icon)
+
+ buttons[i+numWeapon] = button
+ end
+
+ local display = getn(buttons)
+ if wrapAfter and maxWraps then
+ display = min(display, wrapAfter * maxWraps)
+ end
+
+ local left, right, top, bottom = huge, -huge, -huge, huge
+ for index = 1, display do
+ button = buttons[index]
+ local tick, cycle = floor(mod((index - 1), wrapAfter)), floor((index - 1) / wrapAfter)
+ button:ClearAllPoints()
+ button:SetPoint(point, header, cycle * wrapXOffset + tick * xOffset, cycle * wrapYOffset + tick * yOffset)
+
+ button:SetWidth(size)
+ button:SetHeight(size)
+
+ if button.time then
+ local font = LSM:Fetch("font", self.db.font)
+ button.time:ClearAllPoints()
+ button.time:SetPoint("TOP", button, "BOTTOM", 1 + self.db.timeXOffset, 0 + self.db.timeYOffset)
+ E:FontTemplate(button.time, font, self.db.fontSize, self.db.fontOutline)
+
+ button.count:ClearAllPoints()
+ button.count:SetPoint("BOTTOMRIGHT", -1 + self.db.countXOffset, 0 + self.db.countYOffset)
+ E:FontTemplate(button.count, font, self.db.fontSize, self.db.fontOutline)
+ end
+
+ button:Show()
+ left = min(left, button:GetLeft() or huge)
+ right = max(right, button:GetRight() or -huge)
+ top = max(top, button:GetTop() or -huge)
+ bottom = min(bottom, button:GetBottom() or huge)
+ end
+ local deadIndex = (getn(auraTable) + numWeapon) + 1
+ button = _G[headerName.."AuraButton"..deadIndex]
+ while button do
+ if button:IsShown() then button:Hide() end
+ deadIndex = deadIndex + 1
+ button = _G[headerName.."AuraButton"..deadIndex]
+ end
+
+ if display >= 1 then
+ header:SetWidth(max(right - left, minWidth))
+ header:SetHeight(max(top - bottom, minHeight))
+ else
+ header:SetWidth(minWidth)
+ header:SetHeight(minHeight)
+ end
+end
+
+local freshTable
+local releaseTable
+do
+ local tableReserve = {}
+ freshTable = function ()
+ local t = next(tableReserve) or {}
+ tableReserve[t] = nil
+ return t
+ end
+ releaseTable = function (t)
+ tableReserve[t] = wipe(t)
+ end
+end
+
+local function sortFactory(key, separateOwn, reverse)
+ if separateOwn ~= 0 then
+ if reverse then
+ return function(a, b)
+ if a.filter == b.filter then
+ local ownA, ownB = a.caster == "player", b.caster == "player"
+ if ownA ~= ownB then
+ return ownA == (separateOwn > 0)
+ end
+ return a[key] > b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ else
+ return function(a, b)
+ if a.filter == b.filter then
+ local ownA, ownB = a.caster == "player", b.caster == "player"
+ if ownA ~= ownB then
+ return ownA == (separateOwn > 0)
+ end
+ return a[key] < b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ end
+ else
+ if reverse then
+ return function(a, b)
+ if a.filter == b.filter then
+ return a[key] > b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ else
+ return function(a, b)
+ if a.filter == b.filter then
+ return a[key] < b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ end
+ end
+end
+
+local sorters = {}
+for _, key in ipairs{"index", "expires"} do
+ local label = string.upper(key)
+ sorters[label] = {}
+ for bool in pairs{[true] = true, [false] = false} do
+ sorters[label][bool] = {}
+ for sep = -1, 1 do
+ sorters[label][bool][sep] = sortFactory(key, sep, bool)
+ end
+ end
+end
+sorters.TIME = sorters.EXPIRES
+
+local sortingTable = {}
+function A:UpdateHeader(header)
+ local filter = header.filter
+ local db = self.db.debuffs
+
+ wipe(sortingTable)
+
+ local weaponPosition
+ if filter == "HELPFUL" then
+ db = self.db.buffs
+ weaponPosition = 1
+ end
+
+ for i = 0, 23 do
+ local aura, _ = freshTable()
+ aura.index, aura.untilCancelled = GetPlayerBuff(i, filter)
+ if aura.index < 0 then
+ releaseTable(aura)
+ else
+ aura.icon, aura.count, aura.dispelType, aura.expires = GetPlayerBuffTexture(aura.index), GetPlayerBuffApplications(aura.index), GetPlayerBuffDispelType(aura.index), GetPlayerBuffTimeLeft(aura.index)
+ aura.filter = filter
+ sortingTable[i+1] = aura
+ end
+ end
+
+ local sortMethod = (sorters[db.sortMethod] or sorters["INDEX"])[db.sortDir == "-"][db.seperateOwn]
+ tsort(sortingTable, sortMethod)
+
+ self:ConfigureAuras(header, sortingTable, weaponPosition)
+ while sortingTable[1] do
+ releaseTable(wipe(sortingTable))
+ end
+end
+
+function A:CreateAuraHeader(filter)
+ local name = "ElvUIPlayerDebuffs"
+ if filter == "HELPFUL" then
+ name = "ElvUIPlayerBuffs"
+ end
+
+ local header = CreateFrame("Frame", name, UIParent)
+ header:SetClampedToScreen(true)
+ header.filter = filter
+
+ header:RegisterEvent("PLAYER_AURAS_CHANGED")
+ header:SetScript("OnEvent", function()
+ A:UpdateHeader(this)
+ end)
+
+ self:UpdateHeader(header)
+
+ return header
+end
+
+function A:Initialize()
+ if self.db then return end
+
+ if E.private.auras.disableBlizzard then
+ E:Kill(BuffFrame)
+ E:Kill(TemporaryEnchantFrame)
+ end
+
+ if not E.private.auras.enable then return end
+
+ self.db = E.db.auras
+
+ self.BuffFrame = self:CreateAuraHeader("HELPFUL")
+ self.BuffFrame:SetPoint("TOPRIGHT", MMHolder, "TOPLEFT", -(6 + E.Border), -E.Border - E.Spacing)
+ E:CreateMover(self.BuffFrame, "BuffsMover", L["Player Buffs"])
+
+ self.BuffFrame.GetUpdateWeaponEnchant = function(self)
+ local hasMainHandEnchant, _, _, hasOffHandEnchant = GetWeaponEnchantInfo()
+ if hasMainHandEnchant and not self.hasMainHandEnchant then
+ self.hasMainHandEnchant = true
+ return true
+ elseif hasOffHandEnchant and not self.hasOffHandEnchant then
+ self.hasOffHandEnchant = true
+ return true
+ elseif self.hasMainHandEnchant and not hasMainHandEnchant then
+ self.hasMainHandEnchant = false
+ return true
+ elseif self.hasOffHandEnchant and not hasOffHandEnchant then
+ self.hasOffHandEnchant = false
+ return true
+ end
+ end
+
+ self.BuffFrame:SetScript("OnUpdate", function()
+ if this:GetUpdateWeaponEnchant() then A:UpdateHeader(this) end
+ end)
+
+ self.DebuffFrame = self:CreateAuraHeader("HARMFUL")
+ self.DebuffFrame:SetPoint("BOTTOMRIGHT", MMHolder, "BOTTOMLEFT", -(6 + E.Border), E.Border + E.Spacing)
+ E:CreateMover(self.DebuffFrame, "DebuffsMover", L["Player Debuffs"])
+end
+
+local function InitializeCallback()
+ A:Initialize()
+end
+
+E:RegisterModule(A:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Auras/Load_Auras.xml b/ElvUI/Modules/Auras/Load_Auras.xml
new file mode 100644
index 0000000..2be9b8a
--- /dev/null
+++ b/ElvUI/Modules/Auras/Load_Auras.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Bags/BagBar.lua b/ElvUI/Modules/Bags/BagBar.lua
new file mode 100644
index 0000000..c153da5
--- /dev/null
+++ b/ElvUI/Modules/Bags/BagBar.lua
@@ -0,0 +1,168 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Bags");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local tinsert = table.insert
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local NUM_BAG_FRAMES = NUM_BAG_FRAMES
+
+local TOTAL_BAGS = NUM_BAG_FRAMES + 2
+
+local ElvUIKeyRing = CreateFrame("CheckButton", "ElvUIKeyRingButton", UIParent, "ItemButtonTemplate")
+ElvUIKeyRing:RegisterForClicks("anyUp")
+E:StripTextures(ElvUIKeyRing)
+ElvUIKeyRing:SetScript("OnClick", function() if CursorHasItem() then PutKeyInKeyRing() else ToggleKeyRing() end end)
+ElvUIKeyRing:SetScript("OnReceiveDrag", function() if CursorHasItem() then PutKeyInKeyRing() end end)
+ElvUIKeyRing:SetScript("OnEnter", function() GameTooltip:SetOwner(this, "ANCHOR_LEFT") local color = HIGHLIGHT_FONT_COLOR GameTooltip:SetText(KEYRING, color.r, color.g, color.b) GameTooltip:AddLine() end)
+ElvUIKeyRing:SetScript("OnLeave", function() GameTooltip:Hide() end)
+_G[ElvUIKeyRing:GetName().."IconTexture"]:SetTexture("Interface\\ContainerFrame\\KeyRing-Bag-Icon")
+_G[ElvUIKeyRing:GetName().."IconTexture"]:SetTexCoord(unpack(E.TexCoords))
+
+local function OnEnter()
+ if not E.db.bags.bagBar.mouseover then return end
+ UIFrameFadeIn(ElvUIBags, 0.2, ElvUIBags:GetAlpha(), 1)
+end
+
+local function OnLeave()
+ if not E.db.bags.bagBar.mouseover then return end
+ UIFrameFadeOut(ElvUIBags, 0.2, ElvUIBags:GetAlpha(), 0)
+end
+
+function B:SkinBag(bag)
+ local icon = _G[bag:GetName().."IconTexture"]
+ bag.oldTex = icon:GetTexture()
+
+ E:StripTextures(bag)
+ E:CreateBackdrop(bag, "Default", true)
+ bag.backdrop:SetAllPoints()
+ E:StyleButton(bag, true)
+ icon:SetTexture(bag.oldTex)
+ icon:Show()
+ E:SetInside(icon)
+ icon:SetTexCoord(unpack(E.TexCoords))
+end
+
+function B:SizeAndPositionBagBar()
+ if not ElvUIBags then return end
+
+ local buttonSpacing = E.db.bags.bagBar.spacing
+ local backdropSpacing = E.db.bags.bagBar.backdropSpacing
+ local bagBarSize = E.db.bags.bagBar.size
+ local showBackdrop = E.db.bags.bagBar.showBackdrop
+ local growthDirection = E.db.bags.bagBar.growthDirection
+ local sortDirection = E.db.bags.bagBar.sortDirection
+
+ if E.db.bags.bagBar.mouseover then
+ ElvUIBags:SetAlpha(0)
+ else
+ ElvUIBags:SetAlpha(1)
+ end
+
+ if showBackdrop then
+ ElvUIBags.backdrop:Show()
+ else
+ ElvUIBags.backdrop:Hide()
+ end
+
+ ElvUIKeyRingButton:SetWidth(bagBarSize)
+ ElvUIKeyRingButton:SetHeight(bagBarSize)
+ ElvUIKeyRingButton:ClearAllPoints()
+
+ for i = 1, getn(ElvUIBags.buttons) do
+ local button = ElvUIBags.buttons[i]
+ local prevButton = ElvUIBags.buttons[i-1]
+ button:SetWidth(E.db.bags.bagBar.size)
+ button:SetHeight(E.db.bags.bagBar.size)
+ button:ClearAllPoints()
+
+ if growthDirection == "HORIZONTAL" and sortDirection == "ASCENDING" then
+ if i == 1 then
+ button:SetPoint("LEFT", ElvUIBags, "LEFT", (showBackdrop and (backdropSpacing + E.Border) or 0), 0)
+ elseif prevButton then
+ button:SetPoint("LEFT", prevButton, "RIGHT", buttonSpacing, 0)
+ end
+ elseif growthDirection == "VERTICAL" and sortDirection == "ASCENDING" then
+ if i == 1 then
+ button:SetPoint("TOP", ElvUIBags, "TOP", 0, -(showBackdrop and (backdropSpacing + E.Border) or 0))
+ elseif prevButton then
+ button:SetPoint("TOP", prevButton, "BOTTOM", 0, -buttonSpacing)
+ end
+ elseif growthDirection == "HORIZONTAL" and sortDirection == "DESCENDING" then
+ if i == 1 then
+ button:SetPoint("RIGHT", ElvUIBags, "RIGHT", -(showBackdrop and (backdropSpacing + E.Border) or 0), 0)
+ elseif prevButton then
+ button:SetPoint("RIGHT", prevButton, "LEFT", -buttonSpacing, 0)
+ end
+ else
+ if i == 1 then
+ button:SetPoint("BOTTOM", ElvUIBags, "BOTTOM", 0, (showBackdrop and (backdropSpacing + E.Border) or 0))
+ elseif prevButton then
+ button:SetPoint("BOTTOM", prevButton, "TOP", 0, buttonSpacing)
+ end
+ end
+ end
+
+ if growthDirection == "HORIZONTAL" then
+ ElvUIBags:SetWidth(bagBarSize*(TOTAL_BAGS) + buttonSpacing*(TOTAL_BAGS-1) + ((showBackdrop == true and (E.Border + backdropSpacing) or E.Spacing)*2))
+ ElvUIBags:SetHeight(bagBarSize + ((showBackdrop and (E.Border + backdropSpacing) or E.Spacing)*2))
+ else
+ ElvUIBags:SetHeight(bagBarSize*(TOTAL_BAGS) + buttonSpacing*(TOTAL_BAGS-1) + ((showBackdrop == true and (E.Border + backdropSpacing) or E.Spacing)*2))
+ ElvUIBags:SetWidth(bagBarSize + ((showBackdrop and (E.Border + backdropSpacing) or E.Spacing)*2))
+ end
+end
+
+function B:LoadBagBar()
+ if not E.private.bags.bagBar then return end
+
+ local ElvUIBags = CreateFrame("Frame", "ElvUIBags", E.UIParent)
+ ElvUIBags:SetPoint("TOPRIGHT", RightChatPanel, "TOPLEFT", -4, 0)
+ ElvUIBags.buttons = {}
+ E:CreateBackdrop(ElvUIBags)
+ ElvUIBags.backdrop:SetAllPoints()
+ ElvUIBags:EnableMouse(true)
+ ElvUIBags:SetScript("OnEnter", OnEnter)
+ ElvUIBags:SetScript("OnLeave", OnLeave)
+
+ MainMenuBarBackpackButton:SetParent(ElvUIBags)
+ MainMenuBarBackpackButton.SetParent = E.dummy
+ MainMenuBarBackpackButton:ClearAllPoints()
+ E:FontTemplate(MainMenuBarBackpackButtonCount, nil, 10)
+ MainMenuBarBackpackButtonCount:ClearAllPoints()
+ MainMenuBarBackpackButtonCount:SetPoint("BOTTOMRIGHT", MainMenuBarBackpackButton, "BOTTOMRIGHT", -1, 4)
+ MainMenuBarBackpackButton:Show()
+ MainMenuBarBackpackButton:SetAlpha(1)
+ HookScript(MainMenuBarBackpackButton, "OnEnter", OnEnter)
+ HookScript(MainMenuBarBackpackButton, "OnLeave", OnLeave)
+ tinsert(ElvUIBags.buttons, MainMenuBarBackpackButton)
+ self:SkinBag(MainMenuBarBackpackButton)
+
+ for i = 0, NUM_BAG_FRAMES - 1 do
+ local b = _G["CharacterBag"..i.."Slot"]
+ b:SetParent(ElvUIBags)
+ b.SetParent = E.dummy
+ b:Show()
+ b:SetAlpha(1)
+
+ HookScript(b, "OnEnter", OnEnter)
+ HookScript(b, "OnLeave", OnLeave)
+
+ self:SkinBag(b)
+ tinsert(ElvUIBags.buttons, b)
+ end
+
+ E:SetTemplate(ElvUIKeyRingButton)
+ E:StyleButton(ElvUIKeyRingButton, true)
+ E:SetInside(_G[ElvUIKeyRingButton:GetName().."IconTexture"])
+ ElvUIKeyRingButton:SetParent(ElvUIBags)
+ ElvUIKeyRingButton.SetParent = E.dummy
+ HookScript(ElvUIKeyRingButton, "OnEnter", OnEnter)
+ HookScript(ElvUIKeyRingButton, "OnLeave", OnLeave)
+ tinsert(ElvUIBags.buttons, ElvUIKeyRingButton)
+
+ self:SizeAndPositionBagBar()
+ E:CreateMover(ElvUIBags, "BagsMover", L["Bags"])
+end
diff --git a/ElvUI/Modules/Bags/Bags.lua b/ElvUI/Modules/Bags/Bags.lua
new file mode 100644
index 0000000..39a4f6d
--- /dev/null
+++ b/ElvUI/Modules/Bags/Bags.lua
@@ -0,0 +1,1263 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:NewModule("Bags", "AceHook-3.0", "AceEvent-3.0", "AceTimer-3.0");
+local Search = LibStub("LibItemSearch-1.2");
+-- local LIP = LibStub("ItemPrice-1.1", true);
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local type, ipairs, pairs, unpack, select, assert = type, ipairs, pairs, unpack, select, assert
+local tinsert = table.insert
+local floor, ceil = math.floor, math.ceil
+local len, gsub, sub, find, match = string.len, string.gsub, string.sub, string.find, string.match
+--WoW API / Variables
+local BankFrameItemButton_Update = BankFrameItemButton_Update
+local BankFrameItemButton_UpdateLocked = BankFrameItemButton_UpdateLocked
+local CloseBag, CloseBackpack, CloseBankFrame = CloseBag, CloseBackpack, CloseBankFrame
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local CreateFrame = CreateFrame
+local DeleteCursorItem = DeleteCursorItem
+local GetContainerItemCooldown = GetContainerItemCooldown
+local GetContainerItemInfo = GetContainerItemInfo
+local GetContainerItemLink = GetContainerItemLink
+local GetContainerNumFreeSlots = GetContainerNumFreeSlots
+local GetContainerNumSlots = GetContainerNumSlots
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local GetKeyRingSize = GetKeyRingSize
+local GetMoney = GetMoney
+local GetNumBankSlots = GetNumBankSlots
+local IsBagOpen, IsOptionFrameOpen = IsBagOpen, IsOptionFrameOpen
+local IsControlKeyDown = IsControlKeyDown
+local PickupContainerItem = PickupContainerItem
+local PickupMerchantItem = PickupMerchantItem
+local PlaySound = PlaySound
+local SetItemButtonCount = SetItemButtonCount
+local SetItemButtonDesaturated = SetItemButtonDesaturated
+local SetItemButtonTexture = SetItemButtonTexture
+local SetItemButtonTextureVertexColor = SetItemButtonTextureVertexColor
+local ToggleFrame = ToggleFrame
+local UseContainerItem = UseContainerItem
+
+local BANK_CONTAINER = BANK_CONTAINER
+local KEYRING_CONTAINER = KEYRING_CONTAINER
+local MAX_CONTAINER_ITEMS = MAX_CONTAINER_ITEMS
+local NUM_BAG_FRAMES = NUM_BAG_FRAMES
+local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
+local SEARCH = SEARCH
+
+local SEARCH_STRING = ""
+
+B.ProfessionColors = {
+ ["0x0008"] = {224/255, 187/255, 74/255}, -- Leatherworking
+ ["0x0010"] = {74/255, 77/255, 224/255}, -- Inscription
+ ["0x0020"] = {18/255, 181/255, 32/255}, -- Herbs
+ ["0x0040"] = {160/255, 3/255, 168/255}, -- Enchanting
+ ["0x0080"] = {232/255, 118/255, 46/255}, -- Engineering
+ ["0x0400"] = {105/255, 79/255, 7/255}, -- Mining
+ ["0x010000"] = {222/255, 13/255, 65/255} -- Cooking
+}
+
+function B:GetContainerFrame(arg)
+ if type(arg) == "boolean" and arg == true then
+ return self.BankFrame
+ elseif type(arg) == "number" then
+ if self.BankFrame then
+ for _, bagID in ipairs(self.BankFrame.BagIDs) do
+ if bagID == arg then
+ return self.BankFrame
+ end
+ end
+ end
+ end
+
+ return self.BagFrame
+end
+
+function B:Tooltip_Show()
+ GameTooltip:SetOwner(this)
+ GameTooltip:ClearLines()
+ GameTooltip:AddLine(this.ttText)
+
+ if this.ttText2 then
+ GameTooltip:AddLine(" ")
+ GameTooltip:AddDoubleLine(this.ttText2, this.ttText2desc, 1, 1, 1)
+ end
+
+ GameTooltip:Show()
+end
+
+function B:Tooltip_Hide()
+ GameTooltip:Hide()
+end
+
+function B:DisableBlizzard()
+ BankFrame:UnregisterAllEvents()
+
+ for i = 1, NUM_CONTAINER_FRAMES do
+ E:Kill(_G["ContainerFrame"..i])
+ end
+end
+
+function B:SearchReset()
+ SEARCH_STRING = ""
+end
+
+function B:IsSearching()
+ if SEARCH_STRING ~= "" and SEARCH_STRING ~= SEARCH then
+ return true
+ end
+ return false
+end
+
+function B:UpdateSearch()
+ if this.Instructions then this.Instructions:SetShown(this:GetText() == "") end
+ local MIN_REPEAT_CHARACTERS = 3
+ local searchString = this:GetText()
+ local prevSearchString = SEARCH_STRING
+ if len(searchString) > MIN_REPEAT_CHARACTERS then
+ local repeatChar = true
+ for i = 1, MIN_REPEAT_CHARACTERS, 1 do
+ if sub(searchString,(0-i), (0-i)) ~= sub(searchString,(-1-i),(-1-i)) then
+ repeatChar = false
+ break
+ end
+ end
+ if repeatChar then
+ B.ResetAndClear(this)
+ return
+ end
+ end
+
+ --Keep active search term when switching between bank and reagent bank
+ if searchString == SEARCH and prevSearchString ~= "" then
+ searchString = prevSearchString
+ elseif searchString == SEARCH then
+ searchString = ""
+ end
+
+ SEARCH_STRING = searchString
+
+ B:SetSearch(SEARCH_STRING)
+end
+
+function B:OpenEditbox()
+ self.BagFrame.detail:Hide()
+ self.BagFrame.editBox:Show()
+ self.BagFrame.editBox:SetText(SEARCH)
+ self.BagFrame.editBox:HighlightText()
+end
+
+function B:ResetAndClear()
+ local editbox = self:GetParent().editBox or this
+ if editbox then editbox:SetText(SEARCH) end
+
+ self:ClearFocus()
+ B:SearchReset()
+end
+
+function B:SetSearch(query)
+ local empty = len(gsub(query, " ", "")) == 0
+ for _, bagFrame in pairs(self.BagFrames) do
+ for _, bagID in ipairs(bagFrame.BagIDs) do
+ for slotID = 1, GetContainerNumSlots(bagID) do
+ local link = GetContainerItemLink(bagID, slotID)
+ local button = bagFrame.Bags[bagID][slotID]
+ local success, result = pcall(Search.Matches, Search, link, query)
+ if empty or (success and result) then
+ SetItemButtonDesaturated(button)
+ button:SetAlpha(1)
+ else
+ SetItemButtonDesaturated(button, 1)
+ button:SetAlpha(0.4)
+ end
+ end
+ end
+ end
+
+ if ElvUIKeyFrameItem1 then
+ local numKey = GetKeyRingSize()
+ for slotID = 1, numKey do
+ local link = GetContainerItemLink(KEYRING_CONTAINER, slotID)
+ local button = _G["ElvUIKeyFrameItem"..slotID]
+ local success, result = pcall(Search.Matches, Search, link, query)
+ if empty or (success and result) then
+ SetItemButtonDesaturated(button)
+ button:SetAlpha(1)
+ else
+ SetItemButtonDesaturated(button, 1)
+ button:SetAlpha(0.4)
+ end
+ end
+ end
+end
+
+function B:UpdateItemLevelDisplay()
+ if E.private.bags.enable ~= true then return end
+ for _, bagFrame in pairs(self.BagFrames) do
+ for _, bagID in ipairs(bagFrame.BagIDs) do
+ for slotID = 1, GetContainerNumSlots(bagID) do
+ local slot = bagFrame.Bags[bagID][slotID]
+ if slot and slot.itemLevel then
+ E:FontTemplate(slot.itemLevel, E.LSM:Fetch("font", E.db.bags.itemLevelFont), E.db.bags.itemLevelFontSize, E.db.bags.itemLevelFontOutline)
+ end
+ end
+ end
+
+ if bagFrame.UpdateAllSlots then
+ bagFrame:UpdateAllSlots()
+ end
+ end
+end
+
+function B:UpdateCountDisplay()
+ if E.private.bags.enable ~= true then return end
+ local color = E.db.bags.countFontColor
+
+ for _, bagFrame in pairs(self.BagFrames) do
+ for _, bagID in ipairs(bagFrame.BagIDs) do
+ for slotID = 1, GetContainerNumSlots(bagID) do
+ local slot = bagFrame.Bags[bagID][slotID]
+ if slot and slot.Count then
+ E:FontTemplate(slot.Count, E.LSM:Fetch("font", E.db.bags.countFont), E.db.bags.countFontSize, E.db.bags.countFontOutline)
+ slot.Count:SetTextColor(color.r, color.g, color.b)
+ end
+ end
+ end
+ if bagFrame.UpdateAllSlots then
+ bagFrame:UpdateAllSlots()
+ end
+ end
+end
+
+function B:UpdateSlot(bagID, slotID)
+ if (self.Bags[bagID] and self.Bags[bagID].numSlots ~= GetContainerNumSlots(bagID)) or not self.Bags[bagID] or not self.Bags[bagID][slotID] then return end
+
+ local slot, _ = self.Bags[bagID][slotID], nil
+ local bagType = self.Bags[bagID].type
+ local texture, count, locked = GetContainerItemInfo(bagID, slotID)
+ local clink = GetContainerItemLink(bagID, slotID)
+
+ slot.name, slot.rarity = nil, nil
+
+ slot:Show()
+ slot.itemLevel:SetText("")
+
+ if B.ProfessionColors[bagType] then
+ slot:SetBackdropBorderColor(unpack(B.ProfessionColors[bagType]))
+ elseif clink then
+ local iLvl, itemEquipLoc
+ slot.name, _, slot.rarity, iLvl, _, _, _, itemEquipLoc = GetItemInfo(match(clink, "item:(%d+)"))
+
+ local r, g, b
+
+ if slot.rarity then
+ r, g, b = GetItemQualityColor(slot.rarity)
+ end
+
+ --Item Level
+ if iLvl and B.db.itemLevel and (itemEquipLoc ~= nil and itemEquipLoc ~= "" and itemEquipLoc ~= "INVTYPE_AMMO" and itemEquipLoc ~= "INVTYPE_BAG" and itemEquipLoc ~= "INVTYPE_QUIVER" and itemEquipLoc ~= "INVTYPE_TABARD") and (slot.rarity and slot.rarity > 1) then
+ if iLvl >= E.db.bags.itemLevelThreshold then
+ slot.itemLevel:SetText(iLvl)
+ slot.itemLevel:SetTextColor(r, g, b)
+ end
+ end
+
+ -- color slot according to item quality
+ if slot.rarity then
+ slot:SetBackdropBorderColor(r, g, b)
+ else
+ slot:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end
+ else
+ slot:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end
+
+ if texture then
+ if bagID ~= BANK_CONTAINER then
+ local start, duration, enable = GetContainerItemCooldown(bagID, slotID)
+ CooldownFrame_SetTimer(slot.cooldown, start, duration, enable)
+ if duration > 0 and enable == 0 then
+ SetItemButtonTextureVertexColor(slot, 0.4, 0.4, 0.4)
+ else
+ SetItemButtonTextureVertexColor(slot, 1, 1, 1)
+ end
+ end
+ slot.hasItem = 1
+ else
+ if bagID ~= BANK_CONTAINER then
+ slot.cooldown:Hide()
+ end
+ slot.hasItem = nil
+ end
+
+ SetItemButtonTexture(slot, texture)
+ SetItemButtonCount(slot, count)
+ SetItemButtonDesaturated(slot, locked, 0.5, 0.5, 0.5)
+
+ if GameTooltip:IsOwned(slot) and not slot.hasItem then
+ B:Tooltip_Hide()
+ end
+end
+
+function B:UpdateBagSlots(bagID)
+ for slotID = 1, GetContainerNumSlots(bagID) do
+ if self.UpdateSlot then
+ self:UpdateSlot(bagID, slotID)
+ else
+ self:GetParent():UpdateSlot(bagID, slotID)
+ end
+ end
+end
+
+function B:UpdateCooldowns()
+ for _, bagID in ipairs(self.BagIDs) do
+ if bagID ~= BANK_CONTAINER then
+ for slotID = 1, GetContainerNumSlots(bagID) do
+ local start, duration, enable = GetContainerItemCooldown(bagID, slotID)
+ CooldownFrame_SetTimer(self.Bags[bagID][slotID].cooldown, start, duration, enable)
+ if duration > 0 and enable == 0 then
+ SetItemButtonTextureVertexColor(self.Bags[bagID][slotID], 0.4, 0.4, 0.4)
+ else
+ SetItemButtonTextureVertexColor(self.Bags[bagID][slotID], 1, 1, 1)
+ end
+ end
+ end
+ end
+end
+
+function B:UpdateAllSlots()
+ for _, bagID in ipairs(self.BagIDs) do
+ if self.Bags[bagID] then
+ self.Bags[bagID]:UpdateBagSlots(bagID)
+ end
+ end
+end
+
+function B:SetSlotAlphaForBag(f)
+ for _, bagID in ipairs(f.BagIDs) do
+ if f.Bags[bagID] then
+ local numSlots = GetContainerNumSlots(bagID)
+ for slotID = 1, numSlots do
+ if f.Bags[bagID][slotID] then
+ if bagID == self.id then
+ f.Bags[bagID][slotID]:SetAlpha(1)
+ else
+ f.Bags[bagID][slotID]:SetAlpha(0.1)
+ end
+ end
+ end
+ end
+ end
+end
+
+function B:ResetSlotAlphaForBags(f)
+ for _, bagID in ipairs(f.BagIDs) do
+ if f.Bags[bagID] then
+ local numSlots = GetContainerNumSlots(bagID)
+ for slotID = 1, numSlots do
+ if f.Bags[bagID][slotID] then
+ f.Bags[bagID][slotID]:SetAlpha(1)
+ end
+ end
+ end
+ end
+end
+
+function B:Layout(isBank)
+ if E.private.bags.enable ~= true then return end
+ local f = self:GetContainerFrame(isBank)
+
+ if not f then return end
+ local buttonSize = isBank and self.db.bankSize or self.db.bagSize
+ local buttonSpacing = E.PixelMode and 2 or 4
+ local containerWidth = ((isBank and self.db.bankWidth) or self.db.bagWidth)
+ local numContainerColumns = floor(containerWidth / (buttonSize + buttonSpacing))
+ local holderWidth = ((buttonSize + buttonSpacing) * numContainerColumns) - buttonSpacing
+ local numContainerRows = 0
+ local countColor = E.db.bags.countFontColor
+ f.holderFrame:SetWidth(holderWidth)
+
+ f.totalSlots = 0
+ local lastButton
+ local lastRowButton
+ local lastContainerButton
+ local numContainerSlots = GetNumBankSlots()
+ for i, bagID in ipairs(f.BagIDs) do
+ --Bag Containers
+ if (not isBank and bagID <= 3 ) or (isBank and bagID ~= -1 and numContainerSlots >= 1 and not (i - 1 > numContainerSlots)) then
+ if not f.ContainerHolder[i] then
+ if isBank then
+ f.ContainerHolder[i] = CreateFrame("CheckButton", "ElvUIBankBag"..bagID - 4, f.ContainerHolder, "BankItemButtonBagTemplate")
+ f.ContainerHolder[i]:SetScript("OnClick", function()
+ local inventoryID = this:GetInventorySlot()
+ PutItemInBag(inventoryID) --Put bag on empty slot, or drop item in this bag
+ end)
+ else
+ f.ContainerHolder[i] = CreateFrame("CheckButton", "ElvUIMainBag"..bagID.."Slot", f.ContainerHolder, "BagSlotButtonTemplate")
+ f.ContainerHolder[i]:SetScript("OnClick", function()
+ local id = this:GetID()
+ PutItemInBag(id) --Put bag on empty slot, or drop item in this bag
+ end)
+ end
+
+ E:CreateBackdrop(f.ContainerHolder[i], "Default", true)
+ f.ContainerHolder[i].backdrop:SetAllPoints()
+ E:StyleButton(f.ContainerHolder[i])
+ f.ContainerHolder[i]:SetNormalTexture("")
+ f.ContainerHolder[i]:SetCheckedTexture("")
+ f.ContainerHolder[i]:SetPushedTexture("")
+ f.ContainerHolder[i].id = isBank and bagID or bagID + 1
+ HookScript(f.ContainerHolder[i], "OnEnter", function() B.SetSlotAlphaForBag(this, f) end)
+ HookScript(f.ContainerHolder[i], "OnLeave", function() B.ResetSlotAlphaForBags(this, f) end)
+
+ if isBank then
+ f.ContainerHolder[i]:SetID(bagID)
+ if not f.ContainerHolder[i].tooltipText then
+ f.ContainerHolder[i].tooltipText = ""
+ end
+ end
+
+ f.ContainerHolder[i].iconTexture = _G[f.ContainerHolder[i]:GetName().."IconTexture"]
+ E:SetInside(f.ContainerHolder[i].iconTexture)
+ f.ContainerHolder[i].iconTexture:SetTexCoord(unpack(E.TexCoords))
+ end
+
+ f.ContainerHolder:SetWidth(((buttonSize + buttonSpacing) * (isBank and i - 1 or i)) + buttonSpacing)
+ f.ContainerHolder:SetHeight(buttonSize + (buttonSpacing * 2))
+
+ --[[if isBank then
+ BankFrameItemButton_OnUpdate()
+ end--]]
+
+ f.ContainerHolder[i]:SetWidth(buttonSize)
+ f.ContainerHolder[i]:SetHeight(buttonSize)
+ f.ContainerHolder[i]:ClearAllPoints()
+ if (isBank and i == 2) or (not isBank and i == 1) then
+ f.ContainerHolder[i]:SetPoint("BOTTOMLEFT", f.ContainerHolder, "BOTTOMLEFT", buttonSpacing, buttonSpacing)
+ else
+ f.ContainerHolder[i]:SetPoint("LEFT", lastContainerButton, "RIGHT", buttonSpacing, 0)
+ end
+
+ lastContainerButton = f.ContainerHolder[i]
+ end
+
+ --Bag Slots
+ local numSlots = GetContainerNumSlots(bagID)
+ if numSlots > 0 then
+ if not f.Bags[bagID] then
+ f.Bags[bagID] = CreateFrame("Frame", f:GetName().."Bag"..bagID, f)
+ f.Bags[bagID]:SetID(bagID)
+ f.Bags[bagID].UpdateBagSlots = B.UpdateBagSlots
+ -- f.Bags[bagID].UpdateSlot = B.UpdateSlot
+ end
+
+ f.Bags[bagID].numSlots = numSlots
+ -- f.Bags[bagID].type = select(2, GetContainerNumFreeSlots(bagID))
+
+ --Hide unused slots
+ for i = 1, MAX_CONTAINER_ITEMS do
+ if f.Bags[bagID][i] then
+ f.Bags[bagID][i]:Hide()
+ end
+ end
+
+ for slotID = 1, numSlots do
+ f.totalSlots = f.totalSlots + 1
+ if not f.Bags[bagID][slotID] then
+ f.Bags[bagID][slotID] = CreateFrame("CheckButton", f.Bags[bagID]:GetName().."Slot"..slotID, f.Bags[bagID], bagID == -1 and "BankItemButtonGenericTemplate" or "ContainerFrameItemButtonTemplate")
+ E:StyleButton(f.Bags[bagID][slotID])
+ E:SetTemplate(f.Bags[bagID][slotID], "Default", true)
+ f.Bags[bagID][slotID]:SetNormalTexture("")
+ f.Bags[bagID][slotID]:SetCheckedTexture("")
+
+ f.Bags[bagID][slotID].Count = _G[f.Bags[bagID][slotID]:GetName().."Count"]
+ f.Bags[bagID][slotID].Count:ClearAllPoints()
+ f.Bags[bagID][slotID].Count:SetPoint("BOTTOMRIGHT", 0, 2)
+ E:FontTemplate(f.Bags[bagID][slotID].Count, E.LSM:Fetch("font", E.db.bags.countFont), E.db.bags.countFontSize, E.db.bags.countFontOutline)
+ f.Bags[bagID][slotID].Count:SetTextColor(countColor.r, countColor.g, countColor.b)
+
+ f.Bags[bagID][slotID].iconTexture = _G[f.Bags[bagID][slotID]:GetName().."IconTexture"]
+ E:SetInside(f.Bags[bagID][slotID].iconTexture, f.Bags[bagID][slotID])
+ f.Bags[bagID][slotID].iconTexture:SetTexCoord(unpack(E.TexCoords))
+
+ if bagID ~= BANK_CONTAINER then
+ f.Bags[bagID][slotID].cooldown = _G[f.Bags[bagID][slotID]:GetName().."Cooldown"]
+ E:RegisterCooldown(f.Bags[bagID][slotID].cooldown)
+ f.Bags[bagID][slotID].bagID = bagID
+ f.Bags[bagID][slotID].slotID = slotID
+ end
+
+ f.Bags[bagID][slotID].itemLevel = f.Bags[bagID][slotID]:CreateFontString(nil, "OVERLAY")
+ f.Bags[bagID][slotID].itemLevel:SetPoint("BOTTOMRIGHT", 0, 2)
+ E:FontTemplate(f.Bags[bagID][slotID].itemLevel, E.LSM:Fetch("font", E.db.bags.itemLevelFont), E.db.bags.itemLevelFontSize, E.db.bags.itemLevelFontOutline)
+ end
+
+ f.Bags[bagID][slotID]:SetID(slotID)
+ f.Bags[bagID][slotID]:SetWidth(buttonSize)
+ f.Bags[bagID][slotID]:SetHeight(buttonSize)
+
+ f:UpdateSlot(bagID, slotID)
+
+ if f.Bags[bagID][slotID]:GetPoint() then
+ f.Bags[bagID][slotID]:ClearAllPoints()
+ end
+
+ if lastButton then
+ if mod(f.totalSlots - 1, numContainerColumns) == 0 then
+ f.Bags[bagID][slotID]:SetPoint("TOP", lastRowButton, "BOTTOM", 0, -buttonSpacing)
+ lastRowButton = f.Bags[bagID][slotID]
+ numContainerRows = numContainerRows + 1
+ else
+ f.Bags[bagID][slotID]:SetPoint("LEFT", lastButton, "RIGHT", buttonSpacing, 0)
+ end
+ else
+ f.Bags[bagID][slotID]:SetPoint("TOPLEFT", f.holderFrame, "TOPLEFT")
+ lastRowButton = f.Bags[bagID][slotID]
+ numContainerRows = numContainerRows + 1
+ end
+
+ lastButton = f.Bags[bagID][slotID]
+ end
+ else
+ for i = 1, MAX_CONTAINER_ITEMS do
+ if f.Bags[bagID] and f.Bags[bagID][i] then
+ f.Bags[bagID][i]:Hide()
+ end
+ end
+
+ if f.Bags[bagID] then
+ f.Bags[bagID].numSlots = numSlots
+ end
+
+ if self.isBank then
+ if self.ContainerHolder[i] then
+ BankFrameItemButton_Update(self.ContainerHolder[i])
+ BankFrameItemButton_UpdateLocked(self.ContainerHolder[i])
+ end
+ end
+ end
+ end
+
+ local numKey = GetKeyRingSize()
+ local numKeyColumns = 6
+ if not isBank then
+ local totalSlots = 0
+ local lastRowButton
+ local numKeyRows = 1
+ for i = 1, numKey do
+ totalSlots = totalSlots + 1
+
+ if not f.keyFrame.slots[i] then
+ f.keyFrame.slots[i] = CreateFrame("CheckButton", "ElvUIKeyFrameItem"..i, f.keyFrame, "ContainerFrameItemButtonTemplate")
+ E:StyleButton(f.keyFrame.slots[i], nil, nil, true)
+ E:SetTemplate(f.keyFrame.slots[i], "Default", true)
+ f.keyFrame.slots[i]:SetNormalTexture("")
+ f.keyFrame.slots[i]:SetID(i)
+
+ f.keyFrame.slots[i].cooldown = _G[f.keyFrame.slots[i]:GetName().."Cooldown"]
+ E:RegisterCooldown(f.keyFrame.slots[i].cooldown)
+
+ f.keyFrame.slots[i].iconTexture = _G[f.keyFrame.slots[i]:GetName().."IconTexture"]
+ E:SetInside(f.keyFrame.slots[i].iconTexture, f.keyFrame.slots[i])
+ f.keyFrame.slots[i].iconTexture:SetTexCoord(unpack(E.TexCoords))
+ end
+
+ f.keyFrame.slots[i]:ClearAllPoints()
+ f.keyFrame.slots[i]:SetWidth(buttonSize)
+ f.keyFrame.slots[i]:SetHeight(buttonSize)
+ if f.keyFrame.slots[i-1] then
+ if mod(totalSlots - 1, numKeyColumns) == 0 then
+ f.keyFrame.slots[i]:SetPoint("TOP", lastRowButton, "BOTTOM", 0, -buttonSpacing)
+ lastRowButton = f.keyFrame.slots[i]
+ numKeyRows = numKeyRows + 1
+ else
+ f.keyFrame.slots[i]:SetPoint("RIGHT", f.keyFrame.slots[i-1], "LEFT", -buttonSpacing, 0)
+ end
+ else
+ f.keyFrame.slots[i]:SetPoint("TOPRIGHT", f.keyFrame, "TOPRIGHT", -buttonSpacing, -buttonSpacing)
+ lastRowButton = f.keyFrame.slots[i]
+ end
+
+ self:UpdateKeySlot(i)
+ end
+
+ if numKey < numKeyColumns then
+ numKeyColumns = numKey
+ end
+ f.keyFrame:SetWidth(((buttonSize + buttonSpacing) * numKeyColumns) + buttonSpacing)
+ f.keyFrame:SetHeight(((buttonSize + buttonSpacing) * numKeyRows) + buttonSpacing)
+ end
+
+ f:SetWidth(containerWidth)
+ f:SetHeight((((buttonSize + buttonSpacing) * numContainerRows) - buttonSpacing) + f.topOffset + f.bottomOffset) -- 8 is the cussion of the f.holderFrame
+end
+
+function B:UpdateKeySlot(slotID)
+ assert(slotID)
+ local bagID = KEYRING_CONTAINER
+ local texture, count, locked = GetContainerItemInfo(bagID, slotID)
+ local clink = GetContainerItemLink(bagID, slotID)
+ local slot = _G["ElvUIKeyFrameItem"..slotID]
+ if not slot then return end
+
+ slot.name, slot.rarity = nil, nil
+ slot:Show()
+
+ if clink then
+ local _
+ slot.name, _, slot.rarity = GetItemInfo(clink)
+
+ local r, g, b
+
+ if slot.rarity then
+ r, g, b = GetItemQualityColor(slot.rarity)
+ end
+
+ if slot.rarity and slot.rarity > 1 then
+ slot:SetBackdropBorderColor(r, g, b)
+ else
+ slot:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end
+ else
+ slot:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end
+
+ if texture then
+ local start, duration, enable = GetContainerItemCooldown(bagID, slotID)
+ CooldownFrame_SetTimer(slot.cooldown, start, duration, enable)
+ if duration > 0 and enable == 0 then
+ SetItemButtonTextureVertexColor(slot, 0.4, 0.4, 0.4)
+ else
+ SetItemButtonTextureVertexColor(slot, 1, 1, 1)
+ end
+ else
+ slot.cooldown:Hide()
+ end
+
+ SetItemButtonTexture(slot, texture)
+ SetItemButtonCount(slot, count)
+ SetItemButtonDesaturated(slot, locked, 0.5, 0.5, 0.5)
+end
+
+function B:UpdateAll()
+ if self.BagFrame then
+ self:Layout()
+ end
+
+ if self.BankFrame then
+ self:Layout(true)
+ end
+end
+
+function B:OnEvent()
+ if event == "ITEM_LOCK_CHANGED" or event == "ITEM_UNLOCKED" then
+ local bag, slot = arg1, arg2
+ if bag == KEYRING_CONTAINER then
+ B:UpdateKeySlot(slot)
+ else
+ this:UpdateSlot(bag, slot)
+ end
+ elseif event == "BAG_UPDATE" then
+ local bag = arg1
+ if bag == KEYRING_CONTAINER then
+ if not _G["ElvUIKeyFrameItem"..GetKeyRingSize()] then
+ B:Layout(false)
+ end
+ for slotID = 1, GetKeyRingSize() do
+ B:UpdateKeySlot(slotID)
+ end
+ end
+
+ for _, bagID in ipairs(this.BagIDs) do
+ local numSlots = GetContainerNumSlots(bagID)
+ if (not this.Bags[bagID] and numSlots ~= 0) or (this.Bags[bagID] and numSlots ~= this.Bags[bagID].numSlots) then
+ B:Layout(this.isBank)
+ return
+ end
+ end
+
+ this:UpdateBagSlots(arg1, arg2)
+ if B:IsSearching() then
+ B:SetSearch(SEARCH_STRING)
+ end
+ elseif event == "BAG_UPDATE_COOLDOWN" then
+ if not this:IsShown() then return end
+ this:UpdateCooldowns()
+ elseif event == "PLAYERBANKSLOTS_CHANGED" then
+ this:UpdateAllSlots()
+ end
+end
+
+function B:UpdateGoldText()
+ self.BagFrame.goldText:SetText(E:FormatMoney(GetMoney(), E.db["bags"].moneyFormat))
+end
+
+function B:GetGraysValue()
+ local c = 0
+
+ for b = 0, NUM_BAG_FRAMES do
+ for s = 0, GetContainerNumSlots(b) do
+ local l = GetContainerItemLink(b, s)
+ if l and find(l,"ff9d9d9d") then
+ -- local p = LIP:GetSellValue(l) * select(2, GetContainerItemInfo(b, s))
+ -- if(select(3, GetItemInfo(l)) == 0 and p > 0) then
+ -- c = c + p
+ -- end
+ end
+ end
+ end
+
+ return c
+end
+
+function B:VendorGrays(delete, _, getValue)
+ if (not MerchantFrame or not MerchantFrame:IsShown()) and not delete and not getValue then
+ E:Print(L["You must be at a vendor."])
+ return
+ end
+
+ local c = 0
+ local count = 0
+ for b = 0, NUM_BAG_FRAMES do
+ for s = 1, GetContainerNumSlots(b) do
+ local l = GetContainerItemLink(b, s)
+ if l and find(l,"ff9d9d9d") then
+ -- local p = LIP:GetSellValue(l) * select(2, GetContainerItemInfo(b, s))
+
+ if delete then
+ if find(l,"ff9d9d9d") then
+ if not getValue then
+ PickupContainerItem(b, s)
+ DeleteCursorItem()
+ end
+ c = c + p
+ count = count + 1
+ end
+ else
+ if select(3, GetItemInfo(l)) == 0 and p > 0 then
+ if not getValue then
+ UseContainerItem(b, s)
+ PickupMerchantItem()
+ end
+ c = c + p
+ end
+ end
+ end
+ end
+ end
+
+ if getValue then
+ return c
+ end
+
+ if c > 0 and not delete then
+ local g, s, c = floor(c / 10000) or 0, floor(mod(c, 10000) / 100) or 0, mod(c, 100)
+ E:Print(L["Vendored gray items for:"].." |cffffffff"..g..L.goldabbrev.." |cffffffff"..s..L.silverabbrev.." |cffffffff"..c..L.copperabbrev..".")
+ end
+end
+
+function B:VendorGrayCheck()
+ local value = B:GetGraysValue()
+
+ if value == 0 then
+ E:Print(L["No gray items to delete."])
+ elseif not MerchantFrame or not MerchantFrame:IsShown() then
+ E.PopupDialogs["DELETE_GRAYS"].Money = value
+ E:StaticPopup_Show("DELETE_GRAYS")
+ else
+ B:VendorGrays()
+ end
+end
+
+function B:ContructContainerFrame(name, isBank)
+ local f = CreateFrame("Button", name, E.UIParent)
+ E:SetTemplate(f, "Transparent")
+ f:SetFrameStrata("DIALOG")
+ f.UpdateSlot = B.UpdateSlot
+ f.UpdateAllSlots = B.UpdateAllSlots
+ f.UpdateBagSlots = B.UpdateBagSlots
+ f.UpdateCooldowns = B.UpdateCooldowns
+ f:RegisterEvent("ITEM_LOCK_CHANGED")
+ f:RegisterEvent("ITEM_UNLOCKED")
+ f:RegisterEvent("BAG_UPDATE_COOLDOWN")
+ f:RegisterEvent("BAG_UPDATE")
+ f:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
+
+ f:SetScript("OnEvent", B.OnEvent)
+ f:Hide()
+
+ f.isBank = isBank
+
+ f.bottomOffset = isBank and 8 or 28
+ f.topOffset = isBank and 45 or 50
+ f.BagIDs = isBank and {-1, 5, 6, 7, 8, 9, 10, 11} or {0, 1, 2, 3, 4}
+ f.Bags = {}
+
+ local mover = (isBank and ElvUIBankMover or ElvUIBagMover)
+ if mover then
+ f:SetPoint(mover.POINT, mover)
+ f.mover = mover
+ end
+
+ f:SetMovable(true)
+ f:RegisterForDrag("LeftButton", "RightButton")
+ f:RegisterForClicks("AnyUp")
+ f:SetScript("OnDragStart", function() if IsShiftKeyDown() then this:StartMoving() end end)
+ f:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
+ f:SetScript("OnClick", function() if IsControlKeyDown() then B.PostBagMove(this.mover) end end)
+ f:SetScript("OnEnter", function()
+ GameTooltip:SetOwner(this, "ANCHOR_TOPLEFT", 0, 4)
+ GameTooltip:ClearLines()
+ GameTooltip:AddDoubleLine(L["Hold Shift + Drag:"], L["Temporary Move"], 1, 1, 1)
+ GameTooltip:AddDoubleLine(L["Hold Control + Right Click:"], L["Reset Position"], 1, 1, 1)
+
+ GameTooltip:Show()
+ end)
+ f:SetScript("OnLeave", function() GameTooltip:Hide() end)
+
+ f.closeButton = CreateFrame("Button", name.."CloseButton", f, "UIPanelCloseButton")
+ f.closeButton:SetPoint("TOPRIGHT", -4, -4)
+
+ E:GetModule("Skins"):HandleCloseButton(f.closeButton)
+
+ f.holderFrame = CreateFrame("Frame", nil, f)
+ f.holderFrame:SetPoint("TOP", f, "TOP", 0, -f.topOffset)
+ f.holderFrame:SetPoint("BOTTOM", f, "BOTTOM", 0, 8)
+
+ f.ContainerHolder = CreateFrame("Button", name.."ContainerHolder", f)
+ f.ContainerHolder:SetPoint("BOTTOMLEFT", f, "TOPLEFT", 0, 1)
+ E:SetTemplate(f.ContainerHolder, "Transparent")
+ f.ContainerHolder:Hide()
+
+ if isBank then
+ f.bagText = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.bagText)
+ f.bagText:SetPoint("BOTTOMRIGHT", f.holderFrame, "TOPRIGHT", -2, 4)
+ f.bagText:SetJustifyH("RIGHT")
+ f.bagText:SetText(L["Bank"])
+
+ f.sortButton = CreateFrame("Button", name.."SortButton", f)
+ f.sortButton:SetWidth(16 + E.Border)
+ f.sortButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.sortButton)
+ f.sortButton:SetPoint("RIGHT", f.bagText, "LEFT", -5, E.Border * 2)
+ f.sortButton:SetNormalTexture("Interface\\AddOns\\ElvUI\\media\\textures\\INV_Pet_RatCage")
+ f.sortButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.sortButton:GetNormalTexture())
+ f.sortButton:SetPushedTexture("Interface\\AddOns\\ElvUI\\media\\textures\\INV_Pet_RatCage")
+ f.sortButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.sortButton:GetPushedTexture())
+ f.sortButton:SetDisabledTexture("Interface\\AddOns\\ElvUI\\media\\textures\\INV_Pet_RatCage")
+ f.sortButton:GetDisabledTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.sortButton:GetDisabledTexture())
+ f.sortButton:GetDisabledTexture():SetDesaturated(true)
+ E:StyleButton(f.sortButton, nil, true)
+ f.sortButton.ttText = L["Sort Bags"]
+ f.sortButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.sortButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.sortButton:SetScript("OnClick", function() B:CommandDecorator(B.SortBags, "bank")() end)
+ if E.db.bags.disableBankSort then
+ f.sortButton:Disable()
+ end
+
+ f.bagsButton = CreateFrame("Button", name.."BagsButton", f.holderFrame)
+ f.bagsButton:SetWidth(16 + E.Border)
+ f.bagsButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.bagsButton)
+ f.bagsButton:SetPoint("RIGHT", f.sortButton, "LEFT", -5, 0)
+ f.bagsButton:SetNormalTexture("Interface\\Buttons\\Button-Backpack-Up")
+ f.bagsButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.bagsButton:GetNormalTexture())
+ f.bagsButton:SetPushedTexture("Interface\\Buttons\\Button-Backpack-Up")
+ f.bagsButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.bagsButton:GetPushedTexture())
+ E:StyleButton(f.bagsButton, nil, true)
+ f.bagsButton.ttText = L["Toggle Bags"]
+ f.bagsButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.bagsButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.bagsButton:SetScript("OnClick", function()
+ local numSlots = GetNumBankSlots()
+ PlaySound("igMainMenuOption")
+ if numSlots >= 1 then
+ ToggleFrame(f.ContainerHolder)
+ else
+ E:StaticPopup_Show("NO_BANK_BAGS")
+ end
+ end)
+
+ f.purchaseBagButton = CreateFrame("Button", nil, f.holderFrame)
+ f.purchaseBagButton:SetWidth(16 + E.Border)
+ f.purchaseBagButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.purchaseBagButton)
+ f.purchaseBagButton:SetPoint("RIGHT", f.bagsButton, "LEFT", -5, 0)
+ f.purchaseBagButton:SetNormalTexture("Interface\\ICONS\\INV_Misc_Coin_01")
+ f.purchaseBagButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.purchaseBagButton:GetNormalTexture())
+ f.purchaseBagButton:SetPushedTexture("Interface\\ICONS\\INV_Misc_Coin_01")
+ f.purchaseBagButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.purchaseBagButton:GetPushedTexture())
+ E:StyleButton(f.purchaseBagButton, nil, true)
+ f.purchaseBagButton.ttText = L["Purchase Bags"]
+ f.purchaseBagButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.purchaseBagButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.purchaseBagButton:SetScript("OnClick", function()
+ local _, full = GetNumBankSlots()
+ if full then
+ E:StaticPopup_Show("CANNOT_BUY_BANK_SLOT")
+ else
+ E:StaticPopup_Show("BUY_BANK_SLOT")
+ end
+ end)
+
+ f:SetScript("OnHide", function()
+ CloseBankFrame()
+
+ if E.db.bags.clearSearchOnClose then
+ B.ResetAndClear(f.editBox)
+ end
+ end)
+
+ f.editBox = CreateFrame("EditBox", name.."EditBox", f)
+ f.editBox:SetFrameLevel(f.editBox:GetFrameLevel() + 2)
+ E:CreateBackdrop(f.editBox, "Default")
+ f.editBox.backdrop:SetPoint("TOPLEFT", f.editBox, "TOPLEFT", -20, 2)
+ f.editBox:SetHeight(15)
+ f.editBox:SetPoint("BOTTOMLEFT", f.holderFrame, "TOPLEFT", (E.Border * 2) + 18, E.Border * 2 + 2)
+ f.editBox:SetPoint("RIGHT", f.purchaseBagButton, "LEFT", -5, 0)
+ f.editBox:SetAutoFocus(false)
+ f.editBox:SetScript("OnEscapePressed", self.ResetAndClear)
+ f.editBox:SetScript("OnEnterPressed", function() this:ClearFocus() end)
+ f.editBox:SetScript("OnEditFocusGained", function() this:HighlightText() end)
+ f.editBox:SetScript("OnTextChanged", self.UpdateSearch)
+ f.editBox:SetScript("OnChar", self.UpdateSearch)
+ f.editBox:SetText(SEARCH)
+ E:FontTemplate(f.editBox)
+
+ f.editBox.searchIcon = f.editBox:CreateTexture(nil, "OVERLAY")
+ f.editBox.searchIcon:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\UI-Searchbox-Icon")
+ f.editBox.searchIcon:SetPoint("LEFT", f.editBox.backdrop, "LEFT", E.Border + 1, -1)
+ f.editBox.searchIcon:SetWidth(15)
+ f.editBox.searchIcon:SetHeight(15)
+ else
+ f.keyFrame = CreateFrame("Frame", name.."KeyFrame", f)
+ f.keyFrame:SetPoint("TOPRIGHT", f, "TOPLEFT", -(E.PixelMode and 1 or 3), 0)
+ E:SetTemplate(f.keyFrame, "Transparent")
+ f.keyFrame:SetID(KEYRING_CONTAINER)
+ f.keyFrame.slots = {}
+ f.keyFrame:Hide()
+
+ f.goldText = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.goldText)
+ f.goldText:SetPoint("BOTTOMRIGHT", f.holderFrame, "TOPRIGHT", -2, 4)
+ f.goldText:SetJustifyH("RIGHT")
+
+ f.sortButton = CreateFrame("Button", name.."SortButton", f)
+ f.sortButton:SetWidth(16 + E.Border)
+ f.sortButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.sortButton)
+ f.sortButton:SetPoint("RIGHT", f.goldText, "LEFT", -5, E.Border * 2)
+ f.sortButton:SetNormalTexture("Interface\\AddOns\\ElvUI\\media\\textures\\INV_Pet_RatCage")
+ f.sortButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.sortButton:GetNormalTexture())
+ f.sortButton:SetPushedTexture("Interface\\AddOns\\ElvUI\\media\\textures\\INV_Pet_RatCage")
+ f.sortButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.sortButton:GetPushedTexture())
+ f.sortButton:SetDisabledTexture("Interface\\AddOns\\ElvUI\\media\\textures\\INV_Pet_RatCage")
+ f.sortButton:GetDisabledTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.sortButton:GetDisabledTexture())
+ f.sortButton:GetDisabledTexture():SetDesaturated(true)
+ E:StyleButton(f.sortButton, nil, true)
+ f.sortButton.ttText = L["Sort Bags"]
+ f.sortButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.sortButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.sortButton:SetScript("OnClick", function() B:CommandDecorator(B.SortBags, "bags")() end)
+ if E.db.bags.disableBagSort then
+ f.sortButton:Disable()
+ end
+
+ f.keyButton = CreateFrame("Button", name.."KeyButton", f)
+ f.keyButton:SetWidth(16 + E.Border)
+ f.keyButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.keyButton)
+ f.keyButton:SetPoint("RIGHT", f.sortButton, "LEFT", -5, 0)
+ f.keyButton:SetNormalTexture("Interface\\ICONS\\INV_Misc_Key_14")
+ f.keyButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.keyButton:GetNormalTexture())
+ f.keyButton:SetPushedTexture("Interface\\ICONS\\INV_Misc_Key_14")
+ f.keyButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.keyButton:GetPushedTexture())
+ E:StyleButton(f.keyButton, nil, true)
+ f.keyButton.ttText = L["Toggle Key"]
+ f.keyButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.keyButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.keyButton:SetScript("OnClick", function() ToggleFrame(f.keyFrame) end)
+
+ f.bagsButton = CreateFrame("Button", name.."BagsButton", f)
+ f.bagsButton:SetWidth(16 + E.Border)
+ f.bagsButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.bagsButton)
+ f.bagsButton:SetPoint("RIGHT", f.keyButton, "LEFT", -5, 0)
+ f.bagsButton:SetNormalTexture("Interface\\Buttons\\Button-Backpack-Up")
+ f.bagsButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.bagsButton:GetNormalTexture())
+ f.bagsButton:SetPushedTexture("Interface\\Buttons\\Button-Backpack-Up")
+ f.bagsButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.bagsButton:GetPushedTexture())
+ E:StyleButton(f.bagsButton, nil, true)
+ f.bagsButton.ttText = L["Toggle Bags"]
+ f.bagsButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.bagsButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.bagsButton:SetScript("OnClick", function() ToggleFrame(f.ContainerHolder) end)
+
+ f.vendorGraysButton = CreateFrame("Button", nil, f.holderFrame)
+ f.vendorGraysButton:SetWidth(16 + E.Border)
+ f.vendorGraysButton:SetHeight(16 + E.Border)
+ E:SetTemplate(f.vendorGraysButton)
+ f.vendorGraysButton:SetPoint("RIGHT", f.bagsButton, "LEFT", -5, 0)
+ f.vendorGraysButton:SetNormalTexture("Interface\\ICONS\\INV_Misc_Coin_01")
+ f.vendorGraysButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.vendorGraysButton:GetNormalTexture())
+ f.vendorGraysButton:SetPushedTexture("Interface\\ICONS\\INV_Misc_Coin_01")
+ f.vendorGraysButton:GetPushedTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(f.vendorGraysButton:GetPushedTexture())
+ E:StyleButton(f.vendorGraysButton, nil, true)
+ f.vendorGraysButton.ttText = L["Vendor Grays"]
+ f.vendorGraysButton:SetScript("OnEnter", self.Tooltip_Show)
+ f.vendorGraysButton:SetScript("OnLeave", self.Tooltip_Hide)
+ f.vendorGraysButton:SetScript("OnClick", B.VendorGrayCheck)
+
+ f.editBox = CreateFrame("EditBox", name.."EditBox", f)
+ f.editBox:SetFrameLevel(f.editBox:GetFrameLevel() + 2)
+ E:CreateBackdrop(f.editBox, "Default")
+ f.editBox.backdrop:SetPoint("TOPLEFT", f.editBox, "TOPLEFT", -20, 2)
+ f.editBox:SetHeight(15)
+ f.editBox:SetPoint("BOTTOMLEFT", f.holderFrame, "TOPLEFT", (E.Border * 2) + 18, E.Border * 2 + 2)
+ f.editBox:SetPoint("RIGHT", f.vendorGraysButton, "LEFT", -5, 0)
+ f.editBox:SetAutoFocus(false)
+ f.editBox:SetScript("OnEscapePressed", self.ResetAndClear)
+ f.editBox:SetScript("OnEnterPressed", function() this:ClearFocus() end)
+ f.editBox:SetScript("OnEditFocusGained", function() this:HighlightText() end)
+ f.editBox:SetScript("OnTextChanged", self.UpdateSearch)
+ f.editBox:SetScript("OnChar", self.UpdateSearch)
+ f.editBox:SetText(SEARCH)
+ E:FontTemplate(f.editBox)
+
+ f.editBox.searchIcon = f.editBox:CreateTexture(nil, "OVERLAY")
+ f.editBox.searchIcon:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\UI-Searchbox-Icon")
+ f.editBox.searchIcon:SetPoint("LEFT", f.editBox.backdrop, "LEFT", E.Border + 1, -1)
+ f.editBox.searchIcon:SetWidth(15)
+ f.editBox.searchIcon:SetHeight(15)
+
+ f:SetScript("OnHide", function()
+ CloseBackpack()
+ for i = 1, NUM_BAG_FRAMES do
+ CloseBag(i)
+ end
+
+ if ElvUIBags and ElvUIBags.buttons then
+ for _, bagButton in pairs(ElvUIBags.buttons) do
+ bagButton:SetChecked(false)
+ end
+ end
+ if E.db.bags.clearSearchOnClose then
+ B.ResetAndClear(f.editBox)
+ end
+ end)
+ end
+
+ f:SetScript("OnShow", function()
+ this:UpdateCooldowns()
+ end)
+
+ tinsert(UISpecialFrames, f:GetName()) --Keep an eye on this for taints..
+ tinsert(self.BagFrames, f)
+ return f
+end
+
+function B:ToggleBags(id)
+ --Closes a bag when inserting a new container..
+ if id and GetContainerNumSlots(id) == 0 then return end
+
+ if self.BagFrame:IsShown() then
+ self:CloseBags()
+ else
+ self:OpenBags()
+ end
+end
+
+function B:ToggleBackpack()
+ if IsOptionFrameOpen() then
+ return
+ end
+
+ if IsBagOpen(0) then
+ self:OpenBags()
+ else
+ self:CloseBags()
+ end
+end
+
+function B:OpenAllBags()
+ if IsOptionFrameOpen() then
+ return
+ end
+
+ if self.BagFrame:IsShown() then
+ self:CloseBags()
+ else
+ self:OpenBags()
+ end
+end
+
+function B:ToggleSortButtonState(isBank)
+ local button, disable
+ if isBank and self.BankFrame then
+ button = self.BankFrame.sortButton
+ disable = E.db.bags.disableBankSort
+ elseif not isBank and self.BagFrame then
+ button = self.BagFrame.sortButton
+ disable = E.db.bags.disableBagSort
+ end
+
+ if button and disable then
+ button:Disable()
+ elseif button and not disable then
+ button:Enable()
+ end
+end
+
+function B:OpenBags()
+ self.BagFrame:Show()
+ self.BagFrame:UpdateAllSlots()
+ E:GetModule("Tooltip"):GameTooltip_SetDefaultAnchor(GameTooltip)
+end
+
+function B:CloseBags()
+ self.BagFrame:Hide()
+
+ if self.BankFrame then
+ self.BankFrame:Hide()
+ end
+
+ E:GetModule("Tooltip"):GameTooltip_SetDefaultAnchor(GameTooltip)
+end
+
+function B:OpenBank()
+ if not self.BankFrame then
+ self.BankFrame = self:ContructContainerFrame("ElvUI_BankContainerFrame", true)
+ end
+
+ self:Layout(true)
+ self.BankFrame:Show()
+ self.BankFrame:UpdateAllSlots()
+ self:OpenBags()
+end
+
+function B:PLAYERBANKBAGSLOTS_CHANGED()
+ self:Layout(true)
+end
+
+function B:CloseBank()
+ if not self.BankFrame then return end -- WHY???, WHO KNOWS!
+ self.BankFrame:Hide()
+end
+
+function B:PostBagMove()
+ if not E.private.bags.enable then return end
+
+ local x, y = self:GetCenter()
+ local screenHeight = UIParent:GetTop()
+ local screenWidth = UIParent:GetRight()
+
+ if not x then return end
+
+ if y > (screenHeight / 2) then
+ self:SetText(self.textGrowDown)
+ self.POINT = ((x > (screenWidth/2)) and "TOPRIGHT" or "TOPLEFT")
+ else
+ self:SetText(self.textGrowUp)
+ self.POINT = ((x > (screenWidth/2)) and "BOTTOMRIGHT" or "BOTTOMLEFT")
+ end
+
+ local bagFrame
+ if self.name == "ElvUIBankMover" then
+ bagFrame = B.BankFrame
+ else
+ bagFrame = B.BagFrame
+ end
+
+ if bagFrame then
+ bagFrame:ClearAllPoints()
+ bagFrame:SetPoint(self.POINT, self)
+ end
+end
+
+function B:Initialize()
+ self:LoadBagBar()
+
+ local BagFrameHolder = CreateFrame("Frame", nil, E.UIParent)
+ BagFrameHolder:SetWidth(200)
+ BagFrameHolder:SetHeight(22)
+ BagFrameHolder:SetFrameLevel(BagFrameHolder:GetFrameLevel() + 400)
+
+ if not E.private.bags.enable then
+ BagFrameHolder:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", -(E.Border*2), 22 + E.Border*4 - E.Spacing*2)
+ E:CreateMover(BagFrameHolder, "ElvUIBagMover", L["Bag Mover"], nil, nil, B.PostBagMove)
+
+ -- self:SecureHook("UpdateContainerFrameAnchors")
+ return
+ end
+
+ E.bags = self
+ self.db = E.db.bags
+ self.BagFrames = {}
+
+ BagFrameHolder:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", 0, 22 + E.Border*4 - E.Spacing*2)
+ E:CreateMover(BagFrameHolder, "ElvUIBagMover", L["Bag Mover (Grow Up)"], nil, nil, B.PostBagMove)
+
+ local BankFrameHolder = CreateFrame("Frame", nil, E.UIParent)
+ BankFrameHolder:SetWidth(200)
+ BankFrameHolder:SetHeight(22)
+ BankFrameHolder:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", 0, 22 + E.Border*4 - E.Spacing*2)
+ BankFrameHolder:SetFrameLevel(BankFrameHolder:GetFrameLevel() + 400)
+ E:CreateMover(BankFrameHolder, "ElvUIBankMover", L["Bank Mover (Grow Up)"], nil, nil, B.PostBagMove)
+
+ ElvUIBagMover.textGrowUp = L["Bag Mover (Grow Up)"]
+ ElvUIBagMover.textGrowDown = L["Bag Mover (Grow Down)"]
+ ElvUIBagMover.POINT = "BOTTOMRIGHT"
+ ElvUIBankMover.textGrowUp = L["Bank Mover (Grow Up)"]
+ ElvUIBankMover.textGrowDown = L["Bank Mover (Grow Down)"]
+ ElvUIBankMover.POINT = "BOTTOMLEFT"
+
+ self.BagFrame = self:ContructContainerFrame("ElvUI_ContainerFrame")
+
+ --Hook onto Blizzard Functions
+ self:RawHook("ToggleBag", "ToggleBags")
+ self:RawHook("OpenBackpack", "OpenBags")
+ self:RawHook("CloseAllBags", "CloseBags")
+ self:RawHook("CloseBackpack", "CloseBags")
+ self:RawHook("ToggleBackpack", "ToggleBags")
+ self:RawHook("OpenAllBags", "OpenAllBags", true)
+
+ self:Layout()
+
+ E.Bags = self
+
+ self:DisableBlizzard()
+ self:RegisterEvent("PLAYER_MONEY", "UpdateGoldText")
+ self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateGoldText")
+ self:RegisterEvent("PLAYER_TRADE_MONEY", "UpdateGoldText")
+ self:RegisterEvent("TRADE_MONEY_CHANGED", "UpdateGoldText")
+ self:RegisterEvent("BANKFRAME_OPENED", "OpenBank")
+ self:RegisterEvent("BANKFRAME_CLOSED", "CloseBank")
+ self:RegisterEvent("PLAYERBANKBAGSLOTS_CHANGED")
+
+ StackSplitFrame:SetFrameStrata("DIALOG")
+end
+
+local function InitializeCallback()
+ B:Initialize()
+end
+
+E:RegisterModule(B:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Bags/Load_Bags.xml b/ElvUI/Modules/Bags/Load_Bags.xml
new file mode 100644
index 0000000..3213cc4
--- /dev/null
+++ b/ElvUI/Modules/Bags/Load_Bags.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Bags/Sort.lua b/ElvUI/Modules/Bags/Sort.lua
new file mode 100644
index 0000000..a8e58ff
--- /dev/null
+++ b/ElvUI/Modules/Bags/Sort.lua
@@ -0,0 +1,813 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Bags");
+local Search = LibStub("LibItemSearch-1.2");
+
+--Cache global variables
+--Lua functions
+local ipairs, pairs, tonumber, select, unpack = ipairs, pairs, tonumber, select, unpack
+local tinsert, tremove, tsort, twipe = table.insert, table.remove, table.sort, table.wipe
+local floor, mod = math.floor, math.mod
+local band = bit.band
+local match, gmatch, find = string.match, string.gmatch, string.find
+--WoW API / Variables
+local GetTime = GetTime
+local GetItemInfo = GetItemInfo
+local GetAuctionItemClasses = GetAuctionItemClasses
+local GetAuctionItemSubClasses = GetAuctionItemSubClasses
+local GetContainerItemInfo = GetContainerItemInfo
+local GetContainerItemLink = GetContainerItemLink
+local PickupContainerItem = PickupContainerItem
+local SplitContainerItem = SplitContainerItem
+local GetContainerNumSlots = GetContainerNumSlots
+local GetContainerNumFreeSlots = GetContainerNumFreeSlots
+local ContainerIDToInventoryID = ContainerIDToInventoryID
+local GetInventoryItemLink = GetInventoryItemLink
+local CursorHasItem = CursorHasItem
+local ARMOR = ARMOR
+
+local bankBags = {BANK_CONTAINER}
+local MAX_MOVE_TIME = 1.25
+
+for i = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
+ tinsert(bankBags, i)
+end
+
+local playerBags = {}
+for i = 0, NUM_BAG_SLOTS do
+ tinsert(playerBags, i)
+end
+
+local allBags = {}
+for _, i in ipairs(playerBags) do
+ tinsert(allBags, i)
+end
+for _, i in ipairs(bankBags) do
+ tinsert(allBags, i)
+end
+
+local coreGroups = {
+ bank = bankBags,
+ bags = playerBags,
+ all = allBags,
+}
+
+local bagCache = {}
+local bagIDs = {}
+local bagQualities = {}
+local bagStacks = {}
+local bagMaxStacks = {}
+local bagGroups = {}
+local initialOrder = {}
+local itemTypes, itemSubTypes
+local bagSorted, bagLocked = {}, {}
+local bagRole
+local moves = {}
+local targetItems = {}
+local sourceUsed = {}
+local targetSlots = {}
+local specialtyBags = {}
+local emptySlots = {}
+
+local moveRetries = 0
+local lastItemID, currentItemID, lockStop, lastDestination, lastMove
+local moveTracker = {}
+
+local inventorySlots = {
+ INVTYPE_AMMO = 0,
+ INVTYPE_HEAD = 1,
+ INVTYPE_NECK = 2,
+ INVTYPE_SHOULDER = 3,
+ INVTYPE_BODY = 4,
+ INVTYPE_CHEST = 5,
+ INVTYPE_ROBE = 5,
+ INVTYPE_WAIST = 6,
+ INVTYPE_LEGS = 7,
+ INVTYPE_FEET = 8,
+ INVTYPE_WRIST = 9,
+ INVTYPE_HAND = 10,
+ INVTYPE_FINGER = 11,
+ INVTYPE_TRINKET = 12,
+ INVTYPE_CLOAK = 13,
+ INVTYPE_WEAPON = 14,
+ INVTYPE_SHIELD = 15,
+ INVTYPE_2HWEAPON = 16,
+ INVTYPE_WEAPONMAINHAND = 18,
+ INVTYPE_WEAPONOFFHAND = 19,
+ INVTYPE_HOLDABLE = 20,
+ INVTYPE_RANGED = 21,
+ INVTYPE_THROWN = 22,
+ INVTYPE_RANGEDRIGHT = 23,
+ INVTYPE_RELIC = 24,
+ INVTYPE_TABARD = 25,
+}
+
+local safe = {
+ [BANK_CONTAINER] = true,
+ [0] = true
+}
+
+local frame = CreateFrame("Frame")
+local t, WAIT_TIME = 0, 0.05
+frame:SetScript("OnUpdate", function(_, elapsed)
+ t = t + (elapsed or 0.01)
+ if t > WAIT_TIME then
+ t = 0
+ B:DoMoves()
+ end
+end)
+frame:Hide()
+B.SortUpdateTimer = frame
+
+local function BuildSortOrder()
+ itemTypes = {}
+ itemSubTypes = {}
+ for i, iType in ipairs({GetAuctionItemClasses()}) do
+ itemTypes[iType] = i
+ itemSubTypes[iType] = {}
+ for ii, isType in ipairs({GetAuctionItemSubClasses(i)}) do
+ itemSubTypes[iType][isType] = ii
+ end
+ end
+end
+
+local function UpdateLocation(from, to)
+ if (bagIDs[from] == bagIDs[to]) and (bagStacks[to] < bagMaxStacks[to]) then
+ local stackSize = bagMaxStacks[to]
+ if (bagStacks[to] + bagStacks[from]) > stackSize then
+ bagStacks[from] = bagStacks[from] - (stackSize - bagStacks[to])
+ bagStacks[to] = stackSize
+ else
+ bagStacks[to] = bagStacks[to] + bagStacks[from]
+ bagStacks[from] = nil
+ bagIDs[from] = nil
+ bagQualities[from] = nil
+ bagMaxStacks[from] = nil
+ end
+ else
+ bagIDs[from], bagIDs[to] = bagIDs[to], bagIDs[from]
+ bagQualities[from], bagQualities[to] = bagQualities[to], bagQualities[from]
+ bagStacks[from], bagStacks[to] = bagStacks[to], bagStacks[from]
+ bagMaxStacks[from], bagMaxStacks[to] = bagMaxStacks[to], bagMaxStacks[from]
+ end
+end
+
+local function PrimarySort(a, b)
+ local aName, _, _, aLvl, _, _, _, _, _, _, aPrice = GetItemInfo(bagIDs[a])
+ local bName, _, _, bLvl, _, _, _, _, _, _, bPrice = GetItemInfo(bagIDs[b])
+
+ if aLvl ~= bLvl and aLvl and bLvl then
+ return aLvl > bLvl
+ end
+ if aPrice ~= bPrice and aPrice and bPrice then
+ return aPrice > bPrice
+ end
+
+ if aName and bName then
+ return aName < bName
+ end
+end
+
+local function DefaultSort(a, b)
+ local aID = bagIDs[a]
+ local bID = bagIDs[b]
+
+ if (not aID) or (not bID) then return aID end
+
+ local aOrder, bOrder = initialOrder[a], initialOrder[b]
+
+ if aID == bID then
+ local aCount = bagStacks[a]
+ local bCount = bagStacks[b]
+ if aCount and bCount and aCount == bCount then
+ return aOrder < bOrder
+ elseif aCount and bCount then
+ return aCount < bCount
+ end
+ end
+
+ local _, _, aRarity, _, _, aType, aSubType, _, aEquipLoc = GetItemInfo(aID)
+ local _, _, bRarity, _, _, bType, bSubType, _, bEquipLoc = GetItemInfo(bID)
+
+ aRarity = bagQualities[a]
+ bRarity = bagQualities[b]
+
+ if aRarity ~= bRarity and aRarity and bRarity then
+ return aRarity > bRarity
+ end
+
+ if itemTypes[aType] ~= itemTypes[bType] then
+ return (itemTypes[aType] or 99) < (itemTypes[bType] or 99)
+ end
+
+ if aType == ARMOR then
+ local aEquipLoc = inventorySlots[aEquipLoc] or -1
+ local bEquipLoc = inventorySlots[bEquipLoc] or -1
+ if aEquipLoc == bEquipLoc then
+ return PrimarySort(a, b)
+ end
+
+ if aEquipLoc and bEquipLoc then
+ return aEquipLoc < bEquipLoc
+ end
+ end
+
+ if aSubType == bSubType then
+ return PrimarySort(a, b)
+ end
+
+ return ((itemSubTypes[aType] or {})[aSubType] or 99) < ((itemSubTypes[bType] or {})[bSubType] or 99)
+end
+
+local function ReverseSort(a, b)
+ return DefaultSort(b, a)
+end
+
+local function UpdateSorted(source, destination)
+ for i, bs in pairs(bagSorted) do
+ if bs == source then
+ bagSorted[i] = destination
+ elseif bs == destination then
+ bagSorted[i] = source
+ end
+ end
+end
+
+local function ShouldMove(source, destination)
+ if destination == source then return end
+
+ if not bagIDs[source] then return end
+ if bagIDs[source] == bagIDs[destination] and bagStacks[source] == bagStacks[destination] then return end
+
+ return true
+end
+
+local function IterateForwards(bagList, i)
+ i = i + 1
+ local step = 1
+ for _, bag in ipairs(bagList) do
+ local slots = B:GetNumSlots(bag, bagRole)
+ if i > slots + step then
+ step = step + slots
+ else
+ for slot = 1, slots do
+ if step == i then
+ return i, bag, slot
+ end
+ step = step + 1
+ end
+ end
+ end
+ bagRole = nil
+end
+
+local function IterateBackwards(bagList, i)
+ i = i + 1
+ local step = 1
+ for ii = getn(bagList), 1, -1 do
+ local bag = bagList[ii]
+ local slots = B:GetNumSlots(bag, bagRole)
+ if i > slots + step then
+ step = step + slots
+ else
+ for slot = slots, 1, -1 do
+ if step == i then
+ return i, bag, slot
+ end
+ step = step + 1
+ end
+ end
+ end
+ bagRole = nil
+end
+
+function B.IterateBags(bagList, reverse, role)
+ bagRole = role
+ return (reverse and IterateBackwards or IterateForwards), bagList, 0
+end
+
+function B:GetItemID(bag, slot)
+ local link = self:GetItemLink(bag, slot)
+ return link and tonumber(match(link, "item:(%d+)"))
+end
+
+function B:GetItemInfo(bag, slot)
+ return GetContainerItemInfo(bag, slot)
+end
+
+function B:GetItemLink(bag, slot)
+ return GetContainerItemLink(bag, slot)
+end
+
+function B:PickupItem(bag, slot)
+ return PickupContainerItem(bag, slot)
+end
+
+function B:SplitItem(bag, slot, amount)
+ return SplitContainerItem(bag, slot, amount)
+end
+
+function B:GetNumSlots(bag, role)
+ if bag then
+ return GetContainerNumSlots(bag);
+ end
+ return 0
+end
+
+local function ConvertLinkToID(link)
+ if not link then return end
+
+ if tonumber(match(link, "item:(%d+)")) then
+ return tonumber(match(link, "item:(%d+)"))
+ end
+end
+
+local function DefaultCanMove()
+ return true
+end
+
+function B:Encode_BagSlot(bag, slot)
+ return (bag*100) + slot
+end
+
+function B:Decode_BagSlot(int)
+ return floor(int/100), mod(int, 100)
+end
+
+function B:IsPartial(bag, slot)
+ local bagSlot = B:Encode_BagSlot(bag, slot)
+ return ((bagMaxStacks[bagSlot] or 0) - (bagStacks[bagSlot] or 0)) > 0
+end
+
+function B:EncodeMove(source, target)
+ return (source * 10000) + target
+end
+
+function B:DecodeMove(move)
+ local s = floor(move/10000)
+ local t = mod(move,10000)
+ s = (t>9000) and (s+1) or s
+ t = (t>9000) and (t-10000) or t
+ return s, t
+end
+
+function B:AddMove(source, destination)
+ UpdateLocation(source, destination)
+ tinsert(moves, 1, B:EncodeMove(source, destination))
+end
+
+function B:ScanBags()
+ for _, bag, slot in B.IterateBags(allBags) do
+ local bagSlot = B:Encode_BagSlot(bag, slot)
+ local itemID = ConvertLinkToID(B:GetItemLink(bag, slot))
+ if itemID then
+ bagMaxStacks[bagSlot] = select(7, GetItemInfo(itemID))
+ bagIDs[bagSlot] = itemID
+ bagQualities[bagSlot] = select(3, GetItemInfo(itemID))
+ bagStacks[bagSlot] = select(2, B:GetItemInfo(bag, slot))
+ end
+ end
+end
+
+-- TEMPORARY MAYBE UNTIL ALTERNATIVE FIX
+function B:GetItemFamily(bagType)
+ local itemSubType = select(6, GetItemInfo(match(bagType, "item:(%d+)")))
+
+ if strupper(itemSubType) == "BAG" then
+ return 0
+ elseif strupper(itemSubType) == "QUIVER" then
+ return 1
+ elseif strupper(itemSubType) == "KEYRING" then
+ return -2
+ else
+ return nil
+ end
+end
+
+function B:IsSpecialtyBag(bagID)
+ if safe[bagID] then return false end
+
+ local inventorySlot = ContainerIDToInventoryID(bagID)
+ if not inventorySlot then return false end
+
+ local bag = GetInventoryItemLink("player", inventorySlot)
+ if not bag then return false end
+
+ local family = B:GetItemFamily(bag)
+ if family == 0 or family == nil then return false end
+
+ return family
+end
+
+function B:CanItemGoInBag(bag, slot, targetBag)
+ local item = bagIDs[B:Encode_BagSlot(bag, slot)]
+ local itemFamily = B:GetItemFamily(item)
+ if itemFamily and itemFamily > 0 then
+ local equipSlot = select(7, GetItemInfo(item))
+ if equipSlot == "INVTYPE_BAG" then
+ itemFamily = 1
+ end
+ end
+ local bagFamily = select(2, GetContainerNumFreeSlots(targetBag))
+ if itemFamily then
+ return (bagFamily == 0) or band(itemFamily, bagFamily) > 0
+ else
+ return false
+ end
+end
+
+function B.Compress(...)
+ for i = 1, getn(arg) do
+ local bags = arg[i]
+ B.Stack(bags, bags, B.IsPartial)
+ end
+end
+
+function B.Stack(sourceBags, targetBags, canMove)
+ if not canMove then canMove = DefaultCanMove end
+
+ for _, bag, slot in B.IterateBags(targetBags, nil, "deposit") do
+ local bagSlot = B:Encode_BagSlot(bag, slot)
+ local itemID = bagIDs[bagSlot]
+
+ if itemID and (bagStacks[bagSlot] ~= bagMaxStacks[bagSlot]) then
+ targetItems[itemID] = (targetItems[itemID] or 0) + 1
+ tinsert(targetSlots, bagSlot)
+ end
+ end
+
+ for _, bag, slot in B.IterateBags(sourceBags, true, "withdraw") do
+ local sourceSlot = B:Encode_BagSlot(bag, slot)
+ local itemID = bagIDs[sourceSlot]
+ if itemID and targetItems[itemID] and canMove(itemID, bag, slot) then
+ for i = getn(targetSlots), 1, -1 do
+ local targetedSlot = targetSlots[i]
+ if bagIDs[sourceSlot] and bagIDs[targetedSlot] == itemID and targetedSlot ~= sourceSlot and not (bagStacks[targetedSlot] == bagMaxStacks[targetedSlot]) and not sourceUsed[targetedSlot] then
+ B:AddMove(sourceSlot, targetedSlot)
+ sourceUsed[sourceSlot] = true
+
+ if bagStacks[targetedSlot] == bagMaxStacks[targetedSlot] then
+ targetItems[itemID] = (targetItems[itemID] > 1) and (targetItems[itemID] - 1) or nil
+ end
+ if bagStacks[sourceSlot] == 0 then
+ targetItems[itemID] = (targetItems[itemID] > 1) and (targetItems[itemID] - 1) or nil
+ break
+ end
+ if not targetItems[itemID] then break end
+ end
+ end
+ end
+ end
+
+ twipe(targetItems)
+ twipe(targetSlots)
+ twipe(sourceUsed)
+end
+
+local blackListedSlots = {}
+local blackList = {}
+local blackListQueries = {}
+
+local function buildBlacklist(...)
+ for entry in pairs(arg) do
+ local itemName = GetItemInfo(entry)
+ if itemName then
+ blackList[itemName] = true
+ elseif entry ~= "" then
+ if find(entry, "%[") and find(entry, "%]") then
+ entry = match(entry, "%[(.*)%]")
+ end
+ blackListQueries[getn(blackListQueries)+1] = entry
+ end
+ end
+end
+
+function B.Sort(bags, sorter, invertDirection)
+ if not sorter then sorter = invertDirection and ReverseSort or DefaultSort end
+ if not itemTypes then BuildSortOrder() end
+
+ twipe(blackList)
+ twipe(blackListQueries)
+ twipe(blackListedSlots)
+
+ buildBlacklist(B.db.ignoredItems)
+ buildBlacklist(E.global.bags.ignoredItems)
+
+ for i, bag, slot in B.IterateBags(bags, nil, "both") do
+ local bagSlot = B:Encode_BagSlot(bag, slot)
+ local link = B:GetItemLink(bag, slot)
+
+ if link then
+ if blackList[GetItemInfo(link)] then
+ blackListedSlots[bagSlot] = true
+ end
+
+ if not blackListedSlots[bagSlot] then
+ for _, itemsearchquery in pairs(blackListQueries) do
+ local success, result = pcall(Search.Matches, Search, link, itemsearchquery)
+ if success and result then
+ blackListedSlots[bagSlot] = blackListedSlots[bagSlot] or result
+ break
+ end
+ end
+ end
+ end
+
+ if not blackListedSlots[bagSlot] then
+ initialOrder[bagSlot] = i
+ tinsert(bagSorted, bagSlot)
+ end
+ end
+
+ tsort(bagSorted, sorter)
+
+ local passNeeded = true
+ while passNeeded do
+ passNeeded = false
+ local i = 1
+ for _, bag, slot in B.IterateBags(bags, nil, "both") do
+ local destination = B:Encode_BagSlot(bag, slot)
+ local source = bagSorted[i]
+
+ if not blackListedSlots[destination] then
+ if ShouldMove(source, destination) then
+ if not (bagLocked[source] or bagLocked[destination]) then
+ B:AddMove(source, destination)
+ UpdateSorted(source, destination)
+ bagLocked[source] = true
+ bagLocked[destination] = true
+ else
+ passNeeded = true
+ end
+ end
+ i = i + 1
+ end
+ end
+ twipe(bagLocked)
+ end
+
+ twipe(bagSorted)
+ twipe(initialOrder)
+end
+
+function B.FillBags(from, to)
+ B.Stack(from, to)
+ for _, bag in ipairs(to) do
+ if B:IsSpecialtyBag(bag) then
+ tinsert(specialtyBags, bag)
+ end
+ end
+ if getn(specialtyBags) > 0 then
+ B:Fill(from, specialtyBags)
+ end
+
+ B.Fill(from, to)
+ twipe(specialtyBags)
+end
+
+function B.Fill(sourceBags, targetBags, reverse, canMove)
+ if not canMove then canMove = DefaultCanMove end
+
+ twipe(blackList)
+ twipe(blackListedSlots)
+
+ buildBlacklist(B.db.ignoredItems)
+ buildBlacklist(E.global.bags.ignoredItems)
+
+ for _, bag, slot in B.IterateBags(targetBags, reverse, "deposit") do
+ local bagSlot = B:Encode_BagSlot(bag, slot)
+ if not bagIDs[bagSlot] then
+ tinsert(emptySlots, bagSlot)
+ end
+ end
+
+ for _, bag, slot in B.IterateBags(sourceBags, not reverse, "withdraw") do
+ if getn(emptySlots) == 0 then break end
+ local bagSlot = B:Encode_BagSlot(bag, slot)
+ local targetBag = B:Decode_BagSlot(emptySlots[1])
+ local link = B:GetItemLink(bag, slot)
+
+ if link and blackList[GetItemInfo(link)] then
+ blackListedSlots[bagSlot] = true
+ end
+
+ if bagIDs[bagSlot] and B:CanItemGoInBag(bag, slot, targetBag) and canMove(bagIDs[bagSlot], bag, slot) and not blackListedSlots[bagSlot] then
+ B:AddMove(bagSlot, tremove(emptySlots, 1))
+ end
+ end
+ twipe(emptySlots)
+end
+
+function B.SortBags(...)
+ for i = 1, getn(arg) do
+ local bags = arg[i]
+ for i, slotNum in ipairs(bags) do
+ local bagType = B:IsSpecialtyBag(slotNum)
+ if bagType == false then bagType = "Normal" end
+ if not bagCache[bagType] then bagCache[bagType] = {} end
+ bagCache[bagType][i] = slotNum
+ end
+ for bagType, sortedBags in pairs(bagCache) do
+ if bagType ~= "Normal" then
+ B.Stack(sortedBags, sortedBags, B.IsPartial)
+ B.Stack(bagCache["Normal"], sortedBags)
+ B.Fill(bagCache["Normal"], sortedBags, B.db.sortInverted)
+ B.Sort(sortedBags, nil, B.db.sortInverted)
+ twipe(sortedBags)
+ end
+ end
+
+ if bagCache["Normal"] then
+ B.Stack(bagCache["Normal"], bagCache["Normal"], B.IsPartial)
+ B.Sort(bagCache["Normal"], nil, B.db.sortInverted)
+ twipe(bagCache["Normal"])
+ end
+ twipe(bagCache)
+ twipe(bagGroups)
+ end
+end
+
+function B:StartStacking()
+ twipe(bagMaxStacks)
+ twipe(bagStacks)
+ twipe(bagIDs)
+ twipe(bagQualities)
+ twipe(moveTracker)
+
+ if getn(moves) > 0 then
+ self.SortUpdateTimer:Show()
+ else
+ B:StopStacking()
+ end
+end
+
+function B:StopStacking(message)
+ twipe(moves)
+ twipe(moveTracker)
+ moveRetries, lastItemID, currentItemID, lockStop, lastDestination, lastMove = 0, nil, nil, nil, nil, nil
+
+ self.SortUpdateTimer:Hide()
+ if message then
+ E:Print(message)
+ end
+end
+
+function B:DoMove(move)
+ if CursorHasItem() then
+ return false, "cursorhasitem"
+ end
+
+ local source, target = B:DecodeMove(move)
+ local sourceBag, sourceSlot = B:Decode_BagSlot(source)
+ local targetBag, targetSlot = B:Decode_BagSlot(target)
+
+ local _, sourceCount, sourceLocked = B:GetItemInfo(sourceBag, sourceSlot)
+ local _, targetCount, targetLocked = B:GetItemInfo(targetBag, targetSlot)
+
+ if sourceLocked or targetLocked then
+ return false, "source/target_locked"
+ end
+
+ local sourceItemID = self:GetItemID(sourceBag, sourceSlot)
+ local targetItemID = self:GetItemID(targetBag, targetSlot)
+
+ if not sourceItemID then
+ if moveTracker[source] then
+ return false, "move incomplete"
+ else
+ return B:StopStacking(L["Confused.. Try Again!"])
+ end
+ end
+
+ local stackSize = select(7, GetItemInfo(sourceItemID))
+ if (sourceItemID == targetItemID) and (targetCount ~= stackSize) and ((targetCount + sourceCount) > stackSize) then
+ B:SplitItem(sourceBag, sourceSlot, stackSize - targetCount)
+ else
+ B:PickupItem(sourceBag, sourceSlot)
+ end
+
+ if CursorHasItem() then
+ B:PickupItem(targetBag, targetSlot)
+ end
+
+ return true, sourceItemID, source, targetItemID, target
+end
+
+function B:DoMoves()
+ if CursorHasItem() and currentItemID then
+ if lastItemID ~= currentItemID then
+ return B:StopStacking(L["Confused.. Try Again!"])
+ end
+
+ if moveRetries < 100 then
+ local targetBag, targetSlot = self:Decode_BagSlot(lastDestination)
+ local _, _, targetLocked = self:GetItemInfo(targetBag, targetSlot)
+ if not targetLocked then
+ self:PickupItem(targetBag, targetSlot)
+ WAIT_TIME = 0.1
+ lockStop = GetTime()
+ moveRetries = moveRetries + 1
+ return
+ end
+ end
+ end
+
+ if lockStop then
+ for slot, itemID in pairs(moveTracker) do
+ local actualItemID = self:GetItemID(self:Decode_BagSlot(slot))
+ if actualItemID ~= itemID then
+ WAIT_TIME = 0.1
+ if (GetTime() - lockStop) > MAX_MOVE_TIME then
+ if lastMove and moveRetries < 100 then
+ local success, moveID, moveSource, targetID, moveTarget = self:DoMove(lastMove)
+ WAIT_TIME = 0.1
+
+ if not success then
+ lockStop = GetTime()
+ moveRetries = moveRetries + 1
+ return
+ end
+
+ moveTracker[moveSource] = targetID
+ moveTracker[moveTarget] = moveID
+ lastDestination = moveTarget
+ lastMove = moves[i]
+ lastItemID = moveID
+ tremove(moves, i)
+ return
+ end
+
+ B:StopStacking()
+ return
+ end
+ return --give processing time to happen
+ end
+ moveTracker[slot] = nil
+ end
+ end
+
+ lastItemID, lockStop, lastDestination, lastMove = nil, nil, nil, nil
+ twipe(moveTracker)
+
+ local success, moveID, targetID, moveSource, moveTarget
+ if getn(moves) > 0 then
+ for i = getn(moves), 1, -1 do
+ success, moveID, moveSource, targetID, moveTarget = B:DoMove(moves[i])
+ if not success then
+ WAIT_TIME = 0.1
+ lockStop = GetTime()
+ return
+ end
+ moveTracker[moveSource] = targetID
+ moveTracker[moveTarget] = moveID
+ lastDestination = moveTarget
+ lastMove = moves[i]
+ lastItemID = moveID
+ tremove(moves, i)
+
+ if moves[i-1] then
+ WAIT_TIME = 0
+ return
+ end
+ end
+ end
+ B:StopStacking()
+end
+
+function B:GetGroup(id)
+ if match(id, "^[-%d,]+$") then
+ local bags = {}
+ for b in gmatch(id, "-?%d+") do
+ tinsert(bags, tonumber(b))
+ end
+ return bags
+ end
+ return coreGroups[id]
+end
+
+function B:CommandDecorator(func, groupsDefaults)
+ return function(groups)
+ if self.SortUpdateTimer:IsShown() then
+ E:Print(L["Already Running.. Bailing Out!"])
+ B:StopStacking()
+ return
+ end
+
+ twipe(bagGroups)
+ if not groups or getn(groups) == 0 then
+ groups = groupsDefaults
+ end
+ for bags in gmatch(groups or "", "[^%s]+") do
+ bags = B:GetGroup(bags)
+ if bags then
+ tinsert(bagGroups, bags)
+ end
+ end
+
+ B:ScanBags()
+ if func(unpack(bagGroups)) == false then
+ return
+ end
+ twipe(bagGroups)
+ B:StartStacking()
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/AlertFrame.lua b/ElvUI/Modules/Blizzard/AlertFrame.lua
new file mode 100644
index 0000000..827be95
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/AlertFrame.lua
@@ -0,0 +1,83 @@
+local E, L, DF = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Blizzard");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs = pairs
+--WoW API / Variables
+local NUM_GROUP_LOOT_FRAMES = NUM_GROUP_LOOT_FRAMES
+
+local AlertFrameHolder = CreateFrame("Frame", "AlertFrameHolder", E.UIParent)
+AlertFrameHolder:SetWidth(250)
+AlertFrameHolder:SetHeight(20)
+AlertFrameHolder:SetPoint("TOP", E.UIParent, "TOP", 0, -18)
+
+function E:PostAlertMove()
+ local position = "TOP"
+ local _, y = AlertFrameMover:GetCenter()
+ local screenHeight = E.UIParent:GetTop()
+ if y > (screenHeight / 2) then
+ position = "TOP"
+ AlertFrameMover:SetText(AlertFrameMover.textString .. " [Grow Down]")
+ else
+ position = "BOTTOM"
+ AlertFrameMover:SetText(AlertFrameMover.textString .. " [Grow Up]")
+ end
+
+ local rollBars = E:GetModule("Misc").RollBars
+ if E.private.general.lootRoll then
+ local lastframe, lastShownFrame
+ for i, frame in pairs(rollBars) do
+ frame:ClearAllPoints()
+ if i ~= 1 then
+ if position == "TOP" then
+ frame:SetPoint("TOP", lastframe, "BOTTOM", 0, -4)
+ else
+ frame:SetPoint("BOTTOM", lastframe, "TOP", 0, 4)
+ end
+ else
+ if position == "TOP" then
+ frame:SetPoint("TOP", AlertFrameHolder, "BOTTOM", 0, -4)
+ else
+ frame:SetPoint("BOTTOM", AlertFrameHolder, "TOP", 0, 4)
+ end
+ end
+ lastframe = frame
+
+ if frame:IsShown() then
+ lastShownFrame = frame
+ end
+ end
+ elseif E.private.skins.blizzard.enable and E.private.skins.blizzard.lootRoll then
+ local lastframe, lastShownFrame
+ for i = 1, NUM_GROUP_LOOT_FRAMES do
+ local frame = _G["GroupLootFrame" .. i]
+ if frame then
+ frame:ClearAllPoints()
+ if i ~= 1 then
+ if position == "TOP" then
+ frame:SetPoint("TOP", lastframe, "BOTTOM", 0, -4)
+ else
+ frame:SetPoint("BOTTOM", lastframe, "TOP", 0, 4)
+ end
+ else
+ if position == "TOP" then
+ frame:SetPoint("TOP", AlertFrameHolder, "BOTTOM", 0, -4)
+ else
+ frame:SetPoint("BOTTOM", AlertFrameHolder, "TOP", 0, 4)
+ end
+ end
+ lastframe = frame
+
+ if frame:IsShown() then
+ lastShownFrame = frame
+ end
+ end
+ end
+ end
+end
+
+function B:AlertMovers()
+ E:CreateMover(AlertFrameHolder, "AlertFrameMover", L["Loot / Alert Frames"], nil, nil, E.PostAlertMove)
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/Blizzard.lua b/ElvUI/Modules/Blizzard/Blizzard.lua
new file mode 100644
index 0000000..bf8d99e
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/Blizzard.lua
@@ -0,0 +1,81 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:NewModule("Blizzard", "AceEvent-3.0", "AceHook-3.0");
+
+local GetNumQuestChoices = GetNumQuestChoices
+local GetNumQuestLogChoices = GetNumQuestLogChoices
+local GetQuestLogRewardHonor = GetQuestLogRewardHonor
+local GetQuestLogRewardMoney = GetQuestLogRewardMoney
+local GetQuestLogRewardSpell = GetQuestLogRewardSpell
+local GetRewardHonor = GetRewardHonor
+local GetRewardMoney = GetRewardMoney
+local GetRewardSpell = GetRewardSpell
+
+E.Blizzard = B
+
+function B:Initialize()
+ self:AlertMovers()
+ self:EnhanceColorPicker()
+ -- self:KillBlizzard()
+ self:PositionCaptureBar()
+ self:PositionDurabilityFrame()
+ self:PositionGMFrames()
+ self:MoveWatchFrame()
+
+ --[[self:RawHook("CombatConfig_Colorize_Update", function()
+ if not CHATCONFIG_SELECTED_FILTER_SETTINGS then return end
+ self.hooks.CombatConfig_Colorize_Update()
+ end, true)
+
+ hooksecurefunc("QuestFrameItems_Update", function(questState)
+ local spacerFrame, money, honor, numQuestRewards, numQuestChoices, numQuestSpellRewards
+
+ if questState == "QuestLog" then
+ spacerFrame = QuestLogSpacerFrame
+ money, honor, numQuestRewards, numQuestChoices, numQuestSpellRewards = GetQuestLogRewardMoney(), GetQuestLogRewardHonor(), GetNumQuestLogRewards(), GetNumQuestLogChoices(), GetQuestLogRewardSpell()
+ else
+ spacerFrame = QuestSpacerFrame
+ money, honor, numQuestRewards, numQuestChoices, numQuestSpellRewards = GetRewardMoney(), GetRewardHonor(), GetNumQuestRewards(), GetNumQuestChoices(), GetRewardSpell()
+ end
+
+ if money == 0 and honor > 0 and (numQuestRewards > 0 or numQuestChoices > 0 or numQuestSpellRewards) then
+ numQuestSpellRewards = numQuestSpellRewards and 1 or 0
+ local rewardsCount = numQuestRewards + numQuestChoices + numQuestSpellRewards
+ local honorFrame = _G[questState.."HonorFrame"]
+
+ if numQuestRewards > 0 then
+ honorFrame:ClearAllPoints()
+ honorFrame:SetPoint("TOPLEFT", questState.."Item"..rewardsCount, "BOTTOMLEFT", 3, 0)
+
+ QuestFrame_SetAsLastShown(questState.."HonorFrame", spacerFrame)
+ else
+ local questItemReceiveText = _G[questState.."ItemReceiveText"]
+ honorFrame:ClearAllPoints()
+ honorFrame:SetPoint("TOPLEFT", questItemReceiveText, "BOTTOMLEFT", 0, -5)
+
+ if numQuestSpellRewards > 0 then
+ questItemReceiveText:SetText(REWARD_ITEMS)
+ questItemReceiveText:SetPoint("TOPLEFT", questState.."Item"..rewardsCount, "BOTTOMLEFT", 3, 15)
+ elseif numQuestChoices > 0 then
+ questItemReceiveText:SetText(REWARD_ITEMS)
+ local index = numQuestChoices
+ if mod(index, 2) == 0 then
+ index = index - 1
+ end
+
+ questItemReceiveText:SetPoint("TOPLEFT", questState.."Item"..index, "BOTTOMLEFT", 3, 15)
+ else
+ questItemReceiveText:SetText(REWARD_ITEMS_ONLY)
+ questItemReceiveText:SetPoint("TOPLEFT", questState.."RewardTitleText", "BOTTOMLEFT", 3, 15)
+ end
+
+ QuestFrame_SetAsLastShown(questItemReceiveText, spacerFrame)
+ end
+ end
+ end)--]]
+end
+
+local function InitializeCallback()
+ B:Initialize()
+end
+
+E:RegisterModule(B:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/CaptureBar.lua b/ElvUI/Modules/Blizzard/CaptureBar.lua
new file mode 100644
index 0000000..3c39bee
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/CaptureBar.lua
@@ -0,0 +1,66 @@
+local E, L, DF = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Blizzard");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+local pvpHolder = CreateFrame("Frame", "PvPHolder", E.UIParent)
+
+function B:WorldStateAlwaysUpFrame_Update()
+ local captureBar
+ for i = 1, NUM_EXTENDED_UI_FRAMES do
+ captureBar = _G["WorldStateCaptureBar" .. i]
+ if captureBar and captureBar:IsShown() then
+ captureBar:ClearAllPoints()
+ captureBar:SetPoint("TOP", WorldStateAlwaysUpFrame, "BOTTOM", 0, -80)
+ end
+ end
+
+ WorldStateAlwaysUpFrame:ClearAllPoints()
+ WorldStateAlwaysUpFrame:SetPoint("CENTER", pvpHolder, "CENTER", 0, 10)
+
+ if AlwaysUpFrame1 then
+ AlwaysUpFrame1:ClearAllPoints()
+ AlwaysUpFrame1:SetPoint("CENTER", WorldStateAlwaysUpFrame, "CENTER", 0, 0)
+ end
+
+ if AlwaysUpFrame2 then
+ AlwaysUpFrame2:SetPoint("TOP", AlwaysUpFrame1, "BOTTOM", 0, -5)
+ end
+
+ local offset = 0
+
+ for i = 1, NUM_ALWAYS_UP_UI_FRAMES do
+ local frameText = _G["AlwaysUpFrame"..i.."Text"]
+ local frameIcon = _G["AlwaysUpFrame"..i.."Icon"]
+ local frameIcon2 = _G["AlwaysUpFrame"..i.."DynamicIconButton"]
+
+ frameText:ClearAllPoints()
+ frameText:SetPoint("CENTER", WorldStateAlwaysUpFrame, "CENTER", 0, offset)
+ frameText:SetJustifyH("CENTER")
+
+ frameIcon:ClearAllPoints()
+ frameIcon:SetPoint("CENTER", frameText, "LEFT", -7, -9)
+ frameIcon:SetWidth(38)
+ frameIcon:SetHeight(38)
+
+ frameIcon2:ClearAllPoints()
+ frameIcon2:SetPoint("LEFT", frameText, "RIGHT", 5, 0)
+ frameIcon2:SetWidth(38)
+ frameIcon2:SetHeight(38)
+
+ offset = offset - 25
+ end
+end
+
+function B:PositionCaptureBar()
+ self:SecureHook("WorldStateAlwaysUpFrame_Update")
+
+ pvpHolder:SetWidth(30)
+ pvpHolder:SetHeight(70)
+ pvpHolder:SetPoint("TOP", E.UIParent, "TOP", 0, -4)
+
+ E:CreateMover(pvpHolder, "PvPMover", L["PvP"], nil, nil, nil, "ALL")
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/ColorPicker.lua b/ElvUI/Modules/Blizzard/ColorPicker.lua
new file mode 100644
index 0000000..2fccdf1
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/ColorPicker.lua
@@ -0,0 +1,298 @@
+--[[
+ Credit to Jaslm, most of this code is his from the addon ColorPickerPlus
+]]
+local E, L, DF = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Blizzard");
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local tonumber, collectgarbage = tonumber, collectgarbage
+local floor = math.floor
+local format = string.format
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local CLASS, DEFAULTS = CLASS, DEFAULTS
+
+local colorBuffer = {}
+local editingText
+
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+
+local function UpdateAlphaText()
+ local a = OpacitySliderFrame:GetValue()
+ a = (1 - a) * 100
+ a = floor(a +.05)
+ ColorPPBoxA:SetText(format("%d", a))
+end
+
+local function UpdateColorTexts(r, g, b)
+ if not r then r, g, b = ColorPickerFrame:GetColorRGB() end
+ r = r*255
+ g = g*255
+ b = b*255
+ ColorPPBoxR:SetText(format("%d", r))
+ ColorPPBoxG:SetText(format("%d", g))
+ ColorPPBoxB:SetText(format("%d", b))
+ ColorPPBoxH:SetText(format("%.2x%.2x%.2x", r, g, b))
+end
+
+function B:EnhanceColorPicker()
+ if IsAddOnLoaded("ColorPickerPlus") then return end
+ ColorPickerFrame:SetClampedToScreen(true)
+
+ --Skin the default frame, move default buttons into place
+ E:SetTemplate(ColorPickerFrame, "Transparent")
+ ColorPickerFrameHeader:SetTexture("")
+ ColorPickerFrameHeader:ClearAllPoints()
+ ColorPickerFrameHeader:SetPoint("TOP", ColorPickerFrame, 0, 0)
+ S:HandleButton(ColorPickerOkayButton)
+ S:HandleButton(ColorPickerCancelButton)
+ ColorPickerCancelButton:ClearAllPoints()
+ ColorPickerOkayButton:ClearAllPoints()
+ ColorPickerCancelButton:SetPoint("BOTTOMRIGHT", ColorPickerFrame, "BOTTOMRIGHT", -6, 6)
+ ColorPickerCancelButton:SetPoint("BOTTOMLEFT", ColorPickerFrame, "BOTTOM", 0, 6)
+ ColorPickerOkayButton:SetPoint("BOTTOMLEFT", ColorPickerFrame,"BOTTOMLEFT", 6,6)
+ ColorPickerOkayButton:SetPoint("RIGHT", ColorPickerCancelButton,"LEFT", -4,0)
+ S:HandleSliderFrame(OpacitySliderFrame)
+ HookScript(ColorPickerFrame, "OnShow", function()
+ -- get color that will be replaced
+ local r, g, b = ColorPickerFrame:GetColorRGB()
+ ColorPPOldColorSwatch:SetTexture(r, g, b)
+
+ -- show/hide the alpha box
+ if ColorPickerFrame.hasOpacity then
+ ColorPPBoxA:Show()
+ ColorPPBoxLabelA:Show()
+ ColorPPBoxH:SetScript("OnTabPressed", function() ColorPPBoxA:SetFocus() end)
+ UpdateAlphaText()
+ this:SetWidth(405)
+ else
+ ColorPPBoxA:Hide()
+ ColorPPBoxLabelA:Hide()
+ ColorPPBoxH:SetScript("OnTabPressed", function() ColorPPBoxR:SetFocus() end)
+ this:SetWidth(345)
+ end
+ end)
+
+ --Memory Fix, Colorpicker will call the self.func() 100x per second, causing fps/memory issues,
+ --this little script will make you have to press ok for you to notice any changes.
+ ColorPickerFrame:SetScript("OnColorSelect", function(_, r, g, b)
+ ColorSwatch:SetTexture(r, g, b)
+ if not editingText then
+ UpdateColorTexts(r, g, b)
+ end
+ end)
+
+ HookScript(ColorPickerOkayButton, "OnClick", function()
+ collectgarbage() --Couldn't hurt to do this, this button usually executes a lot of code.
+ end)
+
+ HookScript(OpacitySliderFrame, "OnValueChanged", function()
+ if not editingText then
+ UpdateAlphaText()
+ end
+ end)
+
+ -- make the Color Picker dialog a bit taller, to make room for edit boxes
+ ColorPickerFrame:SetHeight(ColorPickerFrame:GetHeight() + 40)
+
+ -- move the Color Swatch
+ ColorSwatch:ClearAllPoints()
+ ColorSwatch:SetPoint("TOPLEFT", ColorPickerFrame, "TOPLEFT", 215, -45)
+
+ -- add Color Swatch for original color
+ local t = ColorPickerFrame:CreateTexture("ColorPPOldColorSwatch")
+ local w, h = ColorSwatch:GetWidth(), ColorSwatch:GetHeight()
+ t:SetWidth(w*0.75)
+ t:SetHeight(h*0.75)
+ t:SetTexture(0,0,0)
+ -- OldColorSwatch to appear beneath ColorSwatch
+ t:SetDrawLayer("BORDER")
+ t:SetPoint("BOTTOMLEFT", "ColorSwatch", "TOPRIGHT", -(w/2), -(h/3))
+
+ -- add Color Swatch for the copied color
+ t = ColorPickerFrame:CreateTexture("ColorPPCopyColorSwatch")
+ t:SetWidth(w)
+ t:SetHeight(h)
+ t:SetTexture(0,0,0)
+ t:Hide()
+
+ -- add copy button to the ColorPickerFrame
+ local b = CreateFrame("Button", "ColorPPCopy", ColorPickerFrame, "UIPanelButtonTemplate")
+ S:HandleButton(b)
+ b:SetText(L["Copy"])
+ b:SetWidth(60)
+ b:SetHeight(22)
+ b:SetPoint("TOPLEFT", "ColorSwatch", "BOTTOMLEFT", 0, -5)
+
+ -- copy color into buffer on button click
+ b:SetScript("OnClick", function()
+ -- copy current dialog colors into buffer
+ colorBuffer.r, colorBuffer.g, colorBuffer.b = ColorPickerFrame:GetColorRGB()
+
+ -- enable Paste button and display copied color into swatch
+ ColorPPPaste:Enable()
+ ColorPPCopyColorSwatch:SetTexture(colorBuffer.r, colorBuffer.g, colorBuffer.b)
+ ColorPPCopyColorSwatch:Show()
+
+ if ColorPickerFrame.hasOpacity then
+ colorBuffer.a = OpacitySliderFrame:GetValue()
+ else
+ colorBuffer.a = nil
+ end
+ end)
+
+ --class color button
+ b = CreateFrame("Button", "ColorPPClass", ColorPickerFrame, "UIPanelButtonTemplate")
+ b:SetText(CLASS)
+ S:HandleButton(b)
+ b:SetWidth(80)
+ b:SetHeight(22)
+ b:SetPoint("TOP", "ColorPPCopy", "BOTTOMRIGHT", 0, -7)
+
+ b:SetScript("OnClick", function()
+ local color = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
+ ColorPickerFrame:SetColorRGB(color.r, color.g, color.b)
+ ColorSwatch:SetTexture(color.r, color.g, color.b)
+ if ColorPickerFrame.hasOpacity then
+ OpacitySliderFrame:SetValue(0)
+ end
+ end)
+
+ -- add paste button to the ColorPickerFrame
+ b = CreateFrame("Button", "ColorPPPaste", ColorPickerFrame, "UIPanelButtonTemplate")
+ b:SetText(L["Paste"])
+ S:HandleButton(b)
+ b:SetWidth(60)
+ b:SetHeight(22)
+ b:SetPoint("TOPLEFT", "ColorPPCopy", "TOPRIGHT", 2, 0)
+ b:Disable() -- enable when something has been copied
+
+ -- paste color on button click, updating frame components
+ b:SetScript("OnClick", function()
+ ColorPickerFrame:SetColorRGB(colorBuffer.r, colorBuffer.g, colorBuffer.b)
+ ColorSwatch:SetTexture(colorBuffer.r, colorBuffer.g, colorBuffer.b)
+ if ColorPickerFrame.hasOpacity then
+ if colorBuffer.a then --color copied had an alpha value
+ OpacitySliderFrame:SetValue(colorBuffer.a)
+ end
+ end
+ end)
+
+ -- add defaults button to the ColorPickerFrame
+ b = CreateFrame("Button", "ColorPPDefault", ColorPickerFrame, "UIPanelButtonTemplate")
+ b:SetText(DEFAULTS)
+ S:HandleButton(b)
+ b:SetWidth(80)
+ b:SetHeight(22)
+ b:SetPoint("TOPLEFT", "ColorPPClass", "BOTTOMLEFT", 0, -7)
+ b:Disable() -- enable when something has been copied
+ b:SetScript("OnHide", function()
+ this.colors = nil
+ end)
+ b:SetScript("OnShow", function()
+ if this.colors then
+ this:Enable()
+ else
+ this:Disable()
+ end
+ end)
+
+ -- paste color on button click, updating frame components
+ b:SetScript("OnClick", function()
+ local colorBuffer = this.colors
+ ColorPickerFrame:SetColorRGB(colorBuffer.r, colorBuffer.g, colorBuffer.b)
+ ColorSwatch:SetTexture(colorBuffer.r, colorBuffer.g, colorBuffer.b)
+ if ColorPickerFrame.hasOpacity then
+ if colorBuffer.a then
+ OpacitySliderFrame:SetValue(colorBuffer.a)
+ end
+ end
+ end)
+
+ -- position Color Swatch for copy color
+ ColorPPCopyColorSwatch:SetPoint("BOTTOM", "ColorPPPaste", "TOP", 0, 10)
+
+ -- move the Opacity Slider Frame to align with bottom of Copy ColorSwatch
+ OpacitySliderFrame:ClearAllPoints()
+ OpacitySliderFrame:SetPoint("BOTTOM", "ColorPPDefault", "BOTTOM", 0, 0)
+ OpacitySliderFrame:SetPoint("RIGHT", "ColorPickerFrame", "RIGHT", -35, 18)
+
+ -- set up edit box frames and interior label and text areas
+ local boxes = { "R", "G", "B", "H", "A" }
+ for i = 1, getn(boxes) do
+
+ local rgb = boxes[i]
+ local box = CreateFrame("EditBox", "ColorPPBox"..rgb, ColorPickerFrame, "InputBoxTemplate")
+ S:HandleEditBox(box)
+ box:SetID(i)
+ box:SetFrameStrata("DIALOG")
+ box:SetAutoFocus(false)
+ box:SetTextInsets(0,14,0,0)
+ box:SetJustifyH("CENTER")
+ box:SetHeight(24)
+
+ if i == 4 then
+ -- Hex entry box
+ box:SetMaxLetters(6)
+ box:SetWidth(56)
+ box:SetNumeric(false)
+ else
+ box:SetMaxLetters(3)
+ box:SetWidth(40)
+ box:SetNumeric(true)
+ end
+ box:SetPoint("TOP", "ColorPickerWheel", "BOTTOM", 0, -15)
+
+ -- label
+ local label = box:CreateFontString("ColorPPBoxLabel"..rgb, "ARTWORK", "GameFontNormalSmall")
+ label:SetTextColor(1, 1, 1)
+ label:SetPoint("RIGHT", "ColorPPBox"..rgb, "LEFT", -5, 0)
+ if i == 4 then
+ label:SetText("#")
+ else
+ label:SetText(rgb)
+ end
+
+ -- set up scripts to handle event appropriately
+ if i == 5 then
+ box:SetScript("OnEscapePressed", function() this:ClearFocus() UpdateAlphaText() end)
+ box:SetScript("OnEnterPressed", function() this:ClearFocus() UpdateAlphaText() end)
+ else
+ box:SetScript("OnEscapePressed", function() this:ClearFocus() UpdateColorTexts() end)
+ box:SetScript("OnEnterPressed", function() this:ClearFocus() UpdateColorTexts() end)
+ end
+
+ box:SetScript("OnEditFocusGained", function() this:HighlightText() end)
+ box:SetScript("OnEditFocusLost", function() this:HighlightText(0,0) end)
+ box:SetScript("OnTextSet", function() this:ClearFocus() end)
+ box:Show()
+ end
+
+ -- finish up with placement
+ ColorPPBoxA:SetPoint("RIGHT", "OpacitySliderFrame", "RIGHT", 10, 0)
+ ColorPPBoxH:SetPoint("RIGHT", "ColorPPDefault", "RIGHT", -10, 0)
+ ColorPPBoxB:SetPoint("RIGHT", "ColorPPDefault", "LEFT", -40, 0)
+ ColorPPBoxG:SetPoint("RIGHT", "ColorPPBoxB", "LEFT", -25, 0)
+ ColorPPBoxR:SetPoint("RIGHT", "ColorPPBoxG", "LEFT", -25, 0)
+
+ -- define the order of tab cursor movement
+ ColorPPBoxR:SetScript("OnTabPressed", function() ColorPPBoxG:SetFocus() end)
+ ColorPPBoxG:SetScript("OnTabPressed", function() ColorPPBoxB:SetFocus() end)
+ ColorPPBoxB:SetScript("OnTabPressed", function() ColorPPBoxH:SetFocus() end)
+ ColorPPBoxA:SetScript("OnTabPressed", function() ColorPPBoxR:SetFocus() end)
+
+ -- make the color picker movable.
+ local mover = CreateFrame("Frame", nil, ColorPickerFrame)
+ mover:SetPoint("TOPLEFT", ColorPickerFrame, "TOP", -60, 0)
+ mover:SetPoint("BOTTOMRIGHT", ColorPickerFrame, "TOP", 60, -15)
+ mover:EnableMouse(true)
+ mover:SetScript("OnMouseDown", function() ColorPickerFrame:StartMoving() end)
+ mover:SetScript("OnMouseUp", function() ColorPickerFrame:StopMovingOrSizing() end)
+ ColorPickerFrame:SetUserPlaced(true)
+ ColorPickerFrame:EnableKeyboard(false)
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/Durablity.lua b/ElvUI/Modules/Blizzard/Durablity.lua
new file mode 100644
index 0000000..4cda740
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/Durablity.lua
@@ -0,0 +1,21 @@
+local E, L, DF = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Blizzard");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+function B:PositionDurabilityFrame()
+ DurabilityFrame:SetFrameStrata("HIGH")
+
+ local function SetPosition(self, _, parent)
+ if parent == "MinimapCluster" or parent == _G["MinimapCluster"] then
+ self:ClearAllPoints()
+ self:SetPoint("RIGHT", Minimap, "RIGHT")
+ self:SetScale(0.6)
+ end
+ end
+
+ hooksecurefunc(DurabilityFrame, "SetPoint", SetPosition)
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/GM.lua b/ElvUI/Modules/Blizzard/GM.lua
new file mode 100644
index 0000000..cd7e8d6
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/GM.lua
@@ -0,0 +1,13 @@
+local E, L, DF = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Blizzard");
+
+--Cache global variables
+--Lua functions
+--WoW API / Variables
+
+function B:PositionGMFrames()
+ TicketStatusFrame:ClearAllPoints()
+ TicketStatusFrame:SetPoint("TOPLEFT", E.UIParent, "TOPLEFT", 250, -5)
+
+ E:CreateMover(TicketStatusFrame, "GMMover", L["GM Ticket Frame"])
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/Load_Blizzard.xml b/ElvUI/Modules/Blizzard/Load_Blizzard.xml
new file mode 100644
index 0000000..46ae5c9
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/Load_Blizzard.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Blizzard/WatchFrame.lua b/ElvUI/Modules/Blizzard/WatchFrame.lua
new file mode 100644
index 0000000..2498a3f
--- /dev/null
+++ b/ElvUI/Modules/Blizzard/WatchFrame.lua
@@ -0,0 +1,42 @@
+local E, L, DF = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local B = E:GetModule("Blizzard");
+
+--Cache global variables
+--Lua functions
+local min = math.min
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+local GetScreenWidth = GetScreenWidth
+local GetScreenHeight = GetScreenHeight
+
+local WatchFrameHolder = CreateFrame("Frame", "WatchFrameHolder", E.UIParent)
+WatchFrameHolder:SetWidth(150)
+WatchFrameHolder:SetHeight(22)
+WatchFrameHolder:SetPoint("TOPRIGHT", E.UIParent, "TOPRIGHT", -135, -300)
+
+function B:SetWatchFrameHeight()
+ local top = QuestWatchFrame:GetTop() or 0
+ local screenHeight = GetScreenHeight()
+ local gapFromTop = screenHeight - top
+ local maxHeight = screenHeight - gapFromTop
+ local watchFrameHeight = min(maxHeight, E.db.general.watchFrameHeight)
+
+ QuestWatchFrame:SetHeight(watchFrameHeight)
+end
+
+function B:MoveWatchFrame()
+ E:CreateMover(WatchFrameHolder, "WatchFrameMover", L["Watch Frame"])
+ WatchFrameHolder:SetAllPoints(WatchFrameMover)
+
+ QuestWatchFrame:ClearAllPoints()
+ QuestWatchFrame:SetPoint("TOP", WatchFrameHolder, "TOP")
+ B:SetWatchFrameHeight()
+ QuestWatchFrame:SetClampedToScreen(false)
+
+ hooksecurefunc(QuestWatchFrame, "SetPoint", function(_, _, parent)
+ if parent ~= WatchFrameHolder then
+ QuestWatchFrame:ClearAllPoints()
+ QuestWatchFrame:SetPoint("TOP", WatchFrameHolder, "TOP")
+ end
+ end)
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Chat/Chat.lua b/ElvUI/Modules/Chat/Chat.lua
new file mode 100644
index 0000000..15ab88d
--- /dev/null
+++ b/ElvUI/Modules/Chat/Chat.lua
@@ -0,0 +1,1719 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local CH = E:NewModule("Chat", "AceTimer-3.0", "AceHook-3.0", "AceEvent-3.0");
+local CC = E:GetModule("ClassCache");
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local time, difftime = time, difftime
+local pairs, unpack, select, tostring, next, tonumber, type, assert = pairs, unpack, select, tostring, next, tonumber, type, assert
+local tinsert, tremove, tsort, twipe, tconcat = table.insert, table.remove, table.sort, table.wipe, table.concat
+local strmatch = strmatch
+local gsub, find, match, gmatch, format, split = string.gsub, string.find, string.match, string.gmatch, string.format, string.split
+local strlower, strsub, strlen, strupper = strlower, strsub, strlen, strupper
+--WoW API / Variables
+local BetterDate = BetterDate
+local ChatEdit_SetLastTellTarget = ChatEdit_SetLastTellTarget
+local ChatFrameEditBox = ChatFrameEditBox
+local ChatFrame_ConfigEventHandler = ChatFrame_ConfigEventHandler
+local ChatFrame_SendTell = ChatFrame_SendTell
+local ChatFrame_SystemEventHandler = ChatFrame_SystemEventHandler
+local CreateFrame = CreateFrame
+local FCF_GetCurrentChatFrame = FCF_GetCurrentChatFrame
+local FCF_SetChatWindowFontSize = FCF_SetChatWindowFontSize
+local FloatingChatFrame_OnEvent = FloatingChatFrame_OnEvent
+local GetChannelName = GetChannelName
+local GetDefaultLanguage = GetDefaultLanguage
+local GetGuildRosterMOTD = GetGuildRosterMOTD
+local GetMouseFocus = GetMouseFocus
+local GetNumRaidMembers = GetNumRaidMembers
+local GetTime = GetTime
+local IsInInstance = IsInInstance
+local IsMouseButtonDown = IsMouseButtonDown
+local IsAltKeyDown = IsAltKeyDown
+local IsShiftKeyDown = IsShiftKeyDown
+local PlaySound = PlaySound
+local PlaySoundFile = PlaySoundFile
+local ShowUIPanel, HideUIPanel = ShowUIPanel, HideUIPanel
+local StaticPopup_Visible = StaticPopup_Visible
+local ToggleFrame = ToggleFrame
+local UnitName = UnitName
+local hooksecurefunc = hooksecurefunc
+
+local NUM_CHAT_WINDOWS = NUM_CHAT_WINDOWS
+local DEFAULT_CHAT_FRAME = DEFAULT_CHAT_FRAME
+local SELECTED_DOCK_FRAME = SELECTED_DOCK_FRAME
+
+local GlobalStrings = {
+ ["AFK"] = CHAT_MSG_AFK,
+ ["CHAT_FILTERED"] = CHAT_FILTERED,
+ ["CHAT_IGNORED"] = CHAT_IGNORED,
+ ["CHAT_RESTRICTED"] = CHAT_RESTRICTED,
+ ["CHAT_TELL_ALERT_TIME"] = CHAT_TELL_ALERT_TIME,
+ ["DND"] = CHAT_MSG_DND,
+ ["CHAT_MSG_RAID_WARNING"] = CHAT_MSG_RAID_WARNING
+}
+
+local CreatedFrames = 0
+local lines = {}
+local msgList, msgCount, msgTime = {}, {}, {}
+local chatFilters = {}
+
+local PLAYER_REALM = gsub(E.myrealm,"[%s%-]","")
+local PLAYER_NAME = E.myname.."-"..PLAYER_REALM
+
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+
+local DEFAULT_STRINGS = {
+ BATTLEGROUND = L["BG"],
+ GUILD = L["G"],
+ PARTY = L["P"],
+ RAID = L["R"],
+ OFFICER = L["O"],
+ BATTLEGROUND_LEADER = L["BGL"],
+ RAID_LEADER = L["RL"],
+}
+
+local hyperlinkTypes = {
+ ["item"] = true,
+ ["spell"] = true,
+ ["unit"] = true,
+ ["quest"] = true,
+ ["enchant"] = true,
+ ["instancelock"] = true,
+ ["talent"] = true,
+}
+
+CH.Keywords = {}
+
+local numScrollMessages
+local function ChatFrame_OnMouseScroll()
+ SELECTED_DOCK_FRAME = this
+ numScrollMessages = CH.db.numScrollMessages or 3
+ if CH.db.scrollDirection == "TOP" then
+ if arg1 < 0 then
+ if IsShiftKeyDown() then
+ this:ScrollToBottom()
+ elseif IsAltKeyDown() then
+ this:ScrollDown()
+ else
+ for i = 1, numScrollMessages do
+ this:ScrollDown()
+ end
+ end
+ elseif arg1 > 0 then
+ if IsShiftKeyDown() then
+ this:ScrollToTop()
+ elseif IsAltKeyDown() then
+ this:ScrollUp()
+ else
+ for i = 1, numScrollMessages do
+ this:ScrollUp()
+ end
+ end
+
+ if CH.db.scrollDownInterval ~= 0 then
+ if this.ScrollTimer then
+ CH:CancelTimer(this.ScrollTimer, true)
+ end
+
+ this.ScrollTimer = CH:ScheduleTimer("ScrollToBottom", CH.db.scrollDownInterval)
+ end
+ end
+ else
+ if arg1 < 0 then
+ if IsShiftKeyDown() then
+ this:ScrollToBottom()
+ else
+ for i = 1, numScrollMessages do
+ this:ScrollDown()
+ end
+ end
+ elseif arg1 > 0 then
+ if IsShiftKeyDown() then
+ this:ScrollToTop()
+ else
+ for i = 1, numScrollMessages do
+ this:ScrollUp()
+ end
+ end
+
+ if CH.db.scrollDownInterval ~= 0 then
+ if this.ScrollTimer then
+ CH:CancelTimer(this.ScrollTimer, true)
+ end
+
+ this.ScrollTimer = CH:ScheduleTimer("ScrollToBottom", CH.db.scrollDownInterval)
+ end
+ end
+ end
+end
+
+local function ChatFrame_AddMessageEventFilter(event, filter)
+ assert(event and filter)
+
+ if chatFilters[event] then
+ -- Only allow a filter to be added once
+ for index, filterFunc in next, chatFilters[event] do
+ if filterFunc == filter then
+ return
+ end
+ end
+ else
+ chatFilters[event] = {}
+ end
+
+ tinsert(chatFilters[event], filter)
+end
+
+local function ChatFrame_RemoveMessageEventFilter(event, filter)
+ assert(event and filter)
+
+ if chatFilters[event] then
+ for index, filterFunc in next, chatFilters[event] do
+ if filterFunc == filter then
+ tremove(chatFilters[event], index)
+ end
+ end
+
+ if getn(chatFilters[event]) == 0 then
+ chatFilters[event] = nil
+ end
+ end
+end
+
+local function ChatFrame_GetMessageEventFilters(event)
+ assert(event)
+
+ return chatFilters[event]
+end
+
+function CH:GetGroupDistribution()
+ local inInstance, kind = IsInInstance()
+ if inInstance and kind == "pvp" then
+ return "/bg "
+ end
+ if GetNumRaidMembers() > 0 then
+ return "/ra "
+ end
+ if GetNumPartyMembers() > 0 then
+ return "/p "
+ end
+ return "/s "
+end
+
+function CH:StyleChat(frame)
+ local name = frame:GetName()
+ E:FontTemplate(_G[name.."TabText"], LSM:Fetch("font", self.db.tabFont), self.db.tabFontSize, self.db.tabFontOutline)
+
+ if frame.styled then return end
+
+ frame:SetFrameLevel(4)
+
+ local id = frame:GetID()
+
+ local tab = _G[name.."Tab"]
+ tab.isDocked = frame.isDocked
+
+ for i = 1, getn(CHAT_FRAME_TEXTURES) do
+ E:Kill(_G[name..CHAT_FRAME_TEXTURES[i]])
+ end
+
+ E:Kill(_G[name.."UpButton"])
+ E:Kill(_G[name.."DownButton"])
+ E:Kill(_G[name.."BottomButton"])
+ E:Kill(_G[name.."TabDockRegion"])
+ E:Kill(_G[name.."TabLeft"])
+ E:Kill(_G[name.."TabMiddle"])
+ E:Kill(_G[name.."TabRight"])
+ _G[name.."Tab"]:GetHighlightTexture():SetTexture(nil)
+
+ if frame.isDocked or frame:IsVisible() then
+ tab:Show()
+ end
+
+ hooksecurefunc(tab, "SetAlpha", function(t, alpha)
+ if alpha ~= 1 and (not t.isDocked or SELECTED_CHAT_FRAME:GetID() == t:GetID()) then
+ UIFrameFadeRemoveFrame(t)
+ t:SetAlpha(1)
+ elseif alpha < 0.6 then
+ UIFrameFadeRemoveFrame(t)
+ t:SetAlpha(0.6)
+ end
+ end)
+
+ tab.text = _G[name.."TabText"]
+ tab.text:SetTextColor(unpack(E["media"].rgbvaluecolor))
+ hooksecurefunc(tab.text, "SetTextColor", function(self, r, g, b)
+ local rR, gG, bB = unpack(E["media"].rgbvaluecolor)
+ if r ~= rR or g ~= gG or b ~= bB then
+ self:SetTextColor(rR, gG, bB)
+ end
+ end)
+
+ if id ~= 2 then
+ tab.text:SetPoint("LEFT", _G[name.."TabLeft"], "RIGHT", 0, -4)
+ end
+
+ tab.flash = _G[name.."TabFlash"]
+ tab.flash:ClearAllPoints()
+ tab.flash:SetPoint("TOPLEFT", _G[name.."TabLeft"], "TOPLEFT", -3, id == 2 and -3 or -2)
+ tab.flash:SetPoint("BOTTOMRIGHT", _G[name.."TabRight"], "BOTTOMRIGHT", 3, id == 2 and -7 or -6)
+
+ --frame:SetClampRectInsets(0, 0, 0, 0)
+ frame:SetClampedToScreen(false)
+
+ --copy chat button
+ frame.button = CreateFrame("Button", format("CopyChatButton%d", id), frame)
+ frame.button:EnableMouse(true)
+ frame.button:SetAlpha(0.35)
+ frame.button:SetWidth(20)
+ frame.button:SetHeight(22)
+ frame.button:SetPoint("TOPRIGHT", 0, 0)
+ frame.button:SetFrameLevel(frame:GetFrameLevel() + 5)
+
+ frame.button.tex = frame.button:CreateTexture(nil, "OVERLAY")
+ E:SetInside(frame.button.tex)
+ frame.button.tex:SetTexture([[Interface\AddOns\ElvUI\media\textures\copy.tga]])
+
+ frame.button:SetScript("OnMouseUp", function()
+ if arg1 == "LeftButton" then
+ CH:CopyChat(frame)
+ elseif arg1 == "RightButton" and id ~= 2 then
+ ToggleFrame(ChatMenu)
+ end
+ end)
+
+ frame.button:SetScript("OnEnter", function() this:SetAlpha(1) end)
+ frame.button:SetScript("OnLeave", function()
+ if _G[this:GetParent():GetName().."TabText"]:IsShown() then
+ this:SetAlpha(0.35)
+ else
+ this:SetAlpha(0)
+ end
+ end)
+
+ CreatedFrames = id
+ frame.styled = true
+end
+
+function CH:UpdateSettings()
+ ChatFrameEditBox:SetAltArrowKeyMode(CH.db.useAltKey)
+end
+
+local function colorizeLine(text, r, g, b)
+ local hexCode = E:RGBToHex(r, g, b)
+ local hexReplacement = format("|r%s", hexCode)
+
+ text = gsub(text, "|r", hexReplacement)
+ text = format("%s%s|r", hexCode, text)
+
+ return text
+end
+
+function CH:GetLines(...)
+ local index = 1
+ wipe(lines)
+ for i = getn(arg), 1, -1 do
+ local region = arg[i]
+ if region:GetObjectType() == "FontString" then
+ local line = tostring(region:GetText())
+ local r, g, b = region:GetTextColor()
+
+ line = colorizeLine(line, r, g, b)
+
+ lines[index] = line
+ index = index + 1
+ end
+ end
+ return index - 1
+end
+
+function CH:CopyChat(frame)
+ if not CopyChatFrame:IsShown() then
+ local _, fontSize = GetChatWindowInfo(frame:GetID())
+ if fontSize < 10 then fontSize = 12 end
+ FCF_SetChatWindowFontSize(frame, 0.01)
+ CopyChatFrame:Show()
+ local lineCt = self:GetLines(frame:GetRegions())
+ local text = tconcat(lines, " \n", 1, lineCt)
+ FCF_SetChatWindowFontSize(frame, fontSize)
+ CopyChatFrameEditBox:SetText(text)
+ else
+ CopyChatFrame:Hide()
+ end
+end
+
+function CH:OnEnter()
+ _G[this:GetName().."Text"]:Show()
+end
+
+function CH:OnLeave()
+ _G[this:GetName().."Text"]:Hide()
+end
+
+function CH:SetupChatTabs(frame, hook)
+ if hook and (not self.hooks or not self.hooks[frame] or not self.hooks[frame].OnEnter) then
+ self:HookScript(frame, "OnEnter")
+ self:HookScript(frame, "OnLeave")
+ elseif not hook and self.hooks and self.hooks[frame] and self.hooks[frame].OnEnter then
+ self:Unhook(frame, "OnEnter")
+ self:Unhook(frame, "OnLeave")
+ end
+
+ if not hook then
+ _G[frame:GetName().."Text"]:Show()
+
+ if frame.owner and frame.owner.button and GetMouseFocus() ~= frame.owner.button then
+ frame.owner.button:SetAlpha(0.35)
+ end
+ elseif GetMouseFocus() ~= frame then
+ _G[frame:GetName().."Text"]:Hide()
+
+ if frame.owner and frame.owner.button and GetMouseFocus() ~= frame.owner.button then
+ frame.owner.button:SetAlpha(1)
+ end
+ end
+end
+
+function CH:UpdateAnchors()
+ local frame = _G["ChatFrameEditBox"]
+ if not E.db.datatexts.leftChatPanel and self.db.panelBackdrop == "HIDEBOTH" or self.db.panelBackdrop == "RIGHT" then
+ frame:ClearAllPoints()
+ if E.db.chat.editBoxPosition == "BELOW_CHAT" then
+ frame:SetPoint("TOPLEFT", ChatFrame1, "BOTTOMLEFT")
+ frame:SetPoint("BOTTOMRIGHT", ChatFrame1, "BOTTOMRIGHT", 0, -LeftChatTab:GetHeight())
+ else
+ frame:SetPoint("BOTTOMLEFT", ChatFrame1, "TOPLEFT")
+ frame:SetPoint("TOPRIGHT", ChatFrame1, "TOPRIGHT", 0, LeftChatTab:GetHeight())
+ end
+ else
+ if E.db.datatexts.leftChatPanel and E.db.chat.editBoxPosition == "BELOW_CHAT" then
+ frame:SetAllPoints(LeftChatDataPanel)
+ else
+ frame:SetAllPoints(LeftChatTab)
+ end
+ end
+
+ CH:PositionChat(true)
+end
+
+local function FindRightChatID()
+ local rightChatID
+
+ for i = 1, NUM_CHAT_WINDOWS do
+ local chat = _G["ChatFrame"..i]
+ local id = chat:GetID()
+
+ if E:FramesOverlap(chat, RightChatPanel) and not E:FramesOverlap(chat, LeftChatPanel) then
+ rightChatID = id
+ break
+ end
+ end
+
+ return rightChatID
+end
+
+function CH:UpdateChatTabs()
+ local fadeUndockedTabs = E.db["chat"].fadeUndockedTabs
+ local fadeTabsNoBackdrop = E.db["chat"].fadeTabsNoBackdrop
+
+ for i = 1, CreatedFrames do
+ local chat = _G[format("ChatFrame%d", i)]
+ local tab = _G[format("ChatFrame%sTab", i)]
+ local id = chat:GetID()
+ local isDocked = chat.isDocked
+
+ if chat:IsShown() and (id == self.RightChatWindowID) then
+ if E.db.chat.panelBackdrop == "HIDEBOTH" or E.db.chat.panelBackdrop == "LEFT" then
+ CH:SetupChatTabs(tab, fadeTabsNoBackdrop and true or false)
+ else
+ CH:SetupChatTabs(tab, false)
+ end
+ elseif not isDocked and chat:IsShown() then
+ CH:SetupChatTabs(tab, fadeUndockedTabs and true or false)
+ else
+ if E.db.chat.panelBackdrop == "HIDEBOTH" or E.db.chat.panelBackdrop == "RIGHT" then
+ CH:SetupChatTabs(tab, fadeTabsNoBackdrop and true or false)
+ else
+ CH:SetupChatTabs(tab, false)
+ end
+ end
+ end
+end
+
+function CH:PositionChat(override)
+ if ((not override and self.initialMove) or (not override)) then return end
+ if not RightChatPanel or not LeftChatPanel then return end
+ RightChatPanel:SetWidth(E.db.chat.separateSizes and E.db.chat.panelWidthRight or E.db.chat.panelWidth)
+ RightChatPanel:SetHeight(E.db.chat.separateSizes and E.db.chat.panelHeightRight or E.db.chat.panelHeight)
+ LeftChatPanel:SetWidth(E.db.chat.panelWidth)
+ LeftChatPanel:SetHeight(E.db.chat.panelHeight)
+
+ self.RightChatWindowID = FindRightChatID()
+
+ if not self.db.lockPositions or E.private.chat.enable ~= true then return end
+
+ local chat, tab, id, isDocked
+ local fadeUndockedTabs = E.db["chat"].fadeUndockedTabs
+ local fadeTabsNoBackdrop = E.db["chat"].fadeTabsNoBackdrop
+
+ for i = 1, CreatedFrames do
+ local BASE_OFFSET = 57 + E.Spacing*3
+
+ chat = _G[format("ChatFrame%d", i)]
+ id = chat:GetID()
+ tab = _G[format("ChatFrame%sTab", i)]
+ isDocked = chat.isDocked
+ tab.isDocked = chat.isDocked
+ tab.owner = chat
+
+ if chat:IsShown() and id == self.RightChatWindowID then
+ chat:ClearAllPoints()
+
+ if E.db.datatexts.rightChatPanel then
+ chat:SetPoint("BOTTOMLEFT", RightChatDataPanel, "TOPLEFT", 1, 3)
+ else
+ BASE_OFFSET = BASE_OFFSET - 24
+ chat:SetPoint("BOTTOMLEFT", RightChatDataPanel, "BOTTOMLEFT", 1, 1)
+ end
+ if id ~= 2 then
+ chat:SetWidth((E.db.chat.separateSizes and E.db.chat.panelWidthRight or E.db.chat.panelWidth) - 11)
+ chat:SetHeight((E.db.chat.separateSizes and E.db.chat.panelHeightRight or E.db.chat.panelHeight) - BASE_OFFSET)
+ else
+ chat:SetWidth(E.db.chat.panelWidth - 11, (E.db.chat.panelHeight - BASE_OFFSET))
+ chat:SetHeight(E.db.chat.panelWidth - 11, (E.db.chat.panelHeight - BASE_OFFSET))
+ end
+
+ tab:SetParent(RightChatPanel)
+ chat:SetParent(RightChatPanel)
+
+ if chat:IsMovable() then
+ chat:SetUserPlaced(true)
+ end
+ if E.db.chat.panelBackdrop == "HIDEBOTH" or E.db.chat.panelBackdrop == "LEFT" then
+ CH:SetupChatTabs(tab, fadeTabsNoBackdrop and true or false)
+ else
+ CH:SetupChatTabs(tab, false)
+ end
+ elseif not isDocked and chat:IsShown() then
+ tab:SetParent(UIParent)
+ chat:SetParent(UIParent)
+ CH:SetupChatTabs(tab, fadeUndockedTabs and true or false)
+ else
+ if id ~= 2 then
+ chat:ClearAllPoints()
+ if E.db.datatexts.leftChatPanel then
+ chat:SetPoint("BOTTOMLEFT", LeftChatToggleButton, "TOPLEFT", 1, 3)
+ else
+ BASE_OFFSET = BASE_OFFSET - 24
+ chat:SetPoint("BOTTOMLEFT", LeftChatToggleButton, "BOTTOMLEFT", 1, 1)
+ end
+
+ chat:SetWidth(E.db.chat.panelWidth - 11)
+ chat:SetHeight((E.db.chat.panelHeight - BASE_OFFSET))
+ end
+ chat:SetParent(LeftChatPanel)
+ if i > 2 then
+ tab:SetParent(LeftChatPanel)
+ else
+ tab:SetParent(LeftChatPanel)
+ end
+ if chat:IsMovable() then
+ chat:SetUserPlaced(true)
+ end
+
+ if E.db.chat.panelBackdrop == "HIDEBOTH" or E.db.chat.panelBackdrop == "RIGHT" then
+ CH:SetupChatTabs(tab, fadeTabsNoBackdrop and true or false)
+ else
+ CH:SetupChatTabs(tab, false)
+ end
+ end
+ end
+
+ self.initialMove = true
+end
+
+local function UpdateChatTabColor(_, r, g, b)
+ for i = 1, CreatedFrames do
+ _G["ChatFrame"..i.."TabText"]:SetTextColor(r, g, b)
+ end
+end
+E["valueColorUpdateFuncs"][UpdateChatTabColor] = true
+
+function CH:ScrollToBottom()
+ SELECTED_DOCK_FRAME:ScrollToBottom()
+
+ self:CancelTimer(SELECTED_DOCK_FRAME.ScrollTimer, true)
+end
+
+function CH:PrintURL(url)
+ return "|cFFFFFFFF[|Hurl:"..url.."|h"..url.."|h]|r "
+end
+
+function CH.FindURL(msg, ...)
+ if not msg then return end
+
+ if event and event == "CHAT_MSG_WHISPER" and CH.db.whisperSound ~= "None" and not CH.SoundPlayed then
+ PlaySoundFile(LSM:Fetch("sound", CH.db.whisperSound), "Master")
+ CH.SoundPlayed = true
+ CH.SoundTimer = CH:ScheduleTimer("ThrottleSound", 1)
+ end
+
+ if not CH.db.url then
+ msg = CH:CheckKeyword(msg)
+ return false, msg, unpack(arg)
+ end
+
+ msg = gsub(gsub(msg, "(%S)(|c.-|H.-|h.-|h|r)", '%1 %2'), "(|c.-|H.-|h.-|h|r)(%S)", "%1 %2")
+ -- http://example.com
+ local newMsg, found = gsub(msg, "(%a+)://(%S+)%s?", CH:PrintURL("%1://%2"))
+ if found > 0 then return false, CH:CheckKeyword(newMsg), unpack(arg) end
+ -- www.example.com
+ newMsg, found = gsub(msg, "www%.([_A-Za-z0-9-]+)%.(%S+)%s?", CH:PrintURL("www.%1.%2"))
+ if found > 0 then return false, CH:CheckKeyword(newMsg), unpack(arg) end
+ -- example@example.com
+ newMsg, found = gsub(msg, "([_A-Za-z0-9-%.]+)@([_A-Za-z0-9-]+)(%.+)([_A-Za-z0-9-%.]+)%s?", CH:PrintURL("%1@%2%3%4"))
+ if found > 0 then return false, CH:CheckKeyword(newMsg), unpack(arg) end
+ -- IP address with port 1.1.1.1:1
+ newMsg, found = gsub(msg, "(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)(:%d+)%s?", CH:PrintURL("%1.%2.%3.%4%5"))
+ if found > 0 then return false, CH:CheckKeyword(newMsg), unpack(arg) end
+ -- IP address 1.1.1.1
+ newMsg, found = gsub(msg, "(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%s?", CH:PrintURL("%1.%2.%3.%4"))
+ if found > 0 then return false, CH:CheckKeyword(newMsg), unpack(arg) end
+
+ msg = CH:CheckKeyword(msg)
+
+ return false, msg, unpack(arg)
+end
+
+local SetHyperlink = ItemRefTooltip.SetHyperlink
+function ItemRefTooltip:SetHyperlink(data, ...)
+ if strsub(data, 1, 3) == "url" then
+ local currentLink = strsub(data, 5)
+ if not ChatFrameEditBox:IsShown() then
+ ChatFrameEditBox:Show()
+ ChatEdit_UpdateHeader(ChatFrameEditBox)
+ end
+ ChatFrameEditBox:Insert(currentLink)
+ ChatFrameEditBox:HighlightText()
+ else
+ SetHyperlink(self, data, unpack(arg))
+ end
+end
+
+local function WIM_URLLink(link)
+ if strsub(link, 1, 3) == "url" then
+ local currentLink = strsub(link, 5)
+ if not ChatFrameEditBox:IsShown() then
+ ChatFrameEditBox:Show()
+ ChatEdit_UpdateHeader(ChatFrameEditBox)
+ end
+ ChatFrameEditBox:Insert(currentLink)
+ ChatFrameEditBox:HighlightText()
+ return
+ end
+end
+
+local hyperLinkEntered
+function CH:OnHyperlinkEnter()
+ local linkToken = match(arg1, "([^:]+)")
+ if hyperlinkTypes[linkToken] then
+ ShowUIPanel(GameTooltip)
+ GameTooltip:SetOwner(this, "ANCHOR_CURSOR")
+ GameTooltip:SetHyperlink(arg1)
+ hyperLinkEntered = this
+ GameTooltip:Show()
+ end
+end
+
+function CH:OnHyperlinkLeave()
+ local linkToken = match(arg1, "([^:]+)")
+ if hyperlinkTypes[linkToken] then
+ HideUIPanel(GameTooltip)
+ hyperLinkEntered = nil
+ end
+end
+
+function CH:OnMessageScrollChanged()
+ if hyperLinkEntered == this then
+ HideUIPanel(GameTooltip)
+ hyperLinkEntered = false
+ end
+end
+
+function CH:EnableHyperlink()
+ for i = 1, NUM_CHAT_WINDOWS do
+ local frame = _G["ChatFrame"..i]
+ if (not self.hooks or not self.hooks[frame] or not self.hooks[frame].OnHyperlinkEnter) then
+ self:HookScript(frame, "OnHyperlinkEnter")
+ self:HookScript(frame, "OnHyperlinkLeave")
+ self:HookScript(frame, "OnMessageScrollChanged")
+ end
+ end
+end
+
+function CH:DisableHyperlink()
+ for i = 1, NUM_CHAT_WINDOWS do
+ local frame = _G["ChatFrame"..i]
+ if self.hooks and self.hooks[frame] and self.hooks[frame].OnHyperlinkEnter then
+ self:Unhook(frame, "OnHyperlinkEnter")
+ self:Unhook(frame, "OnHyperlinkLeave")
+ self:Unhook(frame, "OnMessageScrollChanged")
+ end
+ end
+end
+
+function CH:DisableChatThrottle()
+ twipe(msgList) twipe(msgCount) twipe(msgTime)
+end
+
+function CH.ShortChannel()
+ return format("|Hchannel:%s|h[%s]|h", arg8, DEFAULT_STRINGS[strupper(arg8)] or gsub(arg8, "channel:", ""))
+end
+
+function CH:ConcatenateTimeStamp(msg)
+ if CH.db.timeStampFormat and CH.db.timeStampFormat ~= "NONE" then
+ local timeStamp = BetterDate(CH.db.timeStampFormat, CH.timeOverride or time())
+ timeStamp = gsub(timeStamp, " ", "")
+ timeStamp = gsub(timeStamp, "AM", " AM")
+ timeStamp = gsub(timeStamp, "PM", " PM")
+ if CH.db.useCustomTimeColor then
+ local color = CH.db.customTimeColor
+ local hexColor = E:RGBToHex(color.r, color.g, color.b)
+ msg = format("%s[%s]|r %s", hexColor, timeStamp, msg)
+ else
+ msg = format("[%s] %s", timeStamp, msg)
+ end
+ CH.timeOverride = nil
+ end
+
+ return msg
+end
+
+function GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+ if not E.private.general.classCache then return arg2 end
+
+ if arg2 and arg2 ~= "" then
+ local name, realm = strsplit("-", arg2)
+ local englishClass = CC:GetClassByName(name, realm)
+
+ if englishClass then
+ local classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[englishClass] or RAID_CLASS_COLORS[englishClass]
+ if not classColorTable then
+ return arg2
+ end
+
+ return format("\124cff%.2x%.2x%.2x", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255)..arg2.."\124r"
+ end
+ end
+
+ return arg2
+end
+
+function CH:ChatFrame_MessageEventHandler(event, ...)
+ if event == "UPDATE_CHAT_WINDOWS" then
+ local name, fontSize, r, g, b, a, shown, locked = GetChatWindowInfo(self:GetID())
+ if fontSize > 0 then
+ local fontFile, unused, fontFlags = self:GetFont()
+ self:SetFont(fontFile, fontSize, fontFlags)
+ end
+ if shown then
+ self:Show()
+ end
+ -- Do more stuff!!!
+ ChatFrame_RegisterForMessages(GetChatWindowMessages(self:GetID()))
+ ChatFrame_RegisterForChannels(GetChatWindowChannels(self:GetID()))
+ return
+ end
+ if event == "PLAYER_ENTERING_WORLD" then
+ self.defaultLanguage = GetDefaultLanguage()
+ return
+ end
+ if event == "TIME_PLAYED_MSG" then
+ ChatFrame_DisplayTimePlayed(arg1, arg2)
+ return
+ end
+ if event == "PLAYER_LEVEL_UP" then
+ -- Level up
+ local info = ChatTypeInfo["SYSTEM"]
+
+ local string = format(TEXT(LEVEL_UP), arg1)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+
+ if arg3 > 0 then
+ string = format(TEXT(LEVEL_UP_HEALTH_MANA), arg2, arg3)
+ else
+ string = format(TEXT(LEVEL_UP_HEALTH), arg2)
+ end
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+
+ if arg4 > 0 then
+ string = format(GetText("LEVEL_UP_CHAR_POINTS", nil, arg4), arg4)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+
+ if arg5 > 0 then
+ string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT0_NAME), arg5)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ if arg6 > 0 then
+ string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT1_NAME), arg6)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ if arg7 > 0 then
+ string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT2_NAME), arg7)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ if arg8 > 0 then
+ string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT3_NAME), arg8)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ if arg9 > 0 then
+ string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT4_NAME), arg9)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ return
+ end
+ if event == "CHARACTER_POINTS_CHANGED" then
+ local info = ChatTypeInfo["SYSTEM"]
+ if arg2 > 0 then
+ local cp1, cp2 = UnitCharacterPoints("player")
+ if cp2 then
+ local string = format(GetText("LEVEL_UP_SKILL_POINTS", nil, cp2), cp2)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ end
+ return
+ end
+ if event == "GUILD_MOTD" then
+ if arg1 and (strlen(arg1) > 0) then
+ local info = ChatTypeInfo["GUILD"]
+ local string = format(TEXT(GUILD_MOTD_TEMPLATE), arg1)
+ self:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ return
+ end
+ if event == "EXECUTE_CHAT_LINE" then
+ self.editBox:SetText(arg1)
+ ChatEdit_SendText(self.editBox)
+ ChatEdit_OnEscapePressed(self.editBox)
+ return
+ end
+ if event == "UPDATE_CHAT_COLOR" then
+ local info = ChatTypeInfo[strupper(arg1)]
+ if info then
+ info.r = arg2
+ info.g = arg3
+ info.b = arg4
+ self:UpdateColorByID(info.id, info.r, info.g, info.b)
+
+ if strupper(arg1) == "WHISPER" then
+ info = ChatTypeInfo["REPLY"]
+ if info then
+ info.r = arg2
+ info.g = arg3
+ info.b = arg4
+ self:UpdateColorByID(info.id, info.r, info.g, info.b)
+ end
+ end
+ end
+ return
+ end
+ if strsub(event, 1, 8) == "CHAT_MSG" then
+ local type = strsub(event, 10)
+ local info = ChatTypeInfo[type]
+ local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 = unpack(arg)
+
+ local filter, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10 = false
+ if chatFilters[event] then
+ for _, filterFunc in next, chatFilters[event] do
+ filter, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10 = filterFunc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, event)
+ arg1 = newarg1 or arg1
+ if filter then
+ return true
+ elseif newarg1 and newarg2 then
+ arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 = newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10
+ end
+ end
+ end
+
+ local coloredName = GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+
+ local channelLength = arg4 and strlen(arg4)
+ if (strsub(type, 1, 7) == "CHANNEL") and (type ~= "CHANNEL_LIST") and ((arg1 ~= "INVITE") or (type ~= "CHANNEL_NOTICE_USER")) then
+ if arg1 == "WRONG_PASSWORD" then
+ local staticPopup = _G[StaticPopup_Visible("CHAT_CHANNEL_PASSWORD") or ""]
+ if staticPopup and staticPopup.data == arg9 then
+ -- Don't display invalid password messages if we're going to prompt for a password (bug 102312)
+ return
+ end
+ end
+
+ local found = 0
+ for index, value in pairs(self.channelList) do
+ if channelLength > strlen(value) then
+ -- arg9 is the channel name without the number in front...
+ if ((arg7 > 0) and (self.zoneChannelList[index] == arg7)) or (strupper(value) == strupper(arg9)) then
+ found = 1
+ info = ChatTypeInfo["CHANNEL"..arg8]
+ if (type == "CHANNEL_NOTICE") and (arg1 == "YOU_LEFT") then
+ self.channelList[index] = nil
+ self.zoneChannelList[index] = nil
+ end
+ break
+ end
+ end
+ end
+ if found == 0 or not info then
+ return true
+ end
+ end
+
+ if type == "SYSTEM" or type == "TEXT_EMOTE" or type == "SKILL" or type == "LOOT" or type == "MONEY" or
+ type == "OPENING" or type == "TRADESKILLS" or type == "PET_INFO" then
+ self:AddMessage(CH:ConcatenateTimeStamp(arg1), info.r, info.g, info.b, info.id)
+ elseif strsub(type,1,7) == "COMBAT_" then
+ self:AddMessage(CH:ConcatenateTimeStamp(arg1), info.r, info.g, info.b, info.id)
+ elseif strsub(type,1,6) == "SPELL_" then
+ self:AddMessage(CH:ConcatenateTimeStamp(arg1), info.r, info.g, info.b, info.id)
+ elseif strsub(type,1,10) == "BG_SYSTEM_" then
+ self:AddMessage(CH:ConcatenateTimeStamp(arg1), info.r, info.g, info.b, info.id)
+ elseif type == "IGNORED" then
+ self:AddMessage(format(CH:ConcatenateTimeStamp(GlobalStrings.CHAT_IGNORED), arg2), info.r, info.g, info.b, info.id)
+ elseif type == "FILTERED" then
+ self:AddMessage(format(CH:ConcatenateTimeStamp(GlobalStrings.CHAT_FILTERED), arg2), info.r, info.g, info.b, info.id)
+ elseif type == "RESTRICTED" then
+ self:AddMessage(CH:ConcatenateTimeStamp(GlobalStrings.CHAT_RESTRICTED), info.r, info.g, info.b, info.id)
+ elseif type == "CHANNEL_LIST" then
+ if channelLength > 0 then
+ self:AddMessage(format(CH:ConcatenateTimeStamp(_G["CHAT_"..type.."_GET"]..arg1), arg4), info.r, info.g, info.b, info.id)
+ else
+ self:AddMessage(CH:ConcatenateTimeStamp(arg1), info.r, info.g, info.b, info.id)
+ end
+ elseif type == "CHANNEL_NOTICE_USER" then
+ local globalstring = _G["CHAT_"..arg1.."_NOTICE"]
+ globalstring = CH:ConcatenateTimeStamp(globalstring)
+
+ if strlen(arg5) > 0 then
+ -- TWO users in this notice (E.G. x kicked y)
+ self:AddMessage(format(globalstring, arg4, arg2, arg5), info.r, info.g, info.b, info.id)
+ else
+ self:AddMessage(format(globalstring, arg4, arg2), info.r, info.g, info.b, info.id)
+ end
+ elseif type == "CHANNEL_NOTICE" then
+ local globalstring = _G["CHAT_"..arg1.."_NOTICE"]
+ if arg10 > 0 then
+ arg4 = arg4.." "..arg10
+ end
+ self:AddMessage(format(CH:ConcatenateTimeStamp(globalstring), arg4), info.r, info.g, info.b, info.id)
+ else
+ local body
+ local _, fontHeight = GetChatWindowInfo(self:GetID())
+
+ if fontHeight == 0 then
+ --fontHeight will be 0 if it's still at the default (14)
+ fontHeight = 14
+ end
+
+ -- Add AFK/DND flags
+ local pflag
+ if arg6 ~= "" then
+ if arg6 == "DND" or arg6 == "AFK" then
+ pflag = (pflag or "").._G["CHAT_FLAG_"..arg6]
+ else
+ pflag = _G["CHAT_FLAG_"..arg6]
+ end
+ else
+ if pflag == true then
+ pflag = ""
+ end
+ end
+
+ pflag = pflag or ""
+
+ local showLink = 1
+ if strsub(type, 1, 7) == "MONSTER" or strsub(type, 1, 9) == "RAID_BOSS" then
+ showLink = nil
+ else
+ arg1 = gsub(arg1, "%%", "%%%%")
+ end
+
+ local showLink = 1
+ if strsub(type, 1, 7) == "MONSTER" or type == "RAID_BOSS_EMOTE" then
+ showLink = nil
+ else
+ arg1 = gsub(arg1, "%%", "%%%%")
+ end
+
+ if (strlen(arg3) > 0) and (arg3 ~= "Universal") and (arg3 ~= GetDefaultLanguage()) then
+ local languageHeader = "["..arg3.."] "
+ if showLink and (strlen(arg2) > 0) then
+ body = format(_G["CHAT_"..type.."_GET"]..languageHeader..arg1, pflag.."|Hplayer:"..arg2.."|h".."["..coloredName.."]".."|h")
+ else
+ body = format(_G["CHAT_"..type.."_GET"]..languageHeader..arg1, pflag..arg2)
+ end
+ else
+ if showLink and (strlen(arg2) > 0) and (type ~= "EMOTE") then
+ body = format(_G["CHAT_"..type.."_GET"]..arg1, pflag.."|Hplayer:"..arg2.."|h".."["..coloredName.."]".."|h")
+ elseif showLink and (strlen(arg2) > 0) and (type == "EMOTE") then
+ body = format(_G["CHAT_"..type.."_GET"]..arg1, pflag.."|Hplayer:"..arg2.."|h".."["..coloredName.."]".."|h")
+ else
+ arg1 = gsub(arg1, "%%s %%s", "%%s")
+ body = format(_G["CHAT_"..type.."_GET"]..arg1, pflag..arg2)
+
+ -- Add raid boss emote message
+ if type == "RAID_BOSS_EMOTE" then
+ RaidBossEmoteFrame:AddMessage(body, info.r, info.g, info.b, 1.0)
+ PlaySound("RaidBossEmoteWarning")
+ end
+ end
+ end
+
+ -- Add Channel
+ arg4 = gsub(arg4, "%s%-%s.*", "")
+ if channelLength > 0 then
+ body = "|Hchannel:channel:"..arg8.."|h["..arg4.."]|h "..body
+ end
+
+ if CH.db.shortChannels then
+ body = gsub(body, "|Hchannel:(.-)|h%[(.-)%]|h", CH.ShortChannel)
+ body = gsub(body, "CHANNEL:", "")
+ body = gsub(body, "^(.-|h) "..L["whispers"], "%1")
+ body = gsub(body, "^(.-|h) "..L["says"], "%1")
+ body = gsub(body, "^(.-|h) "..L["yells"], "%1")
+ body = gsub(body, "<"..GlobalStrings.AFK..">", "[|cffFF0000"..L["AFK"].."|r] ")
+ body = gsub(body, "<"..GlobalStrings.DND..">", "[|cffE7E716"..L["DND"].."|r] ")
+ body = gsub(body, "^%["..GlobalStrings.CHAT_MSG_RAID_WARNING.."%]", "["..L["RW"].."]")
+ end
+ self:AddMessage(CH:ConcatenateTimeStamp(body), info.r, info.g, info.b, info.id)
+ end
+
+ if type == "WHISPER" then
+ ChatEdit_SetLastTellTarget(self.editBox, arg2)
+ if self.tellTimer and (GetTime() > self.tellTimer) then
+ PlaySound("TellMessage")
+ end
+ self.tellTimer = GetTime() + GlobalStrings.CHAT_TELL_ALERT_TIME
+ FCF_FlashTab()
+ end
+
+ return true
+ end
+end
+
+function CH:ChatFrame_OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+ if CH.ChatFrame_MessageEventHandler(self, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) then
+ return
+ end
+end
+
+function CH:FloatingChatFrame_OnEvent()
+ CH.ChatFrame_OnEvent(this, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+ FloatingChatFrame_OnEvent(this, event, 1)
+end
+
+local function OnTextChanged(self)
+ local text = self:GetText()
+
+ local MIN_REPEAT_CHARACTERS = E.db.chat.numAllowedCombatRepeat
+ if strlen(text) > MIN_REPEAT_CHARACTERS then
+ local repeatChar = true
+ for i = 1, MIN_REPEAT_CHARACTERS, 1 do
+ if strsub(text,(0-i), (0-i)) ~= strsub(text, (-1-i), (-1-i)) then
+ repeatChar = false
+ break
+ end
+ end
+ if repeatChar then
+ self:Hide()
+ return
+ end
+ end
+
+ if strlen(text) < 5 then
+ if strsub(text, 1, 4) == "/tt " then
+ local unitname, realm = UnitName("target")
+ if unitname and realm then
+ unitname = unitname .. "-" .. gsub(realm, " ", "")
+ end
+ ChatFrame_SendTell((unitname or L["Invalid Target"]), ChatFrame1)
+ end
+
+ if strsub(text, 1, 4) == "/gr " then
+ self:SetText(CH:GetGroupDistribution() .. strsub(text, 5))
+ ChatEdit_ParseText(self, 0)
+ end
+ end
+
+ local new, found = gsub(text, "|Kf(%S+)|k(%S+)%s(%S+)|k", "%2 %3")
+ if found > 0 then
+ new = gsub(new, "|", "")
+ self:SetText(new)
+ end
+end
+
+function CH:SetupChat()
+ if E.private.chat.enable ~= true then return end
+
+ for i = 1, NUM_CHAT_WINDOWS do
+ local frame = _G["ChatFrame"..i]
+ local id = frame:GetID()
+ local _, fontSize = GetChatWindowInfo(id)
+ self:StyleChat(frame)
+
+ frame:SetFont(LSM:Fetch("font", self.db.font), fontSize, self.db.fontOutline)
+ if self.db.fontOutline ~= "NONE" then
+ frame:SetShadowColor(0, 0, 0, 0.2)
+ else
+ frame:SetShadowColor(0, 0, 0, 1)
+ end
+ frame:SetTimeVisible(100)
+ frame:SetShadowOffset((E.mult or 1), -(E.mult or 1))
+ frame:SetFading(self.db.fade)
+
+ if not frame.scriptsSet then
+ frame:SetScript("OnMouseWheel", ChatFrame_OnMouseScroll)
+ frame:EnableMouseWheel(true)
+
+ if id ~= 2 then
+ frame:SetScript("OnEvent", CH.FloatingChatFrame_OnEvent)
+ end
+
+ hooksecurefunc(frame, "StopMovingOrSizing", function()
+ CH:PositionChat(true)
+ end)
+
+ frame.scriptsSet = true
+ end
+ end
+
+ local editbox = _G["ChatFrameEditBox"]
+ if not editbox.isSkinned then
+ local a, b, c = select(6, editbox:GetRegions()) E:Kill(a) E:Kill(b) E:Kill(c)
+ E:SetTemplate(editbox, "Default", true)
+ editbox:SetAltArrowKeyMode(CH.db.useAltKey)
+ editbox:SetAllPoints(LeftChatDataPanel)
+ self:SecureHook(editbox, "AddHistoryLine", "ChatEdit_AddHistory")
+ HookScript(editbox, "OnTextChanged", function() OnTextChanged(this) end)
+
+ editbox.historyLines = ElvCharacterDB.ChatEditHistory
+ editbox.historyIndex = 0
+ editbox:Hide()
+
+ HookScript(editbox, "OnEditFocusGained", function() this:Show() if not LeftChatPanel:IsShown() then LeftChatPanel.editboxforced = true LeftChatToggleButton:GetScript("OnEnter")(LeftChatToggleButton) end end)
+ HookScript(editbox, "OnEditFocusLost", function() if LeftChatPanel.editboxforced then LeftChatPanel.editboxforced = nil if LeftChatPanel:IsShown() then LeftChatToggleButton:GetScript("OnLeave")(LeftChatToggleButton) end end this.historyIndex = 0 this:Hide() end)
+
+ for _, text in pairs(ElvCharacterDB.ChatEditHistory) do
+ editbox:AddHistoryLine(text)
+ end
+ editbox.isSkinned = true
+ end
+
+ if self.db.hyperlinkHover then
+ self:EnableHyperlink()
+ end
+
+ DEFAULT_CHAT_FRAME:SetParent(LeftChatPanel)
+ self:ScheduleTimer("PositionChat", 1)
+end
+
+local function PrepareMessage(author, message)
+ if not author then return message end
+ return format("%s%s", strupper(author), message)
+end
+
+function CH:ChatThrottleHandler(_, ...)
+ local arg1, arg2 = unpack(arg)
+
+ if arg2 and arg2 ~= "" then
+ local message = PrepareMessage(arg2, arg1)
+ if msgList[message] == nil then
+ msgList[message] = true
+ msgCount[message] = 1
+ msgTime[message] = time()
+ else
+ msgCount[message] = msgCount[message] + 1
+ end
+ end
+end
+
+function CH.CHAT_MSG_CHANNEL(message, author, ...)
+ if not (message and author) then return end
+
+ local blockFlag = false
+ local msg = PrepareMessage(author, message)
+
+ if msg == nil then return CH.FindURL(message, author, unpack(arg)) end
+
+ -- ignore player messages
+ if author and author == UnitName("player") then return CH.FindURL(message, author, unpack(arg)) end
+ if msgList[msg] and CH.db.throttleInterval ~= 0 then
+ if difftime(time(), msgTime[msg]) <= CH.db.throttleInterval then
+ blockFlag = true
+ end
+ end
+
+ if blockFlag then
+ return true
+ else
+ if CH.db.throttleInterval ~= 0 then
+ msgTime[msg] = time()
+ end
+
+ return CH.FindURL(message, author, unpack(arg))
+ end
+end
+
+function CH.CHAT_MSG_YELL(message, author, ...)
+ if not (message and author) then return end
+
+ local blockFlag = false
+ local msg = PrepareMessage(author, message)
+
+ if msg == nil then return CH.FindURL(message, author, unpack(arg)) end
+
+ -- ignore player messages
+ if author and author == UnitName("player") then return CH.FindURL(message, author, unpack(arg)) end
+ if msgList[msg] and msgCount[msg] > 1 and CH.db.throttleInterval ~= 0 then
+ if difftime(time(), msgTime[msg]) <= CH.db.throttleInterval then
+ blockFlag = true
+ end
+ end
+
+ if blockFlag then
+ return true
+ else
+ if CH.db.throttleInterval ~= 0 then
+ msgTime[msg] = time()
+ end
+
+ return CH.FindURL(message, author, unpack(arg))
+ end
+end
+
+function CH.CHAT_MSG_SAY(message, author, ...)
+ if not (message and author) then return end
+
+ return CH.FindURL(message, author, unpack(arg))
+end
+
+function CH:ThrottleSound()
+ self.SoundPlayed = nil
+end
+
+local protectLinks = {}
+function CH:CheckKeyword(message)
+ for itemLink in gmatch(message, "|%x+|Hitem:.-|h.-|h|r") do
+ protectLinks[itemLink] = gsub(itemLink, "%s","|s")
+ for keyword, _ in pairs(CH.Keywords) do
+ if itemLink == keyword then
+ if self.db.keywordSound ~= "None" and not self.SoundPlayed then
+ PlaySoundFile(LSM:Fetch("sound", self.db.keywordSound), "Master")
+ self.SoundPlayed = true
+ self.SoundTimer = CH:ScheduleTimer("ThrottleSound", 1)
+ end
+ end
+ end
+ end
+
+ for itemLink, tempLink in pairs(protectLinks) do
+ message = gsub(message, gsub(itemLink, "([%(%)%.%%%+%-%*%?%[%^%$])","%%%1"), tempLink)
+ end
+
+ local classColorTable, tempWord, rebuiltString, lowerCaseWord, wordMatch, classMatch
+ local isFirstWord = true
+ for word in gmatch(message, "%s-[^%s]+%s*") do
+ tempWord = gsub(word, "[%s%p]", "")
+ lowerCaseWord = strlower(tempWord)
+ for keyword, _ in pairs(CH.Keywords) do
+ if lowerCaseWord == strlower(keyword) then
+ word = gsub(word, tempWord, format("%s%s|r", E.media.hexvaluecolor, tempWord))
+ if self.db.keywordSound ~= "None" and not self.SoundPlayed then
+ PlaySoundFile(LSM:Fetch("sound", self.db.keywordSound), "Master")
+ self.SoundPlayed = true
+ self.SoundTimer = CH:ScheduleTimer("ThrottleSound", 1)
+ end
+ end
+ end
+
+ if self.db.classColorMentionsChat and E.private.general.classCache then
+ tempWord = gsub(word, "^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$","%1%2")
+
+ classMatch = CC:GetCacheTable()[E.myrealm][tempWord]
+ wordMatch = classMatch and lowerCaseWord
+
+ if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then
+ classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classMatch] or RAID_CLASS_COLORS[classMatch]
+ word = gsub(word, gsub(tempWord, "%-","%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord))
+ end
+ end
+
+ if isFirstWord then
+ rebuiltString = word
+ isFirstWord = false
+ else
+ rebuiltString = format("%s%s", rebuiltString, word)
+ end
+ end
+
+ for itemLink, tempLink in pairs(protectLinks) do
+ rebuiltString = gsub(rebuiltString, gsub(tempLink, "([%(%)%.%%%+%-%*%?%[%^%$])","%%%1"), itemLink)
+ protectLinks[itemLink] = nil
+ end
+
+ return rebuiltString
+end
+
+function CH:AddLines(lines, ...)
+ for i = getn(arg), 1, -1 do
+ local x = select(i, unpack(arg))
+ if x:GetObjectType() == "FontString" and not x:GetName() then
+ tinsert(lines, x:GetText())
+ end
+ end
+end
+
+function CH:ChatEdit_UpdateHeader()
+ local type = this.chatType
+ if type == "CHANNEL" then
+ local id = GetChannelName(this.channelTarget)
+ if id == 0 then
+ this:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ else
+ this:SetBackdropBorderColor(ChatTypeInfo[type..id].r, ChatTypeInfo[type..id].g, ChatTypeInfo[type..id].b)
+ end
+ elseif type then
+ this:SetBackdropBorderColor(ChatTypeInfo[type].r, ChatTypeInfo[type].g, ChatTypeInfo[type].b)
+ end
+end
+
+function CH:ChatEdit_OnEnterPressed()
+ local type = this.chatType
+ if ChatTypeInfo[type].sticky == 1 then
+ if not self.db.sticky then type = "SAY" end
+ this.chatType = type
+ end
+end
+
+function CH:SetItemRef(link, text, button)
+ if strsub(link, 1, 7) == "channel" then
+ if IsModifiedClick("CHATLINK") then
+ ToggleFriendsFrame(4)
+ elseif button == "LeftButton" then
+ local chanLink = sub(link, 9)
+ local chatType, chatTarget = strsplit(":", chanLink)
+
+ if strupper(chatType) == "CHANNEL" then
+ if GetChannelName(tonumber(chatTarget)) ~= 0 then
+ ChatFrame_OpenChat("/"..chatTarget, this)
+ end
+ else
+ ChatFrame_OpenChat("/"..chatType, this)
+ end
+--[[ -- TODO
+ elseif button == "RightButton" then
+ local chanLink = sub(link, 9)
+ local chatType, chatTarget = strsplit(":", chanLink)
+
+ if not strupper(chatType) == "CHANNEL" and GetChannelName(tonumber(chatTarget)) == 0 then
+ ChatChannelDropDown_Show(this, strupper(chatType), chatTarget, Chat_GetColoredChatName(strupper(chatType), chatTarget))
+ end
+]]
+ end
+
+ return
+ end
+
+ return self.hooks.SetItemRef(link, text, button)
+end
+
+function CH:SetChatFont(chatFrame, fontSize)
+ if not chatFrame then
+ chatFrame = FCF_GetCurrentChatFrame()
+ end
+ if not fontSize then
+ fontSize = this.value
+ end
+ chatFrame:SetFont(LSM:Fetch("font", self.db.font), fontSize, self.db.fontOutline)
+
+ if self.db.fontOutline ~= "NONE" then
+ chatFrame:SetShadowColor(0, 0, 0, 0.2)
+ else
+ chatFrame:SetShadowColor(0, 0, 0, 1)
+ end
+ chatFrame:SetShadowOffset((E.mult or 1), -(E.mult or 1))
+end
+
+function CH:ChatEdit_AddHistory(_, line)
+ if find(line, "/rl") then return end
+
+ if strlen(line) > 0 then
+ for _, text in pairs(ElvCharacterDB.ChatEditHistory) do
+ if text == line then
+ return
+ end
+ end
+
+ tinsert(ElvCharacterDB.ChatEditHistory, getn(ElvCharacterDB.ChatEditHistory) + 1, line)
+ if getn(ElvCharacterDB.ChatEditHistory) > 20 then
+ tremove(ElvCharacterDB.ChatEditHistory, 1)
+ end
+ end
+end
+
+function CH:UpdateChatKeywords()
+ twipe(CH.Keywords)
+ local keywords = self.db.keywords
+ keywords = gsub(keywords,",%s",",")
+
+ for i = 1, getn({split(",", keywords)}) do
+ local stringValue = select(i, split(",", keywords))
+ if stringValue ~= "" then
+ CH.Keywords[stringValue] = true
+ end
+ end
+end
+
+function CH:UpdateFading()
+ for i = 1, NUM_CHAT_WINDOWS do
+ local frame = _G["ChatFrame"..i]
+ if frame then
+ frame:SetFading(self.db.fade)
+ end
+ end
+end
+
+function CH:DisplayChatHistory()
+ local data, chat, d = ElvCharacterDB.ChatHistoryLog
+ if not (data and next(data)) then return end
+
+ CH.SoundPlayed = true
+ for i = 1, NUM_CHAT_WINDOWS do
+ chat = _G["ChatFrame"..i]
+ for i = 1, getn(data) do
+ d = data[i]
+ if type(d) == "table" then
+ CH.timeOverride = d[51]
+ for _, messageType in pairs(chat.messageTypeList) do
+ if gsub(strsub(d[50],10),"_INFORM","") == messageType then
+ CH.ChatFrame_MessageEventHandler(chat,d[50],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8],d[9],d[10],d[11])
+ end
+ end
+ end
+ end
+ end
+ CH.SoundPlayed = nil
+end
+
+tremove(ChatTypeGroup["GUILD"], 2)
+function CH:DelayGuildMOTD()
+ local delay, delayFrame, chat = 0, CreateFrame("Frame")
+ tinsert(ChatTypeGroup["GUILD"], 2, "GUILD_MOTD")
+ delayFrame:SetScript("OnUpdate", function()
+ delay = delay + arg1
+ if delay < 7 then return end
+ local msg = GetGuildRosterMOTD()
+ for i = 1, NUM_CHAT_WINDOWS do
+ local channel
+ chat = _G["ChatFrame"..i]
+ for k, v in pairs(chat.messageTypeList) do
+ if v == "GUILD" then
+ channel = v
+ end
+ end
+ if chat and channel then
+ if msg and strlen(msg) > 0 then
+ local info = ChatTypeInfo["GUILD"]
+ local string = format(GUILD_MOTD_TEMPLATE, msg)
+ chat:AddMessage(string, info.r, info.g, info.b, info.id)
+ end
+ chat:RegisterEvent("GUILD_MOTD")
+ end
+ end
+ this:SetScript("OnUpdate", nil)
+ end)
+end
+
+function CH:SaveChatHistory(event, ...)
+ if not self.db.chatHistory then return end
+ local data = ElvCharacterDB.ChatHistoryLog
+
+ if self.db.throttleInterval ~= 0 and (event == "CHAT_MESSAGE_SAY" or event == "CHAT_MESSAGE_YELL" or event == "CHAT_MSG_CHANNEL") then
+ self:ChatThrottleHandler(event, unpack(arg))
+
+ local message, author = unpack(arg)
+ local msg = PrepareMessage(author, message)
+ if author and author ~= PLAYER_NAME and msgList[msg] then
+ if difftime(time(), msgTime[msg]) <= CH.db.throttleInterval then
+ return
+ end
+ end
+ end
+
+ local temp = {}
+ for i = 1, getn(arg) do
+ temp[i] = select(i, unpack(arg)) or false
+ end
+
+ if getn(temp) > 0 then
+ temp[50] = event
+ temp[51] = time()
+
+ tinsert(data, temp)
+ while getn(data) >= 128 do
+ tremove(data, 1)
+ end
+ end
+ temp = nil -- Destory!
+end
+
+function CH:ChatFrame_AddMessageEventFilter(event, filter)
+ assert(event and filter)
+
+ if chatFilters[event] then
+ -- Only allow a filter to be added once
+ for _, filterFunc in next, chatFilters[event] do
+ if filterFunc == filter then
+ return
+ end
+ end
+ else
+ chatFilters[event] = {}
+ end
+
+ tinsert(chatFilters[event], filter)
+end
+
+function CH:ChatFrame_RemoveMessageEventFilter(event, filter)
+ assert(event and filter)
+
+ if chatFilters[event] then
+ for index, filterFunc in next, chatFilters[event] do
+ if filterFunc == filter then
+ tremove(chatFilters[event], index)
+ end
+ end
+
+ if getn(chatFilters[event]) == 0 then
+ chatFilters[event] = nil
+ end
+ end
+end
+
+function CH:FCF_SetWindowAlpha(frame, alpha)
+ frame.oldAlpha = alpha or 1
+end
+
+local FindURL_Events = {
+ "CHAT_MSG_WHISPER",
+ "CHAT_MSG_WHISPER_INFORM",
+ "CHAT_MSG_GUILD",
+ "CHAT_MSG_OFFICER",
+ "CHAT_MSG_PARTY",
+ "CHAT_MSG_RAID",
+ "CHAT_MSG_RAID_LEADER",
+ "CHAT_MSG_RAID_WARNING",
+ "CHAT_MSG_BATTLEGROUND",
+ "CHAT_MSG_BATTLEGROUND_LEADER",
+ "CHAT_MSG_CHANNEL",
+ "CHAT_MSG_SAY",
+ "CHAT_MSG_YELL",
+ "CHAT_MSG_EMOTE",
+ "CHAT_MSG_TEXT_EMOTE",
+ "CHAT_MSG_AFK",
+ "CHAT_MSG_DND",
+}
+
+
+function CH:Initialize()
+ if ElvCharacterDB.ChatHistory then
+ ElvCharacterDB.ChatHistory = nil --Depreciated
+ end
+ if ElvCharacterDB.ChatLog then
+ ElvCharacterDB.ChatLog = nil --Depreciated
+ end
+
+ self.db = E.db.chat
+
+ self:DelayGuildMOTD() --Keep this before `is Chat Enabled` check
+ if E.private.chat.enable ~= true then return end
+
+ if not ElvCharacterDB.ChatEditHistory then
+ ElvCharacterDB.ChatEditHistory = {}
+ end
+
+ if not ElvCharacterDB.ChatHistoryLog or not self.db.chatHistory then
+ ElvCharacterDB.ChatHistoryLog = {}
+ end
+
+ self:UpdateChatKeywords()
+
+ self:UpdateFading()
+ E.Chat = self
+ self:SecureHook("ChatEdit_UpdateHeader")
+ self:SecureHook("ChatEdit_OnEnterPressed")
+ self:RawHook("SetItemRef", true)
+
+ E:Kill(ChatFrameMenuButton)
+
+ if WIM then
+ WIM.RegisterWidgetTrigger("chat_display", "whisper,chat,w2w,demo", "OnHyperlinkClick", function(self) CH.clickedframe = self end)
+ WIM.RegisterItemRefHandler("url", WIM_URLLink)
+ end
+
+ self:SecureHook("FCF_SetChatWindowFontSize", "SetChatFont")
+ self:RegisterEvent("UPDATE_CHAT_WINDOWS", "SetupChat")
+ self:RegisterEvent("UPDATE_FLOATING_CHAT_WINDOWS", "SetupChat")
+
+ self:SetupChat()
+ self:UpdateAnchors()
+ if not E.db.chat.lockPositions then
+ CH:UpdateChatTabs() --It was not done in PositionChat, so do it now
+ end
+
+ --First get all pre-existing filters and copy them to our version of chatFilters using ChatFrame_GetMessageEventFilters
+ for name, _ in pairs(ChatTypeGroup) do
+ for i = 1, getn(ChatTypeGroup[name]) do
+ local filterFuncTable = ChatFrame_GetMessageEventFilters(ChatTypeGroup[name][i])
+ if filterFuncTable then
+ chatFilters[ChatTypeGroup[name][i]] = {}
+
+ for j = 1, getn(filterFuncTable) do
+ local filterFunc = filterFuncTable[j]
+ tinsert(chatFilters[ChatTypeGroup[name][i]], filterFunc)
+ end
+ end
+ end
+ end
+
+ --CHAT_MSG_CHANNEL isn't located inside ChatTypeGroup
+ local filterFuncTable = ChatFrame_GetMessageEventFilters("CHAT_MSG_CHANNEL")
+ if filterFuncTable then
+ chatFilters["CHAT_MSG_CHANNEL"] = {}
+
+ for j = 1, getn(filterFuncTable) do
+ local filterFunc = filterFuncTable[j]
+ tinsert(chatFilters["CHAT_MSG_CHANNEL"], filterFunc)
+ end
+ end
+
+ --Now hook onto Blizzards functions for other addons
+ hooksecurefunc(self, "ChatFrame_AddMessageEventFilter", ChatFrame_AddMessageEventFilter)
+ hooksecurefunc(self, "ChatFrame_RemoveMessageEventFilter", ChatFrame_RemoveMessageEventFilter)
+
+ self:SecureHook("FCF_SetWindowAlpha")
+
+ ChatTypeInfo["SAY"].sticky = 1
+ ChatTypeInfo["EMOTE"].sticky = 1
+ ChatTypeInfo["YELL"].sticky = 1
+ ChatTypeInfo["WHISPER"].sticky = 1
+ ChatTypeInfo["PARTY"].sticky = 1
+ ChatTypeInfo["RAID"].sticky = 1
+ ChatTypeInfo["RAID_WARNING"].sticky = 1
+ ChatTypeInfo["BATTLEGROUND"].sticky = 1
+ ChatTypeInfo["GUILD"].sticky = 1
+ ChatTypeInfo["OFFICER"].sticky = 1
+ ChatTypeInfo["CHANNEL"].sticky = 1
+
+ if self.db.chatHistory then
+ self:DisplayChatHistory()
+ end
+
+ for _, event in pairs(FindURL_Events) do
+ ChatFrame_AddMessageEventFilter(event, CH[event] or CH.FindURL)
+ local nType = strsub(event, 10)
+ if nType ~= "AFK" and nType ~= "DND" then
+ self:RegisterEvent(event, "SaveChatHistory")
+ end
+ end
+
+ local S = E:GetModule("Skins")
+
+ local frame = CreateFrame("Frame", "CopyChatFrame", E.UIParent)
+ tinsert(UISpecialFrames, "CopyChatFrame")
+ E:SetTemplate(frame, "Transparent")
+ frame:SetWidth(700)
+ frame:SetHeight(200)
+ frame:SetPoint("BOTTOM", E.UIParent, "BOTTOM", 0, 3)
+ frame:Hide()
+ frame:SetMovable(true)
+ frame:EnableMouse(true)
+ frame:SetResizable(true)
+ frame:SetMinResize(350, 100)
+ frame:SetScript("OnMouseDown", function()
+ if arg1 == "LeftButton" and not this.isMoving then
+ this:StartMoving()
+ this.isMoving = true
+ elseif arg1 == "RightButton" and not this.isSizing then
+ this:StartSizing()
+ this.isSizing = true
+ end
+ end)
+ frame:SetScript("OnMouseUp", function()
+ if arg1 == "LeftButton" and this.isMoving then
+ this:StopMovingOrSizing()
+ this.isMoving = false
+ elseif arg1 == "RightButton" and this.isSizing then
+ this:StopMovingOrSizing()
+ this.isSizing = false
+ end
+ end)
+ frame:SetScript("OnHide", function()
+ if this.isMoving or this.isSizing then
+ this:StopMovingOrSizing()
+ this.isMoving = false
+ this.isSizing = false
+ end
+ end)
+ frame:SetFrameStrata("DIALOG")
+
+ local scrollArea = CreateFrame("ScrollFrame", "CopyChatScrollFrame", frame, "UIPanelScrollFrameTemplate")
+ scrollArea:SetWidth(662)
+ scrollArea:SetHeight(162)
+ scrollArea:SetPoint("TOPLEFT", frame, "TOPLEFT", 8, -30)
+ S:HandleScrollBar(CopyChatScrollFrameScrollBar)
+
+ HookScript(scrollArea, "OnVerticalScroll", function()
+ CopyChatFrameEditBox:SetHitRectInsets(0, 0, arg1, (CopyChatFrameEditBox:GetHeight() - arg1 - this:GetHeight()))
+ end)
+
+ local editBox = CreateFrame("EditBox", "CopyChatFrameEditBox", frame)
+ editBox:SetMultiLine(true)
+ editBox:SetMaxLetters(99999)
+ editBox:EnableMouse(true)
+ editBox:SetAutoFocus(false)
+ editBox:SetFontObject(GameFontNormal)
+ editBox:SetWidth(scrollArea:GetWidth())
+ editBox:SetHeight(200)
+ editBox:SetScript("OnEscapePressed", function() CopyChatFrame:Hide() end)
+ scrollArea:SetScrollChild(editBox)
+ --[[CopyChatFrameEditBox:SetScript("OnTextChanged", function()
+ local scrollBar = CopyChatScrollFrameScrollBar
+ local _, max = scrollBar:GetMinMaxValues()
+ for i = 1, max do
+ scrollBar:SetValue(scrollBar:GetValue() + (scrollBar:GetHeight() / 2))
+ end
+ end)]]
+
+ frame:SetScript("OnSizeChanged", function()
+ local width, height = this:GetWidth() - 38, this:GetHeight() - 38
+ scrollArea:SetWidth(width)
+ scrollArea:SetHeight(height)
+ CopyChatFrameEditBox:SetWidth(width)
+ CopyChatFrameEditBox:SetHeight(height)
+ end)
+
+ local close = CreateFrame("Button", "CopyChatFrameCloseButton", frame, "UIPanelCloseButton")
+ close:SetPoint("TOPRIGHT", 0, 0)
+ close:SetFrameLevel(close:GetFrameLevel() + 1)
+ S:HandleCloseButton(close)
+end
+
+local function InitializeCallback()
+ CH:Initialize()
+end
+
+E:RegisterModule(CH:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Chat/Load_Chat.xml b/ElvUI/Modules/Chat/Load_Chat.xml
new file mode 100644
index 0000000..2a357f4
--- /dev/null
+++ b/ElvUI/Modules/Chat/Load_Chat.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/DataBars/DataBars.lua b/ElvUI/Modules/DataBars/DataBars.lua
new file mode 100644
index 0000000..c1dab2b
--- /dev/null
+++ b/ElvUI/Modules/DataBars/DataBars.lua
@@ -0,0 +1,66 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local mod = E:NewModule("DataBars", "AceEvent-3.0");
+E.DataBars = mod
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+local UIFrameFadeOut = UIFrameFadeOut
+
+function mod:OnLeave()
+ if (this == ElvUI_ExperienceBar and mod.db.experience.mouseover) or (this == ElvUI_ReputationBar and mod.db.reputation.mouseover) then
+ UIFrameFadeOut(this, 1, this:GetAlpha(), 0)
+ end
+ GameTooltip:Hide()
+end
+
+function mod:CreateBar(name, onEnter, onClick, ...)
+ local bar = CreateFrame("Button", name, E.UIParent)
+ bar:SetPoint(unpack(arg))
+ bar:SetScript("OnEnter", onEnter)
+ bar:SetScript("OnLeave", mod.OnLeave)
+ bar:SetScript("OnClick", onClick)
+ bar:SetFrameStrata("LOW")
+ E:SetTemplate(bar, "Transparent")
+ bar:Hide()
+
+ bar.statusBar = CreateFrame("StatusBar", nil, bar)
+ E:SetInside(bar.statusBar)
+ bar.statusBar:SetStatusBarTexture(E.media.normTex)
+ E:RegisterStatusBar(bar.statusBar)
+ bar.text = bar.statusBar:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(bar.text)
+ bar.text:SetPoint("CENTER", 0, 0)
+
+ return bar
+end
+
+function mod:UpdateDataBarDimensions()
+ self:UpdateExperienceDimensions()
+ self:UpdateReputationDimensions()
+end
+
+function mod:PLAYER_LEVEL_UP(level, level2)
+ print(level, level2)
+ local maxLevel = 60
+ if (level ~= maxLevel or not self.db.experience.hideAtMaxLevel) and self.db.experience.enable then
+ self:UpdateExperience("PLAYER_LEVEL_UP", level)
+ else
+ self.expBar:Hide()
+ end
+end
+
+function mod:Initialize()
+ self.db = E.db.databars
+
+ self:LoadExperienceBar()
+ self:LoadReputationBar()
+ self:RegisterEvent("PLAYER_LEVEL_UP")
+end
+
+local function InitializeCallback()
+ mod:Initialize()
+end
+
+E:RegisterModule(mod:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/DataBars/Experience.lua b/ElvUI/Modules/DataBars/Experience.lua
new file mode 100644
index 0000000..fd325a3
--- /dev/null
+++ b/ElvUI/Modules/DataBars/Experience.lua
@@ -0,0 +1,166 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local mod = E:GetModule("DataBars");
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local format = format
+local min = min
+--WoW API / Variables
+local GetPetExperience, UnitXP, UnitXPMax = GetPetExperience, UnitXP, UnitXPMax
+local UnitLevel = UnitLevel
+local GetXPExhaustion = GetXPExhaustion
+
+function mod:GetXP(unit)
+ if unit == "pet" then
+ return GetPetExperience()
+ else
+ return UnitXP(unit), UnitXPMax(unit)
+ end
+end
+
+function mod:UpdateExperience(event)
+ if not mod.db.experience.enable then return end
+
+ local bar = self.expBar
+ local hideXP = (UnitLevel("player") == 60 and self.db.experience.hideAtMaxLevel)
+
+ if hideXP then
+ E:DisableMover(self.expBar.mover:GetName())
+ bar:Hide()
+ elseif not hideXP then
+ E:EnableMover(self.expBar.mover:GetName())
+ bar:Show()
+
+ local cur, max = self:GetXP("player")
+ if max <= 0 then max = 1 end
+ bar.statusBar:SetMinMaxValues(0, max)
+ bar.statusBar:SetValue(cur - 1 >= 0 and cur - 1 or 0)
+ bar.statusBar:SetValue(cur)
+
+ local rested = GetXPExhaustion()
+ local text = ""
+ local textFormat = self.db.experience.textFormat
+
+ if rested and rested > 0 then
+ bar.rested:SetMinMaxValues(0, max)
+ bar.rested:SetValue(min(cur + rested, max))
+
+ if textFormat == "PERCENT" then
+ text = format("%d%% R:%d%%", cur / max * 100, rested / max * 100)
+ elseif textFormat == "CURMAX" then
+ text = format("%s - %s R:%s", E:ShortValue(cur), E:ShortValue(max), E:ShortValue(rested))
+ elseif textFormat == "CURPERC" then
+ text = format("%s - %d%% R:%s [%d%%]", E:ShortValue(cur), cur / max * 100, E:ShortValue(rested), rested / max * 100)
+ elseif textFormat == "CUR" then
+ text = format("%s R:%s", E:ShortValue(cur), E:ShortValue(rested))
+ elseif textFormat == "REM" then
+ text = format("%s R:%s", E:ShortValue(max - cur), E:ShortValue(rested))
+ elseif textFormat == "CURREM" then
+ text = format("%s - %s R:%s", E:ShortValue(cur), E:ShortValue(max - cur), E:ShortValue(rested))
+ elseif textFormat == "CURPERCREM" then
+ text = format("%s - %d%% (%s) R:%s", E:ShortValue(cur), cur / max * 100, E:ShortValue(max - cur), E:ShortValue(rested))
+ end
+ else
+ bar.rested:SetMinMaxValues(0, 1)
+ bar.rested:SetValue(0)
+
+ if textFormat == "PERCENT" then
+ text = format("%d%%", cur / max * 100)
+ elseif textFormat == "CURMAX" then
+ text = format("%s - %s", E:ShortValue(cur), E:ShortValue(max))
+ elseif textFormat == "CURPERC" then
+ text = format("%s - %d%%", E:ShortValue(cur), cur / max * 100)
+ elseif textFormat == "CUR" then
+ text = format("%s", E:ShortValue(cur))
+ elseif textFormat == "REM" then
+ text = format("%s", E:ShortValue(max - cur))
+ elseif textFormat == "CURREM" then
+ text = format("%s - %s", E:ShortValue(cur), E:ShortValue(max - cur))
+ elseif textFormat == "CURPERCREM" then
+ text = format("%s - %d%% (%s)", E:ShortValue(cur), cur / max * 100, E:ShortValue(max - cur))
+ end
+ end
+
+ bar.text:SetText(text)
+ end
+end
+
+function mod:ExperienceBar_OnEnter()
+ if mod.db.experience.mouseover then
+ UIFrameFadeIn(this, 0.4, this:GetAlpha(), 1)
+ end
+ GameTooltip:ClearLines()
+ GameTooltip:SetOwner(this, "ANCHOR_CURSOR", 0, -4)
+
+ local cur, max = mod:GetXP("player")
+ local rested = GetXPExhaustion()
+ GameTooltip:AddLine(L["Experience"])
+ GameTooltip:AddLine(" ")
+
+ GameTooltip:AddDoubleLine(L["XP:"], format(" %d / %d (%d%%)", cur, max, cur/max * 100), 1, 1, 1)
+ GameTooltip:AddDoubleLine(L["Remaining:"], format(" %d (%d%% - %d "..L["Bars"]..")", max - cur, (max - cur) / max * 100, 20 * (max - cur) / max), 1, 1, 1)
+
+ if rested then
+ GameTooltip:AddDoubleLine(L["Rested:"], format("+%d (%d%%)", rested, rested / max * 100), 1, 1, 1)
+ end
+
+ GameTooltip:Show()
+end
+
+function mod:ExperienceBar_OnClick()
+
+end
+
+function mod:UpdateExperienceDimensions()
+ self.expBar:SetWidth(self.db.experience.width)
+ self.expBar:SetHeight(self.db.experience.height)
+
+ E:FontTemplate(self.expBar.text, LSM:Fetch("font", self.db.experience.font), self.db.experience.textSize, self.db.experience.fontOutline)
+ self.expBar.rested:SetOrientation(self.db.experience.orientation)
+
+ self.expBar.statusBar:SetOrientation(self.db.experience.orientation)
+
+ if self.db.experience.mouseover then
+ self.expBar:SetAlpha(0)
+ else
+ self.expBar:SetAlpha(1)
+ end
+end
+
+function mod:EnableDisable_ExperienceBar()
+ local maxLevel = 60
+ if (UnitLevel("player") ~= maxLevel or not self.db.experience.hideAtMaxLevel) and self.db.experience.enable then
+ self:RegisterEvent("PLAYER_XP_UPDATE", "UpdateExperience")
+ self:RegisterEvent("DISABLE_XP_GAIN", "UpdateExperience")
+ self:RegisterEvent("ENABLE_XP_GAIN", "UpdateExperience")
+ self:RegisterEvent("UPDATE_EXHAUSTION", "UpdateExperience")
+ self:UnregisterEvent("UPDATE_EXPANSION_LEVEL")
+ self:UpdateExperience()
+ E:EnableMover(self.expBar.mover:GetName())
+ else
+ self:UnregisterEvent("PLAYER_XP_UPDATE")
+ self:UnregisterEvent("DISABLE_XP_GAIN")
+ self:UnregisterEvent("ENABLE_XP_GAIN")
+ self:UnregisterEvent("UPDATE_EXHAUSTION")
+ self:RegisterEvent("UPDATE_EXPANSION_LEVEL", "EnableDisable_ExperienceBar")
+ self.expBar:Hide()
+ E:DisableMover(self.expBar.mover:GetName())
+ end
+end
+
+function mod:LoadExperienceBar()
+ self.expBar = self:CreateBar("ElvUI_ExperienceBar", self.ExperienceBar_OnEnter, self.ExperienceBar_OnClick, "LEFT", LeftChatPanel, "RIGHT", -E.Border + E.Spacing*3, 0)
+ self.expBar.statusBar:SetStatusBarColor(0, 0.4, 1, .8)
+ self.expBar.rested = CreateFrame("StatusBar", nil, self.expBar)
+ E:SetInside(self.expBar.rested)
+ self.expBar.rested:SetStatusBarTexture(E.media.normTex)
+ E:RegisterStatusBar(self.expBar.rested)
+ self.expBar.rested:SetStatusBarColor(1, 0, 1, 0.2)
+
+ self:UpdateExperienceDimensions()
+
+ E:CreateMover(self.expBar, "ExperienceBarMover", L["Experience Bar"])
+ self:EnableDisable_ExperienceBar()
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/DataBars/Load_DataBars.xml b/ElvUI/Modules/DataBars/Load_DataBars.xml
new file mode 100644
index 0000000..dfe5f03
--- /dev/null
+++ b/ElvUI/Modules/DataBars/Load_DataBars.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/DataBars/Reputation.lua b/ElvUI/Modules/DataBars/Reputation.lua
new file mode 100644
index 0000000..ab1ea43
--- /dev/null
+++ b/ElvUI/Modules/DataBars/Reputation.lua
@@ -0,0 +1,132 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local mod = E:GetModule("DataBars");
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local format = format
+--WoW API / Variables
+local GetWatchedFactionInfo, GetNumFactions, GetFactionInfo = GetWatchedFactionInfo, GetNumFactions, GetFactionInfo
+local InCombatLockdown = InCombatLockdown
+local FACTION_BAR_COLORS = FACTION_BAR_COLORS
+local REPUTATION, STANDING = REPUTATION, STANDING
+
+local backupColor = FACTION_BAR_COLORS[1]
+local FactionStandingLabelUnknown = UNKNOWN
+function mod:UpdateReputation(event)
+ if not mod.db.reputation.enable then return end
+
+ local bar = self.repBar
+
+ local ID, standingLabel
+ local name, reaction, min, max, value = GetWatchedFactionInfo()
+ local numFactions = GetNumFactions()
+
+ if not name then
+ bar:Hide()
+ elseif name then
+ bar:Show()
+
+ local text = ""
+ local textFormat = self.db.reputation.textFormat
+ local color = FACTION_BAR_COLORS[reaction] or backupColor
+ bar.statusBar:SetStatusBarColor(color.r, color.g, color.b)
+
+ bar.statusBar:SetMinMaxValues(min, max)
+ bar.statusBar:SetValue(value)
+
+ for i = 1, numFactions do
+ local factionName, _, standingID = GetFactionInfo(i)
+ if factionName == name then
+ ID = standingID;
+ end
+ end
+
+ if ID then
+ standingLabel = _G["FACTION_STANDING_LABEL"..ID]
+ else
+ standingLabel = FactionStandingLabelUnknown
+ end
+
+ --Prevent a division by zero
+ local maxMinDiff = max - min
+ if maxMinDiff == 0 then
+ maxMinDiff = 1
+ end
+
+ if textFormat == "PERCENT" then
+ text = format("%s: %d%% [%s]", name, ((value - min) / maxMinDiff * 100), standingLabel)
+ elseif textFormat == "CURMAX" then
+ text = format("%s: %s - %s [%s]", name, E:ShortValue(value - min), E:ShortValue(max - min), standingLabel)
+ elseif textFormat == "CURPERC" then
+ text = format("%s: %s - %d%% [%s]", name, E:ShortValue(value - min), ((value - min) / maxMinDiff * 100), standingLabel)
+ elseif textFormat == "CUR" then
+ text = format("%s: %s [%s]", name, E:ShortValue(value - min), standingLabel)
+ elseif textFormat == "REM" then
+ text = format("%s: %s [%s]", name, E:ShortValue((max - min) - (value-min)), standingLabel)
+ elseif textFormat == "CURREM" then
+ text = format("%s: %s - %s [%s]", name, E:ShortValue(value - min), E:ShortValue((max - min) - (value-min)), standingLabel)
+ elseif textFormat == "CURPERCREM" then
+ text = format("%s: %s - %d%% (%s) [%s]", name, E:ShortValue(value - min), ((value - min) / maxMinDiff * 100), E:ShortValue((max - min) - (value-min)), standingLabel)
+ end
+
+ bar.text:SetText(text)
+ end
+end
+
+function mod:ReputationBar_OnEnter()
+ if mod.db.reputation.mouseover then
+ UIFrameFadeIn(this, 0.4, this:GetAlpha(), 1)
+ end
+ GameTooltip:ClearLines()
+ GameTooltip:SetOwner(this, "ANCHOR_CURSOR", 0, -4)
+
+ local name, reaction, min, max, value = GetWatchedFactionInfo()
+ if name then
+ GameTooltip:AddLine(name)
+ GameTooltip:AddLine(" ")
+
+ GameTooltip:AddDoubleLine(STANDING..":", _G["FACTION_STANDING_LABEL"..reaction], 1, 1, 1)
+ GameTooltip:AddDoubleLine(REPUTATION..":", format("%d / %d (%d%%)", value - min, max - min, (value - min) / ((max - min == 0) and max or (max - min)) * 100), 1, 1, 1)
+ end
+ GameTooltip:Show()
+end
+
+function mod:ReputationBar_OnClick()
+ ToggleCharacter("ReputationFrame");
+end
+
+function mod:UpdateReputationDimensions()
+ self.repBar:SetWidth(self.db.reputation.width)
+ self.repBar:SetHeight(self.db.reputation.height)
+ self.repBar.statusBar:SetOrientation(self.db.reputation.orientation)
+ E:FontTemplate(self.repBar.text, LSM:Fetch("font", self.db.reputation.font), self.db.reputation.textSize, self.db.reputation.fontOutline)
+ if self.db.reputation.mouseover then
+ self.repBar:SetAlpha(0)
+ else
+ self.repBar:SetAlpha(1)
+ end
+end
+
+function mod:EnableDisable_ReputationBar()
+ if self.db.reputation.enable then
+ self:RegisterEvent("UPDATE_FACTION", "UpdateReputation")
+ self:UpdateReputation()
+ E:EnableMover(self.repBar.mover:GetName())
+ else
+ self:UnregisterEvent("UPDATE_FACTION")
+ self.repBar:Hide()
+ E:DisableMover(self.repBar.mover:GetName())
+ end
+end
+
+function mod:LoadReputationBar()
+ self.repBar = self:CreateBar("ElvUI_ReputationBar", self.ReputationBar_OnEnter, self.ReputationBar_OnClick, "RIGHT", RightChatPanel, "LEFT", E.Border - E.Spacing*3, 0)
+ E:RegisterStatusBar(self.repBar.statusBar)
+
+ self:UpdateReputationDimensions()
+
+ E:CreateMover(self.repBar, "ReputationBarMover", L["Reputation Bar"])
+ self:EnableDisable_ReputationBar()
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Armor.lua b/ElvUI/Modules/DataTexts/Armor.lua
new file mode 100644
index 0000000..eec6418
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Armor.lua
@@ -0,0 +1,70 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local format = string.format
+local join = string.join
+--WoW API / Variables
+local UnitArmor = UnitArmor
+local UnitLevel = UnitLevel
+local ARMOR = ARMOR
+
+local lastPanel
+local chanceString = "%.2f%%"
+local displayString = ""
+local _, effectiveArmor
+
+local function GetArmorReduction(armor, attackerLevel)
+ local levelModifier = attackerLevel
+ if levelModifier > 59 then
+ levelModifier = levelModifier + (4.5 * (levelModifier - 59))
+ end
+ local temp = 0.1 * armor/(8.5 * levelModifier + 40)
+ temp = temp/(1 + temp)
+
+ if temp > 0.75 then return 75 end
+ if temp < 0 then return 0 end
+
+ return temp*100
+end
+
+local function OnEvent(self)
+ _, effectiveArmor = UnitArmor("player")
+
+ self.text:SetText(format(displayString, ARMOR, effectiveArmor))
+ lastPanel = self
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+
+ DT.tooltip:AddLine(L["Mitigation By Level: "])
+ DT.tooltip:AddLine(" ")
+
+ local playerLevel = UnitLevel("player") + 3
+ for i = 1, 4 do
+ local armorReduction = GetArmorReduction(effectiveArmor, playerLevel)
+ DT.tooltip:AddDoubleLine(playerLevel, format(chanceString, armorReduction), 1, 1, 1)
+ playerLevel = playerLevel - 1
+ end
+
+ local targetLevel = UnitLevel("target")
+ if targetLevel and targetLevel > 0 and (targetLevel > playerLevel + 3 or targetLevel < playerLevel) then
+ local armorReduction = GetArmorReduction(effectiveArmor, targetLevel)
+ DT.tooltip:AddDoubleLine(targetLevel, format(chanceString, armorReduction), 1, 1, 1)
+ end
+
+ DT.tooltip:Show()
+end
+
+local function ValueColorUpdate(hex)
+ displayString = join("", "%s: ", hex, "%d|r")
+
+ if lastPanel ~= nil then
+ OnEvent(lastPanel)
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Armor", {"UNIT_RESISTANCES"}, OnEvent, nil, nil, OnEnter, nil, ARMOR)
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/AttackPower.lua b/ElvUI/Modules/DataTexts/AttackPower.lua
new file mode 100644
index 0000000..b932e53
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/AttackPower.lua
@@ -0,0 +1,66 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local max = math.max
+local format, join, sub = string.format, string.join, string.sub
+--WoW API / Variables
+local UnitAttackPower = UnitAttackPower
+local UnitRangedAttackPower = UnitRangedAttackPower
+local ATTACK_POWER_COLON = ATTACK_POWER_COLON
+local ATTACK_POWER_MAGIC_NUMBER = ATTACK_POWER_MAGIC_NUMBER
+local MELEE_ATTACK_POWER = MELEE_ATTACK_POWER
+local MELEE_ATTACK_POWER_TOOLTIP = MELEE_ATTACK_POWER_TOOLTIP
+local RANGED_ATTACK_POWER = RANGED_ATTACK_POWER
+local RANGED_ATTACK_POWER_TOOLTIP = RANGED_ATTACK_POWER_TOOLTIP
+local ATTACK_POWER_TOOLTIP = ATTACK_POWER_TOOLTIP
+
+local ATTACK_POWER = sub(ATTACK_POWER_COLON, 1, -2)
+
+local base, posBuff, negBuff, effective, Rbase, RposBuff, RnegBuff, Reffective, pwr
+local displayNumberString = ""
+local lastPanel
+
+local function OnEvent(self)
+ if(E.myclass == "HUNTER") then
+ Rbase, RposBuff, RnegBuff = UnitRangedAttackPower("player")
+ Reffective = Rbase + RposBuff + RnegBuff
+ pwr = Reffective
+ else
+ base, posBuff, negBuff = UnitAttackPower("player")
+ effective = base + posBuff + negBuff
+ pwr = effective
+ end
+
+ self.text:SetText(format(displayNumberString, ATTACK_POWER, pwr))
+ lastPanel = self
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+
+ if(E.myclass == "HUNTER") then
+ DT.tooltip:AddDoubleLine(RANGED_ATTACK_POWER, pwr, 1, 1, 1)
+
+ local line = format(RANGED_ATTACK_POWER_TOOLTIP, max((pwr), 0) / ATTACK_POWER_MAGIC_NUMBER)
+
+ DT.tooltip:AddLine(line, nil, nil, nil, true)
+ else
+ DT.tooltip:AddDoubleLine(MELEE_ATTACK_POWER, pwr, 1, 1, 1)
+ DT.tooltip:AddLine(format(MELEE_ATTACK_POWER_TOOLTIP, max((base + posBuff + negBuff), 0) / ATTACK_POWER_MAGIC_NUMBER), nil, nil, nil, true)
+ end
+
+ DT.tooltip:Show()
+end
+
+local function ValueColorUpdate(hex)
+ displayNumberString = join("", "%s: ", hex, "%d|r")
+
+ if(lastPanel ~= nil) then
+ OnEvent(lastPanel)
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Attack Power", {"UNIT_ATTACK_POWER", "UNIT_RANGED_ATTACK_POWER"}, OnEvent, nil, nil, OnEnter, nil, ATTACK_POWER_TOOLTIP)
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Avoidance.lua b/ElvUI/Modules/DataTexts/Avoidance.lua
new file mode 100644
index 0000000..d4bed30
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Avoidance.lua
@@ -0,0 +1,124 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local format, join = string.format, string.join
+local abs = math.abs
+--WoW API / Variables
+local GetInventorySlotInfo = GetInventorySlotInfo
+local GetInventoryItemID = GetInventoryItemID
+local GetItemInfo = GetItemInfo
+local UnitLevel = UnitLevel
+local GetDodgeChance = GetDodgeChance
+local GetParryChance = GetParryChance
+local GetBlockChance = GetBlockChance
+local GetBonusBarOffset = GetBonusBarOffset
+local BOSS = BOSS
+local DODGE_CHANCE = DODGE_CHANCE
+local PARRY_CHANCE = PARRY_CHANCE
+local BLOCK_CHANCE = BLOCK_CHANCE
+
+DEFENSE = "Defense";
+DODGE_CHANCE = "Dodge Chance";
+PARRY_CHANCE = "Parry Chance";
+BLOCK_CHANCE = "Block Chance";
+
+local displayString, lastPanel
+local targetlv, playerlv
+local baseMissChance, levelDifference, dodge, parry, block, avoidance, unhittable
+local chanceString = "%.2f%%"
+local AVD_DECAY_RATE = 0.2
+
+local function IsWearingShield()
+ local slotID = GetInventorySlotInfo("SecondaryHandSlot")
+ local itemID = nil
+
+ if itemID then
+ return select(9, GetItemInfo(itemID))
+ end
+end
+
+local function OnEvent(self)
+ targetlv, playerlv = UnitLevel("target"), UnitLevel("player")
+
+ baseMissChance = E.myrace == "NightElf" and 7 or 5
+ if targetlv == -1 then
+ levelDifference = 3
+ elseif targetlv > playerlv then
+ levelDifference = (targetlv - playerlv)
+ elseif targetlv < playerlv and targetlv > 0 then
+ levelDifference = (targetlv - playerlv)
+ else
+ levelDifference = 0
+ end
+
+ if levelDifference >= 0 then
+ dodge = (GetDodgeChance() - levelDifference * AVD_DECAY_RATE)
+ parry = (GetParryChance() - levelDifference * AVD_DECAY_RATE)
+ block = (GetBlockChance() - levelDifference * AVD_DECAY_RATE)
+ baseMissChance = (baseMissChance - levelDifference * AVD_DECAY_RATE)
+ else
+ dodge = (GetDodgeChance() + abs(levelDifference * AVD_DECAY_RATE))
+ parry = (GetParryChance() + abs(levelDifference * AVD_DECAY_RATE))
+ block = (GetBlockChance() + abs(levelDifference * AVD_DECAY_RATE))
+ baseMissChance = (baseMissChance+ abs(levelDifference * AVD_DECAY_RATE))
+ end
+
+ if dodge <= 0 then dodge = 0 end
+ if parry <= 0 then parry = 0 end
+ if block <= 0 then block = 0 end
+
+ if E.myclass == "DRUID" and GetBonusBarOffset() == 3 then
+ parry = 0
+ end
+
+ if IsWearingShield() ~= "INVTYPE_SHIELD" then
+ block = 0
+ end
+
+ avoidance = (dodge + parry + block + baseMissChance)
+ unhittable = avoidance - 102.4
+
+ self.text:SetText(format(displayString, DEFENSE, avoidance))
+
+ lastPanel = self
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+
+ if targetlv > 1 then
+ DT.tooltip:AddDoubleLine(L["Avoidance Breakdown"], join("", " (", L["lvl"], " ", targetlv, ")"))
+ elseif targetlv == -1 then
+ DT.tooltip:AddDoubleLine(L["Avoidance Breakdown"], join("", " (", BOSS, ")"))
+ else
+ DT.tooltip:AddDoubleLine(L["Avoidance Breakdown"], join("", " (", L["lvl"], " ", playerlv, ")"))
+ end
+
+ DT.tooltip:AddLine(" ")
+ DT.tooltip:AddDoubleLine(DODGE_CHANCE, format(chanceString, dodge), 1, 1, 1)
+ DT.tooltip:AddDoubleLine(PARRY_CHANCE, format(chanceString, parry), 1, 1, 1)
+ DT.tooltip:AddDoubleLine(BLOCK_CHANCE, format(chanceString, block), 1, 1, 1)
+ DT.tooltip:AddDoubleLine(L["Miss Chance"], format(chanceString, baseMissChance), 1, 1, 1)
+ DT.tooltip:AddLine(" ")
+
+ if unhittable > 0 then
+ DT.tooltip:AddDoubleLine(L["Unhittable:"], "+" .. format(chanceString, unhittable), 1, 1, 1, 0, 1, 0)
+ else
+ DT.tooltip:AddDoubleLine(L["Unhittable:"], format(chanceString, unhittable), 1, 1, 1, 1, 0, 0)
+ end
+
+ DT.tooltip:Show()
+end
+
+local function ValueColorUpdate(hex)
+ displayString = join("", "%s: ", hex, "%.2f%%|r")
+
+ if lastPanel ~= nil then
+ OnEvent(lastPanel)
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Avoidance", {"COMBAT_RATING_UPDATE", "PLAYER_TARGET_CHANGED"}, OnEvent, nil, nil, OnEnter, nil, L["Avoidance Breakdown"])
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/DataTexts.lua b/ElvUI/Modules/DataTexts/DataTexts.lua
new file mode 100644
index 0000000..450068d
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/DataTexts.lua
@@ -0,0 +1,322 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:NewModule("DataTexts", "AceTimer-3.0", "AceHook-3.0", "AceEvent-3.0");
+local LDB = LibStub:GetLibrary("LibDataBroker-1.1");
+local LSM = LibStub("LibSharedMedia-3.0");
+local TT = E:GetModule("Tooltip");
+
+local pairs, type, error = pairs, type, error
+local len = string.len
+
+local CreateFrame = CreateFrame
+local InCombatLockdown = InCombatLockdown
+local IsInInstance = IsInInstance
+
+function DT:Initialize()
+ E.DataTexts = DT
+
+ self.tooltip = CreateFrame("GameTooltip", "DatatextTooltip", E.UIParent, "GameTooltipTemplate")
+ DatatextTooltipTextLeft1:SetFontObject(GameTooltipText)
+ DatatextTooltipTextRight1:SetFontObject(GameTooltipText)
+ TT:HookScript(self.tooltip, "OnShow", "SetStyle")
+
+ self:RegisterLDB()
+ LDB.RegisterCallback(E, "LibDataBroker_DataObjectCreated", DT.SetupObjectLDB)
+
+ self:LoadDataTexts()
+
+ self:RegisterEvent("PLAYER_ENTERING_WORLD")
+end
+
+DT.RegisteredPanels = {}
+DT.RegisteredDataTexts = {}
+
+DT.PointLocation = {
+ [1] = "middle",
+ [2] = "left",
+ [3] = "right"
+}
+
+local hasEnteredWorld = false
+function DT:PLAYER_ENTERING_WORLD()
+ hasEnteredWorld = true
+ self:LoadDataTexts()
+end
+
+local function LoadDataTextsDelayed()
+ E.Delay(0.5, function() DT:LoadDataTexts() end)
+end
+
+local hex = "|cffFFFFFF"
+
+function DT:SetupObjectLDB(name, obj)
+ local curFrame = nil
+
+ local function OnEnter()
+ DT:SetupTooltip(this)
+ if obj.OnTooltipShow then
+ obj.OnTooltipShow(DT.tooltip)
+ end
+ if obj.OnEnter then
+ obj.OnEnter(this)
+ end
+ DT.tooltip:Show()
+ end
+
+ local function OnLeave()
+ if obj.OnLeave then
+ obj.OnLeave(this)
+ end
+ DT.tooltip:Hide()
+ end
+
+ local function OnClick(self, button)
+ if obj.OnClick then
+ obj.OnClick(self, button)
+ end
+ end
+
+ local function textUpdate(_, name, _, value)
+ if value == nil or (len(value) >= 3) or value == "n/a" or name == value then
+ curFrame.text:SetText(value ~= "n/a" and value or name)
+ else
+ curFrame.text:SetText(format("%s: %s%s|r", name, hex, value))
+ end
+ end
+
+ local function OnEvent(self)
+ curFrame = self
+ LDB:RegisterCallback("LibDataBroker_AttributeChanged_"..name.."_text", textUpdate)
+ LDB:RegisterCallback("LibDataBroker_AttributeChanged_"..name.."_value", textUpdate)
+ LDB.callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_text", name, nil, obj.text, obj)
+ end
+
+ DT:RegisterDatatext(name, {"PLAYER_ENTER_WORLD"}, OnEvent, nil, OnClick, OnEnter, OnLeave)
+
+ if DT.PanelLayoutOptions then
+ DT:PanelLayoutOptions()
+ end
+
+ if hasEnteredWorld then
+ LoadDataTextsDelayed()
+ end
+end
+
+function DT:RegisterLDB()
+ for name, obj in LDB:DataObjectIterator() do
+ self:SetupObjectLDB(name, obj)
+ end
+end
+
+local function ValueColorUpdate(newHex)
+ hex = newHex
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+function DT:GetDataPanelPoint(panel, i, numPoints)
+ if(numPoints == 1) then
+ return "CENTER", panel, "CENTER"
+ else
+ if(i == 1) then
+ return "CENTER", panel, "CENTER"
+ elseif(i == 2) then
+ return "RIGHT", panel.dataPanels["middle"], "LEFT", -4, 0
+ elseif(i == 3) then
+ return "LEFT", panel.dataPanels["middle"], "RIGHT", 4, 0
+ end
+ end
+end
+
+function DT:UpdateAllDimensions()
+ for _, panel in pairs(DT.RegisteredPanels) do
+ local width = (panel:GetWidth() / panel.numPoints) - 4
+ local height = panel:GetHeight() - 4
+ for i = 1, panel.numPoints do
+ local pointIndex = DT.PointLocation[i]
+ panel.dataPanels[pointIndex]:SetWidth(width)
+ panel.dataPanels[pointIndex]:SetHeight(height)
+ panel.dataPanels[pointIndex]:SetPoint(DT:GetDataPanelPoint(panel, i, panel.numPoints))
+ end
+ end
+end
+
+function DT:Data_OnLeave()
+ DT.tooltip:Hide()
+end
+
+function DT:SetupTooltip(panel)
+ local parent = panel:GetParent()
+ self.tooltip:Hide()
+ self.tooltip:SetOwner(parent, parent.anchor, parent.xOff, parent.yOff)
+ self.tooltip:ClearLines()
+ GameTooltip:Hide()
+end
+
+function DT:RegisterPanel(panel, numPoints, anchor, xOff, yOff)
+ DT.RegisteredPanels[panel:GetName()] = panel
+ panel.dataPanels = {}
+ panel.numPoints = numPoints
+
+ panel.xOff = xOff
+ panel.yOff = yOff
+ panel.anchor = anchor
+ for i = 1, numPoints do
+ local pointIndex = DT.PointLocation[i]
+ if not panel.dataPanels[pointIndex] then
+ panel.dataPanels[pointIndex] = CreateFrame("Button", panel:GetName().."DataText"..i, panel)
+ panel.dataPanels[pointIndex]:RegisterForClicks("LeftButtonUp", "RightButtonUp")
+ panel.dataPanels[pointIndex].text = panel.dataPanels[pointIndex]:CreateFontString(nil, "OVERLAY")
+ panel.dataPanels[pointIndex].text:SetAllPoints()
+ E:FontTemplate(panel.dataPanels[pointIndex].text)
+ panel.dataPanels[pointIndex].text:SetJustifyH("CENTER")
+ panel.dataPanels[pointIndex].text:SetJustifyV("MIDDLE")
+ end
+
+ panel.dataPanels[pointIndex]:SetPoint(DT:GetDataPanelPoint(panel, i, numPoints))
+ end
+
+ panel:SetScript("OnSizeChanged", DT.UpdateAllDimensions)
+ DT.UpdateAllDimensions(panel)
+end
+
+function DT:AssignPanelToDataText(panel, data)
+ panel.name = ""
+ if data["name"] then
+ panel.name = data["name"]
+ end
+
+ if data["events"] then
+ for _, event in pairs(data["events"]) do
+ -- random error 132
+ if event == "PLAYER_ENTERING_WORLD" then
+ event = "PLAYER_LOGIN"
+ end
+ panel:RegisterEvent(event)
+ end
+ end
+
+ if data["eventFunc"] then
+ panel:SetScript("OnEvent", function()
+ data["eventFunc"](this, event)
+ end)
+ data["eventFunc"](panel, "ELVUI_FORCE_RUN")
+ end
+
+ if data["onUpdate"] then
+ panel:SetScript("OnUpdate", function()
+ data["onUpdate"](this, arg1)
+ end)
+ data["onUpdate"](panel, 20000)
+ end
+
+ if data["onClick"] then
+ panel:SetScript("OnClick", function()
+ data["onClick"](this, arg1)
+ end)
+ end
+
+ if data["onEnter"] then
+ panel:SetScript("OnEnter", function()
+ data["onEnter"](this)
+ end)
+ end
+
+ if data["onLeave"] then
+ panel:SetScript("OnLeave", function()
+ data["onLeave"](this)
+ end)
+ else
+ panel:SetScript("OnLeave", DT.Data_OnLeave)
+ end
+end
+
+function DT:LoadDataTexts()
+ self.db = E.db.datatexts
+ LDB:UnregisterAllCallbacks(self)
+
+ local inInstance, instanceType = IsInInstance()
+ local fontTemplate = LSM:Fetch("font", self.db.font)
+ for panelName, panel in pairs(DT.RegisteredPanels) do
+ for i = 1, panel.numPoints do
+ local pointIndex = DT.PointLocation[i]
+ panel.dataPanels[pointIndex]:UnregisterAllEvents()
+ panel.dataPanels[pointIndex]:SetScript("OnUpdate", nil)
+ panel.dataPanels[pointIndex]:SetScript("OnEnter", nil)
+ panel.dataPanels[pointIndex]:SetScript("OnLeave", nil)
+ panel.dataPanels[pointIndex]:SetScript("OnClick", nil)
+ E:FontTemplate(panel.dataPanels[pointIndex].text, fontTemplate, self.db.fontSize, self.db.fontOutline)
+ panel.dataPanels[pointIndex].text:SetText(nil)
+ panel.dataPanels[pointIndex].pointIndex = pointIndex
+
+ if (panelName == "LeftChatDataPanel" or panelName == "RightChatDataPanel") and (inInstance and (instanceType == "pvp")) and not DT.ForceHideBGStats and E.db.datatexts.battleground then
+ panel.dataPanels[pointIndex]:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
+ panel.dataPanels[pointIndex]:RegisterEvent("PLAYER_REGEN_ENABLED")
+ panel.dataPanels[pointIndex]:SetScript("OnEvent", DT.UPDATE_BATTLEFIELD_SCORE)
+ panel.dataPanels[pointIndex]:SetScript("OnEnter", DT.BattlegroundStats)
+ panel.dataPanels[pointIndex]:SetScript("OnLeave", DT.Data_OnLeave)
+ panel.dataPanels[pointIndex]:SetScript("OnClick", DT.HideBattlegroundTexts)
+ DT.UPDATE_BATTLEFIELD_SCORE(panel.dataPanels[pointIndex])
+ else
+ for name, data in pairs(DT.RegisteredDataTexts) do
+ for option, value in pairs(self.db.panels) do
+ if value and type(value) == "table" then
+ if option == panelName and self.db.panels[option][pointIndex] and self.db.panels[option][pointIndex] == name then
+ DT:AssignPanelToDataText(panel.dataPanels[pointIndex], data)
+ end
+ elseif value and type(value) == "string" and value == name then
+ if self.db.panels[option] == name and option == panelName then
+ DT:AssignPanelToDataText(panel.dataPanels[pointIndex], data)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ if DT.ForceHideBGStats then
+ DT.ForceHideBGStats = nil
+ end
+end
+
+function DT:RegisterDatatext(name, events, eventFunc, updateFunc, clickFunc, onEnterFunc, onLeaveFunc, localizedName)
+ if name then
+ DT.RegisteredDataTexts[name] = {}
+ else
+ error("Cannot register datatext no name was provided.")
+ end
+
+ DT.RegisteredDataTexts[name]["name"] = name
+
+ if type(events) ~= "table" and events ~= nil then
+ error("Events must be registered as a table.")
+ else
+ DT.RegisteredDataTexts[name]["events"] = events
+ DT.RegisteredDataTexts[name]["eventFunc"] = eventFunc
+ end
+
+ if updateFunc and type(updateFunc) == "function" then
+ DT.RegisteredDataTexts[name]["onUpdate"] = updateFunc
+ end
+
+ if clickFunc and type(clickFunc) == "function" then
+ DT.RegisteredDataTexts[name]["onClick"] = clickFunc
+ end
+
+ if onEnterFunc and type(onEnterFunc) == "function" then
+ DT.RegisteredDataTexts[name]["onEnter"] = onEnterFunc
+ end
+
+ if onLeaveFunc and type(onLeaveFunc) == "function" then
+ DT.RegisteredDataTexts[name]["onLeave"] = onLeaveFunc
+ end
+
+ if localizedName and type(localizedName) == "string" then
+ DT.RegisteredDataTexts[name]["localizedName"] = localizedName
+ end
+end
+
+local function InitializeCallback()
+ DT:Initialize()
+end
+
+E:RegisterModule(DT:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Durability.lua b/ElvUI/Modules/DataTexts/Durability.lua
new file mode 100644
index 0000000..c3e510d
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Durability.lua
@@ -0,0 +1,102 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs = pairs
+local format, join, upper = string.format, string.join, string.upper
+--WoW API / Variables
+local GetInventoryItemDurability = GetInventoryItemDurability
+local GetInventoryItemTexture = GetInventoryItemTexture
+local GetInventorySlotInfo = GetInventorySlotInfo
+local ToggleCharacter = ToggleCharacter
+local DURABILITY_TEMPLATE = string.gsub(DURABILITY_TEMPLATE, "%%d / %%d", "(%%d+) / (%%d+)")
+
+local DURABILITY = "Durability" -- Neel ElvUI locale
+
+local displayString = ""
+local tooltipString = "%d%%"
+local totalDurability = 0
+local current, max, lastPanel
+local invDurability = {}
+local slots = {
+ "RangedSlot",
+ "SecondaryHandSlot",
+ "MainHandSlot",
+ "FeetSlot",
+ "LegsSlot",
+ "HandsSlot",
+ "WristSlot",
+ "WaistSlot",
+ "ChestSlot",
+ "ShoulderSlot",
+ "HeadSlot"
+}
+
+local scan
+local function GetInventoryItemDurability(slot)
+ if not GetInventoryItemTexture("player", slot) then return nil, nil end
+
+ if not scan then
+ scan = CreateFrame("GameTooltip", "DurabilityScan", nil, "ShoppingTooltipTemplate")
+ scan:SetOwner(UIParent, "ANCHOR_NONE")
+ end
+
+ scan:ClearLines()
+ scan:SetInventoryItem("player", slot)
+
+ for i = 4, scan:NumLines() do
+ local text = _G[scan:GetName().."TextLeft"..i]:GetText()
+ for durability, max in string.gfind(text, DURABILITY_TEMPLATE) do
+ return tonumber(durability), tonumber(max)
+ end
+ end
+end
+
+local function OnEvent(self, t)
+ lastPanel = self
+ totalDurability = 100
+
+ for _, value in pairs(slots) do
+ local slot = GetInventorySlotInfo(value)
+ current, max = GetInventoryItemDurability(slot)
+
+ if current then
+ current, max = GetInventoryItemDurability(slot)
+
+ invDurability[value] = (current / max) * 100
+
+ if ((current / max) * 100) < totalDurability then
+ totalDurability = (current / max) * 100
+ end
+ end
+ end
+
+ self.text:SetText(format(displayString, totalDurability))
+end
+
+local function OnClick()
+ ToggleCharacter("PaperDollFrame")
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+
+ for slot, durability in pairs(invDurability) do
+ DT.tooltip:AddDoubleLine(_G[upper(slot)], format(tooltipString, durability), 1, 1, 1, E:ColorGradient(durability * 0.01, 1, 0, 0, 1, 1, 0, 0, 1, 0))
+ end
+
+ DT.tooltip:Show()
+end
+
+local function ValueColorUpdate(hex)
+ displayString = join("", DURABILITY, ": ", hex, "%d%%|r")
+
+ if lastPanel ~= nil then
+ OnEvent(lastPanel, "ELVUI_COLOR_UPDATE")
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Durability", {"PLAYER_ENTERING_WORLD", "UPDATE_INVENTORY_ALERTS", "MERCHANT_SHOW"}, OnEvent, nil, OnClick, OnEnter, nil, DURABILITY)
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Friends.lua b/ElvUI/Modules/DataTexts/Friends.lua
new file mode 100644
index 0000000..7a091d6
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Friends.lua
@@ -0,0 +1,200 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local type, pairs = type, pairs
+local sort, wipe = table.sort, wipe
+local format, find, join, gsub = string.format, string.find, string.join, string.gsub
+--WoW API / Variables
+local UnitIsAFK = UnitIsAFK
+local UnitIsDND = UnitIsDND
+local SendChatMessage = SendChatMessage
+local InviteUnit = InviteUnit
+local SetItemRef = SetItemRef
+local GetFriendInfo = GetFriendInfo
+local GetNumFriends = GetNumFriends
+local GetQuestDifficultyColor = GetQuestDifficultyColor
+local UnitInParty = UnitInParty
+local UnitInRaid = UnitInRaid
+local ToggleFriendsFrame = ToggleFriendsFrame
+local L_EasyMenu = L_EasyMenu
+local AFK = AFK
+local DND = DND
+local LOCALIZED_CLASS_NAMES_MALE = LOCALIZED_CLASS_NAMES_MALE
+local LOCALIZED_CLASS_NAMES_FEMALE = LOCALIZED_CLASS_NAMES_FEMALE
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+
+local function GetNumberFriends()
+ local numFriends = GetNumFriends()
+ local onlineFriends = 0
+ local _, online
+
+ for i = 1, numFriends do
+ _, _, _, _, online = GetFriendInfo(i)
+
+ if online then
+ onlineFriends = onlineFriends + 1
+ end
+ end
+
+ return numFriends, onlineFriends
+end
+
+local menuFrame = CreateFrame("Frame", "FriendDatatextRightClickMenu", E.UIParent, "L_UIDropDownMenuTemplate")
+local menuList = {
+ {text = OPTIONS_MENU, isTitle = true, notCheckable = true},
+ {text = INVITE, hasArrow = true, notCheckable = true},
+ {text = CHAT_MSG_WHISPER_INFORM, hasArrow = true, notCheckable = true},
+ {text = PLAYER_STATUS, hasArrow = true, notCheckable = true,
+ menuList = {
+ {text = "|cff2BC226" .. AVAILABLE .. "|r", notCheckable = true, func = function() end},
+ {text = "|cffE7E716" .. CHAT_MSG_AFK .. "|r", notCheckable = true, func = function() end},
+ {text = "|cffFF0000" .. CHAT_MSG_DND .. "|r", notCheckable = true, func = function() end}
+ }
+ }
+}
+
+local function inviteClick(name)
+ menuFrame:Hide()
+
+ if(type(name) ~= "number") then
+ InviteUnit(name)
+ end
+end
+
+local function whisperClick(name)
+ menuFrame:Hide()
+
+ SetItemRef("player:" .. name, format("|Hplayer:%1$s|h[%1$s]|h", name), "LeftButton")
+end
+
+local lastPanel
+local levelNameString = "|cff%02x%02x%02x%d|r |cff%02x%02x%02x%s|r"
+local levelNameClassString = "|cff%02x%02x%02x%d|r %s%s"
+local worldOfWarcraftString = WORLD_OF_WARCRAFT
+local totalOnlineString = join("", GUILD_ONLINE_LABEL, ": %s/%s")
+local tthead = {r = 0.4, g = 0.78, b = 1}
+local activezone, inactivezone = {r = 0.3, g = 1.0, b = 0.3}, {r = 0.65, g = 0.65, b = 0.65}
+local displayString = ""
+local groupedTable = {"|cffaaaaaa*|r", ""}
+local friendTable = {}
+local friendOnline, friendOffline = gsub(ERR_FRIEND_ONLINE_SS, "\124Hplayer:%%s\124h%[%%s%]\124h", ""), gsub(ERR_FRIEND_OFFLINE_S, "%%s", "")
+local dataValid = false
+
+local function SortAlphabeticName(a, b)
+ if(a[1] and b[1]) then
+ return a[1] < b[1]
+ end
+end
+
+local function BuildFriendTable(total)
+ wipe(friendTable)
+ local name, level, class, area, connected, status, note
+ for i = 1, total do
+ name, level, class, area, connected, status, note = GetFriendInfo(i)
+
+ if status == CHAT_FLAG_AFK then
+ status = "|cffFFFFFF[|r|cffFF0000" .. L["AFK"] .. "|r|cffFFFFFF]|r"
+ elseif status == CHAT_FLAG_DND then
+ status = "|cffFFFFFF[|r|cffFF0000" .. L["DND"] .. "|r|cffFFFFFF]|r"
+ end
+
+ if(connected) then
+ for k, v in pairs(LOCALIZED_CLASS_NAMES_MALE) do if(class == v) then class = k end end
+ for k, v in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do if(class == v) then class = k end end
+ friendTable[i] = {name, level, class, area, connected, status, note}
+ end
+ end
+ sort(friendTable, SortAlphabeticName)
+end
+
+local function OnEvent(self, event, ...)
+ local _, onlineFriends = GetNumberFriends()
+
+ if event == "CHAT_MSG_SYSTEM" then
+ local message = arg1
+ if not (find(message, friendOnline) or find(message, friendOffline)) then return end
+ end
+ dataValid = false
+
+ self.text:SetText(format(displayString, L["Friends"], onlineFriends))
+
+ lastPanel = self
+end
+
+local function OnClick(_, btn)
+ DT.tooltip:Hide()
+
+ if btn == "RightButton" then
+ local menuCountWhispers = 0
+ local menuCountInvites = 0
+ local classc, levelc, info
+
+ menuList[2].menuList = {}
+ menuList[3].menuList = {}
+
+ if getn(friendTable) > 0 then
+ for i = 1, getn(friendTable) do
+ info = friendTable[i]
+ if (info[5]) then
+ menuCountInvites = menuCountInvites + 1
+ menuCountWhispers = menuCountWhispers + 1
+
+ classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[info[3]], GetQuestDifficultyColor(info[2])
+ classc = classc or GetQuestDifficultyColor(info[2])
+
+ menuList[2].menuList[menuCountInvites] = {text = format(levelNameString, levelc.r*255,levelc.g*255,levelc.b*255, info[2],classc.r*255,classc.g*255,classc.b*255, info[1]), arg1 = info[1], notCheckable = true, func = inviteClick}
+ menuList[3].menuList[menuCountWhispers] = {text = format(levelNameString, levelc.r*255,levelc.g*255,levelc.b*255, info[2],classc.r*255,classc.g*255,classc.b*255, info[1]), arg1 = info[1], notCheckable = true, func = whisperClick}
+ end
+ end
+ end
+ L_EasyMenu(menuList, menuFrame, "cursor", 0, 0, "MENU", 2)
+ else
+ ToggleFriendsFrame(1)
+ end
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+
+ local numberOfFriends, onlineFriends = GetNumberFriends()
+ if onlineFriends == 0 then return end
+
+ if not dataValid then
+ if numberOfFriends > 0 then BuildFriendTable(numberOfFriends) end
+ dataValid = true
+ end
+
+ local zonec, classc, levelc, info
+ DT.tooltip:AddDoubleLine(L["Friends List"], format(totalOnlineString, onlineFriends, numberOfFriends), tthead.r, tthead.g, tthead.b, tthead.r, tthead.g, tthead.b)
+ if onlineFriends > 0 then
+ DT.tooltip:AddLine(" ")
+ DT.tooltip:AddLine(worldOfWarcraftString)
+ for i = 1, getn(friendTable) do
+ info = friendTable[i]
+ if info[5] then
+ if(GetRealZoneText() == info[4]) then zonec = activezone else zonec = inactivezone end
+ classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[info[3]], GetQuestDifficultyColor(info[2])
+
+ classc = classc or GetQuestDifficultyColor(info[2])
+
+ DT.tooltip:AddDoubleLine(format(levelNameClassString, levelc.r*255,levelc.g*255,levelc.b*255, info[2], info[1], " " .. info[6]), info[4], classc.r,classc.g,classc.b, zonec.r,zonec.g,zonec.b)
+ end
+ end
+ end
+
+ DT.tooltip:Show()
+end
+
+local function ValueColorUpdate(hex)
+ displayString = join("", "%s: ", hex, "%d|r")
+
+ if lastPanel ~= nil then
+ OnEvent(lastPanel, "ELVUI_COLOR_UPDATE")
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Friends", {"PLAYER_LOGIN", "FRIENDLIST_UPDATE", "CHAT_MSG_SYSTEM"}, OnEvent, nil, OnClick, OnEnter, nil, L["Friends"])
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Gold.lua b/ElvUI/Modules/DataTexts/Gold.lua
new file mode 100644
index 0000000..7ca9ea4
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Gold.lua
@@ -0,0 +1,81 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local pairs = pairs
+local join = string.join
+--WoW API / Variables
+local GetMoney = GetMoney
+local IsShiftKeyDown = IsShiftKeyDown
+
+local Profit = 0
+local Spent = 0
+local resetInfoFormatter = join("", "|cffaaaaaa", L["Reset Data: Hold Shift + Right Click"], "|r")
+
+local function OnEvent(self)
+ local NewMoney = GetMoney()
+ ElvDB = ElvDB or {}
+ ElvDB["gold"] = ElvDB["gold"] or {}
+ ElvDB["gold"][E.myrealm] = ElvDB["gold"][E.myrealm] or {}
+ ElvDB["gold"][E.myrealm][E.myname] = ElvDB["gold"][E.myrealm][E.myname] or NewMoney
+
+ local OldMoney = ElvDB["gold"][E.myrealm][E.myname] or NewMoney
+
+ local Change = NewMoney - OldMoney
+ if OldMoney > NewMoney then
+ Spent = Spent - Change
+ else
+ Profit = Profit + Change
+ end
+
+ self.text:SetText(E:FormatMoney(NewMoney, E.db.datatexts.goldFormat or "BLIZZARD"))
+
+ ElvDB["gold"][E.myrealm][E.myname] = NewMoney
+end
+
+local function OnClick(self, btn)
+ if btn == "RightButton" and IsShiftKeyDown() then
+ ElvDB.gold = nil
+ OnEvent(self)
+ DT.tooltip:Hide()
+ else
+ OpenAllBags()
+ end
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+ local style = E.db.datatexts.goldFormat or "BLIZZARD"
+
+ DT.tooltip:AddLine(L["Session:"])
+ DT.tooltip:AddDoubleLine(L["Earned:"], E:FormatMoney(Profit, style), 1, 1, 1, 1, 1, 1)
+ DT.tooltip:AddDoubleLine(L["Spent:"], E:FormatMoney(Spent, style), 1, 1, 1, 1, 1, 1)
+ if Profit < Spent then
+ DT.tooltip:AddDoubleLine(L["Deficit:"], E:FormatMoney(Profit-Spent, style), 1, 0, 0, 1, 1, 1)
+ elseif (Profit - Spent) > 0 then
+ DT.tooltip:AddDoubleLine(L["Profit:"], E:FormatMoney(Profit-Spent, style), 0, 1, 0, 1, 1, 1)
+ end
+ DT.tooltip:AddLine(" ")
+
+ local totalGold = 0;
+ DT.tooltip:AddLine(L["Character: "])
+
+ for k, _ in pairs(ElvDB["gold"][E.myrealm]) do
+ if ElvDB["gold"][E.myrealm][k] then
+ DT.tooltip:AddDoubleLine(k, E:FormatMoney(ElvDB["gold"][E.myrealm][k], style), 1, 1, 1, 1, 1, 1)
+ totalGold = totalGold + ElvDB["gold"][E.myrealm][k]
+ end
+ end
+
+ DT.tooltip:AddLine(" ")
+ DT.tooltip:AddLine(L["Server: "])
+ DT.tooltip:AddDoubleLine(L["Total: "], E:FormatMoney(totalGold, style), 1, 1, 1, 1, 1, 1)
+
+ DT.tooltip:AddLine(" ")
+ DT.tooltip:AddLine(resetInfoFormatter)
+
+ DT.tooltip:Show()
+end
+
+DT:RegisterDatatext("Gold", {"PLAYER_ENTERING_WORLD", "PLAYER_MONEY", "SEND_MAIL_MONEY_CHANGED", "SEND_MAIL_COD_CHANGED", "PLAYER_TRADE_MONEY", "TRADE_MONEY_CHANGED"}, OnEvent, nil, OnClick, OnEnter, nil, L["Gold"])
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Guild.lua b/ElvUI/Modules/DataTexts/Guild.lua
new file mode 100644
index 0000000..3f54b11
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Guild.lua
@@ -0,0 +1,243 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local unpack = unpack
+local format, join = string.format, string.join
+local sort, wipe = table.sort, wipe
+--WoW API / Variables
+local EasyMenu = EasyMenu
+local GetGuildInfo = GetGuildInfo
+local GetGuildRosterInfo = GetGuildRosterInfo
+local GetGuildRosterMOTD = GetGuildRosterMOTD
+local GetMouseFocus = GetMouseFocus
+local GetNumGuildMembers = GetNumGuildMembers
+local GetQuestDifficultyColor = GetQuestDifficultyColor
+local GetRealZoneText = GetRealZoneText
+local GuildRoster = GuildRoster
+local InviteUnit = InviteUnit
+local IsInGuild = IsInGuild
+local IsShiftKeyDown = IsShiftKeyDown
+local LoadAddOn = LoadAddOn
+local SetItemRef = SetItemRef
+local ToggleFriendsFrame = ToggleFriendsFrame
+local UnitInParty = UnitInParty
+local UnitInRaid = UnitInRaid
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local MOTD_COLON = MOTD_COLON
+
+local FRIENDS_LIST_ONLINE = "FRIENDS_LIST_ONLINE"
+
+local tthead, ttsubh, ttoff = {r=0.4, g=0.78, b=1}, {r=0.75, g=0.9, b=1}, {r=.3,g=1,b=.3}
+local activezone, inactivezone = {r=0.3, g=1.0, b=0.3}, {r=0.65, g=0.65, b=0.65}
+local displayString = ""
+local noGuildString = ""
+local guildInfoString = "%s"
+local guildInfoString2 = join("", GUILD, ": %d/%d")
+local guildMotDString = "%s |cffaaaaaa |cffffffff%s"
+local levelNameString = "|cff%02x%02x%02x%d|r |cff%02x%02x%02x%s|r %s"
+local levelNameStatusString = "|cff%02x%02x%02x%d|r %s "
+local nameRankString = "%s |cff999999-|cffffffff %s"
+local moreMembersOnlineString = join("", "+ %d ", FRIENDS_LIST_ONLINE, "...")
+local noteString = join("", "|cff999999 ", LABEL_NOTE, ":|r %s")
+local officerNoteString = join("", "|cff999999 ", GUILD_RANK1_DESC, ":|r %s")
+local guildTable, guildMotD = {}, ""
+local lastPanel
+
+local function SortGuildTable(shift)
+ sort(guildTable, function(a, b)
+ if a and b then
+ if shift then
+ return a[9] < b[9]
+ else
+ return a[1] < b[1]
+ end
+ end
+ end)
+end
+
+local function BuildGuildTable()
+ wipe(guildTable)
+ local _, name, rank, level, zone, note, officernote, connected, status, class
+
+ local totalMembers = GetNumGuildMembers()
+ for i = 1, totalMembers do
+ name, rank, _, level, class, zone, note, officernote, connected, status = GetGuildRosterInfo(i)
+
+ if connected then
+ guildTable[getn(guildTable) + 1] = {name, rank, level, zone, note, officernote, connected, status, string.upper(class)}
+ end
+ end
+end
+
+local function UpdateGuildMessage()
+ guildMotD = GetGuildRosterMOTD()
+end
+
+local eventHandlers = {
+ ["CHAT_MSG_SYSTEM"] = function()
+ GuildRoster()
+ end,
+ -- when we enter the world and guildframe is not available then
+ -- load guild frame, update guild message and guild xp
+ ["PLAYER_ENTERING_WORLD"] = function()
+ if IsInGuild() then
+ GuildRoster()
+ end
+ end,
+ -- Guild Roster updated, so rebuild the guild table
+ ["GUILD_ROSTER_UPDATE"] = function(self)
+ GuildRoster()
+ BuildGuildTable()
+ UpdateGuildMessage()
+ if GetMouseFocus() == self then
+ self:GetScript("OnEnter")(self, nil, true)
+ end
+ end,
+ ["PLAYER_GUILD_UPDATE"] = function()
+ GuildRoster()
+ end,
+ -- our guild message of the day changed
+ ["GUILD_MOTD"] = function(_, arg1)
+ guildMotD = arg1
+ end,
+ ["ELVUI_FORCE_RUN"] = E.noop,
+ ["ELVUI_COLOR_UPDATE"] = E.noop,
+}
+
+local function OnEvent(self, event, ...)
+ lastPanel = self
+
+ if IsInGuild() then
+ eventHandlers[event](self, unpack(arg))
+ self.text:SetText(format(displayString, getn(guildTable)))
+ else
+ self.text:SetText(noGuildString)
+ end
+end
+
+local menuFrame = CreateFrame("Frame", "GuildDatatTextRightClickMenu", E.UIParent, "L_UIDropDownMenuTemplate")
+local menuList = {
+ { text = OPTIONS_MENU, isTitle = true, notCheckable = true},
+ { text = INVITE, hasArrow = true, notCheckable = true,},
+ { text = CHAT_MSG_WHISPER_INFORM, hasArrow = true, notCheckable=true,}
+}
+
+local function inviteClick(_, playerName)
+ menuFrame:Hide()
+ InviteUnit(playerName)
+end
+
+local function whisperClick(_, playerName)
+ menuFrame:Hide()
+ SetItemRef("player:"..playerName, ("|Hplayer:%1$s|h[%1$s]|h"):format(playerName), "LeftButton")
+end
+
+local function OnClick(_, btn)
+ if btn == "RightButton" and IsInGuild() then
+ DT.tooltip:Hide()
+
+ local classc, levelc, grouped, info
+ local menuCountWhispers = 0
+ local menuCountInvites = 0
+
+ menuList[2].menuList = {}
+ menuList[3].menuList = {}
+
+ for i = 1, getn(guildTable) do
+ info = guildTable[i]
+ if info[7] and info[1] ~= E.myname then
+ classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[info[9]], GetQuestDifficultyColor(info[3])
+ --if UnitInParty(info[1]) or UnitInRaid(info[1]) then
+ -- grouped = "|cffaaaaaa*|r"
+ --elseif not info[11] then
+ menuCountInvites = menuCountInvites + 1
+ grouped = ""
+ menuList[2].menuList[menuCountInvites] = {text = format(levelNameString, levelc.r*255,levelc.g*255,levelc.b*255, info[3], classc.r*255,classc.g*255,classc.b*255, info[1], ""), arg1 = info[1],notCheckable=true, func = inviteClick}
+ --end
+ menuCountWhispers = menuCountWhispers + 1
+ if not grouped then grouped = "" end
+ menuList[3].menuList[menuCountWhispers] = {text = format(levelNameString, levelc.r*255,levelc.g*255,levelc.b*255, info[3], classc.r*255,classc.g*255,classc.b*255, info[1], grouped), arg1 = info[1],notCheckable=true, func = whisperClick}
+ end
+ end
+
+ L_EasyMenu(menuList, menuFrame, "cursor", 0, 0, "MENU", 2)
+ else
+ ToggleFriendsFrame(3)
+ end
+end
+
+local function OnEnter(self, _, noUpdate)
+ if not IsInGuild() then return end
+
+ DT:SetupTooltip(self)
+
+ local online, total = 0, GetNumGuildMembers(true)
+ for i = 0, total do
+ local _, _, _, _, _, _, _, _, _, status = GetGuildRosterInfo(i)
+ if status then
+ online = online + 1
+ end
+ end
+ if getn(guildTable) == 0 then BuildGuildTable() end
+
+ SortGuildTable(IsShiftKeyDown())
+
+ local guildName, guildRank = GetGuildInfo("player")
+
+ if guildName and guildRank then
+ DT.tooltip:AddDoubleLine(format(guildInfoString, guildName), format(guildInfoString2, online, total),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
+ DT.tooltip:AddLine(guildRank, unpack(tthead))
+ end
+
+ if guildMotD ~= "" then
+ DT.tooltip:AddLine(" ")
+ DT.tooltip:AddLine(format(guildMotDString, GUILD_MOTD_LABEL, guildMotD), ttsubh.r, ttsubh.g, ttsubh.b, 1)
+ end
+
+ local zonec, classc, levelc, info
+ local shown = 0
+
+ DT.tooltip:AddLine(" ")
+ for i = 1, getn(guildTable) do
+ -- if more then 30 guild members are online, we don't Show any more, but inform user there are more
+ if 30 - shown <= 1 then
+ if online - 30 > 1 then DT.tooltip:AddLine(format(moreMembersOnlineString, online - 30), ttsubh.r, ttsubh.g, ttsubh.b) end
+ break
+ end
+
+ info = guildTable[i]
+ if GetRealZoneText() == info[4] then zonec = activezone else zonec = inactivezone end
+
+ classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[info[9]], GetQuestDifficultyColor(info[3])
+
+ if IsShiftKeyDown() then
+ DT.tooltip:AddDoubleLine(format(nameRankString, info[1], info[2]), info[4], classc.r, classc.g, classc.b, zonec.r, zonec.g, zonec.b)
+ if info[5] ~= "" then DT.tooltip:AddLine(format(noteString, info[5]), ttsubh.r, ttsubh.g, ttsubh.b, 1) end
+ if info[6] ~= "" then DT.tooltip:AddLine(format(officerNoteString, info[6]), ttoff.r, ttoff.g, ttoff.b, 1) end
+ else
+ DT.tooltip:AddDoubleLine(format(levelNameStatusString, levelc.r*255, levelc.g*255, levelc.b*255, info[3], info[1], info[4]), info[4], classc.r,classc.g,classc.b, zonec.r,zonec.g,zonec.b)
+ end
+ shown = shown + 1
+ end
+
+ DT.tooltip:Show()
+
+ if not noUpdate then
+ GuildRoster()
+ end
+end
+
+local function ValueColorUpdate(hex)
+ displayString = join("", GUILD, ": ", hex, "%d|r")
+ noGuildString = join("", hex, L["No Guild"])
+
+ if lastPanel ~= nil then
+ OnEvent(lastPanel, "ELVUI_COLOR_UPDATE")
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Guild", {"PLAYER_ENTERING_WORLD", "CHAT_MSG_SYSTEM", "GUILD_ROSTER_UPDATE", "PLAYER_GUILD_UPDATE", "GUILD_MOTD"}, OnEvent, nil, OnClick, OnEnter, nil, GUILD)
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Load_DataTexts.xml b/ElvUI/Modules/DataTexts/Load_DataTexts.xml
new file mode 100644
index 0000000..cacfb11
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Load_DataTexts.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/System.lua b/ElvUI/Modules/DataTexts/System.lua
new file mode 100644
index 0000000..9344c39
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/System.lua
@@ -0,0 +1,92 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local collectgarbage = collectgarbage
+local floor = math.floor
+local format = string.format
+local gcinfo = gcinfo
+--WoW API / Variables
+local GetNetStats = GetNetStats
+local GetFramerate = GetFramerate
+
+local int = 6
+local statusColors = {
+ "|cff0CD809",
+ "|cffE8DA0F",
+ "|cffFF9000",
+ "|cffD80909"
+}
+
+local enteredFrame = false
+local homeLatencyString = "%d ms"
+local kiloByteString = "%d kb"
+local megaByteString = "%.2f mb"
+
+local function formatMem(memory)
+ local mult = 10 ^ 1
+ if(memory > 999) then
+ local mem = ((memory / 1024) * mult) / mult
+ return format(megaByteString, mem)
+ else
+ local mem = (memory * mult) / mult
+ return format(kiloByteString, mem)
+ end
+end
+
+local function ToggleGameMenuFrame()
+ if GameMenuFrame:IsShown() then
+ PlaySound("igMainMenuQuit")
+ HideUIPanel(GameMenuFrame)
+ else
+ PlaySound("igMainMenuOpen")
+ ShowUIPanel(GameMenuFrame)
+ end
+end
+
+local function OnClick(_, btn)
+ if btn == "RightButton" then
+ collectgarbage()
+ elseif btn == "LeftButton" then
+ ToggleGameMenuFrame()
+ end
+end
+
+local function OnEnter(self)
+ enteredFrame = true
+ DT:SetupTooltip(self)
+
+ local totalMemory = gcinfo()
+ local _, _, latency = GetNetStats()
+ DT.tooltip:AddDoubleLine(L["Home Latency:"], format(homeLatencyString, latency), 0.69, 0.31, 0.31, 0.84, 0.75, 0.65)
+ DT.tooltip:AddDoubleLine(L["Total Memory:"], formatMem(totalMemory), 0.69, 0.31, 0.31, 0.84, 0.75, 0.65)
+
+ DT.tooltip:Show()
+end
+
+local function OnLeave()
+ enteredFrame = false
+ DT.tooltip:Hide()
+end
+
+local function OnUpdate(self, t)
+ int = int - t
+
+ if int < 0 then
+ local framerate = floor(GetFramerate())
+ local _, _, latency = GetNetStats()
+
+ self.text:SetText(format("FPS: %s%d|r MS: %s%d|r",
+ statusColors[framerate >= 30 and 1 or (framerate >= 20 and framerate < 30) and 2 or (framerate >= 10 and framerate < 20) and 3 or 4],
+ framerate,
+ statusColors[latency < 150 and 1 or (latency >= 150 and latency < 300) and 2 or (latency >= 300 and latency < 500) and 3 or 4],
+ latency))
+ int = 1
+ if enteredFrame then
+ OnEnter(this)
+ end
+ end
+end
+
+DT:RegisterDatatext("System", nil, nil, OnUpdate, OnClick, OnEnter, OnLeave, L["System"])
\ No newline at end of file
diff --git a/ElvUI/Modules/DataTexts/Time.lua b/ElvUI/Modules/DataTexts/Time.lua
new file mode 100644
index 0000000..94e8af9
--- /dev/null
+++ b/ElvUI/Modules/DataTexts/Time.lua
@@ -0,0 +1,77 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local DT = E:GetModule("DataTexts");
+
+--Cache global variables
+--Lua functions
+local time = time
+local format, join = string.format, string.join
+--WoW API / Variables
+local GetGameTime = GetGameTime
+local GetNumSavedInstances = GetNumSavedInstances
+local GetSavedInstanceInfo = GetSavedInstanceInfo
+local SecondsToTime = SecondsToTime
+local TIMEMANAGER_TOOLTIP_REALMTIME = "Realm time:"
+
+local timeDisplayFormat = ""
+local dateDisplayFormat = ""
+local europeDisplayFormat_nocolor = join("", "%02d", ":|r%02d")
+local lockoutInfoFormatNoEnc = "%s%s |cffaaaaaa(%s)"
+local difficultyInfo = {"N", "N", "H", "H"}
+local lockoutColorExtended, lockoutColorNormal = {r = 0.3, g = 1, b = 0.3}, {r = .8, g = .8, b = .8}
+
+local function OnLeave()
+ DT.tooltip:Hide()
+end
+
+local function OnEnter(self)
+ DT:SetupTooltip(self)
+
+ local name, _, reset, difficultyId, locked, extended, isRaid, maxPlayers
+ local oneraid, lockoutColor
+ for i = 1, GetNumSavedInstances() do
+ name, _, reset, difficultyId, locked, extended, _, isRaid, maxPlayers = GetSavedInstanceInfo(i)
+ if isRaid and (locked or extended) and name then
+ if not oneraid then
+ DT.tooltip:AddLine(L["Saved Raid(s)"])
+ DT.tooltip:AddLine(" ")
+ oneraid = true
+ end
+ if extended then
+ lockoutColor = lockoutColorExtended
+ else
+ lockoutColor = lockoutColorNormal
+ end
+
+ DT.tooltip:AddDoubleLine(format(lockoutInfoFormatNoEnc, maxPlayers, difficultyInfo[difficultyId], name), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
+ end
+ end
+
+ DT.tooltip:AddDoubleLine(TIMEMANAGER_TOOLTIP_REALMTIME, format(europeDisplayFormat_nocolor, GetGameTime()), 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
+
+ DT.tooltip:Show()
+end
+
+local lastPanel
+local int = 5
+local function OnUpdate(self, t)
+ int = int - t
+
+ if int > 0 then return end
+
+ self.text:SetText(gsub(gsub(BetterDate(E.db.datatexts.timeFormat.." "..E.db.datatexts.dateFormat, time()), ":", timeDisplayFormat), "%s", dateDisplayFormat))
+
+ lastPanel = self
+ int = 1
+end
+
+local function ValueColorUpdate(hex)
+ timeDisplayFormat = join("", hex, ":|r")
+ dateDisplayFormat = join("", hex, " ")
+
+ if lastPanel ~= nil then
+ OnUpdate(lastPanel, 20000)
+ end
+end
+E["valueColorUpdateFuncs"][ValueColorUpdate] = true
+
+DT:RegisterDatatext("Time", nil, nil, OnUpdate, nil, OnEnter, OnLeave)
\ No newline at end of file
diff --git a/ElvUI/Modules/Load_Modules.xml b/ElvUI/Modules/Load_Modules.xml
new file mode 100644
index 0000000..5665104
--- /dev/null
+++ b/ElvUI/Modules/Load_Modules.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Maps/Load_Maps.xml b/ElvUI/Modules/Maps/Load_Maps.xml
new file mode 100644
index 0000000..90fa943
--- /dev/null
+++ b/ElvUI/Modules/Maps/Load_Maps.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Maps/Minimap.lua b/ElvUI/Modules/Maps/Minimap.lua
new file mode 100644
index 0000000..85b9bc3
--- /dev/null
+++ b/ElvUI/Modules/Maps/Minimap.lua
@@ -0,0 +1,379 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:NewModule("Minimap", "AceEvent-3.0");
+E.Minimap = M
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local strsub = strsub
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local ToggleCharacter = ToggleCharacter
+local ToggleFrame = ToggleFrame
+local ToggleAchievementFrame = ToggleAchievementFrame
+local ToggleFriendsFrame = ToggleFriendsFrame
+local IsAddOnLoaded = IsAddOnLoaded
+local ToggleHelpFrame = ToggleHelpFrame
+local GetZonePVPInfo = GetZonePVPInfo
+local IsShiftKeyDown = IsShiftKeyDown
+local ToggleDropDownMenu = ToggleDropDownMenu
+local Minimap_OnClick = Minimap_OnClick
+local GetMinimapZoneText = GetMinimapZoneText
+
+local menuFrame = CreateFrame("Frame", "MinimapRightClickMenu", E.UIParent, "L_UIDropDownMenuTemplate")
+local menuList = {
+ {text = CHARACTER_BUTTON,
+ func = function() ToggleCharacter("PaperDollFrame") end},
+ {text = SPELLBOOK_ABILITIES_BUTTON,
+ func = function() ToggleFrame(SpellBookFrame) end},
+ {text = TALENTS_BUTTON,
+ func = ToggleTalentFrame},
+ {text = QUESTLOG_BUTTON,
+ func = function() ToggleFrame(QuestLogFrame) end},
+ {text = SOCIAL_BUTTON,
+ func = function() ToggleFriendsFrame(1) end},
+ {text = L["Farm Mode"],
+ func = FarmMode},
+ {text = BATTLEFIELD_MINIMAP,
+ func = ToggleBattlefieldMinimap},
+ {text = HELPFRAME_HOME_ISSUE3_HEADER,
+ func = function() ToggleCharacter("HonorFrame") end},
+ {text = HELP_BUTTON,
+ func = ToggleHelpFrame}
+}
+
+function GetMinimapShape()
+ return "SQUARE"
+end
+
+function M:GetLocTextColor()
+ local pvpType = GetZonePVPInfo()
+ if(pvpType == "sanctuary") then
+ return 0.035, 0.58, 0.84
+ elseif(pvpType == "arena") then
+ return 0.84, 0.03, 0.03
+ elseif(pvpType == "friendly") then
+ return 0.05, 0.85, 0.03
+ elseif(pvpType == "hostile") then
+ return 0.84, 0.03, 0.03
+ elseif(pvpType == "contested") then
+ return 0.9, 0.85, 0.05
+ else
+ return 0.84, 0.03, 0.03
+ end
+end
+
+function M:Minimap_OnMouseUp(btn)
+ local position = this:GetPoint()
+ if arg1 == "MiddleButton" or (arg1 == "RightButton" and IsShiftKeyDown()) then
+ if position then
+ L_EasyMenu(menuList, menuFrame, "cursor", 0, 0, "MENU", 2)
+ else
+ L_EasyMenu(menuList, menuFrame, "cursor", -160, 0, "MENU", 2)
+ end
+ else
+ Minimap_OnClick(this)
+ end
+end
+
+function M:Minimap_OnMouseWheel()
+ if arg1 > 0 then
+ _G.MinimapZoomIn:Click()
+ elseif arg1 < 0 then
+ _G.MinimapZoomOut:Click()
+ end
+end
+
+function M:Update_ZoneText()
+ if E.db.general.minimap.locationText == "HIDE" or not E.private.general.minimap.enable then return end
+ Minimap.location:SetText(strsub(GetMinimapZoneText(),1,46))
+ Minimap.location:SetTextColor(self:GetLocTextColor())
+ E:FontTemplate(Minimap.location, E.LSM:Fetch("font", E.db.general.minimap.locationFont), E.db.general.minimap.locationFontSize, E.db.general.minimap.locationFontOutline)
+end
+
+function M:PLAYER_REGEN_ENABLED()
+ self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+ self:UpdateSettings()
+end
+
+local isResetting
+local function ResetZoom()
+ Minimap:SetZoom(0)
+ MinimapZoomIn:Enable()
+ MinimapZoomOut:Disable()
+ isResetting = false
+end
+local function SetupZoomReset()
+ if(E.db.general.minimap.resetZoom.enable and not isResetting) then
+ isResetting = true
+ E:Delay(E.db.general.minimap.resetZoom.time, ResetZoom)
+ end
+end
+hooksecurefunc(Minimap, "SetZoom", SetupZoomReset)
+
+function M:UpdateSettings()
+ E.MinimapSize = E.private.general.minimap.enable and E.db.general.minimap.size or Minimap:GetWidth() + 10
+ E.MinimapWidth = E.MinimapSize
+ E.MinimapHeight = E.MinimapSize
+
+ if E.private.general.minimap.enable then
+ Minimap:SetScale(E.MinimapSize / 140)
+ end
+
+ if(LeftMiniPanel and RightMiniPanel) then
+ if(E.db.datatexts.minimapPanels and E.private.general.minimap.enable) then
+ LeftMiniPanel:Show()
+ RightMiniPanel:Show()
+ else
+ LeftMiniPanel:Hide()
+ RightMiniPanel:Hide()
+ end
+ end
+
+ if(BottomMiniPanel) then
+ if(E.db.datatexts.minimapBottom and E.private.general.minimap.enable) then
+ BottomMiniPanel:Show()
+ else
+ BottomMiniPanel:Hide()
+ end
+ end
+
+ if(BottomLeftMiniPanel) then
+ if(E.db.datatexts.minimapBottomLeft and E.private.general.minimap.enable) then
+ BottomLeftMiniPanel:Show()
+ else
+ BottomLeftMiniPanel:Hide()
+ end
+ end
+
+ if(BottomRightMiniPanel) then
+ if(E.db.datatexts.minimapBottomRight and E.private.general.minimap.enable) then
+ BottomRightMiniPanel:Show()
+ else
+ BottomRightMiniPanel:Hide()
+ end
+ end
+
+ if(TopMiniPanel) then
+ if(E.db.datatexts.minimapTop and E.private.general.minimap.enable) then
+ TopMiniPanel:Show()
+ else
+ TopMiniPanel:Hide()
+ end
+ end
+
+ if(TopLeftMiniPanel) then
+ if(E.db.datatexts.minimapTopLeft and E.private.general.minimap.enable) then
+ TopLeftMiniPanel:Show()
+ else
+ TopLeftMiniPanel:Hide()
+ end
+ end
+
+ if(TopRightMiniPanel) then
+ if(E.db.datatexts.minimapTopRight and E.private.general.minimap.enable) then
+ TopRightMiniPanel:Show()
+ else
+ TopRightMiniPanel:Hide()
+ end
+ end
+
+ if MMHolder then
+ MMHolder:SetWidth(E.MinimapWidth + E.Border + E.Spacing*3)
+
+ if E.db.datatexts.minimapPanels then
+ MMHolder:SetHeight(E.MinimapHeight + (LeftMiniPanel and (LeftMiniPanel:GetHeight() + E.Border) or 24) + E.Spacing*3)
+ else
+ MMHolder:SetHeight(E.MinimapHeight + E.Border + E.Spacing*3)
+ end
+ end
+
+ if Minimap.location then
+ Minimap.location:SetWidth(E.MinimapSize)
+
+ if(E.db.general.minimap.locationText ~= "SHOW" or not E.private.general.minimap.enable) then
+ Minimap.location:Hide()
+ else
+ Minimap.location:Show()
+ end
+ end
+
+ if MinimapMover then
+ MinimapMover:SetWidth(MMHolder:GetWidth())
+ MinimapMover:SetHeight(MMHolder:GetHeight())
+ end
+
+ if GameTimeFrame then
+ if E.private.general.minimap.hideCalendar then
+ GameTimeFrame:Hide()
+ else
+ local pos = E.db.general.minimap.icons.calendar.position or "TOPRIGHT"
+ local scale = E.db.general.minimap.icons.calendar.scale or 1
+ GameTimeFrame:ClearAllPoints()
+ GameTimeFrame:SetPoint(pos, Minimap, pos, E.db.general.minimap.icons.calendar.xOffset or 0, E.db.general.minimap.icons.calendar.yOffset or 0)
+ GameTimeFrame:SetScale(scale)
+ GameTimeFrame:Show()
+ end
+ end
+
+ if MiniMapMailFrame then
+ local pos = E.db.general.minimap.icons.mail.position or "TOPRIGHT"
+ local scale = E.db.general.minimap.icons.mail.scale or 1
+ MiniMapMailFrame:ClearAllPoints()
+ MiniMapMailFrame:SetPoint(pos, Minimap, pos, E.db.general.minimap.icons.mail.xOffset or 3, E.db.general.minimap.icons.mail.yOffset or 4)
+ MiniMapMailFrame:SetScale(scale)
+ end
+
+ if MiniMapBattlefieldFrame then
+ local pos = E.db.general.minimap.icons.battlefield.position or "BOTTOMRIGHT"
+ local scale = E.db.general.minimap.icons.battlefield.scale or 1
+ MiniMapBattlefieldFrame:ClearAllPoints()
+ MiniMapBattlefieldFrame:SetPoint(pos, Minimap, pos, E.db.general.minimap.icons.battlefield.xOffset or 3, E.db.general.minimap.icons.battlefield.yOffset or 0)
+ MiniMapBattlefieldFrame:SetScale(scale)
+ end
+
+ if MiniMapInstanceDifficulty then
+ local pos = E.db.general.minimap.icons.difficulty.position or "TOPLEFT"
+ local scale = E.db.general.minimap.icons.difficulty.scale or 1
+ local x = E.db.general.minimap.icons.difficulty.xOffset or 0
+ local y = E.db.general.minimap.icons.difficulty.yOffset or 0
+ MiniMapInstanceDifficulty:ClearAllPoints()
+ MiniMapInstanceDifficulty:SetPoint(pos, Minimap, pos, x, y)
+ MiniMapInstanceDifficulty:SetScale(scale)
+ end
+end
+
+local function MinimapPostDrag()
+ MinimapCluster:ClearAllPoints()
+ MinimapCluster:SetAllPoints(Minimap)
+ MinimapBackdrop:ClearAllPoints()
+ MinimapBackdrop:SetAllPoints(Minimap)
+end
+
+function M:Initialize()
+ E:SetTemplate(menuFrame, "Transparent", true)
+
+ self:UpdateSettings()
+
+ if not E.private.general.minimap.enable then
+ Minimap:SetMaskTexture("Textures\\MinimapMask")
+ return
+ end
+
+ local mmholder = CreateFrame("Frame", "MMHolder", UIParent)
+ mmholder:SetPoint("TOPRIGHT", E.UIParent, "TOPRIGHT", -3, -3)
+ mmholder:SetWidth(E.MinimapWidth + 29)
+ mmholder:SetHeight(E.MinimapHeight + 53)
+ Minimap:ClearAllPoints()
+ Minimap:SetPoint("TOPRIGHT", mmholder, "TOPRIGHT", -E.Border, -E.Border)
+
+ Minimap:SetMaskTexture("Interface\\ChatFrame\\ChatFrameBackground")
+ Minimap.backdrop = CreateFrame("Frame", nil, UIParent)
+ E:SetOutside(Minimap.backdrop, Minimap)
+ Minimap.backdrop:SetFrameStrata(Minimap:GetFrameStrata())
+ Minimap.backdrop:SetFrameLevel(Minimap:GetFrameLevel() - 1)
+ E:SetTemplate(Minimap.backdrop, "Default")
+ HookScript(Minimap, "OnEnter", function()
+ if E.db.general.minimap.locationText ~= "MOUSEOVER" or not E.private.general.minimap.enable then
+ return
+ end
+ this.location:Show()
+ end)
+
+ HookScript(Minimap, "OnLeave", function()
+ if E.db.general.minimap.locationText ~= "MOUSEOVER" or not E.private.general.minimap.enable then
+ return
+ end
+ this.location:Hide()
+ end)
+
+ Minimap.location = Minimap:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(Minimap.location, nil, nil, "OUTLINE")
+ Minimap.location:SetPoint("TOP", Minimap, "TOP", 0, -2)
+ Minimap.location:SetJustifyH("CENTER")
+ Minimap.location:SetJustifyV("MIDDLE")
+ if E.db.general.minimap.locationText ~= "SHOW" or not E.private.general.minimap.enable then
+ Minimap.location:Hide()
+ end
+
+ MinimapBorder:Hide()
+ MinimapBorderTop:Hide()
+
+ MinimapToggleButton:Hide()
+
+ MinimapZoomIn:Hide()
+ MinimapZoomOut:Hide()
+
+ MinimapZoneTextButton:Hide()
+
+ MiniMapMailBorder:Hide()
+ MiniMapMailIcon:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\mail")
+
+ MiniMapBattlefieldBorder:Hide()
+
+ E:CreateMover(MMHolder, "MinimapMover", L["Minimap"], nil, nil, MinimapPostDrag)
+
+ Minimap:EnableMouseWheel(true)
+ Minimap:SetScript("OnMouseWheel", M.Minimap_OnMouseWheel)
+ Minimap:SetScript("OnMouseUp", M.Minimap_OnMouseUp)
+
+ self:RegisterEvent("ZONE_CHANGED_NEW_AREA", "Update_ZoneText")
+ self:RegisterEvent("ZONE_CHANGED", "Update_ZoneText")
+ self:RegisterEvent("ZONE_CHANGED_INDOORS", "Update_ZoneText")
+ self:RegisterEvent("PLAYER_ENTERING_WORLD", "Update_ZoneText")
+
+ local fm = CreateFrame("Minimap", "FarmModeMap", E.UIParent)
+ fm:SetWidth(E.db.farmSize)
+ fm:SetHeight(E.db.farmSize)
+ fm:SetPoint("TOP", E.UIParent, "TOP", 0, -120)
+ fm:SetClampedToScreen(true)
+ E:CreateBackdrop(fm, "Default")
+ fm:EnableMouseWheel(true)
+ fm:SetScript("OnMouseWheel", M.Minimap_OnMouseWheel)
+ fm:SetScript("OnMouseUp", M.Minimap_OnMouseUp)
+ fm:RegisterForDrag("LeftButton", "RightButton")
+ fm:SetMovable(true)
+ fm:SetScript("OnDragStart", function() this:StartMoving() end)
+ fm:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
+ fm:Hide()
+
+ FarmModeMap:SetScript("OnShow", function()
+ if(BuffsMover and not E:HasMoverBeenMoved("BuffsMover")) then
+ BuffsMover:ClearAllPoints()
+ BuffsMover:SetPoint("TOPRIGHT", E.UIParent, "TOPRIGHT", -3, -3)
+ end
+
+ if(DebuffsMover and not E:HasMoverBeenMoved("DebuffsMover")) then
+ DebuffsMover:ClearAllPoints()
+ DebuffsMover:SetPoint("TOPRIGHT", ElvUIPlayerBuffs, "BOTTOMRIGHT", 0, -3)
+ end
+
+ MinimapCluster:ClearAllPoints()
+ MinimapCluster:SetAllPoints(FarmModeMap)
+ end)
+
+ FarmModeMap:SetScript("OnHide", function()
+ if(BuffsMover and not E:HasMoverBeenMoved("BuffsMover")) then
+ E:ResetMovers(L["Player Buffs"])
+ end
+
+ if(DebuffsMover and not E:HasMoverBeenMoved("DebuffsMover")) then
+ E:ResetMovers(L["Player Debuffs"])
+ end
+
+ MinimapCluster:ClearAllPoints()
+ MinimapCluster:SetAllPoints(Minimap)
+ end)
+
+ HookScript(UIParent, "OnShow", function()
+ if not FarmModeMap.enabled then
+ FarmModeMap:Hide()
+ end
+ end)
+end
+
+local function InitializeCallback()
+ M:Initialize()
+end
+
+E:RegisterInitialModule(M:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Maps/WorldMap.lua b/ElvUI/Modules/Maps/WorldMap.lua
new file mode 100644
index 0000000..c84348b
--- /dev/null
+++ b/ElvUI/Modules/Maps/WorldMap.lua
@@ -0,0 +1,113 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:NewModule("WorldMap", "AceHook-3.0", "AceEvent-3.0", "AceTimer-3.0");
+E.WorldMap = M
+
+--Cache global variables
+--Lua functions
+local format = string.format
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local GetPlayerMapPosition = GetPlayerMapPosition
+local GetCursorPosition = GetCursorPosition
+local PLAYER = PLAYER
+
+local INVERTED_POINTS = {
+ ["TOPLEFT"] = "BOTTOMLEFT",
+ ["TOPRIGHT"] = "BOTTOMRIGHT",
+ ["BOTTOMLEFT"] = "TOPLEFT",
+ ["BOTTOMRIGHT"] = "TOPRIGHT",
+ ["TOP"] = "BOTTOM",
+ ["BOTTOM"] = "TOP"
+}
+
+function M:UpdateCoords()
+ if not WorldMapFrame:IsShown() then return end
+ local x, y = GetPlayerMapPosition("player")
+ x = x and E:Round(100 * x, 2) or 0
+ y = y and E:Round(100 * y, 2) or 0
+
+ if x ~= 0 and y ~= 0 then
+ CoordsHolder.playerCoords:SetText(PLAYER..": "..format("%.2f, %.2f", x, y))
+ else
+ CoordsHolder.playerCoords:SetText("")
+ end
+
+ local scale = WorldMapDetailFrame:GetEffectiveScale()
+ local width = WorldMapDetailFrame:GetWidth()
+ local height = WorldMapDetailFrame:GetHeight()
+ local centerX, centerY = WorldMapDetailFrame:GetCenter()
+ local x, y = GetCursorPosition()
+ local adjustedX = (x / scale - (centerX - (width / 2))) / width
+ local adjustedY = (centerY + (height / 2) - y / scale) / height
+
+ if adjustedX >= 0 and adjustedY >= 0 and adjustedX <= 1 and adjustedY <= 1 then
+ adjustedX = E:Round(100 * adjustedX, 2)
+ adjustedY = E:Round(100 * adjustedY, 2)
+ CoordsHolder.mouseCoords:SetText(L["Mouse"]..": "..format("%.2f, %.2f", adjustedX, adjustedY))
+ else
+ CoordsHolder.mouseCoords:SetText("")
+ end
+end
+
+function M:PositionCoords()
+ local db = E.global.general.WorldMapCoordinates
+ local position = db.position
+ local xOffset = db.xOffset
+ local yOffset = db.yOffset
+
+ local x, y = 5, 5
+ if position == "BOTTOMRIGHT" or position == "TOPRIGHT" then x = -5 end
+ if position == "TOPLEFT" or position == "TOP" or position == "TOPRIGHT" then y = -5 end
+
+ CoordsHolder.playerCoords:ClearAllPoints()
+ CoordsHolder.playerCoords:SetPoint(position, WorldMapDetailFrame, position, x + xOffset, y + yOffset)
+ CoordsHolder.mouseCoords:ClearAllPoints()
+ CoordsHolder.mouseCoords:SetPoint(position, CoordsHolder.playerCoords, INVERTED_POINTS[position], 0, y)
+end
+
+function M:Initialize()
+ if E.global.general.WorldMapCoordinates.enable then
+ local coordsHolder = CreateFrame("Frame", "CoordsHolder", WorldMapFrame)
+ coordsHolder:SetFrameStrata(WorldMapDetailFrame:GetFrameStrata())
+ coordsHolder.playerCoords = coordsHolder:CreateFontString(nil, "OVERLAY")
+ coordsHolder.mouseCoords = coordsHolder:CreateFontString(nil, "OVERLAY")
+ coordsHolder.playerCoords:SetTextColor(1, 1 ,0)
+ coordsHolder.mouseCoords:SetTextColor(1, 1 ,0)
+ coordsHolder.playerCoords:SetFontObject(NumberFontNormal)
+ coordsHolder.mouseCoords:SetFontObject(NumberFontNormal)
+ coordsHolder.playerCoords:SetPoint("BOTTOMLEFT", WorldMapDetailFrame, "BOTTOMLEFT", 5, 5)
+ coordsHolder.playerCoords:SetText(PLAYER..": 0, 0")
+ coordsHolder.mouseCoords:SetPoint("BOTTOMLEFT", coordsHolder.playerCoords, "TOPLEFT", 0, 5)
+ coordsHolder.mouseCoords:SetText("MOUSE_LABEL"..": 0, 0")
+
+ coordsHolder:SetScript("OnUpdate", self.UpdateCoords)
+
+ self:PositionCoords()
+ end
+
+ if E.global.general.smallerWorldMap then
+ BlackoutWorld:SetTexture(nil)
+
+ WorldMapFrame:SetParent(E.UIParent)
+ WorldMapFrame:SetScale(1)
+ WorldMapFrame:EnableKeyboard(false)
+ WorldMapFrame:EnableMouse(false)
+ WorldMapFrame:SetToplevel()
+
+ UIPanelWindows["WorldMapFrame"] = {area = "center", pushable = 0, whileDead = 1}
+
+ HookScript(DropDownList1, "OnShow", function()
+ if DropDownList1:GetScale() ~= UIParent:GetScale() then
+ DropDownList1:SetScale(UIParent:GetScale())
+ end
+ end)
+
+ WorldMapTooltip:SetFrameLevel(WorldMapPositioningGuide:GetFrameLevel() + 110)
+ end
+end
+
+local function InitializeCallback()
+ M:Initialize()
+end
+
+E:RegisterInitialModule(M:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/AFK.lua b/ElvUI/Modules/Misc/AFK.lua
new file mode 100644
index 0000000..13c4da5
--- /dev/null
+++ b/ElvUI/Modules/Misc/AFK.lua
@@ -0,0 +1,330 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local AFK = E:NewModule("AFK", "AceEvent-3.0", "AceTimer-3.0");
+-- local CH = E:GetModule("Chat")
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local GetTime = GetTime
+local floor = math.floor
+--WoW API / Variables
+local CinematicFrame = CinematicFrame
+local CreateFrame = CreateFrame
+local GetBattlefieldStatus = GetBattlefieldStatus
+local GetGuildInfo = GetGuildInfo
+local GetScreenHeight = GetScreenHeight
+local GetScreenWidth = GetScreenWidth
+local UnitAffectingCombat = UnitAffectingCombat
+local IsInGuild = IsInGuild
+local IsShiftKeyDown = IsShiftKeyDown
+local Screenshot = Screenshot
+local SetCVar = SetCVar
+local UnitFactionGroup = UnitFactionGroup
+
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local MAX_BATTLEFIELD_QUEUES = MAX_BATTLEFIELD_QUEUES
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+
+local AFK_SPEED = 7.35
+
+local ignoreKeys = {
+ LALT = true,
+ LSHIFT = true,
+ RSHIFT = true
+}
+
+local printKeys = {
+ ["PRINTSCREEN"] = true,
+}
+
+if IsMacClient() then
+ printKeys[_G["KEY_PRINTSCREEN_MAC"]] = true
+end
+
+function AFK:UpdateTimer()
+ local time = GetTime() - self.startTime
+ self.AFKMode.bottom.time:SetText(format("%02d:%02d", floor(time / 60), time - floor(time / 60) * 60))
+end
+
+local function StopAnimation(self)
+ self:SetSequenceTime(0, 0)
+ self:SetScript("OnUpdate", nil)
+ self:SetScript("OnAnimFinished", nil)
+end
+
+local function UpdateAnimation(...)
+ this.animTime = this.animTime + (arg1 * 1000)
+ this:SetSequenceTime(67, this.animTime)
+
+ if this.animTime >= 3000 then
+ StopAnimation(this)
+ end
+end
+
+local function OnAnimFinished(self)
+ if self.animTime > 500 then
+ StopAnimation(self)
+ end
+end
+
+local recountVis
+local function RecountVisability(save)
+ if Recount and Recount.db and Recount.db.profile then
+ if save then
+ recountVis = Recount.db.profile.MainWindowVis
+ else
+ Recount.db.profile.MainWindowVis = recountVis
+ RecountDB.profiles[Recount.db.keys.profile].MainWindowVis = recountVis
+ end
+ end
+end
+
+local LRC
+local function RockConfigFix()
+ if not LRC then
+ LRC = LibStub("LibRockConfig-1.0", true)
+ end
+ if LRC then
+ if LRC.base and LRC.base:IsShown() then
+ LRC.base.addonChooser:Select(LRC.base.addonChooser.value)
+ end
+ end
+end
+
+function AFK:SetAFK(status)
+ if status and not self.isAFK then
+ if InspectFrame then
+ InspectPaperDollFrame:Hide()
+ end
+
+ RecountVisability(true)
+ UIParent:Hide()
+ self.AFKMode:Show()
+ RecountVisability()
+
+ E.global.afkEnabled = true
+ E.global.afkCameraSpeedYaw = GetCVar("cameraYawMoveSpeed")
+ E.global.afkCameraSpeedPitch = GetCVar("cameraPitchMoveSpeed")
+ MoveViewLeftStart()
+
+ SetCVar("cameraYawMoveSpeed", AFK_SPEED)
+ SetCVar("cameraPitchMoveSpeed", E.global.afkCameraSpeedPitch)
+
+ if IsInGuild() then
+ local guildName, guildRankName = GetGuildInfo("player")
+ self.AFKMode.bottom.guild:SetText(format("%s - %s", guildName, guildRankName))
+ else
+ self.AFKMode.bottom.guild:SetText(L["No Guild"])
+ end
+
+ self.startTime = GetTime()
+ self.timer = self:ScheduleRepeatingTimer("UpdateTimer", 1)
+
+ self.AFKMode.chat:RegisterEvent("CHAT_MSG_WHISPER")
+ self.AFKMode.chat:RegisterEvent("CHAT_MSG_GUILD")
+
+ self.AFKMode.bottom.model:SetModelScale(1)
+ self.AFKMode.bottom.model:RefreshUnit()
+ self.AFKMode.bottom.model:SetModelScale(0.8)
+
+ self.AFKMode.bottom.model.animTime = 0
+ self.AFKMode.bottom.model:SetScript("OnUpdate", UpdateAnimation)
+ self.AFKMode.bottom.model:SetScript("OnAnimFinished", OnAnimFinished)
+
+ self.isAFK = true
+ elseif not status and self.isAFK then
+ self.AFKMode:Hide()
+ UIParent:Show()
+
+ E.global.afkEnabled = nil
+ SetCVar("cameraYawMoveSpeed", E.global.afkCameraSpeedYaw)
+ SetCVar("cameraPitchMoveSpeed", E.global.afkCameraSpeedPitch)
+
+ MoveViewLeftStop()
+
+ self:CancelTimer(self.timer)
+ self.AFKMode.bottom.time:SetText("00:00")
+
+ self.AFKMode.chat:UnregisterAllEvents()
+ self.AFKMode.chat:Clear()
+
+ self.isAFK = false
+
+ RockConfigFix()
+ end
+end
+
+function AFK:OnEvent(event, ...)
+ if event == "PLAYER_REGEN_DISABLED" or event == "UPDATE_BATTLEFIELD_STATUS" then
+ if event == "UPDATE_BATTLEFIELD_STATUS" then
+ local status, _, instanceID
+ for i = 1, MAX_BATTLEFIELD_QUEUES do
+ status, _, instanceID = GetBattlefieldStatus(i)
+ if instanceID ~= 0 then
+ status = status
+ end
+ end
+ local status = status
+ if status == "confirm" then
+ self:SetAFK(false)
+ end
+ else
+ self:SetAFK(false)
+ end
+
+ if event == "PLAYER_REGEN_DISABLED" then
+ self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnEvent")
+ end
+
+ return
+ end
+
+ if event == "PLAYER_REGEN_ENABLED" then
+ self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+ end
+
+ if not E.db.general.afk then return end
+ if UnitAffectingCombat("player") or CinematicFrame:IsShown() then return end
+ -- if UnitCastingInfo("player") ~= nil then
+ -- --Don't activate afk if player is crafting stuff, check back in 30 seconds
+ -- self:ScheduleTimer("OnEvent", 30)
+ -- return
+ -- end
+
+ if arg1 == format(MARKED_AFK_MESSAGE, DEFAULT_AFK_MESSAGE) then
+ self:SetAFK(true)
+ elseif arg1 == CLEARED_AFK then
+ self:SetAFK(false)
+ end
+end
+
+function AFK:Toggle()
+ if E.db.general.afk then
+ self:RegisterEvent("CHAT_MSG_SYSTEM", "OnEvent")
+ self:RegisterEvent("PLAYER_FLAGS_CHANGED", "OnEvent")
+ self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnEvent")
+ self:RegisterEvent("UPDATE_BATTLEFIELD_STATUS", "OnEvent")
+
+ SetCVar("autoClearAFK", "1")
+ else
+ self:UnregisterEvent("CHAT_MSG_SYSTEM")
+ self:UnregisterEvent("PLAYER_FLAGS_CHANGED")
+ self:UnregisterEvent("PLAYER_REGEN_DISABLED")
+ self:UnregisterEvent("UPDATE_BATTLEFIELD_STATUS")
+
+ self:CancelAllTimers()
+ end
+end
+
+local function OnKeyDown(_, key)
+ if ignoreKeys[key] then return end
+ if printKeys[key] then
+ Screenshot()
+ else
+ AFK:SetAFK(false)
+ AFK:ScheduleTimer("OnEvent", 60)
+ end
+end
+
+local function Chat_OnMouseWheel(self, delta)
+ if delta == 1 and IsShiftKeyDown() then
+ self:ScrollToTop()
+ elseif delta == -1 and IsShiftKeyDown() then
+ self:ScrollToBottom()
+ elseif delta == -1 then
+ self:ScrollDown()
+ else
+ self:ScrollUp()
+ end
+end
+
+function AFK:Initialize()
+ if E.global.afkEnabled then
+ SetCVar("cameraYawMoveSpeed", E.global.afkCameraSpeedYaw)
+ SetCVar("cameraPitchMoveSpeed", E.global.afkCameraSpeedPitch)
+ E.global.afkEnabled = nil
+ end
+
+ local _, class = UnitClass("player")
+ local classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+
+ self.AFKMode = CreateFrame("Frame", "ElvUIAFKFrame")
+ self.AFKMode:SetFrameLevel(1)
+ self.AFKMode:SetScale(UIParent:GetScale())
+ self.AFKMode:SetAllPoints(UIParent)
+ self.AFKMode:Hide()
+ self.AFKMode:EnableKeyboard(true)
+ self.AFKMode:SetScript("OnKeyDown", OnKeyDown)
+
+ self.AFKMode.chat = CreateFrame("ScrollingMessageFrame", "AFKChat", self.AFKMode)
+ self.AFKMode.chat:SetWidth(500)
+ self.AFKMode.chat:SetHeight(200)
+ self.AFKMode.chat:SetPoint("TOPLEFT", self.AFKMode, "TOPLEFT", 4, -3)
+ E:FontTemplate(self.AFKMode.chat)
+ self.AFKMode.chat:SetJustifyH("LEFT")
+ self.AFKMode.chat:SetMaxLines(500)
+ self.AFKMode.chat:EnableMouseWheel(true)
+ self.AFKMode.chat:SetFading(false)
+ self.AFKMode.chat:SetMovable(true)
+ self.AFKMode.chat:EnableMouse(true)
+ self.AFKMode.chat:SetClampedToScreen(true)
+ -- self.AFKMode.chat:SetClampRectInsets(-4, 3, 3, -4)
+ self.AFKMode.chat:RegisterForDrag("LeftButton")
+ self.AFKMode.chat:SetScript("OnDragStart", self.AFKMode.chat.StartMoving)
+ self.AFKMode.chat:SetScript("OnDragStop", self.AFKMode.chat.StopMovingOrSizing)
+ self.AFKMode.chat:SetScript("OnMouseWheel", Chat_OnMouseWheel)
+ -- self.AFKMode.chat:SetScript("OnEvent", CH.ChatFrame_OnEvent)
+
+ self.AFKMode.bottom = CreateFrame("Frame", nil, self.AFKMode)
+ self.AFKMode.bottom:SetFrameLevel(0)
+ E:SetTemplate(self.AFKMode.bottom, "Transparent")
+ self.AFKMode.bottom:SetPoint("BOTTOM", self.AFKMode, "BOTTOM", 0, -E.Border)
+ self.AFKMode.bottom:SetWidth(GetScreenWidth() + (E.Border*2))
+ self.AFKMode.bottom:SetHeight(GetScreenHeight() * 0.1)
+
+ self.AFKMode.bottom.logo = self.AFKMode:CreateTexture(nil, "OVERLAY")
+ self.AFKMode.bottom.logo:SetWidth(320)
+ self.AFKMode.bottom.logo:SetHeight(150)
+ self.AFKMode.bottom.logo:SetPoint("CENTER", self.AFKMode.bottom, "CENTER", 0, 50)
+ self.AFKMode.bottom.logo:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\logo")
+
+ local factionGroup = UnitFactionGroup("player")
+ self.AFKMode.bottom.faction = self.AFKMode.bottom:CreateTexture(nil, "OVERLAY")
+ self.AFKMode.bottom.faction:SetPoint("BOTTOMLEFT", self.AFKMode.bottom, "BOTTOMLEFT", -20, -16)
+ self.AFKMode.bottom.faction:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\"..factionGroup.."-Logo")
+ self.AFKMode.bottom.faction:SetWidth(140)
+ self.AFKMode.bottom.faction:SetHeight(140)
+
+ self.AFKMode.bottom.name = self.AFKMode.bottom:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(self.AFKMode.bottom.name, nil, 20)
+ self.AFKMode.bottom.name:SetText(format("%s - %s", E.myname, E.myrealm))
+ self.AFKMode.bottom.name:SetPoint("TOPLEFT", self.AFKMode.bottom.faction, "TOPRIGHT", -10, -28)
+ self.AFKMode.bottom.name:SetTextColor(classColor.r, classColor.g, classColor.b)
+
+ self.AFKMode.bottom.guild = self.AFKMode.bottom:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(self.AFKMode.bottom.guild, nil, 20)
+ self.AFKMode.bottom.guild:SetText(L["No Guild"])
+ self.AFKMode.bottom.guild:SetPoint("TOPLEFT", self.AFKMode.bottom.name, "BOTTOMLEFT", 0, -6)
+ self.AFKMode.bottom.guild:SetTextColor(0.7, 0.7, 0.7)
+
+ self.AFKMode.bottom.time = self.AFKMode.bottom:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(self.AFKMode.bottom.time, nil, 20)
+ self.AFKMode.bottom.time:SetText("00:00")
+ self.AFKMode.bottom.time:SetPoint("TOPLEFT", self.AFKMode.bottom.guild, "BOTTOMLEFT", 0, -6)
+ self.AFKMode.bottom.time:SetTextColor(0.7, 0.7, 0.7)
+
+ self.AFKMode.bottom.model = CreateFrame("PlayerModel", "ElvUIAFKPlayerModel", self.AFKMode.bottom)
+ self.AFKMode.bottom.model:SetPoint("BOTTOMRIGHT", self.AFKMode.bottom, "BOTTOMRIGHT", 120, -100)
+ self.AFKMode.bottom.model:SetWidth(800)
+ self.AFKMode.bottom.model:SetHeight(800)
+ self.AFKMode.bottom.model:SetFacing(6)
+ self.AFKMode.bottom.model:SetUnit("player")
+
+ self:Toggle()
+end
+
+local function InitializeCallback()
+ AFK:Initialize()
+end
+
+E:RegisterModule(AFK:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/ChatBubbles.lua b/ElvUI/Modules/Misc/ChatBubbles.lua
new file mode 100644
index 0000000..0a86ef3
--- /dev/null
+++ b/ElvUI/Modules/Misc/ChatBubbles.lua
@@ -0,0 +1,203 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:GetModule("Misc");
+local CH = E:GetModule("Chat");
+local CC = E:GetModule("ClassCache");
+
+--Cache global variables
+--Lua functions
+local select, unpack, type = select, unpack, type
+local format, gsub, match, gmatch = string.format, string.gsub, string.match, string.gmatch
+local strlower = strlower
+--WoW API / Variables
+local CreateFrame = CreateFrame
+
+function M:UpdateBubbleBorder()
+ if not this.text then return end
+
+ if E.private.general.chatBubbles == "backdrop" then
+ if E.PixelMode then
+ this:SetBackdropBorderColor(this.text:GetTextColor())
+ else
+ local r, g, b = this.text:GetTextColor()
+ this.bordertop:SetTexture(r, g, b)
+ this.borderbottom:SetTexture(r, g, b)
+ this.borderleft:SetTexture(r, g, b)
+ this.borderright:SetTexture(r, g, b)
+ end
+ end
+
+ if E.private.chat.enable and E.private.general.classCache and E.private.general.classColorMentionsSpeech then
+ local classColorTable, isFirstWord, rebuiltString, lowerCaseWord, tempWord, wordMatch, classMatch
+ local text = this.text:GetText()
+ if text and match(text, "%s-[^%s]+%s*") then
+ for word in gmatch(text, "%s-[^%s]+%s*") do
+ tempWord = gsub(word, "^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$","%1%2")
+ lowerCaseWord = strlower(tempWord)
+
+ classMatch = CC:GetCacheTable()[E.myrealm][tempWord]
+ wordMatch = classMatch and lowerCaseWord
+
+ if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then
+ classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classMatch] or RAID_CLASS_COLORS[classMatch]
+ word = gsub(word, gsub(tempWord, "%-","%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord))
+ end
+
+ if not isFirstWord then
+ rebuiltString = word
+ isFirstWord = true
+ else
+ rebuiltString = format("%s%s", rebuiltString, word)
+ end
+ end
+
+ if rebuiltString ~= nil then
+ this.text:SetText(rebuiltString)
+ end
+ end
+ end
+end
+
+function M:SkinBubble(frame)
+ local mult = E.mult * UIParent:GetScale()
+ for i = 1, frame:GetNumRegions() do
+ local region = select(i, frame:GetRegions())
+ if region:GetObjectType() == "Texture" then
+ region:SetTexture(nil)
+ elseif region:GetObjectType() == "FontString" then
+ frame.text = region
+ end
+ end
+
+ if frame.text then
+ if E.private.general.chatBubbles == "backdrop" then
+ if E.PixelMode then
+ E:SetTemplate(frame, "Transparent", true)
+ frame:SetBackdropColor(unpack(E.media.backdropfadecolor))
+ frame:SetBackdropBorderColor(0, 0, 0)
+ else
+ frame:SetBackdrop(nil)
+ end
+
+ local r, g, b = frame.text:GetTextColor()
+ if not E.PixelMode then
+ if not frame.backdrop then
+ frame.backdrop = frame:CreateTexture(nil, "BACKGROUND")
+ frame.backdrop:SetAllPoints(frame)
+ frame.backdrop:SetTexture(unpack(E.media.backdropfadecolor))
+
+ frame.bordertop = frame:CreateTexture(nil, "OVERLAY")
+ frame.bordertop:SetPoint("TOPLEFT", frame, "TOPLEFT", -mult*2, mult*2)
+ frame.bordertop:SetPoint("TOPRIGHT", frame, "TOPRIGHT", mult*2, mult*2)
+ frame.bordertop:SetHeight(mult)
+ frame.bordertop:SetTexture(r, g, b)
+
+ frame.bordertop.backdrop = frame:CreateTexture(nil, "BORDER")
+ frame.bordertop.backdrop:SetPoint("TOPLEFT", frame.bordertop, "TOPLEFT", -mult, mult)
+ frame.bordertop.backdrop:SetPoint("TOPRIGHT", frame.bordertop, "TOPRIGHT", mult, mult)
+ frame.bordertop.backdrop:SetHeight(mult * 3)
+ frame.bordertop.backdrop:SetTexture(0, 0, 0)
+
+ frame.borderbottom = frame:CreateTexture(nil, "OVERLAY")
+ frame.borderbottom:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", -mult*2, -mult*2)
+ frame.borderbottom:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", mult*2, -mult*2)
+ frame.borderbottom:SetHeight(mult)
+ frame.borderbottom:SetTexture(r, g, b)
+
+ frame.borderbottom.backdrop = frame:CreateTexture(nil, "BORDER")
+ frame.borderbottom.backdrop:SetPoint("BOTTOMLEFT", frame.borderbottom, "BOTTOMLEFT", -mult, -mult)
+ frame.borderbottom.backdrop:SetPoint("BOTTOMRIGHT", frame.borderbottom, "BOTTOMRIGHT", mult, -mult)
+ frame.borderbottom.backdrop:SetHeight(mult * 3)
+ frame.borderbottom.backdrop:SetTexture(0, 0, 0)
+
+ frame.borderleft = frame:CreateTexture(nil, "OVERLAY")
+ frame.borderleft:SetPoint("TOPLEFT", frame, "TOPLEFT", -mult*2, mult*2)
+ frame.borderleft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", mult*2, -mult*2)
+ frame.borderleft:SetWidth(mult)
+ frame.borderleft:SetTexture(r, g, b)
+
+ frame.borderleft.backdrop = frame:CreateTexture(nil, "BORDER")
+ frame.borderleft.backdrop:SetPoint("TOPLEFT", frame.borderleft, "TOPLEFT", -mult, mult)
+ frame.borderleft.backdrop:SetPoint("BOTTOMLEFT", frame.borderleft, "BOTTOMLEFT", -mult, -mult)
+ frame.borderleft.backdrop:SetWidth(mult * 3)
+ frame.borderleft.backdrop:SetTexture(0, 0, 0)
+
+ frame.borderright = frame:CreateTexture(nil, "OVERLAY")
+ frame.borderright:SetPoint("TOPRIGHT", frame, "TOPRIGHT", mult*2, mult*2)
+ frame.borderright:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -mult*2, -mult*2)
+ frame.borderright:SetWidth(mult)
+ frame.borderright:SetTexture(r, g, b)
+
+ frame.borderright.backdrop = frame:CreateTexture(nil, "BORDER")
+ frame.borderright.backdrop:SetPoint("TOPRIGHT", frame.borderright, "TOPRIGHT", mult, mult)
+ frame.borderright.backdrop:SetPoint("BOTTOMRIGHT", frame.borderright, "BOTTOMRIGHT", mult, -mult)
+ frame.borderright.backdrop:SetWidth(mult * 3)
+ frame.borderright.backdrop:SetTexture(0, 0, 0)
+ end
+ else
+ frame:SetBackdropColor(unpack(E.media.backdropfadecolor))
+ frame:SetBackdropBorderColor(r, g, b)
+ end
+
+ E:FontTemplate(frame.text, E.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
+ elseif E.private.general.chatBubbles == "backdrop_noborder" then
+ frame:SetBackdrop(nil)
+
+ if not frame.backdrop then
+ frame.backdrop = frame:CreateTexture(nil, "ARTWORK")
+ E:SetInside(frame.backdrop, frame, 4, 4)
+ frame.backdrop:SetTexture(unpack(E.media.backdropfadecolor))
+ end
+ E:FontTemplate(frame.text, E.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
+
+ frame:SetClampedToScreen(false)
+ elseif E.private.general.chatBubbles == "nobackdrop" then
+ frame:SetBackdrop(nil)
+ E:FontTemplate(frame.text, E.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
+ frame:SetClampedToScreen(false)
+ end
+ end
+
+ HookScript(frame, "OnShow", M.UpdateBubbleBorder)
+ frame:SetFrameStrata("DIALOG")
+ M.UpdateBubbleBorder(frame)
+ frame.isBubblePowered = true
+end
+
+function M:IsChatBubble(frame)
+ for i = 1, frame:GetNumRegions() do
+ local region = select(i, frame:GetRegions())
+ if region.GetTexture and region:GetTexture() and type(region:GetTexture() == "string" and strlower(region:GetTexture()) == [[interface\tooltips\chatbubble-background]]) then return true end
+ end
+ return false
+end
+
+local numChildren = 0
+function M:LoadChatBubbles()
+ if E.private.general.bubbles == false then
+ E.private.general.chatBubbles = "disabled"
+ E.private.general.bubbles = nil
+ end
+
+ if E.private.general.chatBubbles == "disabled" then return end
+
+ local frame = CreateFrame("Frame")
+ frame.lastupdate = -2
+
+ frame:SetScript("OnUpdate", function()
+ this.lastupdate = this.lastupdate + arg1
+ if this.lastupdate < .1 then return end
+ this.lastupdate = 0
+
+ local count = WorldFrame:GetNumChildren()
+ if count ~= numChildren then
+ for i = numChildren + 1, count do
+ local frame = select(i, WorldFrame:GetChildren())
+
+ if frame.GetObjectType and frame:GetObjectType() == "Frame" and M:IsChatBubble(frame) then
+ M:SkinBubble(frame)
+ end
+ end
+ numChildren = count
+ end
+ end)
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/Load_Misc.xml b/ElvUI/Modules/Misc/Load_Misc.xml
new file mode 100644
index 0000000..101dda9
--- /dev/null
+++ b/ElvUI/Modules/Misc/Load_Misc.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/Loot.lua b/ElvUI/Modules/Misc/Loot.lua
new file mode 100644
index 0000000..50d05da
--- /dev/null
+++ b/ElvUI/Modules/Misc/Loot.lua
@@ -0,0 +1,328 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:GetModule("Misc");
+
+--Cache global variables
+--Lua functions
+local max = math.max
+local tinsert = table.insert
+local unpack, pairs = unpack, pairs
+--WoW API / Variables
+local CloseLoot = CloseLoot
+local CursorOnUpdate = CursorOnUpdate
+local CursorUpdate = CursorUpdate
+local GetCVar = GetCVar
+local GetCursorPosition = GetCursorPosition
+local GetLootSlotInfo = GetLootSlotInfo
+local GetLootSlotLink = GetLootSlotLink
+local GetNumLootItems = GetNumLootItems
+local GiveMasterLoot = GiveMasterLoot
+local IsFishingLoot = IsFishingLoot
+local LootSlot = LootSlot
+local LootSlotIsCoin = LootSlotIsCoin
+local LootSlotIsItem = LootSlotIsItem
+local ResetCursor = ResetCursor
+local UnitIsDead = UnitIsDead
+local UnitIsFriend = UnitIsFriend
+local UnitName = UnitName
+local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
+local LOOT = LOOT
+
+-- Credit Haste
+local lootFrame, lootFrameHolder
+local iconSize = 30
+
+local sq, ss, sn
+local OnEnter = function()
+ local slot = this:GetID()
+ if(LootSlotIsItem(slot)) then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
+ GameTooltip:SetLootItem(slot)
+ CursorUpdate(this)
+ end
+
+ this.drop:Show()
+ this.drop:SetVertexColor(1, 1, 0)
+end
+
+local OnLeave = function()
+ if this.quality and (this.quality > 1) then
+ local color = ITEM_QUALITY_COLORS[this.quality]
+ this.drop:SetVertexColor(color.r, color.g, color.b)
+ else
+ this.drop:Hide()
+ end
+
+ GameTooltip:Hide()
+ ResetCursor()
+end
+
+local OnClick = function()
+ LootFrame.selectedQuality = this.quality
+ LootFrame.selectedItemName = this.name:GetText()
+ LootFrame.selectedSlot = this:GetID()
+ LootFrame.selectedLootButton = this:GetName()
+
+ StaticPopup_Hide("CONFIRM_LOOT_DISTRIBUTION")
+ ss = this:GetID()
+ sq = this.quality
+ sn = this.name:GetText()
+ --LootSlot(ss)
+end
+
+local OnShow = function()
+ if(GameTooltip:IsOwned(this)) then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
+ GameTooltip:SetLootItem(this:GetID())
+ CursorOnUpdate(this)
+ end
+end
+
+local function anchorSlots(self)
+ local shownSlots = 0
+ for i = 1, getn(self.slots) do
+ local frame = self.slots[i]
+ if(frame:IsShown()) then
+ shownSlots = shownSlots + 1
+
+ frame:SetPoint("TOP", lootFrame, 4, (-8 + iconSize) - (shownSlots * iconSize))
+ end
+ end
+
+ self:SetHeight(max(shownSlots * iconSize + 16, 20))
+end
+
+local function createSlot(id)
+ local frame = CreateFrame("LootButton", "ElvLootSlot"..id, lootFrame)
+ frame:SetPoint("LEFT", 8, 0)
+ frame:SetPoint("RIGHT", -8, 0)
+ frame:SetHeight(iconSize - 2)
+ frame:SetID(id)
+
+ frame:SetScript("OnEnter", OnEnter)
+ frame:SetScript("OnLeave", OnLeave)
+ frame:SetScript("OnClick", OnClick)
+ frame:SetScript("OnShow", OnShow)
+
+ local iconFrame = CreateFrame("Frame", nil, frame)
+ iconFrame:SetWidth(iconSize - 2)
+ iconFrame:SetHeight(iconSize - 2)
+ iconFrame:SetPoint("RIGHT", frame)
+ E:SetTemplate(iconFrame, "Default")
+ frame.iconFrame = iconFrame
+ E["frames"][iconFrame] = nil
+
+ local icon = iconFrame:CreateTexture(nil, "ARTWORK")
+ icon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(icon)
+ frame.icon = icon
+
+ local count = iconFrame:CreateFontString(nil, "OVERLAY")
+ count:SetJustifyH("RIGHT")
+ count:SetPoint("BOTTOMRIGHT", iconFrame, -2, 2)
+ E:FontTemplate(count, nil, nil, "OUTLINE")
+ count:SetText(1)
+ frame.count = count
+
+ local name = frame:CreateFontString(nil, "OVERLAY")
+ name:SetJustifyH("LEFT")
+ name:SetPoint("LEFT", frame)
+ name:SetPoint("RIGHT", icon, "LEFT")
+ name:SetNonSpaceWrap(true)
+ E:FontTemplate(name, nil, nil, "OUTLINE")
+ frame.name = name
+
+ local drop = frame:CreateTexture(nil, "ARTWORK")
+ drop:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight")
+ drop:SetPoint("LEFT", icon, "RIGHT", 0, 0)
+ drop:SetPoint("RIGHT", frame)
+ drop:SetAllPoints(frame)
+ drop:SetAlpha(.3)
+ frame.drop = drop
+
+ lootFrame.slots[id] = frame
+ return frame
+end
+
+function M:LOOT_SLOT_CLEARED()
+ if not lootFrame:IsShown() then return end
+
+ lootFrame.slots[arg1]:Hide()
+ anchorSlots(lootFrame)
+end
+
+function M:LOOT_CLOSED()
+ StaticPopup_Hide("LOOT_BIND")
+ lootFrame:Hide()
+
+ for _, v in pairs(lootFrame.slots) do
+ v:Hide()
+ end
+end
+
+function M:OPEN_MASTER_LOOT_LIST()
+ ToggleDropDownMenu(1, nil, GroupLootDropDown, lootFrame.slots[ss], 0, 0)
+end
+
+function M:UPDATE_MASTER_LOOT_LIST()
+ UIDropDownMenu_Refresh(GroupLootDropDown)
+end
+
+function M:LOOT_OPENED(_, autoLoot)
+ lootFrame:Show()
+
+ if(not lootFrame:IsShown()) then
+ CloseLoot(autoLoot == 0)
+ end
+
+ local items = GetNumLootItems()
+
+ if(IsFishingLoot()) then
+ lootFrame.title:SetText(L["Fishy Loot"])
+ elseif(not UnitIsFriend("player", "target") and UnitIsDead("target")) then
+ lootFrame.title:SetText(UnitName("target"))
+ else
+ lootFrame.title:SetText(LOOT)
+ end
+
+ -- Blizzard uses strings here
+ if E.private.general.lootUnderMouse then
+ local x, y = GetCursorPosition()
+ x = x / lootFrame:GetEffectiveScale()
+ y = y / lootFrame:GetEffectiveScale()
+
+ lootFrame:ClearAllPoints()
+ lootFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x - 40, y + 20)
+ lootFrame:GetCenter()
+ lootFrame:Raise()
+ else
+ lootFrame:ClearAllPoints()
+ lootFrame:SetPoint("TOPLEFT", lootFrameHolder, "TOPLEFT")
+ end
+
+ local m, w, t = 0, 0, lootFrame.title:GetStringWidth()
+ if(items > 0) then
+ for i = 1, items do
+ local slot = lootFrame.slots[i] or createSlot(i)
+ local texture, item, quantity, quality = GetLootSlotInfo(i)
+ local color = ITEM_QUALITY_COLORS[quality]
+
+ if(LootSlotIsCoin(i)) then
+ item = item:gsub("\n", ", ")
+ end
+
+ if quantity and (quantity > 1) then
+ slot.count:SetText(quantity)
+ slot.count:Show()
+ else
+ slot.count:Hide()
+ end
+
+ if quality and (quality > 1) then
+ slot.drop:SetVertexColor(color.r, color.g, color.b)
+ slot.drop:Show()
+ else
+ slot.drop:Hide()
+ end
+
+ slot.quality = quality
+ slot.name:SetText(item)
+ if color then
+ slot.name:SetTextColor(color.r, color.g, color.b)
+ end
+ slot.icon:SetTexture(texture)
+
+ if quality then
+ m = max(m, quality)
+ end
+ w = max(w, slot.name:GetStringWidth())
+
+ slot:SetID(i)
+ slot:SetSlot(i)
+
+ slot:Enable()
+ slot:Show()
+ end
+ else
+ local slot = lootFrame.slots[1] or createSlot(1)
+ local color = ITEM_QUALITY_COLORS[0]
+
+ slot.name:SetText(L["Empty Slot"])
+ if color then
+ slot.name:SetTextColor(color.r, color.g, color.b)
+ end
+ slot.icon:SetTexture[[Interface\Icons\INV_Misc_Herb_AncientLichen]]
+
+ items = 1
+ w = max(w, slot.name:GetStringWidth())
+
+ slot.count:Hide()
+ slot.drop:Hide()
+ slot:Disable()
+ slot:Show()
+ end
+ anchorSlots(lootFrame)
+
+ w = w + 60
+ t = t + 5
+
+ local color = ITEM_QUALITY_COLORS[m]
+ lootFrame:SetBackdropBorderColor(color.r, color.g, color.b, .8)
+ lootFrame:SetWidth(max(w, t))
+end
+
+function M:LoadLoot()
+ if not E.private.general.loot then return end
+
+ lootFrameHolder = CreateFrame("Frame", "ElvLootFrameHolder", E.UIParent)
+ lootFrameHolder:SetPoint("TOPLEFT", 36, -195)
+ lootFrameHolder:SetWidth(150)
+ lootFrameHolder:SetHeight(22)
+
+ lootFrame = CreateFrame("Button", "ElvLootFrame", lootFrameHolder)
+ lootFrame:SetClampedToScreen(true)
+ lootFrame:SetPoint("TOPLEFT", 0, 0)
+ lootFrame:SetWidth(256)
+ lootFrame:SetHeight(64)
+ E:SetTemplate(lootFrame, "Transparent")
+ lootFrame:SetFrameStrata("FULLSCREEN")
+ lootFrame:SetToplevel(true)
+ lootFrame.title = lootFrame:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(lootFrame.title, nil, nil, "OUTLINE")
+ lootFrame.title:SetPoint("BOTTOMLEFT", lootFrame, "TOPLEFT", 0, 1)
+ lootFrame.slots = {}
+ lootFrame:SetScript("OnHide", function()
+ StaticPopup_Hide("CONFIRM_LOOT_DISTRIBUTION")
+ CloseLoot()
+ end)
+ E["frames"][lootFrame] = nil
+
+ self:RegisterEvent("LOOT_OPENED")
+ self:RegisterEvent("LOOT_SLOT_CLEARED")
+ self:RegisterEvent("LOOT_CLOSED")
+ self:RegisterEvent("OPEN_MASTER_LOOT_LIST")
+ self:RegisterEvent("UPDATE_MASTER_LOOT_LIST")
+
+ E:CreateMover(lootFrameHolder, "LootFrameMover", L["Loot Frame"])
+
+ -- Fuzz
+ LootFrame:UnregisterAllEvents()
+ ElvLootFrame:Hide() -- May need another fix. Frame shows without.
+ tinsert(UISpecialFrames, "ElvLootFrame")
+
+ function _G.GroupLootDropDown_GiveLoot()
+ if(sq >= MASTER_LOOT_THREHOLD) then
+ local dialog = StaticPopup_Show("CONFIRM_LOOT_DISTRIBUTION", ITEM_QUALITY_COLORS[sq].hex..sn..FONT_COLOR_CODE_CLOSE, this:GetText())
+ if (dialog) then
+ dialog.data = this.value
+ end
+ else
+ GiveMasterLoot(ss, this.value)
+ end
+ CloseDropDownMenus()
+ end
+
+ E.PopupDialogs["CONFIRM_LOOT_DISTRIBUTION"].OnAccept = function(data)
+ GiveMasterLoot(ss, data)
+ end
+ StaticPopupDialogs["CONFIRM_LOOT_DISTRIBUTION"].preferredIndex = 3
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/LootRoll.lua b/ElvUI/Modules/Misc/LootRoll.lua
new file mode 100644
index 0000000..3f4954c
--- /dev/null
+++ b/ElvUI/Modules/Misc/LootRoll.lua
@@ -0,0 +1,323 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:GetModule("Misc");
+
+--Cache global variables
+--Lua functions
+local find = string.find
+local pairs, unpack, ipairs, next, tonumber = pairs, unpack, ipairs, next, tonumber
+local tinsert = table.insert
+--WoW API / Variables
+local CursorOnUpdate = CursorOnUpdate
+local DressUpItemLink = DressUpItemLink
+local GetLootRollItemInfo = GetLootRollItemInfo
+local GetLootRollItemLink = GetLootRollItemLink
+local GetLootRollTimeLeft = GetLootRollTimeLeft
+local IsModifiedClick = IsModifiedClick
+local IsShiftKeyDown = IsShiftKeyDown
+local ResetCursor = ResetCursor
+local RollOnLoot = RollOnLoot
+local ShowInspectCursor = ShowInspectCursor
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+
+local pos = "TOP"
+local cancelled_rolls = {}
+local FRAME_WIDTH, FRAME_HEIGHT = 328, 28
+M.RollBars = {}
+
+local locale = GetLocale()
+local rollpairs = locale == "deDE" and {
+ ["(.*) würfelt nicht für: (.+|r)$"] = "pass",
+ ["(.*) hat für (.+) 'Gier' ausgewählt"] = "greed",
+ ["(.*) hat für (.+) 'Bedarf' ausgewählt"] = "need",
+} or locale == "frFR" and {
+ ["(.*) a passé pour : (.+)"] = "pass",
+ ["(.*) a choisi Cupidité pour : (.+)"] = "greed",
+ ["(.*) a choisi Besoin pour : (.+)"] = "need",
+} or locale == "zhTW" and {
+ ["(.*)放棄了:(.+)"] = "pass",
+ ["(.*)選擇了貪婪:(.+)"] = "greed",
+ ["(.*)選擇了需求:(.+)"] = "need",
+} or locale == "ruRU" and {
+ ["(.*) отказывается от предмета (.+)%."] = "pass",
+ ["Разыгрывается: (.+)%. (.*): \"Не откажусь\""] = "greed",
+ ["Разыгрывается: (.+)%. (.*): \"Мне это нужно\""] = "need",
+} or locale == "koKR" and {
+ ["(.*)님이 주사위 굴리기를 포기했습니다: (.+)"] = "pass",
+ ["(.*)님이 차비를 선택했습니다: (.+)"] = "greed",
+ ["(.*)님이 입찰을 선택했습니다: (.+)"] = "need",
+} or locale == "esES" and {
+ ["^(.*) pasó de: (.+|r)$"] = "pass",
+ ["(.*) eligió Codicia para: (.+)"] = "greed",
+ ["(.*) eligió Necesidad para: (.+)"] = "need",
+} or locale == "esMX" and {
+ ["^(.*) pasó de: (.+|r)$"] = "pass",
+ ["(.*) eligió Codicia para: (.+)"] = "greed",
+ ["(.*) eligió Necesidad para: (.+)"] = "need",
+} or {
+ ["^(.*) passed on: (.+|r)$"] = "pass",
+ ["(.*) has selected Greed for: (.+)"] = "greed",
+ ["(.*) has selected Need for: (.+)"] = "need",
+}
+
+local function ClickRoll(frame)
+ RollOnLoot(frame.parent.rollID, frame.rolltype)
+end
+
+local function HideTip() GameTooltip:Hide() end
+local function HideTip2() GameTooltip:Hide() ResetCursor() end
+
+local rolltypes = {"need", "greed", [0] = "pass"}
+local function SetTip(frame)
+ GameTooltip:SetOwner(frame, "ANCHOR_RIGHT")
+ GameTooltip:SetText(frame.tiptext)
+ if(frame:IsEnabled() == 0) then
+ GameTooltip:AddLine("|cffff3333"..L["Can't Roll"])
+ end
+
+ for name, tbl in pairs(frame.parent.rolls) do
+ if(tbl[1] == rolltypes[frame.rolltype] and tbl[2]) then
+ local classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[tbl[2]] or RAID_CLASS_COLORS[tbl[2]]
+ GameTooltip:AddLine(name, classColor.r, classColor.g, classColor.b)
+ end
+ end
+ GameTooltip:Show()
+end
+
+local function SetItemTip(frame)
+ if(not frame.link) then return end
+ GameTooltip:SetOwner(frame, "ANCHOR_TOPLEFT")
+ GameTooltip:SetHyperlink(frame.link)
+ if(IsShiftKeyDown()) then
+ GameTooltip_ShowCompareItem()
+ end
+ if(IsModifiedClick("DRESSUP")) then
+ ShowInspectCursor()
+ else
+ ResetCursor()
+ end
+end
+
+local function ItemOnUpdate(self)
+ if(IsShiftKeyDown()) then
+ GameTooltip_ShowCompareItem()
+ end
+ CursorOnUpdate(self)
+end
+
+local function LootClick(frame)
+ if(IsControlKeyDown()) then
+ DressUpItemLink(frame.link)
+ elseif(IsShiftKeyDown()) then
+ ChatEdit_InsertLink(frame.link)
+ end
+end
+
+local function OnEvent(frame, _, rollID)
+ cancelled_rolls[rollID] = true
+ if(frame.rollID ~= rollID) then return end
+
+ frame.rollID = nil
+ frame.time = nil
+ frame:Hide()
+end
+
+local function StatusUpdate(frame)
+ if(not frame.parent.rollID) then return end
+ local t = GetLootRollTimeLeft(frame.parent.rollID)
+ local perc = t / frame.parent.time
+ frame.spark:Point("CENTER", frame, "LEFT", perc * frame:GetWidth(), 0)
+ frame:SetValue(t)
+
+ if(t > 1000000000) then
+ frame:GetParent():Hide()
+ end
+end
+
+local function CreateRollButton(parent, ntex, ptex, htex, rolltype, tiptext)
+ local f = CreateFrame("Button", nil, parent)
+ E:Point(f, unpack(args))
+ f:Size(FRAME_HEIGHT - 4)
+ f:SetNormalTexture(ntex)
+ if(ptex) then f:SetPushedTexture(ptex) end
+ f:SetHighlightTexture(htex)
+ f.rolltype = rolltype
+ f.parent = parent
+ f.tiptext = tiptext
+ f:SetScript("OnEnter", SetTip)
+ f:SetScript("OnLeave", HideTip)
+ f:SetScript("OnClick", ClickRoll)
+ local txt = f:CreateFontString(nil, nil)
+ txt:FontTemplate(nil, nil, "OUTLINE")
+ txt:Point("CENTER", 0, rolltype == 2 and 1 or rolltype == 0 and -1.2 or 0)
+ return f, txt
+end
+
+function M:CreateRollFrame()
+ local frame = CreateFrame("Frame", nil, E.UIParent)
+ frame:Size(FRAME_WIDTH, FRAME_HEIGHT)
+ frame:SetTemplate("Default")
+ frame:SetScript("OnEvent", OnEvent)
+ frame:RegisterEvent("CANCEL_LOOT_ROLL")
+ frame:Hide()
+
+ local button = CreateFrame("Button", nil, frame)
+ button:Point("RIGHT", frame, "LEFT", -(E.Spacing*3), 0)
+ button:Size(FRAME_HEIGHT - (E.Border * 2))
+ button:CreateBackdrop("Default")
+ button:SetScript("OnEnter", SetItemTip)
+ button:SetScript("OnLeave", HideTip2)
+ button:SetScript("OnUpdate", ItemOnUpdate)
+ button:SetScript("OnClick", LootClick)
+ frame.button = button
+
+ button.icon = button:CreateTexture(nil, "OVERLAY")
+ button.icon:SetAllPoints()
+ button.icon:SetTexCoord(unpack(E.TexCoords))
+
+ local tfade = frame:CreateTexture(nil, "BORDER")
+ tfade:Point("TOPLEFT", frame, "TOPLEFT", 4, 0)
+ tfade:Point("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -4, 0)
+ tfade:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
+ tfade:SetBlendMode("ADD")
+ tfade:SetGradientAlpha("VERTICAL", .1, .1, .1, 0, .1, .1, .1, 0)
+
+ local status = CreateFrame("StatusBar", nil, frame)
+ status:SetInside()
+ status:SetScript("OnUpdate", StatusUpdate)
+ status:SetFrameLevel(status:GetFrameLevel() - 1)
+ status:SetStatusBarTexture(E["media"].normTex)
+ E:RegisterStatusBar(status)
+ status:SetStatusBarColor(.8, .8, .8, .9)
+ status.parent = frame
+ frame.status = status
+
+ status.bg = status:CreateTexture(nil, "BACKGROUND")
+ status.bg:SetAlpha(0.1)
+ status.bg:SetAllPoints()
+ local spark = frame:CreateTexture(nil, "OVERLAY")
+ spark:Size(14, FRAME_HEIGHT)
+ spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
+ spark:SetBlendMode("ADD")
+ status.spark = spark
+
+ local need, needtext = CreateRollButton(frame, "Interface\\Buttons\\UI-GroupLoot-Dice-Up", "Interface\\Buttons\\UI-GroupLoot-Dice-Highlight", "Interface\\Buttons\\UI-GroupLoot-Dice-Down", 1, NEED, "LEFT", frame.button, "RIGHT", 5, -1)
+ local greed, greedtext = CreateRollButton(frame, "Interface\\Buttons\\UI-GroupLoot-Coin-Up", "Interface\\Buttons\\UI-GroupLoot-Coin-Highlight", "Interface\\Buttons\\UI-GroupLoot-Coin-Down", 2, GREED, "LEFT", need, "RIGHT", 0, -1)
+ local pass, passtext = CreateRollButton(frame, "Interface\\AddOns\\ElvUI\\media\\textures\\UI-GroupLoot-Pass-Up", nil, "Interface\\AddOns\\ElvUI\\media\\textures\\UI-GroupLoot-Pass-Down", 0, PASS, "LEFT", greed, "RIGHT", 0, 2)
+ frame.needbutt, frame.greedbutt = need, greed
+ frame.need, frame.greed, frame.pass = needtext, greedtext, passtext
+
+ local bind = frame:CreateFontString()
+ bind:Point("LEFT", pass, "RIGHT", 3, 1)
+ bind:FontTemplate(nil, nil, "OUTLINE")
+ frame.fsbind = bind
+
+ local loot = frame:CreateFontString(nil, "ARTWORK")
+ loot:FontTemplate(nil, nil, "OUTLINE")
+ loot:Point("LEFT", bind, "RIGHT", 0, 0)
+ loot:Point("RIGHT", frame, "RIGHT", -5, 0)
+ loot:Size(200, 10)
+ loot:SetJustifyH("LEFT")
+ frame.fsloot = loot
+
+ frame.rolls = {}
+
+ return frame
+end
+
+local function GetFrame()
+ for _, f in ipairs(M.RollBars) do
+ if(not f.rollID) then
+ return f
+ end
+ end
+
+ local f = M:CreateRollFrame()
+ if(pos == "TOP") then
+ f:Point("TOP", next(M.RollBars) and M.RollBars[getn(M.RollBars)] or AlertFrameHolder, "BOTTOM", 0, -4)
+ else
+ f:Point("BOTTOM", next(M.RollBars) and M.RollBars[getn(M.RollBars)] or AlertFrameHolder, "TOP", 0, 4)
+ end
+
+ tinsert(M.RollBars, f)
+
+ return f
+end
+
+function M:START_LOOT_ROLL(_, rollID, time)
+ if(cancelled_rolls[rollID]) then return end
+
+ local f = GetFrame()
+ f.rollID = rollID
+ f.time = time
+ for i in pairs(f.rolls) do f.rolls[i] = nil end
+ f.need:SetText(0)
+ f.greed:SetText(0)
+ f.pass:SetText(0)
+
+ local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(rollID)
+ f.button.icon:SetTexture(texture)
+ f.button.link = GetLootRollItemLink(rollID)
+
+ f.needbutt:Enable()
+ f.greedbutt:Enable()
+ SetDesaturation(f.needbutt:GetNormalTexture())
+ SetDesaturation(f.greedbutt:GetNormalTexture())
+ f.needbutt:SetAlpha(1)
+ f.greedbutt:SetAlpha(1)
+
+ f.fsbind:SetText(bindOnPickUp and "BoP" or "BoE")
+ f.fsbind:SetVertexColor(bindOnPickUp and 1 or .3, bindOnPickUp and .3 or 1, bindOnPickUp and .1 or .3)
+
+ local color = ITEM_QUALITY_COLORS[quality]
+ f.fsloot:SetText(name)
+ f.status:SetStatusBarColor(color.r, color.g, color.b, .7)
+ f.status.bg:SetTexture(color.r, color.g, color.b)
+
+ f.status:SetMinMaxValues(0, time)
+ f.status:SetValue(time)
+
+ f:SetPoint("CENTER", WorldFrame, "CENTER")
+ f:Show()
+
+ if(E.db.general.autoRoll and UnitLevel("player") == MAX_PLAYER_LEVEL and quality == 2 and not bindOnPickUp) then
+ RollOnLoot(rollID, 2)
+ end
+end
+
+function M:ParseRollChoice(msg)
+ if not msg then return end
+ for i, v in pairs(rollpairs) do
+ local _, _, playername, itemname = find(msg, i)
+ if(locale == "ruRU" and (v == "greed" or v == "need")) then
+ local temp = playername
+ playername = itemname
+ itemname = temp
+ end
+ if(playername and itemname and playername ~= "Everyone") then return playername, itemname, v end
+ end
+end
+
+function M:CHAT_MSG_LOOT(_, msg)
+ local playername, itemname, rolltype = self:ParseRollChoice(msg)
+ if(playername and itemname and rolltype) then
+ local class = select(2, UnitClass(playername))
+ for _, f in ipairs(M.RollBars) do
+ if(f.rollID and f.button.link == itemname and not f.rolls[playername]) then
+ f.rolls[playername] = { rolltype, class }
+ f[rolltype]:SetText(tonumber(f[rolltype]:GetText()) + 1)
+ return
+ end
+ end
+ end
+end
+
+function M:LoadLootRoll()
+ if(not E.private.general.lootRoll) then return end
+
+ self:RegisterEvent("CHAT_MSG_LOOT")
+ self:RegisterEvent("START_LOOT_ROLL")
+ UIParent:UnregisterEvent("START_LOOT_ROLL")
+ UIParent:UnregisterEvent("CANCEL_LOOT_ROLL")
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/Misc.lua b/ElvUI/Modules/Misc/Misc.lua
new file mode 100644
index 0000000..2781ee8
--- /dev/null
+++ b/ElvUI/Modules/Misc/Misc.lua
@@ -0,0 +1,194 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:NewModule("Misc", "AceEvent-3.0", "AceTimer-3.0");
+E.Misc = M
+
+--Cache global variables
+--Lua functions
+local format, gsub = string.format, string.gsub
+--WoW API / Variables
+local CanMerchantRepair = CanMerchantRepair
+local GetFriendInfo = GetFriendInfo
+local GetGuildRosterInfo = GetGuildRosterInfo
+local GetNumFriends = GetNumFriends
+local GetNumGuildMembers = GetNumGuildMembers
+local GetNumPartyMembers = GetNumPartyMembers
+local GetNumRaidMembers = GetNumRaidMembers
+local GetPartyMember = GetPartyMember
+local GetRepairAllCost = GetRepairAllCost
+local GuildRoster = GuildRoster
+local IsInGuild = IsInGuild
+local IsInInstance = IsInInstance
+local IsShiftKeyDown = IsShiftKeyDown
+local RepairAllItems = RepairAllItems
+local UninviteUnit = UninviteUnit
+local UnitInRaid = UnitInRaid
+local UnitName = UnitName
+local UIErrorsFrame = UIErrorsFrame
+local MAX_PARTY_MEMBERS = MAX_PARTY_MEMBERS
+
+local interruptMsg = INTERRUPTED.." %s's \124cff71d5ff\124Hspell:%d\124h[%s]\124h\124r!"
+
+function M:ErrorFrameToggle(event)
+ if not E.db.general.hideErrorFrame then return end
+ if event == "PLAYER_REGEN_DISABLED" then
+ UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE")
+ else
+ UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE")
+ end
+end
+
+function M:COMBAT_LOG_EVENT_UNFILTERED(_, _, event, _, sourceName, _, _, destName, _, _, _, _, spellID, spellName)
+ if E.db.general.interruptAnnounce == "NONE" then return end
+ if not (event == "SPELL_INTERRUPT" and sourceName == UnitName("player")) then return end
+
+ local party = GetNumPartyMembers()
+
+ if E.db.general.interruptAnnounce == "SAY" then
+ if party > 0 then
+ SendChatMessage(format(interruptMsg, destName, spellID, spellName), "SAY")
+ end
+ elseif E.db.general.interruptAnnounce == "EMOTE" then
+ if party > 0 then
+ SendChatMessage(format(interruptMsg, destName, spellID, spellName), "EMOTE")
+ end
+ else
+ local raid = GetNumRaidMembers()
+ local _, instanceType = IsInInstance()
+ local battleground = instanceType == "pvp"
+
+ if E.db.general.interruptAnnounce == "PARTY" then
+ if party > 0 then
+ SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "PARTY")
+ end
+ elseif E.db.general.interruptAnnounce == "RAID" then
+ if raid > 0 then
+ SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "RAID")
+ elseif party > 0 then
+ SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "PARTY")
+ end
+ elseif E.db.general.interruptAnnounce == "RAID_ONLY" then
+ if raid > 0 then
+ SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "RAID")
+ end
+ end
+ end
+end
+
+function M:MERCHANT_SHOW()
+ if E.db.general.vendorGrays then
+ E:GetModule("Bags"):VendorGrays(nil, true)
+ end
+
+ local autoRepair = E.db.general.autoRepair
+ if IsShiftKeyDown() or autoRepair == "NONE" or not CanMerchantRepair() then return end
+
+ local cost, possible = GetRepairAllCost()
+ if cost > 0 then
+ if possible then
+ RepairAllItems(autoRepair == "PLAYER")
+ E:Print(L["Your items have been repaired for: "]..E:FormatMoney(cost, "BLIZZARD"))
+ else
+ E:Print(L["You don't have enough money to repair."])
+ end
+ end
+end
+
+function M:DisbandRaidGroup()
+ if UnitInRaid("player") then
+ for i = 1, GetNumRaidMembers() do
+ local name, _, _, _, _, _, _, online = GetRaidRosterInfo(i)
+ if online and name ~= E.myname then
+ UninviteUnit(name)
+ end
+ end
+ else
+ for i = MAX_PARTY_MEMBERS, 1, -1 do
+ if GetPartyMember(i) then
+ UninviteUnit(UnitName("party"..i))
+ end
+ end
+ end
+ LeaveParty()
+end
+
+function M:PVPMessageEnhancement(_, msg)
+ if not E.db.general.enhancedPvpMessages then return end
+ local _, instanceType = IsInInstance()
+ if instanceType == "pvp" or instanceType == "arena" then
+ RaidNotice_AddMessage(RaidBossEmoteFrame, msg, ChatTypeInfo["RAID_BOSS_EMOTE"])
+ end
+end
+
+local hideStatic = false
+function M:AutoInvite(event, leaderName)
+ if not E.db.general.autoAcceptInvite then return end
+
+ if event == "PARTY_INVITE_REQUEST" then
+ if GetNumPartyMembers() > 0 or GetNumRaidMembers() > 0 then return end
+ hideStatic = true
+
+ -- Update Guild and Friendlist
+ local numFriends = GetNumFriends()
+ if numFriends > 0 then ShowFriends() end
+ if IsInGuild() then GuildRoster() end
+ local inGroup = false
+
+ for friendIndex = 1, numFriends do
+ local friendName = gsub(GetFriendInfo(friendIndex), "-.*", "")
+ if friendName == leaderName then
+ AcceptGroup()
+ inGroup = true
+ break
+ end
+ end
+
+ if not inGroup then
+ for guildIndex = 1, GetNumGuildMembers(true) do
+ local guildMemberName = gsub(GetGuildRosterInfo(guildIndex), "-.*", "")
+ if guildMemberName == leaderName then
+ AcceptGroup()
+ inGroup = true
+ break
+ end
+ end
+ end
+
+ elseif event == "PARTY_MEMBERS_CHANGED" and hideStatic == true then
+ StaticPopup_Hide("PARTY_INVITE")
+ hideStatic = false
+ end
+end
+
+function M:ForceCVars()
+ if E.private.general.loot then
+ if E.private.general.lootUnderMouse then
+ E:DisableMover("LootFrameMover")
+ else
+ E:EnableMover("LootFrameMover")
+ end
+ end
+end
+
+function M:Initialize()
+ self:LoadRaidMarker()
+ self:LoadLoot()
+ self:LoadLootRoll()
+ self:LoadChatBubbles()
+ self:RegisterEvent("MERCHANT_SHOW")
+ self:RegisterEvent("PLAYER_REGEN_DISABLED", "ErrorFrameToggle")
+ self:RegisterEvent("PLAYER_REGEN_ENABLED", "ErrorFrameToggle")
+ -- self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
+ self:RegisterEvent("CHAT_MSG_BG_SYSTEM_HORDE", "PVPMessageEnhancement")
+ self:RegisterEvent("CHAT_MSG_BG_SYSTEM_ALLIANCE", "PVPMessageEnhancement")
+ self:RegisterEvent("CHAT_MSG_BG_SYSTEM_NEUTRAL", "PVPMessageEnhancement")
+ self:RegisterEvent("PARTY_INVITE_REQUEST", "AutoInvite")
+ self:RegisterEvent("PARTY_MEMBERS_CHANGED", "AutoInvite")
+ self:RegisterEvent("CVAR_UPDATE", "ForceCVars")
+ self:RegisterEvent("PLAYER_ENTERING_WORLD", "ForceCVars")
+end
+
+local function InitializeCallback()
+ M:Initialize()
+end
+
+E:RegisterModule(M:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Misc/RaidMarker.lua b/ElvUI/Modules/Misc/RaidMarker.lua
new file mode 100644
index 0000000..9e4ce23
--- /dev/null
+++ b/ElvUI/Modules/Misc/RaidMarker.lua
@@ -0,0 +1,107 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local M = E:GetModule("Misc");
+
+--Cache global variables
+--Lua functions
+local sin, cos, pi = math.sin, math.cos, math.pi
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local GetNumPartyMembers = GetNumPartyMembers
+local UnitInRaid = UnitInRaid
+local UnitIsPartyLeader = UnitIsPartyLeader
+local UnitExists, UnitIsDead = UnitExists, UnitIsDead
+local GetCursorPosition = GetCursorPosition
+local PlaySound = PlaySound
+local SetRaidTarget = SetRaidTarget
+local SetRaidTargetIconTexture = SetRaidTargetIconTexture
+local UIErrorsFrame = UIErrorsFrame
+
+local ButtonIsDown
+
+function M:RaidMarkCanMark()
+ if not self.RaidMarkFrame then return false end
+
+ if GetNumPartyMembers() > 0 then
+ if UnitIsPartyLeader("player") or UnitInRaid("player") and not UnitIsPartyLeader("player") then
+ return true
+ else
+ UIErrorsFrame:AddMessage(L["You don't have permission to mark targets."], 1.0, 0.1, 0.1, 1.0)
+ return false
+ end
+ else
+ return true
+ end
+end
+
+function M:RaidMarkShowIcons()
+ if not UnitExists("target") or UnitIsDead("target") then
+ return
+ end
+ local x, y = GetCursorPosition()
+ local scale = E.UIParent:GetEffectiveScale()
+ self.RaidMarkFrame:SetPoint("CENTER", E.UIParent, "BOTTOMLEFT", x / scale, y / scale)
+ self.RaidMarkFrame:Show()
+end
+
+function RaidMark_HotkeyPressed(keystate)
+ ButtonIsDown = keystate == "down" and M:RaidMarkCanMark()
+ if ButtonIsDown and M.RaidMarkFrame then
+ M:RaidMarkShowIcons()
+ elseif M.RaidMarkFrame then
+ M.RaidMarkFrame:Hide()
+ end
+end
+
+function M:RaidMark_OnEvent()
+ if ButtonIsDown and self.RaidMarkFrame then
+ self:RaidMarkShowIcons()
+ end
+end
+M:RegisterEvent("PLAYER_TARGET_CHANGED", "RaidMark_OnEvent")
+
+function M:RaidMarkButton_OnEnter()
+ this.Texture:ClearAllPoints()
+ this.Texture:SetPoint("TOPLEFT", -10, 10)
+ this.Texture:SetPoint("BOTTOMRIGHT", 10, -10)
+end
+
+function M:RaidMarkButton_OnLeave()
+ this.Texture:SetAllPoints()
+end
+
+function M:RaidMarkButton_OnClick(button)
+ PlaySound("UChatScrollButton")
+ SetRaidTarget("target", button ~= "RightButton" and this:GetID() or 0)
+ this:GetParent():Hide()
+end
+
+function M:LoadRaidMarker()
+ local marker = CreateFrame("Frame", nil, E.UIParent)
+ marker:EnableMouse(true)
+ marker:SetWidth(100)
+ marker:SetHeight(100)
+ marker:SetFrameStrata("DIALOG")
+
+ for i = 1, 8 do
+ local button = CreateFrame("Button", "RaidMarkIconButton" .. i, marker)
+ button:SetWidth(40)
+ button:SetHeight(40)
+ button:SetID(i)
+ button.Texture = button:CreateTexture(button:GetName() .. "NormalTexture", "ARTWORK")
+ button.Texture:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
+ button.Texture:SetAllPoints()
+ SetRaidTargetIconTexture(button.Texture, i)
+ button:RegisterForClicks("LeftbuttonUp","RightbuttonUp")
+ button:SetScript("OnClick", M.RaidMarkButton_OnClick)
+ button:SetScript("OnEnter", M.RaidMarkButton_OnEnter)
+ button:SetScript("OnLeave", M.RaidMarkButton_OnLeave)
+ if i == 8 then
+ button:SetPoint("CENTER", 0, 0)
+ else
+ local angle = pi / 0.7 * i
+ button:SetPoint("CENTER", sin(angle) * 60, cos(angle) * 60)
+ end
+ end
+
+ M.RaidMarkFrame = marker
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/Auras.lua b/ElvUI/Modules/NamePlates/Elements/Auras.lua
new file mode 100644
index 0000000..4babc16
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/Auras.lua
@@ -0,0 +1,544 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+local LSM = LibStub("LibSharedMedia-3.0")
+
+local select, unpack, pairs = select, unpack, pairs
+local tonumber = tonumber
+local band = bit.band
+local gsub = string.gsub
+local tinsert, tremove, wipe = table.insert, table.remove, table.wipe
+
+local CreateFrame = CreateFrame
+local UnitAura = UnitAura
+local UnitGUID = UnitGUID
+local GetSpellTexture = GetSpellTexture
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local AURA_TYPE_BUFF = AURA_TYPE_BUFF
+local AURA_TYPE_DEBUFF = AURA_TYPE_DEBUFF
+
+local RaidIconBit = {
+ ["STAR"] = "0x00100000",
+ ["CIRCLE"] = "0x00200000",
+ ["DIAMOND"] = "0x00400000",
+ ["TRIANGLE"] = "0x00800000",
+ ["MOON"] = "0x01000000",
+ ["SQUARE"] = "0x02000000",
+ ["CROSS"] = "0x04000000",
+ ["SKULL"] = "0x08000000"
+}
+
+local RaidIconIndex = {
+ "STAR",
+ "CIRCLE",
+ "DIAMOND",
+ "TRIANGLE",
+ "MOON",
+ "SQUARE",
+ "CROSS",
+ "SKULL"
+}
+
+local ByRaidIcon = {}
+local ByName = {}
+
+local auraCache = {}
+local buffCache = {}
+local debuffCache = {}
+
+local auraList = {}
+local auraSpellID = {}
+local auraName = {}
+local auraExpiration = {}
+local auraStacks = {}
+local auraCaster = {}
+local auraDuration = {}
+local auraTexture = {}
+local auraType = {}
+local cachedAuraDurations = {}
+
+local TimeColors = {
+ [0] = "|cffeeeeee",
+ [1] = "|cffeeeeee",
+ [2] = "|cffeeeeee",
+ [3] = "|cffFFEE00",
+ [4] = "|cfffe0000"
+}
+
+local AURA_UPDATE_INTERVAL = 0.1
+
+local PolledHideIn
+do
+ local Framelist = {}
+ local Watcherframe = CreateFrame("Frame")
+ local WatcherframeActive = false
+ local timeToUpdate = 0
+
+ local function CheckFramelist()
+ local curTime = GetTime()
+ if curTime < timeToUpdate then return end
+ local framecount = 0
+ timeToUpdate = curTime + AURA_UPDATE_INTERVAL
+
+ for frame, expiration in pairs(Framelist) do
+ if expiration < curTime then
+ frame:Hide()
+ Framelist[frame] = nil
+ else
+ if frame.Poll then frame:Poll(expiration) end
+ framecount = framecount + 1
+ end
+ end
+ if framecount == 0 then Watcherframe:SetScript("OnUpdate", nil); WatcherframeActive = false end
+ end
+
+ function PolledHideIn(frame, expiration)
+ if expiration == 0 then
+ frame:Hide()
+ Framelist[frame] = nil
+ else
+ Framelist[frame] = expiration
+ frame:Show()
+
+ if not WatcherframeActive then
+ Watcherframe:SetScript("OnUpdate", CheckFramelist)
+ WatcherframeActive = true
+ end
+ end
+ end
+end
+
+local function GetSpellDuration(spellID)
+ if spellID then return cachedAuraDurations[spellID] end
+end
+
+local function SetSpellDuration(spellID, duration)
+ if spellID then cachedAuraDurations[spellID] = duration end
+end
+
+local function UpdateAuraTime(frame, expiration)
+ local timeleft = expiration - GetTime()
+ local timervalue, formatid = E:GetTimeInfo(timeleft, 4)
+ local timeFormat = E.TimeFormats[3][2]
+ if timervalue < 4 then
+ timeFormat = E.TimeFormats[4][2]
+ end
+ frame.timeLeft:SetFormattedText(("%s%s|r"):format(TimeColors[formatid], timeFormat), timervalue)
+end
+
+local function RemoveAuraInstance(guid, spellID, caster)
+ if guid and spellID and auraList[guid] then
+ local instanceID = tostring(guid)..tostring(spellID)..(tostring(caster or "UNKNOWN_CASTER"))
+ local auraID = spellID..(tostring(caster or "UNKNOWN_CASTER"))
+ if auraList[guid][auraID] then
+ auraSpellID[instanceID] = nil
+ auraName[instanceID] = nil
+ auraExpiration[instanceID] = nil
+ auraStacks[instanceID] = nil
+ auraCaster[instanceID] = nil
+ auraDuration[instanceID] = nil
+ auraTexture[instanceID] = nil
+ auraType[instanceID] = nil
+ auraList[guid][auraID] = nil
+ end
+ end
+end
+
+local function GetAuraList(guid)
+ if guid and auraList[guid] then return auraList[guid] end
+end
+
+local function GetAuraInstance(guid, auraID)
+ if guid and auraID then
+ local instanceID = guid..auraID
+ local spellID, name, expiration, stacks, caster, duration, texture, type
+ spellID = auraSpellID[instanceID]
+ name = auraName[instanceID]
+ expiration = auraExpiration[instanceID]
+ stacks = auraStacks[instanceID]
+ caster = auraCaster[instanceID]
+ duration = auraDuration[instanceID]
+ texture = auraTexture[instanceID]
+ type = auraType[instanceID]
+ return spellID, name, expiration, stacks, caster, duration, texture, type
+ end
+end
+
+local function SetAuraInstance(guid, name, spellID, expiration, stacks, caster, duration, texture, type)
+ if guid and spellID and caster and texture then
+ local auraID = spellID..(tostring(caster or "UNKNOWN_CASTER"))
+ local instanceID = guid..auraID
+ auraList[guid] = auraList[guid] or {}
+ auraList[guid][auraID] = instanceID
+ auraSpellID[instanceID] = spellID
+ auraName[instanceID] = name
+ auraExpiration[instanceID] = expiration
+ auraStacks[instanceID] = stacks
+ auraCaster[instanceID] = caster
+ auraDuration[instanceID] = duration
+ auraTexture[instanceID] = texture
+ auraType[instanceID] = type
+ end
+end
+
+local function WipeAuraList(guid)
+ if guid and auraList[guid] then
+ local unitAuraList = auraList[guid]
+ for auraID, instanceID in pairs(unitAuraList) do
+ auraSpellID[instanceID] = nil
+ auraName[instanceID] = nil
+ auraExpiration[instanceID] = nil
+ auraStacks[instanceID] = nil
+ auraCaster[instanceID] = nil
+ auraDuration[instanceID] = nil
+ auraTexture[instanceID] = nil
+ auraType[instanceID] = nil
+ unitAuraList[auraID] = nil
+ end
+ end
+end
+
+function mod:CleanAuraLists()
+ local currentTime = GetTime()
+ for guid, instanceList in pairs(auraList) do
+ local auraCount = 0
+ for auraID, instanceID in pairs(instanceList) do
+ local expiration = auraExpiration[instanceID]
+ if expiration and expiration < currentTime then
+ auraList[guid][auraID] = nil
+ auraSpellID[instanceID] = nil
+ auraName[instanceID] = nil
+ auraExpiration[instanceID] = nil
+ auraStacks[instanceID] = nil
+ auraCaster[instanceID] = nil
+ auraDuration[instanceID] = nil
+ auraTexture[instanceID] = nil
+ auraType[instanceID] = nil
+ else
+ auraCount = auraCount + 1
+ end
+ end
+ if auraCount == 0 then
+ auraList[guid] = nil
+ end
+ end
+end
+
+function mod:SetAura(aura, icon, count, expirationTime)
+ aura.icon:SetTexture(icon)
+ if count > 1 then
+ aura.count:SetText(count)
+ else
+ aura.count:SetText("")
+ end
+ aura:Show()
+ PolledHideIn(aura, expirationTime)
+end
+
+function mod:HideAuraIcons(auras)
+ for i = 1, getn(auras.icons) do
+ PolledHideIn(auras.icons[i], 0)
+ end
+end
+
+local currentAura = {}
+function mod:UpdateElement_Auras(frame)
+ if not frame.HealthBar:IsShown() then return end
+
+ local guid = frame.guid
+
+ if not guid then
+ if RAID_CLASS_COLORS[frame.UnitClass] then
+ local name = gsub(frame.oldName:GetText(), "%s%(%*%)","")
+ guid = ByName[name]
+ elseif frame.RaidIcon:IsShown() then
+ guid = ByRaidIcon[frame.RaidIconType]
+ end
+
+ if guid then
+ frame.guid = guid
+ else
+ return
+ end
+ end
+
+ local hasDebuffs = false
+ local hasBuffs = false
+
+ local numDebuff = 0
+ local numBuff = 0
+
+ local aurasOnUnit = GetAuraList(guid)
+
+ debuffCache = wipe(debuffCache)
+ buffCache = wipe(buffCache)
+
+ if aurasOnUnit then
+ local numAuras = 0
+ local aura
+
+ for instanceid in pairs(aurasOnUnit) do
+ numAuras = (numDebuff + numBuff) + 1
+ aura = wipe(currentAura[numAuras] or {})
+
+ aura.spellID, aura.name, aura.expirationTime, aura.count, aura.caster, aura.duration, aura.icon, aura.type = GetAuraInstance(guid, instanceid)
+
+ local filter = false
+ local db = self.db.units[frame.UnitType].buffs.filters
+ if aura.type == AURA_TYPE_DEBUFF then
+ db = self.db.units[frame.UnitType].debuffs.filters
+ end
+
+ if db.personal and aura.caster == UnitGUID("player") then
+ filter = true
+ end
+
+ local trackFilter = E.global["unitframe"]["aurafilters"][db.filter]
+ if db.filter and trackFilter then
+ local spell = trackFilter.spells[tonumber(aura.spellID)] or trackFilter.spells[aura.name]
+ if trackFilter.type == "Whitelist" then
+ if spell and spell.enable then
+ filter = true
+ end
+ elseif trackFilter.type == "Blacklist" and spell and spell.enable then
+ filter = false
+ end
+ end
+
+ if filter ~= true then
+ numAuras = numAuras - 1
+ RemoveAuraInstance(guid, aura.spellID, aura.caster)
+ wipe(aura)
+ end
+
+ if tonumber(aura.spellID) then
+ aura.unit = frame.unit
+ if aura.expirationTime > GetTime() then
+ if aura.type == "BUFF" then
+ numBuff = numBuff + 1
+ buffCache[numBuff] = aura
+ else
+ numDebuff = numDebuff + 1
+ debuffCache[numDebuff] = aura
+ end
+ end
+ end
+ end
+
+ wipe(currentAura)
+ end
+
+ local frameNum = 1
+ local maxAuras = getn(frame.Debuffs.icons)
+ local maxDuration = self.db.units[frame.UnitType].debuffs.filters.maxDuration
+
+ self:HideAuraIcons(frame.Debuffs)
+ if numDebuff > 0 and self.db.units[frame.UnitType].debuffs.enable then
+ for index = 1, getn(debuffCache) do
+ if frameNum > maxAuras then break end
+ local debuff = debuffCache[index]
+ if debuff.spellID and debuff.expirationTime and debuff.duration <= maxDuration then
+ self:SetAura(frame.Debuffs.icons[frameNum], debuff.icon, debuff.count, debuff.expirationTime)
+ frameNum = frameNum + 1
+ hasDebuffs = true
+ end
+ end
+ end
+
+ frameNum = 1
+ maxAuras = getn(frame.Buffs.icons)
+ maxDuration = self.db.units[frame.UnitType].buffs.filters.maxDuration
+
+ self:HideAuraIcons(frame.Buffs)
+ if numBuff > 0 and self.db.units[frame.UnitType].buffs.enable then
+ for index = 1, getn(buffCache) do
+ if frameNum > maxAuras then break end
+ local buff = buffCache[index]
+ if buff.spellID and buff.expirationTime and buff.duration <= maxDuration then
+ self:SetAura(frame.Buffs.icons[frameNum], buff.icon, buff.count, buff.expirationTime)
+ frameNum = frameNum + 1
+ hasBuffs = true
+ end
+ end
+ end
+
+ debuffCache = wipe(debuffCache)
+ buffCache = wipe(buffCache)
+
+ local TopLevel = frame.HealthBar
+ local TopOffset = ((self.db.units[frame.UnitType].showName and select(2, frame.Name:GetFont()) + 5) or 0)
+ if hasDebuffs then
+ TopOffset = TopOffset + 3
+ frame.Debuffs:SetPoint("BOTTOMLEFT", TopLevel, "TOPLEFT", 0, TopOffset)
+ frame.Debuffs:SetPoint("BOTTOMRIGHT", TopLevel, "TOPRIGHT", 0, TopOffset)
+ TopLevel = frame.Debuffs
+ TopOffset = 3
+ end
+
+ if hasBuffs then
+ if not hasDebuffs then
+ TopOffset = TopOffset + 3
+ end
+ frame.Buffs:SetPoint("BOTTOMLEFT", TopLevel, "TOPLEFT", 0, TopOffset)
+ frame.Buffs:SetPoint("BOTTOMRIGHT", TopLevel, "TOPRIGHT", 0, TopOffset)
+ TopLevel = frame.Buffs
+ TopOffset = 3
+ end
+
+ if frame.TopLevelFrame ~= TopLevel then
+ frame.TopLevelFrame = TopLevel
+ frame.TopOffset = TopOffset
+ end
+end
+
+function mod:UpdateElement_AurasByUnitID(unit)
+ --[[local guid = UnitGUID(unit)
+ WipeAuraList(guid)
+
+ local index = 1
+ local name, _, texture, count, _, duration, expirationTime, unitCaster, _, _, spellID = UnitAura(unit, index, "HARMFUL")
+ while name do
+ SetSpellDuration(spellID, duration)
+ SetAuraInstance(guid, name, spellID, expirationTime, count, UnitGUID(unitCaster or ""), duration, texture, AURA_TYPE_DEBUFF)
+ index = index + 1
+ name , _, texture, count, _, duration, expirationTime, unitCaster, _, _, spellID = UnitAura(unit, index, "HARMFUL")
+ end
+
+ index = 1
+ local name, _, texture, count, _, duration, expirationTime, unitCaster, _, _, spellID = UnitAura(unit, index, "HELPFUL")
+ while name do
+ SetSpellDuration(spellID, duration)
+ SetAuraInstance(guid, name, spellID, expirationTime, count, UnitGUID(unitCaster or ""), duration, texture, AURA_TYPE_BUFF)
+ index = index + 1
+ name, _, texture, count, _, duration, expirationTime, unitCaster, _, _, spellID = UnitAura(unit, index, "HELPFUL")
+ end
+
+ local raidIcon, name
+ if UnitPlayerControlled(unit) then name = UnitName(unit) end
+ raidIcon = RaidIconIndex[GetRaidTargetIndex(unit) or ""]
+ if raidIcon then ByRaidIcon[raidIcon] = guid end
+
+ local frame = self:SearchForFrame(guid, raidIcon, name)
+ if frame then
+ self:UpdateElement_Auras(frame)
+ end]]
+end
+
+function mod:COMBAT_LOG_EVENT_UNFILTERED(_, _, event, sourceGUID, _, _, destGUID, destName, destFlags, ...)
+ if destGUID == UnitGUID("target") then return end
+ --if band(destFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) ~= 0 then then return
+ if not (event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" or event == "SPELL_AURA_APPLIED_DOSE" or event == "SPELL_AURA_REMOVED_DOSE" or event == "SPELL_AURA_BROKEN" or event == "SPELL_AURA_BROKEN_SPELL" or event == "SPELL_AURA_REMOVED") then return end
+
+ --local spellID, spellName, _, auraType, stackCount = ...
+
+ if event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" then
+ local duration = GetSpellDuration(spellID)
+ local texture = GetSpellTexture(spellID)
+ SetAuraInstance(destGUID, spellName, spellID, GetTime() + (duration or 0), 1, sourceGUID, duration, texture, auraType)
+ elseif event == "SPELL_AURA_APPLIED_DOSE" or event == "SPELL_AURA_REMOVED_DOSE" then
+ local duration = GetSpellDuration(spellID)
+ local texture = GetSpellTexture(spellID)
+ SetAuraInstance(destGUID, spellName, spellID, GetTime() + (duration or 0), stackCount, sourceGUID, duration, texture, auraType)
+ elseif event == "SPELL_AURA_BROKEN" or event == "SPELL_AURA_BROKEN_SPELL" or event == "SPELL_AURA_REMOVED" then
+ RemoveAuraInstance(destGUID, spellID, sourceGUID)
+ end
+
+ local name, raidIcon
+ if band(destFlags, COMBATLOG_OBJECT_CONTROL_PLAYER) > 0 then
+ local rawName = strsplit("-", destName)
+ ByName[rawName] = destGUID
+ name = rawName
+ end
+
+ for iconName, bitmask in pairs(RaidIconBit) do
+ if band(destFlags, bitmask) > 0 then
+ ByRaidIcon[iconName] = destGUID
+ raidIcon = iconName
+
+ break
+ end
+ end
+
+ local frame = self:SearchForFrame(destGUID, raidIcon, name)
+ if frame then
+ self:UpdateElement_Auras(frame)
+ end
+end
+
+function mod:CreateAuraIcon(parent)
+ local aura = CreateFrame("Frame", nil, parent)
+ self:StyleFrame(aura, true)
+
+ aura.icon = aura:CreateTexture(nil, "OVERLAY")
+ aura.icon:SetAllPoints()
+ aura.icon:SetTexCoord(unpack(E.TexCoords))
+
+ aura.timeLeft = aura:CreateFontString(nil, "OVERLAY")
+ aura.timeLeft:SetPoint("TOPLEFT", 2, 2)
+ aura.timeLeft:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+
+ aura.count = aura:CreateFontString(nil, "OVERLAY")
+ aura.count:SetPoint("BOTTOMRIGHT", 0, 0)
+ aura.count:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+ aura.Poll = parent.PollFunction
+
+ return aura
+end
+
+function mod:Auras_SizeChanged(width)
+ local numAuras = getn(self.icons)
+ for i = 1, numAuras do
+ self.icons[i]:SetWidth(((width - numAuras) / numAuras) - (E.private.general.pixelPerfect and 0 or 3))
+ self.icons[i]:SetHeight((self.db.baseHeight or 18) * (self:GetParent().HealthBar.currentScale or 1))
+ end
+ self:SetHeight((self.db.baseHeight or 18) * (self:GetParent().HealthBar.currentScale or 1))
+end
+
+function mod:UpdateAuraIcons(auras)
+ local maxAuras = auras.db.numAuras
+ local numCurrentAuras = getn(auras.icons)
+ if(numCurrentAuras > maxAuras) then
+ for i = maxAuras, numCurrentAuras do
+ tinsert(auraCache, auras.icons[i])
+ auras.icons[i]:Hide()
+ auras.icons[i] = nil
+ end
+ end
+
+ if(numCurrentAuras ~= maxAuras) then
+ self.Auras_SizeChanged(auras, auras:GetWidth(), auras:GetHeight())
+ end
+
+ for i = 1, maxAuras do
+ auras.icons[i] = auras.icons[i] or tremove(auraCache) or mod:CreateAuraIcon(auras)
+ auras.icons[i]:SetParent(auras)
+ auras.icons[i]:ClearAllPoints()
+ auras.icons[i]:Hide()
+ auras.icons[i]:SetHeight(auras.db.baseHeight or 18)
+
+ if(auras.side == "LEFT") then
+ if(i == 1) then
+ auras.icons[i]:SetPoint("BOTTOMLEFT", auras, "BOTTOMLEFT")
+ else
+ auras.icons[i]:SetPoint("LEFT", auras.icons[i-1], "RIGHT", E.Border + E.Spacing*3, 0)
+ end
+ else
+ if(i == 1) then
+ auras.icons[i]:SetPoint("BOTTOMRIGHT", auras, "BOTTOMRIGHT")
+ else
+ auras.icons[i]:SetPoint("RIGHT", auras.icons[i-1], "LEFT", -(E.Border + E.Spacing*3), 0)
+ end
+ end
+ end
+end
+
+function mod:ConstructElement_Auras(frame, side)
+ local auras = CreateFrame("Frame", nil, frame)
+
+ auras:SetScript("OnSizeChanged", mod.Auras_SizeChanged)
+ auras:SetHeight(18)
+ auras.side = side
+ auras.PollFunction = UpdateAuraTime
+ auras.icons = {}
+
+ return auras
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/CastBar.lua b/ElvUI/Modules/NamePlates/Elements/CastBar.lua
new file mode 100644
index 0000000..ebbae30
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/CastBar.lua
@@ -0,0 +1,247 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+local LSM = LibStub("LibSharedMedia-3.0")
+
+local select, unpack = select, unpack
+
+local CreateFrame = CreateFrame
+local GetTime = GetTime
+local UnitCastingInfo = UnitCastingInfo
+local UnitChannelInfo = UnitChannelInfo
+local FAILED = FAILED
+local INTERRUPTED = INTERRUPTED
+
+function mod:UpdateElement_CastBarOnUpdate(elapsed)
+ if self.casting then
+ self.value = self.value + elapsed
+ if self.value >= self.maxValue then
+ self:SetValue(self.maxValue)
+ self:Hide()
+ return
+ end
+ self:SetValue(self.value)
+
+ if self.castTimeFormat == "CURRENT" then
+ self.Time:SetFormattedText("%.1f", self.value)
+ elseif self.castTimeFormat == "CURRENT_MAX" then
+ self.Time:SetFormattedText("%.1f / %.1f", self.value, self.maxValue)
+ else --REMAINING
+ self.Time:SetFormattedText("%.1f", (self.maxValue - self.value))
+ end
+
+ if self.Spark then
+ local sparkPosition = (self.value / self.maxValue) * self:GetWidth()
+ self.Spark:SetPoint("CENTER", self, "LEFT", sparkPosition, 0)
+ end
+ elseif self.channeling then
+ self.value = self.value - elapsed
+ if self.value <= 0 then
+ self:Hide()
+ return
+ end
+ self:SetValue(self.value)
+
+ if self.channelTimeFormat == "CURRENT" then
+ self.Time:SetFormattedText("%.1f", (self.maxValue - self.value))
+ elseif self.channelTimeFormat == "CURRENT_MAX" then
+ self.Time:SetFormattedText("%.1f / %.1f", (self.maxValue - self.value), self.maxValue)
+ else --REMAINING
+ self.Time:SetFormattedText("%.1f", self.value)
+ end
+ elseif self.holdTime > 0 then
+ self.holdTime = self.holdTime - elapsed
+ else
+ self:Hide()
+ end
+end
+
+function mod:UpdateElement_Cast(frame, event, unit, ...)
+ if self.db.units[frame.UnitType].castbar.enable ~= true then return end
+ if frame.unit ~= unit then return end
+
+ if event == "UNIT_SPELLCAST_START" then
+ local name, _, _, texture, startTime, endTime = UnitCastingInfo(unit)
+ if not name then
+ frame.CastBar:Hide()
+ return
+ end
+
+ if frame.CastBar.Spark then
+ frame.CastBar.Spark:Show()
+ end
+ frame.CastBar.Name:SetText(name)
+ frame.CastBar.value = (GetTime() - (startTime / 1000))
+ frame.CastBar.maxValue = (endTime - startTime) / 1000
+ frame.CastBar:SetMinMaxValues(0, frame.CastBar.maxValue)
+ frame.CastBar:SetValue(frame.CastBar.value)
+
+ if frame.CastBar.Icon then
+ frame.CastBar.Icon.texture:SetTexture(texture)
+ end
+
+ frame.CastBar.casting = true
+ frame.CastBar.channeling = nil
+ frame.CastBar.holdTime = 0
+
+ frame.CastBar:Show()
+ elseif event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_CHANNEL_STOP" then
+ if not frame.CastBar:IsVisible() then
+ frame.CastBar:Hide()
+ end
+ if (frame.CastBar.casting and event == "UNIT_SPELLCAST_STOP") or
+ (frame.CastBar.channeling and event == "UNIT_SPELLCAST_CHANNEL_STOP") then
+ if frame.CastBar.Spark then
+ frame.CastBar.Spark:Hide()
+ end
+
+ frame.CastBar:SetValue(frame.CastBar.maxValue)
+ if event == "UNIT_SPELLCAST_STOP" then
+ frame.CastBar.casting = nil
+ else
+ frame.CastBar.channeling = nil
+ end
+
+ frame.CastBar:Hide()
+ end
+ elseif event == "UNIT_SPELLCAST_FAILED" or event == "UNIT_SPELLCAST_INTERRUPTED" then
+ if frame.CastBar:IsShown() then
+ frame.CastBar:SetValue(frame.CastBar.maxValue)
+ if frame.CastBar.Spark then
+ frame.CastBar.Spark:Hide()
+ end
+
+ if event == "UNIT_SPELLCAST_FAILED" then
+ frame.CastBar.Name:SetText(FAILED)
+ else
+ frame.CastBar.Name:SetText(INTERRUPTED)
+ end
+ frame.CastBar.casting = nil
+ frame.CastBar.channeling = nil
+ frame.CastBar.holdTime = self.db.units[frame.UnitType].castbar.timeToHold --How long the castbar should stay visible after being interrupted, in seconds
+ end
+ elseif event == "UNIT_SPELLCAST_DELAYED" then
+ if frame:IsShown() then
+ local name, _, _, _, startTime, endTime = UnitCastingInfo(unit)
+ if not name then
+ -- if there is no name, there is no bar
+ frame.CastBar:Hide()
+ return
+ end
+
+ frame.CastBar.Name:SetText(name)
+ frame.CastBar.value = (GetTime() - (startTime / 1000))
+ frame.CastBar.maxValue = (endTime - startTime) / 1000
+ frame.CastBar:SetMinMaxValues(0, frame.CastBar.maxValue)
+
+ if not frame.CastBar.casting then
+ if frame.CastBar.Spark then
+ frame.CastBar.Spark:Show()
+ end
+
+ frame.CastBar.casting = true
+ frame.CastBar.channeling = nil
+ end
+ end
+ elseif event == "UNIT_SPELLCAST_CHANNEL_START" then
+ local name, _, _, texture, startTime, endTime = UnitChannelInfo(unit)
+ if not name then
+ frame.CastBar:Hide()
+ return
+ end
+
+ frame.CastBar.Name:SetText(name)
+ frame.CastBar.value = (endTime / 1000) - GetTime()
+ frame.CastBar.maxValue = (endTime - startTime) / 1000
+ frame.CastBar:SetMinMaxValues(0, frame.CastBar.maxValue)
+ frame.CastBar:SetValue(frame.CastBar.value)
+ frame.CastBar.holdTime = 0
+
+ if frame.CastBar.Icon then
+ frame.CastBar.Icon.texture:SetTexture(texture)
+ end
+ if frame.CastBar.Spark then
+ frame.CastBar.Spark:Hide()
+ end
+
+ frame.CastBar.casting = nil
+ frame.CastBar.channeling = true
+
+ frame.CastBar:Show()
+ elseif event == "UNIT_SPELLCAST_CHANNEL_UPDATE" then
+ if frame.CastBar:IsShown() then
+ local name, _, _, _, startTime, endTime = UnitChannelInfo(unit)
+ if not name then
+ frame.CastBar:Hide()
+ return
+ end
+
+ frame.CastBar.Name:SetText(name)
+ frame.CastBar.value = ((endTime / 1000) - GetTime())
+ frame.CastBar.maxValue = (endTime - startTime) / 1000
+ frame.CastBar:SetMinMaxValues(0, frame.CastBar.maxValue)
+ frame.CastBar:SetValue(frame.CastBar.value)
+ end
+ end
+end
+
+function mod:ConfigureElement_CastBar(frame)
+ local castBar = frame.CastBar
+
+ castBar:ClearAllPoints()
+ castBar:SetPoint("TOPLEFT", frame.HealthBar, "BOTTOMLEFT", 0, -self.db.units[frame.UnitType].castbar.offset)
+ castBar:SetPoint("TOPRIGHT", frame.HealthBar, "BOTTOMRIGHT", 0, -self.db.units[frame.UnitType].castbar.offset)
+ castBar:SetHeight(self.db.units[frame.UnitType].castbar.height)
+
+ castBar.Icon:SetPoint("TOPLEFT", frame.HealthBar, "TOPRIGHT", self.db.units[frame.UnitType].castbar.offset, 0);
+ castBar.Icon:SetPoint("BOTTOMLEFT", castBar, "BOTTOMRIGHT", self.db.units[frame.UnitType].castbar.offset, 0);
+ castBar.Icon:SetWidth(self.db.units[frame.UnitType].castbar.height + self.db.units[frame.UnitType].healthbar.height + self.db.units[frame.UnitType].castbar.offset)
+
+ castBar.Time:SetPoint("TOPRIGHT", castBar, "BOTTOMRIGHT", 0, -E.Border*3)
+ castBar.Name:SetPoint("TOPLEFT", castBar, "BOTTOMLEFT", 0, -E.Border*3)
+ castBar.Name:SetPoint("TOPRIGHT", castBar.Time, "TOPLEFT")
+
+ castBar.Name:SetJustifyH("LEFT")
+ castBar.Name:SetJustifyV("TOP")
+ castBar.Name:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+ castBar.Time:SetJustifyH("RIGHT")
+ castBar.Time:SetJustifyV("TOP")
+ castBar.Time:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+
+ if self.db.units[frame.UnitType].castbar.hideSpellName then
+ castBar.Name:Hide()
+ else
+ castBar.Name:Show()
+ end
+ if self.db.units[frame.UnitType].castbar.hideTime then
+ castBar.Time:Hide()
+ else
+ castBar.Time:Show()
+ end
+
+ castBar:SetStatusBarTexture(LSM:Fetch("statusbar", self.db.statusbar))
+ castBar:SetStatusBarColor(self.db.castColor.r, self.db.castColor.g, self.db.castColor.b)
+
+ castBar.castTimeFormat = self.db.units[frame.UnitType].castbar.castTimeFormat
+ castBar.channelTimeFormat = self.db.units[frame.UnitType].castbar.channelTimeFormat
+end
+
+function mod:ConstructElement_CastBar(parent)
+ local frame = CreateFrame("StatusBar", "$parentCastBar", parent)
+ self:StyleFrame(frame)
+ --frame:SetScript("OnUpdate", mod.UpdateElement_CastBarOnUpdate)
+
+ frame.Icon = CreateFrame("Frame", nil, frame)
+ frame.Icon.texture = frame.Icon:CreateTexture(nil, "BORDER")
+ frame.Icon.texture:SetAllPoints()
+ frame.Icon.texture:SetTexCoord(unpack(E.TexCoords))
+ self:StyleFrame(frame.Icon)
+
+ frame.Name = frame:CreateFontString(nil, "OVERLAY")
+ frame.Time = frame:CreateFontString(nil, "OVERLAY")
+ frame.Spark = frame:CreateTexture(nil, "OVERLAY")
+ frame.Spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
+ frame.Spark:SetBlendMode("ADD")
+ --frame.Spark:SetSize(15, 15)
+ frame:Hide()
+ return frame
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/ComboPoints.lua b/ElvUI/Modules/NamePlates/Elements/ComboPoints.lua
new file mode 100644
index 0000000..e9148e1
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/ComboPoints.lua
@@ -0,0 +1,67 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+
+local ComboColors = {
+ [1] = {0.69, 0.31, 0.31},
+ [2] = {0.69, 0.31, 0.31},
+ [3] = {0.65, 0.63, 0.35},
+ [4] = {0.65, 0.63, 0.35},
+ [5] = {0.33, 0.59, 0.33}
+}
+
+local GetComboPoints = GetComboPoints
+local MAX_COMBO_POINTS = MAX_COMBO_POINTS
+
+function mod:UpdateElement_CPoints(frame)
+ if not self.db.comboPoints then return end
+ if frame.UnitType == "FRIENDLY_PLAYER" or frame.UnitType == "FRIENDLY_NPC" then return end
+
+ local numPoints
+ if UnitExists("target") and frame.isTarget then
+ numPoints = GetComboPoints("player", "target")
+ end
+
+ if numPoints and numPoints > 0 then
+ frame.CPoints:Show()
+ for i = 1, MAX_COMBO_POINTS do
+ if i <= numPoints then
+ frame.CPoints[i]:Show()
+ else
+ frame.CPoints[i]:Hide()
+ end
+ end
+ else
+ frame.CPoints:Hide()
+ end
+end
+
+function mod:ConfigureElement_CPoints(frame)
+ if self.db.comboPoints and not frame.CPoints:IsShown() then
+ frame.CPoints:Show()
+ elseif frame.CPoints:IsShown() then
+ frame.CPoints:Hide()
+ end
+end
+
+function mod:ConstructElement_CPoints(parent)
+ local frame = CreateFrame("Frame", nil, parent.HealthBar)
+ frame:SetPoint("CENTER", parent.HealthBar, "BOTTOM")
+ frame:SetWidth(68)
+ frame:SetHeight(1)
+ frame:Hide()
+
+ for i = 1, MAX_COMBO_POINTS do
+ frame[i] = frame:CreateTexture(nil, "OVERLAY")
+ frame[i]:SetTexture([[Interface\AddOns\ElvUI\media\textures\bubbleTex.tga]])
+ frame[i]:SetWidth(12)
+ frame[i]:SetHeight(12)
+ frame[i]:SetVertexColor(unpack(ComboColors[i]))
+
+ if i == 1 then
+ frame[i]:SetPoint("LEFT", frame, "TOPLEFT")
+ else
+ frame[i]:SetPoint("LEFT", frame[i-1], "RIGHT", 2, 0)
+ end
+ end
+ return frame
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/Glow.lua b/ElvUI/Modules/NamePlates/Elements/Glow.lua
new file mode 100644
index 0000000..81d07f3
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/Glow.lua
@@ -0,0 +1,56 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+local LSM = LibStub("LibSharedMedia-3.0")
+
+local CreateFrame = CreateFrame
+
+function mod:UpdateElement_Glow(frame)
+ if not frame.HealthBar:IsShown() then return end
+
+ local r, g, b, shouldShow
+ if frame.isTarget and self.db.useTargetGlow then
+ r, g, b = 1, 1, 1
+ shouldShow = true
+ else
+ local health = frame.oldHealthBar:GetValue()
+ local _, maxHealth = frame.oldHealthBar:GetMinMaxValues()
+ local perc = health / maxHealth
+ if perc <= self.db.lowHealthThreshold then
+ if perc <= self.db.lowHealthThreshold / 2 then
+ r, g, b = 1, 0, 0
+ else
+ r, g, b = 1, 1, 0
+ end
+
+ shouldShow = true
+ end
+ end
+
+ if shouldShow then
+ frame.Glow:Show()
+ if r ~= frame.Glow.r or g ~= frame.Glow.g or b ~= frame.Glow.b then
+ frame.Glow:SetBackdropBorderColor(r, g, b)
+ frame.Glow.r, frame.Glow.g, frame.Glow.b = r, g, b
+ end
+ elseif frame.Glow:IsShown() then
+ frame.Glow:Hide()
+ end
+end
+
+function mod:ConfigureElement_Glow(frame)
+
+end
+
+function mod:ConstructElement_Glow(frame)
+ local f = CreateFrame("Frame", nil, frame)
+ f:SetFrameLevel(frame.HealthBar:GetFrameLevel() - 1)
+ E:SetOutside(f, frame.HealthBar, 3, 3)
+ f:SetBackdrop({
+ edgeFile = LSM:Fetch("border", "ElvUI GlowBorder"), edgeSize = E:Scale(3),
+ insets = {left = E:Scale(5), right = E:Scale(5), top = E:Scale(5), bottom = E:Scale(5)}
+ })
+
+ f:SetScale(E.PixelMode and 1.5 or 2)
+ f:Hide()
+ return f
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/HealerIcon.lua b/ElvUI/Modules/NamePlates/Elements/HealerIcon.lua
new file mode 100644
index 0000000..04b72a0
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/HealerIcon.lua
@@ -0,0 +1,28 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+
+function mod:UpdateElement_HealerIcon(frame)
+ local icon = frame.HealerIcon
+ icon:ClearAllPoints()
+ if frame.HealthBar:IsShown() then
+ icon:SetPoint("RIGHT", frame.HealthBar, "LEFT", -6, 0)
+ else
+ icon:SetPoint("BOTTOM", frame.Name, "TOP", 0, 3)
+ end
+ if self.Healers[frame.UnitName] and frame.UnitType == "ENEMY_PLAYER" then
+ icon:Show()
+ else
+ icon:Hide()
+ end
+end
+
+function mod:ConstructElement_HealerIcon(frame)
+ local texture = frame:CreateTexture(nil, "OVERLAY")
+ texture:SetPoint("RIGHT", frame.HealthBar, "LEFT", -6, 0)
+ texture:SetWidth(40)
+ texture:SetHeight(40)
+ texture:SetTexture([[Interface\AddOns\ElvUI\media\textures\healer.tga]])
+ texture:Hide()
+
+ return texture
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/HealthBar.lua b/ElvUI/Modules/NamePlates/Elements/HealthBar.lua
new file mode 100644
index 0000000..4419266
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/HealthBar.lua
@@ -0,0 +1,180 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+local LSM = LibStub("LibSharedMedia-3.0")
+--local LMH = LibStub("LibMobHealth-4.0")
+
+local tonumber = tonumber
+
+local GetInstanceDifficulty = GetInstanceDifficulty
+local UnitLevel = UnitLevel
+
+function mod:UpdateElement_HealthOnValueChanged()
+ local frame = this:GetParent().UnitFrame
+ if not frame.UnitType then return end -- Bugs
+
+ mod:UpdateElement_Health(frame)
+ mod:UpdateElement_HealthColor(frame)
+ mod:UpdateElement_Glow(frame)
+end
+
+function mod:UpdateElement_HealthColor(frame)
+ if(not frame.HealthBar:IsShown()) then return end
+
+ local r, g, b
+ local scale = 1
+
+ local class = frame.UnitClass
+ local classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+ local useClassColor = mod.db.units[frame.UnitType].healthbar.useClassColor
+
+ if classColor and ((frame.UnitType == "FRIENDLY_PLAYER" and useClassColor and E.private.general.classCache) or (frame.UnitType == "ENEMY_PLAYER" and useClassColor and E.private.general.classCache)) then
+ r, g, b = classColor.r, classColor.g, classColor.b
+ elseif frame.UnitReaction == 1 then
+ r, g, b = mod.db.reactions.tapped.r, mod.db.reactions.tapped.g, mod.db.reactions.tapped.b
+ else
+ local status = mod:UnitDetailedThreatSituation(frame)
+ if status then
+ if status == 3 then
+ if E.Role == "Tank" then
+ r, g, b = mod.db.threat.goodColor.r, mod.db.threat.goodColor.g, mod.db.threat.goodColor.b
+ scale = mod.db.threat.goodScale
+ else
+ r, g, b = mod.db.threat.badColor.r, mod.db.threat.badColor.g, mod.db.threat.badColor.b
+ scale = mod.db.threat.badScale
+ end
+ elseif status == 2 then
+ if E.Role == "Tank" then
+ r, g, b = mod.db.threat.badTransition.r, mod.db.threat.badTransition.g, mod.db.threat.badTransition.b
+ else
+ r, g, b = mod.db.threat.goodTransition.r, mod.db.threat.goodTransition.g, mod.db.threat.goodTransition.b
+ end
+ scale = 1
+ elseif status == 1 then
+ if E.Role == "Tank" then
+ r, g, b = mod.db.threat.goodTransition.r, mod.db.threat.goodTransition.g, mod.db.threat.goodTransition.b
+ else
+ r, g, b = mod.db.threat.badTransition.r, mod.db.threat.badTransition.g, mod.db.threat.badTransition.b
+ end
+ scale = 1
+ else
+ if E.Role == "Tank" then
+ r, g, b = mod.db.threat.badColor.r, mod.db.threat.badColor.g, mod.db.threat.badColor.b
+ scale = mod.db.threat.badScale
+ else
+ r, g, b = mod.db.threat.goodColor.r, mod.db.threat.goodColor.g, mod.db.threat.goodColor.b
+ scale = mod.db.threat.goodScale
+ end
+ end
+ end
+
+ if (not status) or (status and not mod.db.threat.useThreatColor) then
+ local reactionType = frame.UnitReaction
+ if reactionType == 4 then
+ r, g, b = mod.db.reactions.neutral.r, mod.db.reactions.neutral.g, mod.db.reactions.neutral.b
+ elseif reactionType > 4 then
+ if frame.UnitType == "FRIENDLY_PLAYER" then
+ r, g, b = mod.db.reactions.friendlyPlayer.r, mod.db.reactions.friendlyPlayer.g, mod.db.reactions.friendlyPlayer.b
+ else
+ r, g, b = mod.db.reactions.good.r, mod.db.reactions.good.g, mod.db.reactions.good.b
+ end
+ else
+ r, g, b = mod.db.reactions.bad.r, mod.db.reactions.bad.g, mod.db.reactions.bad.b
+ end
+ end
+ end
+
+ if r ~= frame.HealthBar.r or g ~= frame.HealthBar.g or b ~= frame.HealthBar.b then
+ if not frame.CustomColor then
+ frame.HealthBar:SetStatusBarColor(r, g, b)
+ frame.HealthBar.r, frame.HealthBar.g, frame.HealthBar.b = r, g, b
+ else
+ local CustomColor = frame.CustomColor
+ frame.HealthBar:SetStatusBarColor(CustomColor.r, CustomColor.g, CustomColor.b)
+ frame.HealthBar.r, frame.HealthBar.g, frame.HealthBar.b = CustomColor.r, CustomColor.g, CustomColor.b
+ end
+ end
+
+ if (not frame.isTarget or not mod.db.useTargetScale) and not frame.CustomScale then
+ frame.ThreatScale = scale
+ mod:SetFrameScale(frame, scale)
+ end
+end
+
+function mod:UpdateElement_Health(frame)
+ local health = frame.oldHealthBar:GetValue()
+ local _, maxHealth = frame.oldHealthBar:GetMinMaxValues()
+
+ frame.HealthBar:SetMinMaxValues(0, maxHealth)
+ frame.HealthBar:SetValue(health)
+
+ if self.db.units[frame.UnitType].healthbar.text.enable then
+ if maxHealth ~= 100 then
+ frame.HealthBar.text:SetText(E:GetFormattedText(self.db.units[frame.UnitType].healthbar.text.format, health, maxHealth))
+ else
+ local newMaxHealth
+
+ if frame.unit == "target" then
+ --health, maxHealth = LMH:GetUnitHealth("target")
+ else
+ local level = self:UnitLevel(frame)
+ if level == "??" then
+ level = UnitLevel("player") + 3
+ end
+
+ if frame.UnitType == "FRIENDLY_PLAYER" or frame.UnitType == "ENEMY_PLAYER" then
+ -- newMaxHealth = LMH:GetMaxHP(frame.UnitName, tonumber(level), "pc")
+ elseif frame.UnitType == "FRIENDLY_NPC" or frame.UnitType == "ENEMY_NPC" then
+ -- newMaxHealth = LMH:GetMaxHP(frame.UnitName, tonumber(level), "npc", GetInstanceDifficulty())
+ else
+ -- newMaxHealth = LMH:GetMaxHP(frame.UnitName, tonumber(level))
+ end
+
+ if newMaxHealth then
+ health = newMaxHealth / 100 * health
+ maxHealth = newMaxHealth
+ end
+ end
+
+ frame.HealthBar.text:SetText(E:GetFormattedText(self.db.units[frame.UnitType].healthbar.text.format, health, maxHealth))
+ end
+ else
+ frame.HealthBar.text:SetText("")
+ end
+end
+
+function mod:ConfigureElement_HealthBar(frame, configuring)
+ local healthBar = frame.HealthBar
+
+ healthBar:SetPoint("TOP", frame, "CENTER", 0, self.db.units[frame.UnitType].castbar.height + 3)
+ if frame.isTarget and self.db.useTargetScale then
+ healthBar:SetHeight(self.db.units[frame.UnitType].healthbar.height * ((frame.CustomScale and frame.CustomScale * self.db.targetScale) or self.db.targetScale))
+ healthBar:SetWidth(self.db.units[frame.UnitType].healthbar.width * ((frame.CustomScale and frame.CustomScale * self.db.targetScale) or self.db.targetScale))
+ else
+ healthBar:SetHeight((frame.CustomScale and frame.CustomScale * self.db.units[frame.UnitType].healthbar.height) or self.db.units[frame.UnitType].healthbar.height)
+ healthBar:SetWidth((frame.CustomScale and frame.CustomScale * self.db.units[frame.UnitType].healthbar.width) or self.db.units[frame.UnitType].healthbar.width)
+ end
+
+ healthBar:SetStatusBarTexture(LSM:Fetch("statusbar", self.db.statusbar), "BORDER")
+ if(not configuring) and (self.db.units[frame.UnitType].healthbar.enable or frame.isTarget) then
+ healthBar:Show()
+ end
+
+ healthBar.text:SetAllPoints(healthBar)
+ healthBar.text:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+end
+
+function mod:ConstructElement_HealthBar(parent)
+ local frame = CreateFrame("StatusBar", nil, parent)
+ self:StyleFrame(frame)
+ frame:SetFrameLevel(parent:GetFrameLevel())
+
+ frame.text = frame:CreateFontString(nil, "OVERLAY")
+ frame.scale = CreateAnimationGroup(frame)
+
+ frame.scale.width = frame.scale:CreateAnimation("Width")
+ frame.scale.width:SetDuration(0.2)
+ frame.scale.height = frame.scale:CreateAnimation("Height")
+ frame.scale.height:SetDuration(0.2)
+ frame:Hide()
+ return frame
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/Level.lua b/ElvUI/Modules/NamePlates/Elements/Level.lua
new file mode 100644
index 0000000..527d179
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/Level.lua
@@ -0,0 +1,37 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+local LSM = LibStub("LibSharedMedia-3.0")
+
+local format = format
+
+function mod:UpdateElement_Level(frame)
+ if not self.db.units[frame.UnitType].showLevel then return end
+
+ local level, r, g, b = self:UnitLevel(frame)
+
+ if self.db.units[frame.UnitType].healthbar.enable or frame.isTarget then
+ frame.Level:SetText(level)
+ else
+ frame.Level:SetText(format(" [%s]", level))
+ end
+ frame.Level:SetTextColor(r, g, b)
+end
+
+function mod:ConfigureElement_Level(frame)
+ local level = frame.Level
+
+ level:ClearAllPoints()
+
+ if self.db.units[frame.UnitType].healthbar.enable or frame.isTarget then
+ level:SetJustifyH("RIGHT")
+ level:SetPoint("BOTTOMRIGHT", frame.HealthBar, "TOPRIGHT", 0, E.Border*2)
+ else
+ level:SetPoint("LEFT", frame.Name, "RIGHT")
+ level:SetJustifyH("LEFT")
+ end
+ level:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+end
+
+function mod:ConstructElement_Level(frame)
+ return frame:CreateFontString(nil, "OVERLAY")
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/Load_Elements.xml b/ElvUI/Modules/NamePlates/Elements/Load_Elements.xml
new file mode 100644
index 0000000..c66735a
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/Load_Elements.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/Name.lua b/ElvUI/Modules/NamePlates/Elements/Name.lua
new file mode 100644
index 0000000..cb478b1
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/Name.lua
@@ -0,0 +1,63 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+local LSM = LibStub("LibSharedMedia-3.0")
+
+function mod:UpdateElement_Name(frame)
+ if not self.db.units[frame.UnitType].showName then return end
+
+ frame.Name:SetText(frame.UnitName)
+
+ local useClassColor = self.db.units[frame.UnitType].name and self.db.units[frame.UnitType].name.useClassColor
+ if useClassColor and (frame.UnitType == "FRIENDLY_PLAYER" or frame.UnitType == "ENEMY_PLAYER") then
+ local class = frame.UnitClass
+ local color = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+ if class and color then
+ frame.Name:SetTextColor(color.r, color.g, color.b)
+ else
+ frame.Name:SetTextColor(self.db.reactions.friendlyPlayer.r, self.db.reactions.friendlyPlayer.g, self.db.reactions.friendlyPlayer.b)
+ end
+ elseif not self.db.units[frame.UnitType].healthbar.enable and not frame.isTarget then
+ local reactionType = frame.UnitReaction
+
+ local r, g, b
+ if reactionType == 4 then
+ r, g, b = self.db.reactions.neutral.r, self.db.reactions.neutral.g, self.db.reactions.neutral.b
+ elseif reactionType > 4 then
+ if frame.UnitType == "FRIENDLY_PLAYER" then
+ r, g, b = mod.db.reactions.friendlyPlayer.r, mod.db.reactions.friendlyPlayer.g, mod.db.reactions.friendlyPlayer.b
+ else
+ r, g, b = mod.db.reactions.good.r, mod.db.reactions.good.g, mod.db.reactions.good.b
+ end
+ else
+ r, g, b = self.db.reactions.bad.r, self.db.reactions.bad.g, self.db.reactions.bad.b
+ end
+
+ frame.Name:SetTextColor(r, g, b)
+ else
+ frame.Name:SetTextColor(1, 1, 1)
+ end
+end
+
+function mod:ConfigureElement_Name(frame)
+ local name = frame.Name
+
+ name:SetJustifyH("LEFT")
+ name:SetJustifyV("BOTTOM")
+ name:ClearAllPoints()
+ if self.db.units[frame.UnitType].healthbar.enable or frame.isTarget then
+ name:SetJustifyH("LEFT")
+ name:SetPoint("BOTTOMLEFT", frame.HealthBar, "TOPLEFT", 0, E.Border*2)
+ name:SetPoint("BOTTOMRIGHT", frame.Level, "BOTTOMLEFT")
+ else
+ name:SetJustifyH("CENTER")
+ name:SetPoint("BOTTOM", frame, "CENTER", 0, 0)
+ end
+
+ name:SetFont(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+end
+
+function mod:ConstructElement_Name(frame)
+ local name = frame:CreateFontString(nil, "OVERLAY")
+
+ return name
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Elements/RaidIcon.lua b/ElvUI/Modules/NamePlates/Elements/RaidIcon.lua
new file mode 100644
index 0000000..97b8ed2
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Elements/RaidIcon.lua
@@ -0,0 +1,12 @@
+local E, L, V, P, G = unpack(ElvUI)
+local mod = E:GetModule("NamePlates")
+
+function mod:UpdateElement_RaidIcon(frame)
+ local icon = frame.RaidIcon
+ icon:ClearAllPoints()
+ if frame.HealthBar:IsShown() then
+ icon:SetPoint("RIGHT", frame.HealthBar, "LEFT", -6, 0)
+ else
+ icon:SetPoint("BOTTOM", frame.Name, "TOP", 0, 3)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/Load_NamePlates.xml b/ElvUI/Modules/NamePlates/Load_NamePlates.xml
new file mode 100644
index 0000000..fd14b80
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/Load_NamePlates.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/NamePlates/NamePlates.lua b/ElvUI/Modules/NamePlates/NamePlates.lua
new file mode 100644
index 0000000..7eef647
--- /dev/null
+++ b/ElvUI/Modules/NamePlates/NamePlates.lua
@@ -0,0 +1,758 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local mod = E:NewModule("NamePlates", "AceHook-3.0", "AceEvent-3.0", "AceTimer-3.0");
+local CC = E:GetModule("ClassCache");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs, tonumber = pairs, tonumber
+local select = select
+local gsub, match, split = string.gsub, string.match, string.split
+local twipe = table.wipe
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local GetBattlefieldScore = GetBattlefieldScore
+local GetNumBattlefieldScores = GetNumBattlefieldScores
+local UnitClass = UnitClass
+local UnitExists = UnitExists
+local UnitGUID = UnitGUID
+local SetCVar = SetCVar
+local WorldFrame = WorldFrame
+local WorldGetNumChildren, WorldGetChildren = WorldFrame.GetNumChildren, WorldFrame.GetChildren
+
+local numChildren = 0
+local isTarget = false
+local BORDER = "Interface\\Tooltips\\Nameplate-Border"
+local FSPAT = "^%s*$"
+local queryList = {}
+
+local RaidIconCoordinate = {
+ [0] = {[0] = "STAR", [0.25] = "MOON"},
+ [0.25] = {[0] = "CIRCLE", [0.25] = "SQUARE"},
+ [0.5] = {[0] = "DIAMOND", [0.25] = "CROSS"},
+ [0.75] = {[0] = "TRIANGLE", [0.25] = "SKULL"}
+}
+
+local healClasses = {
+ ["DRUID"] = true,
+ ["HUNTER"] = false,
+ ["MAGE"] = false,
+ ["PALADIN"] = true,
+ ["PRIEST"] = true,
+ ["ROGUE"] = false,
+ ["SHAMAN"] = true,
+ ["WARLOCK"] = false,
+ ["WARRIOR"] = false
+}
+
+mod.CreatedPlates = {}
+mod.VisiblePlates = {}
+mod.Healers = {}
+
+function mod:CheckFilter(frame)
+ --[[local db = E.global.nameplates["filter"][frame.UnitName]
+ if db and db.enable then
+ if db.hide then
+ frame:Hide()
+ return
+ else
+ if not frame:IsShown() then
+ frame:Show()
+ end
+
+ if db.customColor then
+ frame.CustomColor = db.color
+ frame.HealthBar:SetStatusBarColor(db.color.r, db.color.g, db.color.b)
+ else
+ frame.CustomColor = nil
+ end
+
+ if db.customScale and db.customScale ~= 1 then
+ frame.CustomScale = db.customScale
+ else
+ frame.CustomScale = nil
+ end
+ end
+ elseif not frame:IsShown() then
+ frame:Show()
+ end]]
+ return true
+end
+
+function mod:CheckBGHealers()
+ local name, class, damageDone, healingDone, _
+ for i = 1, GetNumBattlefieldScores() do
+ name, _, _, _, _, _, _, _, _, class, damageDone, healingDone = GetBattlefieldScore(i)
+ if name and class and healClasses[class] then
+ name = match(name, "(.+)%-.+") or name
+ if name and healingDone > (damageDone * 2) then
+ self.Healers[name] = true
+ elseif name and self.Healers[name] then
+ self.Healers[name] = nil
+ end
+ end
+ end
+end
+
+function mod:SetFrameScale(frame, scale)
+ if frame.HealthBar.currentScale ~= scale then
+ if frame.HealthBar.scale:IsPlaying() then
+ frame.HealthBar.scale:Stop()
+ end
+ frame.HealthBar.scale.width:SetChange(self.db.units[frame.UnitType].healthbar.width * scale)
+ frame.HealthBar.scale.height:SetChange(self.db.units[frame.UnitType].healthbar.height * scale)
+ frame.HealthBar.scale:Play()
+ frame.HealthBar.currentScale = scale
+ end
+end
+
+function mod:SetTargetFrame(frame)
+ if isTarget then return end
+
+ local targetExists = UnitExists("target") == 1
+ if targetExists and frame:GetParent():IsShown() and frame:GetParent():GetAlpha() == 1 then
+ if self.db.useTargetScale then
+ self:SetFrameScale(frame, (frame.CustomScale and frame.CustomScale * self.db.targetScale) or self.db.targetScale)
+ end
+ frame.isTarget = true
+ frame.unit = "target"
+ -- frame.guid = UnitGUID("target")
+
+ if self.db.units[frame.UnitType].healthbar.enable ~= true then
+ frame.Name:ClearAllPoints()
+ frame.Level:ClearAllPoints()
+ frame.HealthBar.r, frame.HealthBar.g, frame.HealthBar.b = nil, nil, nil
+ self:ConfigureElement_HealthBar(frame)
+ self:ConfigureElement_CastBar(frame)
+ self:ConfigureElement_Glow(frame)
+ self:ConfigureElement_Level(frame)
+ self:ConfigureElement_Name(frame)
+
+ self:UpdateElement_All(frame, true)
+ end
+
+ --[[if UnitCastingInfo("target") then
+ frame:GetScript("OnEvent")(frame, "UNIT_SPELLCAST_START", "target")
+ elseif UnitChannelInfo("target") then
+ frame:GetScript("OnEvent")(frame, "UNIT_SPELLCAST_CHANNEL_START", "target")
+ end]]
+
+ frame:SetAlpha(1)
+
+ mod:UpdateElement_AurasByUnitID("target")
+ elseif frame.isTarget then
+ if self.db.useTargetScale then
+ self:SetFrameScale(frame, frame.CustomScale or frame.ThreatScale or 1)
+ end
+ frame.isTarget = nil
+ frame.unit = nil
+ -- frame.guid = nil
+ if self.db.units[frame.UnitType].healthbar.enable ~= true then
+ self:UpdateAllFrame(frame)
+ end
+
+ if targetExists then
+ frame:SetAlpha(self.db.nonTargetTransparency)
+ else
+ frame:SetAlpha(1)
+ end
+ else
+ if targetExists then
+ frame:SetAlpha(self.db.nonTargetTransparency)
+ else
+ frame:SetAlpha(1)
+ end
+ end
+
+ mod:UpdateElement_HealthColor(frame)
+ mod:UpdateElement_Glow(frame)
+ mod:UpdateElement_CPoints(frame)
+
+ return frame.isTarget
+end
+
+function mod:GetNumVisiblePlates()
+ local i = 0
+ for _ in pairs(mod.VisiblePlates) do
+ i = i + 1
+ end
+ return i
+end
+
+function mod:StyleFrame(parent, noBackdrop, point)
+ point = point or parent
+ local noscalemult = E.mult * UIParent:GetScale()
+
+ if point.bordertop then return end
+
+ if not noBackdrop then
+ point.backdrop = parent:CreateTexture(nil, "BACKGROUND")
+ point.backdrop:SetAllPoints(point)
+ point.backdrop:SetTexture(unpack(E["media"].backdropfadecolor))
+ end
+
+ if E.PixelMode then
+ point.bordertop = parent:CreateTexture()
+ point.bordertop:SetPoint("TOPLEFT", point, "TOPLEFT", -noscalemult, noscalemult)
+ point.bordertop:SetPoint("TOPRIGHT", point, "TOPRIGHT", noscalemult, noscalemult)
+ point.bordertop:SetHeight(noscalemult)
+ point.bordertop:SetTexture(unpack(E["media"].bordercolor))
+
+ point.borderbottom = parent:CreateTexture()
+ point.borderbottom:SetPoint("BOTTOMLEFT", point, "BOTTOMLEFT", -noscalemult, -noscalemult)
+ point.borderbottom:SetPoint("BOTTOMRIGHT", point, "BOTTOMRIGHT", noscalemult, -noscalemult)
+ point.borderbottom:SetHeight(noscalemult)
+ point.borderbottom:SetTexture(unpack(E["media"].bordercolor))
+
+ point.borderleft = parent:CreateTexture()
+ point.borderleft:SetPoint("TOPLEFT", point, "TOPLEFT", -noscalemult, noscalemult)
+ point.borderleft:SetPoint("BOTTOMLEFT", point, "BOTTOMLEFT", noscalemult, -noscalemult)
+ point.borderleft:SetWidth(noscalemult)
+ point.borderleft:SetTexture(unpack(E["media"].bordercolor))
+
+ point.borderright = parent:CreateTexture()
+ point.borderright:SetPoint("TOPRIGHT", point, "TOPRIGHT", noscalemult, noscalemult)
+ point.borderright:SetPoint("BOTTOMRIGHT", point, "BOTTOMRIGHT", -noscalemult, -noscalemult)
+ point.borderright:SetWidth(noscalemult)
+ point.borderright:SetTexture(unpack(E["media"].bordercolor))
+ else
+ point.bordertop = parent:CreateTexture(nil, "OVERLAY")
+ point.bordertop:SetPoint("TOPLEFT", point, "TOPLEFT", -noscalemult, noscalemult*2)
+ point.bordertop:SetPoint("TOPRIGHT", point, "TOPRIGHT", noscalemult, noscalemult*2)
+ point.bordertop:SetHeight(noscalemult)
+ point.bordertop:SetTexture(unpack(E.media.bordercolor))
+
+ point.bordertop.backdrop = parent:CreateTexture()
+ point.bordertop.backdrop:SetPoint("TOPLEFT", point.bordertop, "TOPLEFT", noscalemult, noscalemult)
+ point.bordertop.backdrop:SetPoint("TOPRIGHT", point.bordertop, "TOPRIGHT", -noscalemult, noscalemult)
+ point.bordertop.backdrop:SetHeight(noscalemult * 3)
+ point.bordertop.backdrop:SetTexture(0, 0, 0)
+
+ point.borderbottom = parent:CreateTexture(nil, "OVERLAY")
+ point.borderbottom:SetPoint("BOTTOMLEFT", point, "BOTTOMLEFT", -noscalemult, -noscalemult*2)
+ point.borderbottom:SetPoint("BOTTOMRIGHT", point, "BOTTOMRIGHT", noscalemult, -noscalemult*2)
+ point.borderbottom:SetHeight(noscalemult)
+ point.borderbottom:SetTexture(unpack(E.media.bordercolor))
+
+ point.borderbottom.backdrop = parent:CreateTexture()
+ point.borderbottom.backdrop:SetPoint("BOTTOMLEFT", point.borderbottom, "BOTTOMLEFT", noscalemult, -noscalemult)
+ point.borderbottom.backdrop:SetPoint("BOTTOMRIGHT", point.borderbottom, "BOTTOMRIGHT", -noscalemult, -noscalemult)
+ point.borderbottom.backdrop:SetHeight(noscalemult * 3)
+ point.borderbottom.backdrop:SetTexture(0, 0, 0)
+
+ point.borderleft = parent:CreateTexture(nil, "OVERLAY")
+ point.borderleft:SetPoint("TOPLEFT", point, "TOPLEFT", -noscalemult*2, noscalemult*2)
+ point.borderleft:SetPoint("BOTTOMLEFT", point, "BOTTOMLEFT", noscalemult*2, -noscalemult*2)
+ point.borderleft:SetWidth(noscalemult)
+ point.borderleft:SetTexture(unpack(E.media.bordercolor))
+
+ point.borderleft.backdrop = parent:CreateTexture()
+ point.borderleft.backdrop:SetPoint("TOPLEFT", point.borderleft, "TOPLEFT", -noscalemult, noscalemult)
+ point.borderleft.backdrop:SetPoint("BOTTOMLEFT", point.borderleft, "BOTTOMLEFT", -noscalemult, -noscalemult)
+ point.borderleft.backdrop:SetWidth(noscalemult * 3)
+ point.borderleft.backdrop:SetTexture(0, 0, 0)
+
+ point.borderright = parent:CreateTexture(nil, "OVERLAY")
+ point.borderright:SetPoint("TOPRIGHT", point, "TOPRIGHT", noscalemult*2, noscalemult*2)
+ point.borderright:SetPoint("BOTTOMRIGHT", point, "BOTTOMRIGHT", -noscalemult*2, -noscalemult*2)
+ point.borderright:SetWidth(noscalemult)
+ point.borderright:SetTexture(unpack(E.media.bordercolor))
+
+ point.borderright.backdrop = parent:CreateTexture()
+ point.borderright.backdrop:SetPoint("TOPRIGHT", point.borderright, "TOPRIGHT", noscalemult, noscalemult)
+ point.borderright.backdrop:SetPoint("BOTTOMRIGHT", point.borderright, "BOTTOMRIGHT", noscalemult, -noscalemult)
+ point.borderright.backdrop:SetWidth(noscalemult * 3)
+ point.borderright.backdrop:SetTexture(0, 0, 0)
+ end
+end
+
+function mod:RoundColors(r, g, b)
+ return floor(r*100+.5) / 100, floor(g*100+.5) / 100, floor(b*100+.5) / 100
+end
+
+function mod:UnitClass(name, type)
+ --[[if E.private.general.classCache then
+ if type == "FRIENDLY_PLAYER" then
+ local _, class = UnitClass(name)
+ if class then
+ return class
+ else
+ local name, realm = split("-", name)
+ return CC:GetClassByName(name, realm)
+ end
+ end
+ else
+ if type == "FRIENDLY_PLAYER" then
+ return select(2, UnitClass(name))
+ end
+ end--]]
+end
+
+function mod:UnitDetailedThreatSituation(frame)
+ return false
+end
+
+function mod:UnitLevel(frame)
+ local level, boss = frame.oldLevel:GetObjectType() == "FontString" and tonumber(frame.oldLevel:GetText()) or false, frame.BossIcon:IsShown()
+ if boss or not level then
+ return "??", 0.9, 0, 0
+ else
+ return level, frame.oldLevel:GetTextColor()
+ end
+end
+
+function mod:GetUnitInfo(frame)
+ if UnitExists("target") == 1 and frame:GetParent():IsShown() and frame:GetParent():GetAlpha() == 1 then
+ if UnitIsPlayer("target") then
+ if UnitIsEnemy("target", "player") then
+ return 2, "ENEMY_PLAYER"
+ else
+ return 5, "FRIENDLY_PLAYER"
+ end
+ else
+ if UnitIsEnemy("target", "player") then
+ return 2, "ENEMY_NPC"
+ elseif UnitReaction("target", "player") == 4 then
+ return 4, "ENEMY_NPC"
+ else
+ return 5, "FRIENDLY_NPC"
+ end
+ end
+ end
+
+ local r, g, b = mod:RoundColors(frame.oldHealthBar:GetStatusBarColor())
+ if r == 1 and g == 0 and b == 0 then
+ return 2, "ENEMY_NPC"
+ elseif r == 0 and g == 0 and b == 1 then
+ return 5, "FRIENDLY_PLAYER"
+ elseif r == 0 and g == 1 and b == 0 then
+ return 5, "FRIENDLY_NPC"
+ elseif r == 1 and g == 1 and b == 0 then
+ return 4, "ENEMY_NPC"
+ end
+end
+
+function mod:OnShow(self)
+ isTarget = false
+
+ self:SetWidth(0.01)
+ self:SetHeight(0.01)
+
+ mod.VisiblePlates[self.UnitFrame] = true
+
+ self.UnitFrame.UnitName = gsub(self.UnitFrame.oldName:GetText(), FSPAT, "")
+ local unitReaction, unitType = mod:GetUnitInfo(self.UnitFrame)
+ self.UnitFrame.UnitType = unitType
+ self.UnitFrame.UnitClass = mod:UnitClass(self.UnitFrame.oldName:GetText(), unitType)
+ self.UnitFrame.UnitReaction = unitReaction
+
+ if not self.UnitFrame.UnitClass then
+ queryList[self.UnitFrame.UnitName] = self.UnitFrame
+ end
+
+ if unitType == "ENEMY_NPC" and self.UnitFrame.UnitClass then
+ unitType = "ENEMY_PLAYER"
+ self.UnitFrame.UnitType = unitType
+ end
+
+ if not mod:CheckFilter(self.UnitFrame) then return end
+
+ if unitType == "ENEMY_PLAYER" then
+ mod:UpdateElement_HealerIcon(self.UnitFrame)
+ end
+
+ self.UnitFrame.Level:ClearAllPoints()
+ self.UnitFrame.Name:ClearAllPoints()
+
+ mod:ConfigureElement_HealthBar(self.UnitFrame)
+ if mod.db.units[unitType].healthbar.enable then
+ mod:ConfigureElement_CastBar(self.UnitFrame)
+ mod:ConfigureElement_Glow(self.UnitFrame)
+
+ if mod.db.units[unitType].buffs.enable then
+ self.UnitFrame.Buffs.db = mod.db.units[unitType].buffs
+ mod:UpdateAuraIcons(self.UnitFrame.Buffs)
+ end
+
+ if mod.db.units[unitType].debuffs.enable then
+ self.UnitFrame.Debuffs.db = mod.db.units[unitType].debuffs
+ mod:UpdateAuraIcons(self.UnitFrame.Debuffs)
+ end
+ end
+
+ if mod.db.units[unitType].healthbar.enable then
+ mod:ConfigureElement_Name(self.UnitFrame)
+ mod:ConfigureElement_Level(self.UnitFrame)
+ else
+ mod:ConfigureElement_Level(self.UnitFrame)
+ mod:ConfigureElement_Name(self.UnitFrame)
+ end
+
+ --[[if(mod.db.units[unitType].castbar.enable) then
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_START")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_FAILED")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_DELAYED")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE")
+ self.UnitFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
+ end]]
+
+ mod:UpdateElement_All(self.UnitFrame)
+
+ self.UnitFrame:Show()
+end
+
+function mod:OnHide(self)
+ --local self = this
+ mod.VisiblePlates[self.UnitFrame] = nil
+
+ self.UnitFrame.unit = nil
+
+ mod:HideAuraIcons(self.UnitFrame.Buffs)
+ mod:HideAuraIcons(self.UnitFrame.Debuffs)
+ self.UnitFrame.Glow.r, self.UnitFrame.Glow.g, self.UnitFrame.Glow.b = nil, nil, nil
+ self.UnitFrame.Glow:Hide()
+ self.UnitFrame.HealthBar.r, self.UnitFrame.HealthBar.g, self.UnitFrame.HealthBar.b = nil, nil, nil
+ self.UnitFrame.HealthBar:Hide()
+ --self.UnitFrame.CastBar:Hide()
+ self.UnitFrame.Level:ClearAllPoints()
+ self.UnitFrame.Level:SetText("")
+ self.UnitFrame.Name:ClearAllPoints()
+ self.UnitFrame.Name:SetText("")
+ self.UnitFrame.CPoints:Hide()
+ self.UnitFrame:Hide()
+ self.UnitFrame.isTarget = nil
+ self.UnitFrame.displayedUnit = nil
+ self.ThreatData = nil
+ self.UnitFrame.UnitName = nil
+ self.UnitFrame.UnitType = nil
+ self.UnitFrame.ThreatScale = nil
+
+ self.UnitFrame.ThreatReaction = nil
+ self.UnitFrame.guid = nil
+ self.UnitFrame.RaidIconType = nil
+ self.UnitFrame.CustomColor = nil
+ self.UnitFrame.CustomScale = nil
+end
+
+function mod:UpdateAllFrame(frame)
+ mod:OnHide(frame:GetParent())
+ mod:OnShow(frame:GetParent())
+end
+
+function mod:ConfigureAll()
+ if E.private.nameplates.enable ~= true then return end
+
+ self:ForEachPlate("UpdateAllFrame")
+ self:UpdateCVars()
+end
+
+function mod:ForEachPlate(functionToRun, ...)
+ for frame in pairs(self.CreatedPlates) do
+ if frame and frame.UnitFrame then
+ self[functionToRun](self, frame.UnitFrame, unpack(arg))
+ end
+ end
+end
+
+function mod:UpdateElement_All(frame, noTargetFrame)
+ if self.db.units[frame.UnitType].healthbar.enable or frame.isTarget then
+ self:UpdateElement_Health(frame)
+ self:UpdateElement_HealthColor(frame)
+ self:UpdateElement_Auras(frame)
+ end
+ self:UpdateElement_RaidIcon(frame)
+ self:UpdateElement_HealerIcon(frame)
+ self:UpdateElement_Name(frame)
+ self:UpdateElement_Level(frame)
+
+ if not noTargetFrame then
+ mod:ScheduleTimer("ForEachPlate", 0.25, 1, "SetTargetFrame")
+ end
+end
+
+function mod:OnCreated(frame)
+ isTarget = false
+ local HealthBar, CastBar = frame:GetChildren()
+ local Border, Highlight, Name, Level, BossIcon, RaidIcon = frame:GetRegions()
+
+ frame.UnitFrame = CreateFrame("Button", nil, frame)
+ frame.UnitFrame:SetWidth(100)
+ frame.UnitFrame:SetHeight(20)
+ frame.UnitFrame:SetPoint("CENTER", 0, 0)
+ frame.UnitFrame:SetScript("OnEvent", self.OnEvent)
+ frame.UnitFrame:SetScript("OnClick", function()
+ frame:Click()
+ end)
+
+ frame.UnitFrame.HealthBar = self:ConstructElement_HealthBar(frame.UnitFrame)
+ frame.UnitFrame.CastBar = self:ConstructElement_CastBar(frame.UnitFrame)
+ frame.UnitFrame.Level = self:ConstructElement_Level(frame.UnitFrame)
+ frame.UnitFrame.Name = self:ConstructElement_Name(frame.UnitFrame)
+ frame.UnitFrame.Glow = self:ConstructElement_Glow(frame.UnitFrame)
+ frame.UnitFrame.Buffs = self:ConstructElement_Auras(frame.UnitFrame, "LEFT")
+ frame.UnitFrame.Debuffs = self:ConstructElement_Auras(frame.UnitFrame, "RIGHT")
+ frame.UnitFrame.HealerIcon = self:ConstructElement_HealerIcon(frame.UnitFrame)
+ frame.UnitFrame.CPoints = self:ConstructElement_CPoints(frame.UnitFrame)
+
+ --self:QueueObject(CastBarBorder)
+ --self:QueueObject(CastBarIcon)
+ self:QueueObject(HealthBar)
+ --self:QueueObject(CastBar)
+ self:QueueObject(Level)
+ self:QueueObject(Name)
+ self:QueueObject(Border)
+ self:QueueObject(Highlight)
+ --CastBar:Kill()
+ --CastBarIcon:SetParent(E.HiddenFrame)
+ BossIcon:SetAlpha(0)
+
+ frame.UnitFrame.oldHealthBar = HealthBar
+ frame.UnitFrame.oldCastBar = CastBar
+ --frame.UnitFrame.oldCastBar.Icon = CastBarIcon
+ frame.UnitFrame.oldName = Name
+ frame.UnitFrame.oldHighlight = Highlight
+ frame.UnitFrame.oldLevel = Level
+
+ RaidIcon:SetParent(frame.UnitFrame)
+ frame.UnitFrame.RaidIcon = RaidIcon
+
+ frame.UnitFrame.BossIcon = BossIcon
+
+ self:OnShow(frame)
+
+ HookScript(frame, "OnShow", function() self:OnShow(this) end)
+ HookScript(frame, "OnHide", function() self:OnHide(this) end)
+
+ HookScript(HealthBar, "OnValueChanged", self.UpdateElement_HealthOnValueChanged)
+
+ self.CreatedPlates[frame] = true
+ self.VisiblePlates[frame.UnitFrame] = true
+end
+
+function mod:OnEvent(event, unit, ...)
+ if not self.unit then return end
+
+ mod:UpdateElement_Cast(self, event, unit, unpack(arg))
+end
+
+function mod:QueueObject(object)
+ local objectType = object:GetObjectType()
+ if objectType == "Texture" then
+ object:SetTexture("")
+ object:SetTexCoord(0, 0, 0, 0)
+ elseif objectType == "FontString" then
+ object:SetWidth(0.001)
+ elseif objectType == "StatusBar" then
+ object:SetStatusBarTexture("")
+ end
+ object:Hide()
+end
+
+function mod:OnUpdate(elapsed)
+ local count = WorldGetNumChildren(WorldFrame)
+ if count ~= numChildren then
+ for i = numChildren + 1, count do
+ local frame = select(i, WorldGetChildren(WorldFrame))
+ local region = frame:GetRegions()
+
+ if(not mod.CreatedPlates[frame] and region and region:GetObjectType() == "Texture" and region:GetTexture() == BORDER) then
+ mod:OnCreated(frame)
+ end
+ end
+ numChildren = count
+ end
+
+ local i = 0
+ for frame in pairs(mod.VisiblePlates) do
+ i = i + 1
+
+ local getTarget = mod:SetTargetFrame(frame)
+ if not getTarget then
+ frame:GetParent():SetAlpha(1)
+ end
+
+ if i == mod:GetNumVisiblePlates() then
+ isTarget = true
+ end
+ end
+end
+
+function mod:CheckRaidIcon(frame)
+ if frame.RaidIcon:IsShown() then
+ local ux, uy = frame.RaidIcon:GetTexCoord()
+ frame.RaidIconType = RaidIconCoordinate[ux][uy]
+ else
+ frame.RaidIconType = nil
+ end
+end
+
+function mod:SearchNameplateByGUID(guid)
+ for frame in pairs(self.VisiblePlates) do
+ if frame and frame:IsShown() and frame.guid == guid then
+ return frame
+ end
+ end
+end
+
+function mod:SearchNameplateByName(sourceName)
+ if not sourceName then return end
+ local SearchFor = strsplit("-", sourceName)
+ for frame in pairs(self.VisiblePlates) do
+ if frame and frame:IsShown() and frame.UnitName == SearchFor and RAID_CLASS_COLORS[frame.UnitClass] then
+ return frame
+ end
+ end
+end
+
+function mod:SearchNameplateByIconName(raidIcon)
+ for frame in pairs(self.VisiblePlates) do
+ self:CheckRaidIcon(frame)
+ if frame and frame:IsShown() and frame.RaidIcon:IsShown() and (frame.RaidIconType == raidIcon) then
+ return frame
+ end
+ end
+end
+
+function mod:SearchForFrame(guid, raidIcon, name)
+ local frame
+ if guid then frame = self:SearchNameplateByGUID(guid) end
+ if (not frame) and name then frame = self:SearchNameplateByName(name) end
+ if (not frame) and raidIcon then frame = self:SearchNameplateByIconName(raidIcon) end
+
+ return frame
+end
+
+function mod:UpdateCVars()
+ -- SetCVar("showVKeyCastbar", "1")
+ -- SetCVar("nameplateAllowOverlap", self.db.motionType == "STACKED" and "0" or "1")
+end
+
+local function CopySettings(from, to)
+ for setting, value in pairs(from) do
+ if type(value) == "table" then
+ CopySettings(from[setting], to[setting])
+ else
+ if to[setting] ~= nil then
+ to[setting] = from[setting]
+ end
+ end
+ end
+end
+
+function mod:ResetSettings(unit)
+ CopySettings(P.nameplates.units[unit], self.db.units[unit])
+end
+
+function mod:CopySettings(from, to)
+ if from == to then return end
+
+ CopySettings(self.db.units[from], self.db.units[to])
+end
+
+function mod:PLAYER_ENTERING_WORLD()
+ self:CleanAuraLists()
+ twipe(self.Healers)
+ local inInstance, instanceType = IsInInstance()
+ if inInstance and instanceType == "pvp" and self.db.units.ENEMY_PLAYER.markHealers then
+ self.CheckHealerTimer = self:ScheduleRepeatingTimer("CheckBGHealers", 3)
+ self:CheckBGHealers()
+ else
+ if self.CheckHealerTimer then
+ self:CancelTimer(self.CheckHealerTimer)
+ self.CheckHealerTimer = nil
+ end
+ end
+end
+
+function mod:PLAYER_TARGET_CHANGED()
+ isTarget = false
+end
+
+function mod:UNIT_AURA(_, unit)
+ if unit == "target" then
+ self:UpdateElement_AurasByUnitID("target")
+ end
+end
+
+function mod:PLAYER_COMBO_POINTS()
+ self:ForEachPlate("UpdateElement_CPoints")
+end
+
+function mod:PLAYER_REGEN_DISABLED()
+ if self.db.showFriendlyCombat == "TOGGLE_ON" then
+ ShowFriendNameplates();
+ elseif self.db.showFriendlyCombat == "TOGGLE_OFF" then
+ HideFriendNameplates();
+ end
+
+ if self.db.showEnemyCombat == "TOGGLE_ON" then
+ ShowNameplates();
+ elseif self.db.showEnemyCombat == "TOGGLE_OFF" then
+ HideNameplates();
+ end
+end
+
+function mod:PLAYER_REGEN_ENABLED()
+ self:CleanAuraLists()
+ if self.db.showFriendlyCombat == "TOGGLE_ON" then
+ HideFriendNameplates();
+ elseif self.db.showFriendlyCombat == "TOGGLE_OFF" then
+ ShowFriendNameplates();
+ end
+
+ if self.db.showEnemyCombat == "TOGGLE_ON" then
+ HideNameplates();
+ elseif self.db.showEnemyCombat == "TOGGLE_OFF" then
+ ShowNameplates();
+ end
+end
+
+function mod:ClassCacheQueryResult(_, name, class)
+ if queryList[name] then
+ local frame = queryList[name]
+
+ if frame.UnitType then
+ if frame.UnitType == "ENEMY_NPC" then
+ frame.UnitType = "ENEMY_PLAYER"
+ end
+ frame.UnitClass = class
+
+ if self.db.units[frame.UnitType].healthbar.enable then
+ self:UpdateElement_HealthColor(frame)
+ end
+ self:UpdateElement_Name(frame)
+ end
+
+ queryList[name] = nil
+ end
+end
+
+function mod:Initialize()
+ self.db = E.db["nameplates"]
+ if E.private["nameplates"].enable ~= true then return end
+
+ self:UpdateCVars()
+
+ self.Frame = CreateFrame("Frame"):SetScript("OnUpdate", self.OnUpdate)
+
+ self:RegisterEvent("PLAYER_ENTERING_WORLD")
+ self:RegisterEvent("PLAYER_REGEN_ENABLED")
+ self:RegisterEvent("PLAYER_REGEN_DISABLED")
+ self:RegisterEvent("PLAYER_TARGET_CHANGED")
+ --self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
+ --self:RegisterEvent("UNIT_AURA")
+ --self:RegisterEvent("PLAYER_COMBO_POINTS")
+
+ self:RegisterMessage("ClassCacheQueryResult")
+
+ E.NamePlates = self
+end
+
+local function InitializeCallback()
+ mod:Initialize()
+end
+
+E:RegisterModule(mod:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Addons/Ace3.lua b/ElvUI/Modules/Skins/Addons/Ace3.lua
new file mode 100644
index 0000000..92763c7
--- /dev/null
+++ b/ElvUI/Modules/Skins/Addons/Ace3.lua
@@ -0,0 +1,429 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local pairs = pairs
+--WoW API / Variables
+local CreateFrame = CreateFrame
+
+local RegisterAsWidget, RegisterAsContainer
+local function SetModifiedBackdrop()
+ if this.backdrop then this = this.backdrop end
+ this:SetBackdropBorderColor(unpack(E["media"].rgbvaluecolor))
+end
+
+local function SetOriginalBackdrop()
+ if this.backdrop then this = this.backdrop end
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+end
+
+local function SkinScrollBar(frame, thumbTrim)
+ if _G[frame:GetName().."BG"] then _G[frame:GetName().."BG"]:SetTexture(nil) end
+ if _G[frame:GetName().."Track"] then _G[frame:GetName().."Track"]:SetTexture(nil) end
+
+ if _G[frame:GetName().."Top"] then
+ _G[frame:GetName().."Top"]:SetTexture(nil)
+ _G[frame:GetName().."Bottom"]:SetTexture(nil)
+ _G[frame:GetName().."Middle"]:SetTexture(nil)
+ end
+
+ if _G[frame:GetName().."ScrollUpButton"] and _G[frame:GetName().."ScrollDownButton"] then
+ E:StripTextures(_G[frame:GetName().."ScrollUpButton"])
+ if not _G[frame:GetName().."ScrollUpButton"].icon then
+ S:HandleNextPrevButton(_G[frame:GetName().."ScrollUpButton"])
+ S:SquareButton_SetIcon(_G[frame:GetName().."ScrollUpButton"], "UP")
+ _G[frame:GetName().."ScrollUpButton"]:SetWidth(_G[frame:GetName().."ScrollUpButton"]:GetWidth() + 7)
+ _G[frame:GetName().."ScrollUpButton"]:SetHeight(_G[frame:GetName().."ScrollUpButton"]:GetHeight() + 7)
+ end
+
+ E:StripTextures(_G[frame:GetName().."ScrollDownButton"])
+ if not _G[frame:GetName().."ScrollDownButton"].icon then
+ S:HandleNextPrevButton(_G[frame:GetName().."ScrollDownButton"])
+ S:SquareButton_SetIcon(_G[frame:GetName().."ScrollDownButton"], "DOWN")
+ _G[frame:GetName().."ScrollDownButton"]:SetWidth(_G[frame:GetName().."ScrollDownButton"]:GetWidth() + 7)
+ _G[frame:GetName().."ScrollDownButton"]:SetHeight(_G[frame:GetName().."ScrollDownButton"]:GetHeight() + 7)
+ end
+
+ if not frame.trackbg then
+ frame.trackbg = CreateFrame("Frame", nil, frame)
+ frame.trackbg:SetPoint("TOPLEFT", _G[frame:GetName().."ScrollUpButton"], "BOTTOMLEFT", 0, -1)
+ frame.trackbg:SetPoint("BOTTOMRIGHT", _G[frame:GetName().."ScrollDownButton"], "TOPRIGHT", 0, 1)
+ E:SetTemplate(frame.trackbg, "Transparent")
+ end
+
+ if frame:GetThumbTexture() then
+ if not thumbTrim then thumbTrim = 3 end
+ frame:GetThumbTexture():SetTexture(nil)
+ frame:GetThumbTexture():SetHeight(24)
+ if not frame.thumbbg then
+ frame.thumbbg = CreateFrame("Frame", nil, frame)
+ frame.thumbbg:SetPoint("TOPLEFT", frame:GetThumbTexture(), "TOPLEFT", 2, -thumbTrim)
+ frame.thumbbg:SetPoint("TOPLEFT", frame:GetThumbTexture(), "TOPLEFT", 2, -thumbTrim)
+ frame.thumbbg:SetPoint("BOTTOMRIGHT", frame:GetThumbTexture(), "BOTTOMRIGHT", -2, thumbTrim)
+ E:SetTemplate(frame.thumbbg, "Default", true, true)
+ frame.thumbbg:SetBackdropColor(0.3, 0.3, 0.3)
+ if frame.trackbg then
+ frame.thumbbg:SetFrameLevel(frame.trackbg:GetFrameLevel() + 1)
+ end
+ end
+ end
+ end
+end
+
+local function SkinButton(f, strip, noTemplate)
+ local name = f:GetName()
+
+ if(name) then
+ local left = _G[name.."Left"]
+ local middle = _G[name.."Middle"]
+ local right = _G[name.."Right"]
+
+ if(left) then E:Kill(left) end
+ if(middle) then E:Kill(middle) end
+ if(right) then E:Kill(right) end
+ end
+
+ if(f.Left) then E:Kill(f.Left) end
+ if(f.Middle) then E:Kill(f.Middle) end
+ if(f.Right) then E:Kill(f.Right) end
+
+ if f.SetNormalTexture then f:SetNormalTexture("") end
+ if f.SetHighlightTexture then f:SetHighlightTexture("") end
+ if f.SetPushedTexture then f:SetPushedTexture("") end
+ if f.SetDisabledTexture then f:SetDisabledTexture("") end
+
+ if strip then E:StripTextures(f) end
+
+ if not f.template and not noTemplate then
+ E:SetTemplate(f, "Default", true)
+ end
+
+ HookScript(f, "OnEnter", SetModifiedBackdrop)
+ HookScript(f, "OnLeave", SetOriginalBackdrop)
+end
+
+function S:SkinAce3()
+ local AceGUI = LibStub("AceGUI-3.0", true)
+ if not AceGUI then return end
+ local oldRegisterAsWidget = AceGUI.RegisterAsWidget
+
+ RegisterAsWidget = function(self, widget)
+ if not E.private.skins.ace3.enable then
+ return oldRegisterAsWidget(self, widget)
+ end
+ local TYPE = widget.type
+ if TYPE == "MultiLineEditBox" then
+ local frame = widget.frame
+
+ if not widget.scrollBG.template then
+ E:SetTemplate(widget.scrollBG, "Default")
+ end
+
+ SkinButton(widget.button)
+ SkinScrollBar(widget.scrollBar)
+ widget.scrollBar:SetPoint("RIGHT", frame, "RIGHT", 0 -4)
+ widget.scrollBG:SetPoint("TOPRIGHT", widget.scrollBar, "TOPLEFT", -2, 19)
+ widget.scrollBG:SetPoint("BOTTOMLEFT", widget.button, "TOPLEFT")
+ widget.scrollFrame:SetPoint("BOTTOMRIGHT", widget.scrollBG, "BOTTOMRIGHT", -4, 8)
+ elseif TYPE == "CheckBox" then
+ E:Kill(widget.checkbg)
+ E:Kill(widget.highlight)
+
+ if not widget.skinnedCheckBG then
+ widget.skinnedCheckBG = CreateFrame("Frame", nil, widget.frame)
+ E:SetTemplate(widget.skinnedCheckBG, "Default")
+ widget.skinnedCheckBG:SetPoint("TOPLEFT", widget.checkbg, "TOPLEFT", 4, -4)
+ widget.skinnedCheckBG:SetPoint("BOTTOMRIGHT", widget.checkbg, "BOTTOMRIGHT", -4, 4)
+ end
+
+ widget.check:SetParent(widget.skinnedCheckBG)
+ elseif TYPE == "Dropdown" then
+ local frame = widget.dropdown
+ local button = widget.button
+ local text = widget.text
+ E:StripTextures(frame)
+
+ button:ClearAllPoints()
+ button:SetPoint("RIGHT", frame, "RIGHT", -20, 0)
+
+ S:HandleNextPrevButton(button, true)
+
+ if not frame.backdrop then
+ E:CreateBackdrop(frame, "Default")
+ frame.backdrop:SetPoint("TOPLEFT", 20, -2)
+ frame.backdrop:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 2, -2)
+ end
+ button:SetParent(frame.backdrop)
+ text:SetParent(frame.backdrop)
+ HookScript(button, "OnClick", function()
+ local dropdown = this.obj.pullout
+ if dropdown.frame then
+ E:SetTemplate(dropdown.frame, "Default", true)
+ if dropdown.slider then
+ E:SetTemplate(dropdown.slider, "Default")
+ dropdown.slider:SetPoint("TOPRIGHT", dropdown.frame, "TOPRIGHT", -10, -10)
+ dropdown.slider:SetPoint("BOTTOMRIGHT", dropdown.frame, "BOTTOMRIGHT", -10, 10)
+
+ if dropdown.slider:GetThumbTexture() then
+ dropdown.slider:SetThumbTexture(E["media"].blankTex)
+ dropdown.slider:GetThumbTexture():SetVertexColor(0.3, 0.3, 0.3)
+ -- dropdown.slider:GetThumbTexture():Size(10, 12)
+ dropdown.slider:GetThumbTexture():SetWidth(10)
+ dropdown.slider:GetThumbTexture():SetHeight(12)
+ end
+ end
+ end
+ end)
+ elseif TYPE == "LSM30_Font" or TYPE == "LSM30_Sound" or TYPE == "LSM30_Border" or TYPE == "LSM30_Background" or TYPE == "LSM30_Statusbar" then
+ local frame = widget.frame
+ local button = frame.dropButton
+ local text = frame.text
+ E:StripTextures(frame)
+
+ S:HandleNextPrevButton(button, true)
+ frame.text:ClearAllPoints()
+ frame.text:SetPoint("RIGHT", button, "LEFT", -2, 0)
+
+ button:ClearAllPoints()
+ button:SetPoint("RIGHT", frame, "RIGHT", -10, -6)
+
+ if not frame.backdrop then
+ E:CreateBackdrop(frame, "Default")
+ if TYPE == "LSM30_Font" then
+ frame.backdrop:SetPoint("TOPLEFT", 20, -17)
+ elseif TYPE == "LSM30_Sound" then
+ frame.backdrop:SetPoint("TOPLEFT", 20, -17)
+ widget.soundbutton:SetParent(frame.backdrop)
+ widget.soundbutton:ClearAllPoints()
+ widget.soundbutton:SetPoint("LEFT", frame.backdrop, "LEFT", 2, 0)
+ elseif TYPE == "LSM30_Statusbar" then
+ frame.backdrop:SetPoint("TOPLEFT", 20, -17)
+ widget.bar:SetParent(frame.backdrop)
+ E:SetInside(widget.bar)
+ elseif TYPE == "LSM30_Border" or TYPE == "LSM30_Background" then
+ frame.backdrop:SetPoint("TOPLEFT", 42, -16)
+ end
+
+ frame.backdrop:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 2, -2)
+ end
+ button:SetParent(frame.backdrop)
+ text:SetParent(frame.backdrop)
+ HookScript(button, "OnClick", function()
+ local dropdown = this.obj.dropdown
+ if dropdown then
+ E:SetTemplate(dropdown, "Default", true)
+ if dropdown.slider then
+ E:SetTemplate(dropdown.slider, "Transparent")
+ dropdown.slider:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", -10, -10)
+ dropdown.slider:SetPoint("BOTTOMRIGHT", dropdown, "BOTTOMRIGHT", -10, 10)
+
+ if dropdown.slider:GetThumbTexture() then
+ dropdown.slider:SetThumbTexture(E["media"].blankTex)
+ dropdown.slider:GetThumbTexture():SetVertexColor(0.3, 0.3, 0.3)
+ -- dropdown.slider:GetThumbTexture():Size(10, 12)
+ dropdown.slider:GetThumbTexture():SetWidth(10)
+ dropdown.slider:GetThumbTexture():SetHeight(12)
+ end
+ end
+
+ if TYPE == "LSM30_Sound" then
+ local frame = this.obj.frame
+ local width = frame:GetWidth()
+ dropdown:SetPoint("TOPLEFT", frame, "BOTTOMLEFT")
+ dropdown:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 30, 0)
+ end
+ end
+ end)
+ elseif TYPE == "EditBox" then
+ local frame = widget.editbox
+ local button = widget.button
+ E:Kill(_G[frame:GetName().."Left"])
+ E:Kill(_G[frame:GetName().."Middle"])
+ E:Kill(_G[frame:GetName().."Right"])
+ frame:SetHeight(17)
+ E:CreateBackdrop(frame, "Default")
+ frame.backdrop:SetPoint("TOPLEFT", -2, 0)
+ frame.backdrop:SetPoint("BOTTOMRIGHT", 2, 0)
+ frame.backdrop:SetParent(widget.frame)
+ frame:SetParent(frame.backdrop)
+ SkinButton(button)
+ elseif TYPE == "Button" then
+ local frame = widget.frame
+ SkinButton(frame, nil, true)
+ E:StripTextures(frame)
+ E:CreateBackdrop(frame, "Default", true)
+ E:SetInside(frame.backdrop)
+ widget.text:SetParent(frame.backdrop)
+ elseif TYPE == "Button-ElvUI" then
+ local frame = widget.frame
+ SkinButton(frame, nil, true)
+ E:StripTextures(frame)
+ E:CreateBackdrop(frame, "Default", true)
+ E:SetInside(frame.backdrop)
+ widget.text:SetParent(frame.backdrop)
+ elseif TYPE == "Keybinding" then
+ local button = widget.button
+ local msgframe = widget.msgframe
+ local msg = widget.msgframe.msg
+ SkinButton(button)
+ E:StripTextures(msgframe)
+ E:CreateBackdrop(msgframe, "Default", true)
+ E:SetInside(msgframe.backdrop)
+ msgframe:SetToplevel(true)
+
+ msg:ClearAllPoints()
+ msg:SetPoint("LEFT", 10, 0)
+ msg:SetPoint("RIGHT", -10, 0)
+ msg:SetJustifyV("MIDDLE")
+ msg:SetWidth(msg:GetWidth() + 10)
+ elseif TYPE == "Slider" then
+ local frame = widget.slider
+ local editbox = widget.editbox
+ local lowtext = widget.lowtext
+ local hightext = widget.hightext
+ local HEIGHT = 12
+
+ E:StripTextures(frame)
+ E:SetTemplate(frame, "Default")
+ frame:SetHeight(HEIGHT)
+ frame:SetThumbTexture(E["media"].blankTex)
+ frame:GetThumbTexture():SetVertexColor(0.3, 0.3, 0.3)
+ -- frame:GetThumbTexture():Size(HEIGHT-2,HEIGHT+2)
+ frame:GetThumbTexture():SetWidth(HEIGHT-2)
+ frame:GetThumbTexture():SetHeight(HEIGHT+2)
+
+ E:SetTemplate(editbox, "Default")
+ editbox:SetHeight(15)
+ editbox:SetPoint("TOP", frame, "BOTTOM", 0, -1)
+
+ lowtext:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 2, -2)
+ hightext:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", -2, -2)
+
+ --[[elseif TYPE == "ColorPicker" then
+ local frame = widget.frame
+ local colorSwatch = widget.colorSwatch
+ ]]
+ end
+ return oldRegisterAsWidget(self, widget)
+ end
+ AceGUI.RegisterAsWidget = RegisterAsWidget
+
+ local oldRegisterAsContainer = AceGUI.RegisterAsContainer
+ RegisterAsContainer = function(self, widget)
+ if not E.private.skins.ace3.enable then
+ return oldRegisterAsContainer(self, widget)
+ end
+ local TYPE = widget.type
+ if TYPE == "ScrollFrame" then
+ local frame = widget.scrollbar
+ SkinScrollBar(frame)
+ elseif TYPE == "InlineGroup" or TYPE == "TreeGroup" or TYPE == "TabGroup-ElvUI" or TYPE == "Frame" or TYPE == "DropdownGroup" or TYPE == "Window" then
+ local frame = widget.content:GetParent()
+ if TYPE == "Frame" then
+ E:StripTextures(frame)
+ if(not E.GUIFrame) then
+ E.GUIFrame = frame
+ end
+
+ for _, child in ipairs({frame:GetChildren()}) do
+ if child:GetObjectType() == "Button" and child:GetText() then
+ SkinButton(child)
+ else
+ E:StripTextures(child)
+ end
+ end
+
+ --[[for i=1, frame:GetNumChildren() do
+ local child = select(i, frame:GetChildren())
+ if child:GetObjectType() == "Button" and child:GetText() then
+ SkinButton(child)
+ else
+ E:StripTextures(child)
+ end
+ end]]
+ elseif TYPE == "Window" then
+ E:StripTextures(frame)
+ S:HandleCloseButton(frame.obj.closebutton)
+ end
+ E:SetTemplate(frame, "Transparent")
+
+ if widget.treeframe then
+ E:SetTemplate(widget.treeframe, "Transparent")
+ frame:SetPoint("TOPLEFT", widget.treeframe, "TOPRIGHT", 1, 0)
+
+ local oldCreateButton = widget.CreateButton
+ widget.CreateButton = function(self)
+ local button = oldCreateButton(self)
+ E:StripTextures(button.toggle)
+ button.toggle.SetNormalTexture = E.noop
+ button.toggle.SetPushedTexture = E.noop
+ button.toggleText = button.toggle:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(button.toggleText, nil, 19)
+ button.toggleText:SetPoint("CENTER", 0, 0)
+ button.toggleText:SetText("+")
+ return button
+ end
+
+ local oldRefreshTree = widget.RefreshTree
+ widget.RefreshTree = function(self, scrollToSelection)
+ oldRefreshTree(self, scrollToSelection)
+ if not self.tree then return end
+ local status = self.status or self.localstatus
+ local groupstatus = status.groups
+ local lines = self.lines
+ local buttons = self.buttons
+
+ for i, line in pairs(lines) do
+ local button = buttons[i]
+ if groupstatus[line.uniquevalue] and button then
+ button.toggleText:SetText("-")
+ elseif button then
+ button.toggleText:SetText("+")
+ end
+ end
+ end
+ end
+
+ if TYPE == "TabGroup-ElvUI" then
+ local oldCreateTab = widget.CreateTab
+ widget.CreateTab = function(self, id)
+ local tab = oldCreateTab(self, id)
+ E:StripTextures(tab)
+ tab.backdrop = CreateFrame("Frame", nil, tab)
+ E:SetTemplate(tab.backdrop, "Transparent")
+ tab.backdrop:SetFrameLevel(tab:GetFrameLevel() - 1)
+ tab.backdrop:SetPoint("TOPLEFT", 10, -3)
+ tab.backdrop:SetPoint("BOTTOMRIGHT", -10, 0)
+ return tab
+ end
+ end
+
+ if widget.scrollbar then
+ SkinScrollBar(widget.scrollbar)
+ end
+ elseif TYPE == "SimpleGroup" then
+ local frame = widget.content:GetParent()
+ E:SetTemplate(frame, "Transparent", nil, true) --ignore border updates
+ frame:SetBackdropBorderColor(0,0,0,0) --Make border completely transparent
+ end
+
+ return oldRegisterAsContainer(self, widget)
+ end
+ AceGUI.RegisterAsContainer = RegisterAsContainer
+end
+
+local function attemptSkin()
+ local AceGUI = LibStub("AceGUI-3.0", true)
+ if AceGUI and (AceGUI.RegisterAsContainer ~= RegisterAsContainer or AceGUI.RegisterAsWidget ~= RegisterAsWidget) then
+ S:SkinAce3()
+ end
+end
+
+local f = CreateFrame("Frame")
+f:RegisterEvent("ADDON_LOADED")
+f:SetScript("OnEvent", attemptSkin)
+
+S:AddCallback("Ace3", attemptSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Addons/Load_Addons.xml b/ElvUI/Modules/Skins/Addons/Load_Addons.xml
new file mode 100644
index 0000000..67686d3
--- /dev/null
+++ b/ElvUI/Modules/Skins/Addons/Load_Addons.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/AuctionHouse.lua b/ElvUI/Modules/Skins/Blizzard/AuctionHouse.lua
new file mode 100644
index 0000000..1d0b3b3
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/AuctionHouse.lua
@@ -0,0 +1,340 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local pairs = pairs
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.auctionhouse ~= true then return end
+
+ E:StripTextures(AuctionFrame, true)
+ E:CreateBackdrop(AuctionFrame, "Transparent")
+ AuctionFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ AuctionFrame.backdrop:SetPoint("BOTTOMRIGHT", 0, 4)
+
+ E:StripTextures(BrowseFilterScrollFrame)
+ E:StripTextures(BrowseScrollFrame)
+ E:StripTextures(AuctionsScrollFrame)
+ E:StripTextures(BidScrollFrame)
+
+ S:HandleDropDownBox(BrowseDropDown)
+
+ S:HandleScrollBar(BrowseFilterScrollFrameScrollBar)
+ S:HandleScrollBar(BrowseScrollFrameScrollBar)
+ S:HandleScrollBar(AuctionsScrollFrameScrollBar)
+
+ S:HandleCloseButton(AuctionFrameCloseButton)
+
+ -- DressUpFrame
+ E:StripTextures(AuctionDressUpFrame)
+ E:CreateBackdrop(AuctionDressUpFrame, "Default")
+
+ SetAuctionDressUpBackground()
+ AuctionDressUpBackgroundTop:SetDesaturated(true)
+ AuctionDressUpBackgroundBot:SetDesaturated(true)
+
+ E:SetOutside(AuctionDressUpFrame.backdrop, AuctionDressUpBackgroundTop, nil, nil, AuctionDressUpBackgroundBot)
+
+ S:HandleRotateButton(AuctionDressUpModelRotateLeftButton)
+ AuctionDressUpModelRotateLeftButton:SetPoint("TOPLEFT", AuctionDressUpFrame, 8, -17)
+ S:HandleRotateButton(AuctionDressUpModelRotateRightButton)
+ AuctionDressUpModelRotateRightButton:SetPoint("TOPLEFT", AuctionDressUpModelRotateLeftButton, "TOPRIGHT", 3, 0)
+
+ S:HandleButton(AuctionDressUpFrameResetButton)
+ S:HandleCloseButton(AuctionDressUpFrameCloseButton, AuctionDressUpFrame.backdrop)
+
+ local buttons = {
+ "BrowseBidButton",
+ "BidBidButton",
+ "BrowseBuyoutButton",
+ "BidBuyoutButton",
+ "BrowseCloseButton",
+ "BidCloseButton",
+ "BrowseSearchButton",
+ "AuctionsCloseButton",
+ "AuctionsCancelAuctionButton",
+ "AuctionsCreateAuctionButton",
+ }
+
+ for _, button in pairs(buttons) do
+ S:HandleButton(_G[button])
+ end
+
+ --Fix Button Positions
+ AuctionsCloseButton:SetPoint("BOTTOMRIGHT", AuctionFrameAuctions, "BOTTOMRIGHT", 66, 14)
+ AuctionsCancelAuctionButton:SetPoint("RIGHT", AuctionsCloseButton, "LEFT", -4, 0)
+ BidBuyoutButton:SetPoint("RIGHT", BidCloseButton, "LEFT", -4, 0)
+ BidBidButton:SetPoint("RIGHT", BidBuyoutButton, "LEFT", -4, 0)
+ BrowseBuyoutButton:SetPoint("RIGHT", BrowseCloseButton, "LEFT", -4, 0)
+ BrowseBidButton:SetPoint("RIGHT", BrowseBuyoutButton, "LEFT", -4, 0)
+ AuctionsCreateAuctionButton:SetPoint("BOTTOMLEFT", 18, 44)
+
+ BrowseSearchButton:ClearAllPoints()
+ BrowseSearchButton:SetPoint("TOPRIGHT", AuctionFrameBrowse, "TOPRIGHT", 25, -30)
+
+ S:HandleNextPrevButton(BrowseNextPageButton)
+ BrowseNextPageButton:ClearAllPoints()
+ BrowseNextPageButton:SetPoint("BOTTOMLEFT", BrowseSearchButton, "BOTTOMRIGHT", 10, -27)
+
+ S:HandleNextPrevButton(BrowsePrevPageButton)
+ BrowsePrevPageButton:ClearAllPoints()
+ BrowsePrevPageButton:SetPoint("BOTTOMRIGHT", BrowseSearchButton, "BOTTOMLEFT", -10, -27)
+
+ E:StripTextures(AuctionsItemButton)
+ E:SetTemplate(AuctionsItemButton, "Default", true)
+ E:StyleButton(AuctionsItemButton, false, true)
+
+ HookScript(AuctionsItemButton, "OnEvent", function()
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ if event == "NEW_AUCTION_UPDATE" and this:GetNormalTexture() then
+ this:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(this:GetNormalTexture())
+ end
+
+ local itemName = GetAuctionSellItemInfo()
+ if itemName then
+ local _, itemString = GetItemInfoByName(itemName)
+ local _, _, quality = GetItemInfo(itemString, "item:(%d+)")
+ if quality then
+ AuctionsItemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ AuctionsItemButtonName:SetTextColor(GetItemQualityColor(quality))
+ else
+ AuctionsItemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end)
+
+ local sorttabs = {
+ "BrowseQualitySort",
+ "BrowseLevelSort",
+ "BrowseDurationSort",
+ "BrowseHighBidderSort",
+ "BrowseCurrentBidSort",
+ "BidQualitySort",
+ "BidLevelSort",
+ "BidDurationSort",
+ "BidBuyoutSort",
+ "BidStatusSort",
+ "BidBidSort",
+ "AuctionsQualitySort",
+ "AuctionsDurationSort",
+ "AuctionsHighBidderSort",
+ "AuctionsBidSort",
+ }
+
+ for _, sorttab in pairs(sorttabs) do
+ E:Kill(_G[sorttab.."Left"])
+ E:Kill(_G[sorttab.."Middle"])
+ E:Kill(_G[sorttab.."Right"])
+ E:StyleButton(_G[sorttab])
+ end
+
+ for i = 1, 3 do
+ S:HandleTab(_G["AuctionFrameTab"..i])
+ end
+
+ AuctionFrameTab1:ClearAllPoints()
+ AuctionFrameTab1:SetPoint("BOTTOMLEFT", AuctionFrame, "BOTTOMLEFT", 25, -26)
+ AuctionFrameTab1.SetPoint = E.noop
+
+ for i = 1, NUM_FILTERS_TO_DISPLAY do
+ local tab = _G["AuctionFilterButton"..i]
+
+ E:StripTextures(tab)
+ E:StyleButton(tab)
+ end
+
+ local editboxs = {
+ "BrowseName",
+ "BrowseMinLevel",
+ "BrowseMaxLevel",
+ "BrowseBidPriceGold",
+ "BrowseBidPriceSilver",
+ "BrowseBidPriceCopper",
+ "BidBidPriceGold",
+ "BidBidPriceSilver",
+ "BidBidPriceCopper",
+ "StartPriceGold",
+ "StartPriceSilver",
+ "StartPriceCopper",
+ "BuyoutPriceGold",
+ "BuyoutPriceSilver",
+ "BuyoutPriceCopper"
+ }
+
+ for _, editbox in pairs(editboxs) do
+ S:HandleEditBox(_G[editbox])
+ _G[editbox]:SetTextInsets(1, 1, -1, 1)
+ end
+
+ BrowseBidPrice:SetPoint("BOTTOM", -15, 18)
+ BrowseBidText:SetPoint("BOTTOMRIGHT", AuctionFrameBrowse, "BOTTOM", -116, 21)
+
+ BrowseMinLevel:SetWidth(32)
+
+ BrowseLevelHyphen:SetPoint("LEFT", BrowseMinLevel, "RIGHT", -7, 1)
+
+ BrowseMaxLevel:SetPoint("LEFT", BrowseMinLevel, "RIGHT", 8, 0)
+ BrowseMaxLevel:SetWidth(32)
+ BrowseLevelText:SetPoint("BOTTOMLEFT", AuctionFrameBrowse, "TOPLEFT", 195, -48)
+
+ BrowseName:SetWidth(164)
+ BrowseName:SetPoint("TOPLEFT", AuctionFrameBrowse, "TOPLEFT", 20, -54)
+ BrowseNameText:SetPoint("TOPLEFT", BrowseName, "TOPLEFT", 0, 16)
+
+ S:HandleCheckBox(IsUsableCheckButton)
+ IsUsableCheckButton:ClearAllPoints()
+ IsUsableCheckButton:SetPoint("RIGHT", BrowseIsUsableText, "LEFT", 2, 0)
+ BrowseIsUsableText:SetPoint("TOPLEFT", 440, -40)
+
+ S:HandleCheckBox(ShowOnPlayerCheckButton)
+ ShowOnPlayerCheckButton:ClearAllPoints()
+ ShowOnPlayerCheckButton:SetPoint("RIGHT", BrowseShowOnCharacterText, "LEFT", 2, 0)
+
+ BrowseShowOnCharacterText:SetPoint("TOPLEFT", 440, -60)
+
+ for i = 1, NUM_BROWSE_TO_DISPLAY do
+ local button = _G["BrowseButton"..i]
+ local icon = _G["BrowseButton"..i.."Item"]
+ local name = _G["BrowseButton"..i.."Name"]
+ local texture = _G["BrowseButton"..i.."ItemIconTexture"]
+
+ if texture then
+ texture:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(texture)
+ end
+
+ if icon then
+ E:StyleButton(icon)
+ icon:GetNormalTexture():SetTexture("")
+ E:SetTemplate(icon, "Default")
+
+ hooksecurefunc(name, "SetVertexColor", function(_, r, g, b)
+ if r and g and b then
+ icon:SetBackdropBorderColor(r, g, b)
+ end
+ end)
+ hooksecurefunc(name, "Hide", function(_, r, g, b)
+ icon:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end)
+ end
+
+ E:StripTextures(button)
+ E:StyleButton(button, false, true)
+ _G["BrowseButton"..i.."Highlight"] = button:GetHighlightTexture()
+ button:GetHighlightTexture():ClearAllPoints()
+ button:GetHighlightTexture():SetPoint("TOPLEFT", icon, "TOPRIGHT", 2, 0)
+ button:GetHighlightTexture():SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 5)
+ -- button:GetPushedTexture():SetAllPoints(button:GetHighlightTexture())
+ end
+
+ for i = 1, NUM_AUCTIONS_TO_DISPLAY do
+ local button = _G["AuctionsButton"..i]
+ local icon = _G["AuctionsButton"..i.."Item"]
+ local name = _G["AuctionsButton"..i.."Name"]
+ local texture = _G["AuctionsButton"..i.."ItemIconTexture"]
+
+ if texture then
+ texture:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(texture)
+ end
+
+ if icon then
+ E:StyleButton(icon)
+ icon:GetNormalTexture():SetTexture("")
+ E:SetTemplate(icon, "Default")
+
+ hooksecurefunc(name, "SetVertexColor", function(_, r, g, b)
+ if r and g and b then
+ icon:SetBackdropBorderColor(r, g, b)
+ end
+ end)
+ hooksecurefunc(name, "Hide", function(_, r, g, b)
+ icon:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end)
+ end
+
+ E:StripTextures(button)
+ E:StyleButton(button, false, true)
+ _G["AuctionsButton"..i.."Highlight"] = button:GetHighlightTexture()
+ button:GetHighlightTexture():ClearAllPoints()
+ button:GetHighlightTexture():SetPoint("TOPLEFT", icon, "TOPRIGHT", 2, 0)
+ button:GetHighlightTexture():SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 5)
+ -- button:GetPushedTexture():SetAllPoints(button:GetHighlightTexture())
+ end
+
+ for i = 1, NUM_BIDS_TO_DISPLAY do
+ local button = _G["BidButton"..i]
+ local icon = _G["BidButton"..i.."Item"]
+ local name = _G["BidButton"..i.."Name"]
+ local texture = _G["BidButton"..i.."ItemIconTexture"]
+
+ if texture then
+ texture:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(texture)
+ end
+
+ if icon then
+ E:StyleButton(icon)
+ icon:GetNormalTexture():SetTexture("")
+ E:SetTemplate(icon, "Default")
+
+ hooksecurefunc(name, "SetVertexColor", function(_, r, g, b)
+ if r and g and b then
+ icon:SetBackdropBorderColor(r, g, b)
+ end
+ end)
+ hooksecurefunc(name, "Hide", function(_, r, g, b)
+ icon:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end)
+ end
+
+ E:StripTextures(button)
+ E:StyleButton(button, false, true)
+ _G["BidButton"..i.."Highlight"] = button:GetHighlightTexture()
+ button:GetHighlightTexture():ClearAllPoints()
+ button:GetHighlightTexture():SetPoint("TOPLEFT", icon, "TOPRIGHT", 2, 0)
+ button:GetHighlightTexture():SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 5)
+ -- button:GetPushedTexture():SetAllPoints(button:GetHighlightTexture())
+ end
+
+ --Custom Backdrops
+ AuctionFrameBrowse.bg1 = CreateFrame("Frame", nil, AuctionFrameBrowse)
+ E:SetTemplate(AuctionFrameBrowse.bg1, "Default")
+ AuctionFrameBrowse.bg1:SetPoint("TOPLEFT", 20, -103)
+ AuctionFrameBrowse.bg1:SetPoint("BOTTOMRIGHT", -575, 40)
+ BrowseNoResultsText:SetParent(AuctionFrameBrowse.bg1)
+ BrowseSearchCountText:SetParent(AuctionFrameBrowse.bg1)
+ AuctionFrameBrowse.bg1:SetFrameLevel(AuctionFrameBrowse.bg1:GetFrameLevel() - 1)
+
+ AuctionFrameBrowse.bg2 = CreateFrame("Frame", nil, AuctionFrameBrowse)
+ E:SetTemplate(AuctionFrameBrowse.bg2, "Default")
+ AuctionFrameBrowse.bg2:SetPoint("TOPLEFT", AuctionFrameBrowse.bg1, "TOPRIGHT", 4, 0)
+ AuctionFrameBrowse.bg2:SetPoint("BOTTOMRIGHT", AuctionFrame, "BOTTOMRIGHT", -8, 40)
+ AuctionFrameBrowse.bg2:SetFrameLevel(AuctionFrameBrowse.bg2:GetFrameLevel() - 1)
+
+ AuctionFrameBid.bg = CreateFrame("Frame", nil, AuctionFrameBid)
+ E:SetTemplate(AuctionFrameBid.bg, "Default")
+ AuctionFrameBid.bg:SetPoint("TOPLEFT", 20, -72)
+ AuctionFrameBid.bg:SetPoint("BOTTOMRIGHT", 66, 40)
+ AuctionFrameBid.bg:SetFrameLevel(AuctionFrameBid.bg:GetFrameLevel() - 1)
+
+ AuctionFrameAuctions.bg1 = CreateFrame("Frame", nil, AuctionFrameAuctions)
+ E:SetTemplate(AuctionFrameAuctions.bg1, "Default")
+ AuctionFrameAuctions.bg1:SetPoint("TOPLEFT", 15, -72)
+ AuctionFrameAuctions.bg1:SetPoint("BOTTOMRIGHT", -545, 40)
+ AuctionFrameAuctions.bg1:SetFrameLevel(AuctionFrameAuctions.bg1:GetFrameLevel() - 1)
+
+ AuctionFrameAuctions.bg2 = CreateFrame("Frame", nil, AuctionFrameAuctions)
+ E:SetTemplate(AuctionFrameAuctions.bg2, "Default")
+ AuctionFrameAuctions.bg2:SetPoint("TOPLEFT", AuctionFrameAuctions.bg1, "TOPRIGHT", 3, 0)
+ AuctionFrameAuctions.bg2:SetPoint("BOTTOMRIGHT", AuctionFrame, -8, 40)
+ AuctionFrameAuctions.bg2:SetFrameLevel(AuctionFrameAuctions.bg2:GetFrameLevel() - 1)
+end
+
+S:AddCallbackForAddon("Blizzard_AuctionUI", "AuctionHouse", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/BGScore.lua b/ElvUI/Modules/Skins/Blizzard/BGScore.lua
new file mode 100644
index 0000000..54df65b
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/BGScore.lua
@@ -0,0 +1,80 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local split = string.split
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.bgscore ~= true then return end
+
+ E:CreateBackdrop(WorldStateScoreFrame, "Transparent")
+ WorldStateScoreFrame.backdrop:SetPoint("TOPLEFT", 10, -15)
+ WorldStateScoreFrame.backdrop:SetPoint("BOTTOMRIGHT", -113, 67)
+
+ E:StripTextures(WorldStateScoreFrame)
+
+ E:StripTextures(WorldStateScoreScrollFrame)
+ S:HandleScrollBar(WorldStateScoreScrollFrameScrollBar)
+
+ local tab
+ for i = 1, 3 do
+ tab = _G["WorldStateScoreFrameTab"..i]
+
+ S:HandleTab(tab)
+
+ _G["WorldStateScoreFrameTab"..i.."Text"]:SetPoint("CENTER", 0, 2)
+ end
+
+ S:HandleButton(WorldStateScoreFrameLeaveButton)
+ S:HandleCloseButton(WorldStateScoreFrameCloseButton)
+
+ E:StyleButton(WorldStateScoreFrameKB)
+ E:StyleButton(WorldStateScoreFrameDeaths)
+ E:StyleButton(WorldStateScoreFrameHK)
+ E:StyleButton(WorldStateScoreFrameHonorGained)
+ E:StyleButton(WorldStateScoreFrameName)
+
+ for i = 1, 5 do
+ E:StyleButton(_G["WorldStateScoreColumn"..i])
+ end
+
+ hooksecurefunc("WorldStateScoreFrame_Update", function()
+ local offset = FauxScrollFrame_GetOffset(WorldStateScoreScrollFrame)
+
+ for i = 1, MAX_WORLDSTATE_SCORE_BUTTONS do
+ local index = offset + i
+ local name, _, _, _, _, faction = GetBattlefieldScore(index)
+ if name then
+ local n, r = split("-", name, 2)
+ local myName = UnitName("player")
+
+ if name == myName then
+ n = "> "..n.." <"
+ end
+
+ if r then
+ local color
+
+ if faction == 1 then
+ color = "|cff00adf0"
+ else
+ color = "|cffff1919"
+ end
+ r = color..r.."|r"
+ n = n.."|cffffffff - |r"..r
+ end
+
+ local classTextColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classToken] or RAID_CLASS_COLORS[classToken]
+
+ _G["WorldStateScoreButton"..i.."NameText"]:SetText(n)
+ _G["WorldStateScoreButton"..i.."NameText"]:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b)
+ end
+ end
+ end)
+end
+
+S:AddCallback("WorldStateScore", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Bags.lua b/ElvUI/Modules/Skins/Blizzard/Bags.lua
new file mode 100644
index 0000000..405817b
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Bags.lua
@@ -0,0 +1,149 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local match = string.match
+--WoW API / Variables
+local GetItemQualityColor = GetItemQualityColor
+local GetContainerItemLink = GetContainerItemLink
+local BANK_CONTAINER = BANK_CONTAINER
+local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
+
+function S:ContainerFrame_Update()
+ local id = this:GetID()
+ local name = this:GetName()
+ local _, itemButton, itemLink, quality
+
+ for i = 1, this.size, 1 do
+ itemButton = _G[name.."Item"..i]
+
+ itemLink = GetContainerItemLink(id, itemButton:GetID())
+ if itemLink then
+ _, _, quality = GetItemInfo(match(itemLink, "item:(%d+)"))
+ if quality then
+ itemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ itemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ else
+ itemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+end
+
+function S:BankFrameItemButton_OnUpdate()
+ if not this.isBag then
+ local itemLink = GetContainerItemLink(BANK_CONTAINER, this:GetID())
+ if itemLink then
+ local _, _, quality = GetItemInfo(match(itemLink, "item:(%d+)"))
+ if quality then
+ this:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ else
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+end
+
+local function LoadSkin()
+ if not E.private.skins.blizzard.enable and E.private.skins.blizzard.bags and not E.private.bags.enable then return end
+
+ -- ContainerFrame
+ local containerFrame, containerFrameClose
+ for i = 1, NUM_CONTAINER_FRAMES, 1 do
+ containerFrame = _G["ContainerFrame"..i]
+ containerFrameClose = _G["ContainerFrame"..i.."CloseButton"]
+
+ E:StripTextures(containerFrame, true)
+ E:CreateBackdrop(containerFrame, "Transparent")
+ containerFrame.backdrop:SetPoint("TOPLEFT", 9, -4)
+ containerFrame.backdrop:SetPoint("BOTTOMRIGHT", -4, 2)
+
+ S:HandleCloseButton(containerFrameClose)
+
+ S:SecureHookScript(containerFrame, "OnShow", "ContainerFrame_Update")
+
+ local itemButton, itemButtonIcon
+ for k = 1, MAX_CONTAINER_ITEMS, 1 do
+ itemButton = _G["ContainerFrame"..i.."Item"..k]
+ itemButtonIcon = _G["ContainerFrame"..i.."Item"..k.."IconTexture"]
+ itemButtonCooldown = _G["ContainerFrame"..i.."Item"..k.."Cooldown"]
+
+ itemButton:SetNormalTexture("")
+
+ E:SetTemplate(itemButton, "Default", true)
+ E:StyleButton(itemButton)
+
+ E:SetInside(itemButtonIcon)
+ itemButtonIcon:SetTexCoord(unpack(E.TexCoords))
+
+ if itemButtonCooldown then
+ E:RegisterCooldown(itemButtonCooldown)
+ end
+ end
+ end
+
+ S:SecureHook("ContainerFrame_Update")
+
+ -- BankFrame
+ E:CreateBackdrop(BankFrame, "Transparent")
+ BankFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ BankFrame.backdrop:SetPoint("BOTTOMRIGHT", -26, 93)
+
+ E:StripTextures(BankFrame, true)
+
+ S:HandleCloseButton(BankCloseButton)
+
+ local button, buttonIcon
+ for i = 1, NUM_BANKGENERIC_SLOTS, 1 do
+ button = _G["BankFrameItem"..i]
+ buttonIcon = _G["BankFrameItem"..i.."IconTexture"]
+
+ button:SetNormalTexture("")
+
+ E:SetTemplate(button, "Default", true)
+ E:StyleButton(button)
+
+ E:SetInside(buttonIcon)
+ buttonIcon:SetTexCoord(unpack(E.TexCoords))
+ end
+
+ BankFrame.itemBackdrop = CreateFrame("Frame", "BankFrameItemBackdrop", BankFrame)
+ E:SetTemplate(BankFrame.itemBackdrop, "Default")
+ BankFrame.itemBackdrop:SetPoint("TOPLEFT", BankFrameItem1, "TOPLEFT", -6, 6)
+ BankFrame.itemBackdrop:SetPoint("BOTTOMRIGHT", BankFrameItem24, "BOTTOMRIGHT", 6, -6)
+ BankFrame.itemBackdrop:SetFrameLevel(BankFrame:GetFrameLevel())
+
+ for i = 1, NUM_BANKBAGSLOTS, 1 do
+ button = _G["BankFrameBag"..i]
+ buttonIcon = _G["BankFrameBag"..i.."IconTexture"]
+
+ button:SetNormalTexture("")
+
+ E:SetTemplate(button, "Default", true)
+ E:StyleButton(button)
+
+ E:SetInside(buttonIcon)
+ buttonIcon:SetTexCoord(unpack(E.TexCoords))
+
+ E:SetInside(_G["BankFrameBag"..i.."HighlightFrameTexture"])
+ _G["BankFrameBag"..i.."HighlightFrameTexture"]:SetTexture(unpack(E["media"].rgbvaluecolor), 0.3)
+ end
+
+ BankFrame.bagBackdrop = CreateFrame("Frame", "BankFrameBagBackdrop", BankFrame)
+ E:SetTemplate(BankFrame.bagBackdrop, "Default")
+ BankFrame.bagBackdrop:SetPoint("TOPLEFT", BankFrameBag1, "TOPLEFT", -6, 6)
+ BankFrame.bagBackdrop:SetPoint("BOTTOMRIGHT", BankFrameBag6, "BOTTOMRIGHT", 6, -6)
+ BankFrame.bagBackdrop:SetFrameLevel(BankFrame:GetFrameLevel())
+
+ S:HandleButton(BankFramePurchaseButton)
+
+ S:SecureHook("BankFrameItemButton_OnUpdate")
+end
+
+S:AddCallback("SkinBags", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Battlefield.lua b/ElvUI/Modules/Skins/Blizzard/Battlefield.lua
new file mode 100644
index 0000000..eff731f
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Battlefield.lua
@@ -0,0 +1,30 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.battlefield ~= true then return end
+
+ E:StripTextures(BattlefieldFrame)
+
+ E:CreateBackdrop(BattlefieldFrame, "Transparent")
+ BattlefieldFrame.backdrop:SetPoint("TOPLEFT", 11, -12)
+ BattlefieldFrame.backdrop:SetPoint("BOTTOMRIGHT", -34, 74)
+
+ E:StripTextures(BattlefieldListScrollFrame)
+ S:HandleScrollBar(BattlefieldListScrollFrameScrollBar)
+
+ BattlefieldFrameZoneDescription:SetTextColor(1, 1, 1)
+
+ S:HandleButton(BattlefieldFrameCancelButton)
+ S:HandleButton(BattlefieldFrameJoinButton)
+ S:HandleButton(BattlefieldFrameGroupJoinButton)
+
+ S:HandleCloseButton(BattlefieldFrameCloseButton)
+end
+
+S:AddCallback("Battlefield", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Binding.lua b/ElvUI/Modules/Skins/Blizzard/Binding.lua
new file mode 100644
index 0000000..fd99d0b
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Binding.lua
@@ -0,0 +1,39 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.binding ~= true then return end
+
+ E:StripTextures(KeyBindingFrame)
+ E:CreateBackdrop(KeyBindingFrame, "Transparent")
+ KeyBindingFrame.backdrop:SetPoint("TOPLEFT", 2, 0)
+ KeyBindingFrame.backdrop:SetPoint("BOTTOMRIGHT", -42, 12)
+
+ local bindingKey1, bindingKey2
+ for i = 1, KEY_BINDINGS_DISPLAYED do
+ bindingKey1 = _G["KeyBindingFrameBinding"..i.."Key1Button"]
+ bindingKey2 = _G["KeyBindingFrameBinding"..i.."Key2Button"]
+
+ S:HandleButton(bindingKey1)
+ S:HandleButton(bindingKey2)
+ bindingKey2:SetPoint("LEFT", bindingKey1, "RIGHT", 1, 0)
+ end
+
+ S:HandleScrollBar(KeyBindingFrameScrollFrameScrollBar)
+
+ S:HandleCheckBox(KeyBindingFrameCharacterButton)
+
+ S:HandleButton(KeyBindingFrameDefaultButton)
+ S:HandleButton(KeyBindingFrameCancelButton)
+ S:HandleButton(KeyBindingFrameOkayButton)
+ KeyBindingFrameOkayButton:SetPoint("RIGHT", KeyBindingFrameCancelButton, "LEFT", -3, 0)
+ S:HandleButton(KeyBindingFrameUnbindButton)
+ KeyBindingFrameUnbindButton:SetPoint("RIGHT", KeyBindingFrameOkayButton, "LEFT", -3, 0)
+end
+
+S:AddCallbackForAddon("Blizzard_BindingUI", "Binding", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Character.lua b/ElvUI/Modules/Skins/Blizzard/Character.lua
new file mode 100644
index 0000000..3b3142b
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Character.lua
@@ -0,0 +1,333 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local pairs = pairs
+local find, getn = string.find, table.getn
+--WoW API / Variables
+local GetInventoryItemTexture = GetInventoryItemTexture
+local GetInventoryItemQuality = GetInventoryItemQuality
+local GetNumFactions = GetNumFactions
+local FauxScrollFrame_GetOffset = FauxScrollFrame_GetOffset
+local NUM_FACTIONS_DISPLAYED = NUM_FACTIONS_DISPLAYED
+local CHARACTERFRAME_SUBFRAMES = CHARACTERFRAME_SUBFRAMES
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.character ~= true then return end
+
+ -- Character Frame
+ E:StripTextures(CharacterFrame, true)
+
+ E:CreateBackdrop(CharacterFrame, "Transparent")
+ CharacterFrame.backdrop:SetPoint("TOPLEFT", 11, -12)
+ CharacterFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 76)
+
+ S:HandleCloseButton(CharacterFrameCloseButton)
+
+ for i = 1, getn(CHARACTERFRAME_SUBFRAMES) do
+ local tab = _G["CharacterFrameTab"..i]
+ S:HandleTab(tab)
+ end
+
+ E:StripTextures(PaperDollFrame)
+
+ S:HandleRotateButton(CharacterModelFrameRotateLeftButton)
+ CharacterModelFrameRotateLeftButton:SetPoint("TOPLEFT", 3, -3)
+ S:HandleRotateButton(CharacterModelFrameRotateRightButton)
+ CharacterModelFrameRotateRightButton:SetPoint("TOPLEFT", CharacterModelFrameRotateLeftButton, "TOPRIGHT", 3, 0)
+
+ E:StripTextures(CharacterAttributesFrame)
+
+ local function HandleResistanceFrame(frameName)
+ for i = 1, 5 do
+ local frame = _G[frameName..i]
+ frame:SetWidth(24)
+ frame:SetHeight(24)
+
+ local icon, text = _G[frameName..i]:GetRegions()
+ E:SetInside(icon)
+ icon:SetDrawLayer("ARTWORK")
+ text:SetDrawLayer("OVERLAY")
+
+ E:SetTemplate(frame, "Default")
+
+ if i ~= 1 then
+ frame:ClearAllPoints()
+ frame:SetPoint("TOP", _G[frameName..i-1], "BOTTOM", 0, -(E.Border + E.Spacing))
+ end
+ end
+ end
+
+ HandleResistanceFrame("MagicResFrame")
+
+ MagicResFrame1:GetRegions():SetTexCoord(0.21875, 0.8125, 0.25, 0.32421875) --Arcane
+ MagicResFrame2:GetRegions():SetTexCoord(0.21875, 0.8125, 0.0234375, 0.09765625) --Fire
+ MagicResFrame3:GetRegions():SetTexCoord(0.21875, 0.8125, 0.13671875, 0.2109375) --Nature
+ MagicResFrame4:GetRegions():SetTexCoord(0.21875, 0.8125, 0.36328125, 0.4375) --Frost
+ MagicResFrame5:GetRegions():SetTexCoord(0.21875, 0.8125, 0.4765625, 0.55078125) --Shadow
+
+ local slots = {"HeadSlot", "NeckSlot", "ShoulderSlot", "BackSlot", "ChestSlot", "ShirtSlot", "TabardSlot", "WristSlot",
+ "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot", "Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot",
+ "MainHandSlot", "SecondaryHandSlot", "RangedSlot", "AmmoSlot"
+ }
+
+ for _, slot in pairs(slots) do
+ local icon = _G["Character"..slot.."IconTexture"]
+ local cooldown = _G["Character"..slot.."Cooldown"]
+
+ slot = _G["Character"..slot]
+ E:StripTextures(slot)
+ E:StyleButton(slot, false)
+ E:SetTemplate(slot, "Default", true, true)
+
+ icon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(icon)
+
+ slot:SetFrameLevel(PaperDollFrame:GetFrameLevel() + 2)
+
+ if cooldown then
+ E:RegisterCooldown(cooldown)
+ end
+ end
+
+ hooksecurefunc("PaperDollItemSlotButton_Update", function(cooldownOnly)
+ if cooldownOnly then return end
+
+ local textureName = GetInventoryItemTexture("player", this:GetID())
+ if textureName then
+ local rarity = GetInventoryItemQuality("player", this:GetID())
+ this:SetBackdropBorderColor(GetItemQualityColor(rarity))
+ else
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end)
+
+ E:StripTextures(ReputationFrame)
+
+ for i = 1, NUM_FACTIONS_DISPLAYED do
+ local factionBar = _G["ReputationBar"..i]
+ local factionHeader = _G["ReputationHeader"..i]
+ local factionName = _G["ReputationBar"..i.."FactionName"]
+ local factionAtWarCheck = _G["ReputationBar"..i.."AtWarCheck"]
+
+ E:StripTextures(factionBar)
+ E:CreateBackdrop(factionBar, "Default")
+ factionBar:SetStatusBarTexture(E.media.normTex)
+ factionBar:SetWidth(108)
+ factionBar:SetHeight(13)
+ E:RegisterStatusBar(factionBar)
+
+ if i == 1 then
+ factionBar:SetPoint("TOPLEFT", 190, -86)
+ end
+
+ factionName:SetPoint("LEFT", factionBar, "LEFT", -150, 0)
+ factionName:SetWidth(140)
+ factionName.SetWidth = E.noop
+
+ E:StripTextures(factionAtWarCheck)
+ factionAtWarCheck:SetPoint("LEFT", factionBar, "RIGHT", 0, 0)
+
+ factionAtWarCheck.Icon = factionAtWarCheck:CreateTexture(nil, "OVERLAY")
+ factionAtWarCheck.Icon:SetPoint("LEFT", 6, -8)
+ factionAtWarCheck.Icon:SetWidth(32)
+ factionAtWarCheck.Icon:SetHeight(32)
+ factionAtWarCheck.Icon:SetTexture("Interface\\Buttons\\UI-CheckBox-SwordCheck")
+
+ E:StripTextures(factionHeader)
+ factionHeader:SetNormalTexture(nil)
+ factionHeader.SetNormalTexture = E.noop
+ factionHeader:SetPoint("TOPLEFT", factionBar, "TOPLEFT", -175, 0)
+
+ factionHeader.Text = factionHeader:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(factionHeader.Text, nil, 22)
+ factionHeader.Text:SetPoint("LEFT", 3, 0)
+ factionHeader.Text:SetText("+")
+ end
+
+
+ -- PetPaperDollFrame
+ E:StripTextures(PetPaperDollFrame)
+
+ S:HandleButton(PetPaperDollCloseButton)
+
+ S:HandleRotateButton(PetModelFrameRotateLeftButton)
+ PetModelFrameRotateLeftButton:ClearAllPoints()
+ PetModelFrameRotateLeftButton:SetPoint("TOPLEFT", 3, -3)
+ S:HandleRotateButton(PetModelFrameRotateRightButton)
+ PetModelFrameRotateRightButton:ClearAllPoints()
+ PetModelFrameRotateRightButton:SetPoint("TOPLEFT", PetModelFrameRotateLeftButton, "TOPRIGHT", 3, 0)
+
+ E:StripTextures(PetAttributesFrame)
+
+ E:CreateBackdrop(PetResistanceFrame, "Default")
+ E:SetOutside(PetResistanceFrame.backdrop, PetMagicResFrame1, nil, nil, PetMagicResFrame5)
+
+ for i = 1, 5 do
+ local frame = _G["PetMagicResFrame"..i]
+ frame:SetWidth(24)
+ frame:SetHeight(24)
+ end
+
+ PetMagicResFrame1:GetRegions():SetTexCoord(0.21875, 0.78125, 0.25, 0.3203125)
+ PetMagicResFrame2:GetRegions():SetTexCoord(0.21875, 0.78125, 0.0234375, 0.09375)
+ PetMagicResFrame3:GetRegions():SetTexCoord(0.21875, 0.78125, 0.13671875, 0.20703125)
+ PetMagicResFrame4:GetRegions():SetTexCoord(0.21875, 0.78125, 0.36328125, 0.43359375)
+ PetMagicResFrame5:GetRegions():SetTexCoord(0.21875, 0.78125, 0.4765625, 0.546875)
+
+ E:StripTextures(PetPaperDollFrameExpBar)
+ PetPaperDollFrameExpBar:SetStatusBarTexture(E["media"].normTex)
+ E:RegisterStatusBar(PetPaperDollFrameExpBar)
+ E:CreateBackdrop(PetPaperDollFrameExpBar, "Default")
+
+ local function updHappiness()
+ local happiness = GetPetHappiness()
+ local _, isHunterPet = HasPetUI()
+ if not happiness or not isHunterPet then
+ return
+ end
+ local texture = this:GetRegions()
+ if happiness == 1 then
+ texture:SetTexCoord(0.41, 0.53, 0.06, 0.30)
+ elseif happiness == 2 then
+ texture:SetTexCoord(0.22, 0.345, 0.06, 0.30)
+ elseif happiness == 3 then
+ texture:SetTexCoord(0.04, 0.15, 0.06, 0.30)
+ end
+ end
+
+ PetPaperDollPetInfo:SetPoint("TOPLEFT", PetModelFrameRotateLeftButton, "BOTTOMLEFT", 9, -3)
+ PetPaperDollPetInfo:GetRegions():SetTexCoord(0.04, 0.15, 0.06, 0.30)
+ PetPaperDollPetInfo:SetFrameLevel(PetModelFrame:GetFrameLevel() + 2)
+ E:CreateBackdrop(PetPaperDollPetInfo, "Default")
+ PetPaperDollPetInfo:SetWidth(24)
+ PetPaperDollPetInfo:SetHeight(24)
+
+ PetPaperDollPetInfo:RegisterEvent("UNIT_HAPPINESS")
+ PetPaperDollPetInfo:SetScript("OnEvent", updHappiness)
+ PetPaperDollPetInfo:SetScript("OnShow", updHappiness)
+
+
+ -- Reputation Frame
+ hooksecurefunc("ReputationFrame_Update", function()
+ local numFactions = GetNumFactions()
+ local factionIndex, factionHeader
+ local factionOffset = FauxScrollFrame_GetOffset(ReputationListScrollFrame)
+ for i = 1, NUM_FACTIONS_DISPLAYED, 1 do
+ factionHeader = _G["ReputationHeader"..i]
+ factionIndex = factionOffset + i
+ if factionIndex <= numFactions then
+ if factionHeader.isCollapsed then
+ factionHeader.Text:SetText("+")
+ else
+ factionHeader.Text:SetText("-")
+ end
+ end
+ end
+ end)
+
+ E:StripTextures(ReputationListScrollFrame)
+ S:HandleScrollBar(ReputationListScrollFrameScrollBar)
+
+ E:StripTextures(ReputationDetailFrame)
+ E:SetTemplate(ReputationDetailFrame, "Transparent")
+ ReputationDetailFrame:SetPoint("TOPLEFT", ReputationFrame, "TOPRIGHT", -31, -12)
+
+ S:HandleCloseButton(ReputationDetailCloseButton)
+ ReputationDetailCloseButton:SetPoint("TOPRIGHT", 2, 2)
+
+ S:HandleCheckBox(ReputationDetailAtWarCheckBox)
+ S:HandleCheckBox(ReputationDetailInactiveCheckBox)
+ S:HandleCheckBox(ReputationDetailMainScreenCheckBox)
+
+
+ -- Skill Frame
+ E:StripTextures(SkillFrame)
+
+ SkillFrameExpandButtonFrame:DisableDrawLayer("BACKGROUND")
+
+ SkillFrameCollapseAllButton:SetPoint("LEFT", SkillFrameExpandTabLeft, "RIGHT", -40, -3)
+ SkillFrameCollapseAllButton:SetNormalTexture("")
+ SkillFrameCollapseAllButton.SetNormalTexture = E.noop
+ SkillFrameCollapseAllButton:SetHighlightTexture(nil)
+
+ SkillFrameCollapseAllButton.Text = SkillFrameCollapseAllButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(SkillFrameCollapseAllButton.Text, nil, 22)
+ SkillFrameCollapseAllButton.Text:SetPoint("CENTER", -10, 0)
+ SkillFrameCollapseAllButton.Text:SetText("+")
+
+ hooksecurefunc(SkillFrameCollapseAllButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ else
+ self.Text:SetText("+")
+ end
+ end)
+
+ S:HandleButton(SkillFrameCancelButton)
+
+ for i = 1, SKILLS_TO_DISPLAY do
+ local bar = _G["SkillRankFrame"..i]
+ bar:SetStatusBarTexture(E.media.normTex)
+ E:RegisterStatusBar(bar)
+ E:CreateBackdrop(bar, "Default")
+
+ E:StripTextures(_G["SkillRankFrame"..i.."Border"])
+ _G["SkillRankFrame"..i.."Background"]:SetTexture(nil)
+
+ local label = _G["SkillTypeLabel"..i]
+ label:SetNormalTexture("")
+ label.SetNormalTexture = E.noop
+ label:SetHighlightTexture(nil)
+
+ label.Text = label:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(label.Text, nil, 22)
+ label.Text:SetPoint("LEFT", 3, 0)
+ label.Text:SetText("+")
+
+ hooksecurefunc(label, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ else
+ self.Text:SetText("+")
+ end
+ end)
+ end
+
+ E:StripTextures(SkillListScrollFrame)
+ S:HandleScrollBar(SkillListScrollFrameScrollBar)
+
+ E:StripTextures(SkillDetailScrollFrame)
+ S:HandleScrollBar(SkillDetailScrollFrameScrollBar)
+
+ E:StripTextures(SkillDetailStatusBar)
+ SkillDetailStatusBar:SetParent(SkillDetailScrollFrame)
+ E:CreateBackdrop(SkillDetailStatusBar, "Default")
+ SkillDetailStatusBar:SetStatusBarTexture(E.media.normTex)
+ E:RegisterStatusBar(SkillDetailStatusBar)
+
+ E:StripTextures(SkillDetailStatusBarUnlearnButton)
+ SkillDetailStatusBarUnlearnButton:SetPoint("LEFT", SkillDetailStatusBarBorder, "RIGHT", -2, -5)
+ SkillDetailStatusBarUnlearnButton:SetWidth(36)
+ SkillDetailStatusBarUnlearnButton:SetHeight(36)
+
+ SkillDetailStatusBarUnlearnButton.Icon = SkillDetailStatusBarUnlearnButton:CreateTexture(nil, "OVERLAY")
+ SkillDetailStatusBarUnlearnButton.Icon:SetPoint("LEFT", 7, 5)
+ SkillDetailStatusBarUnlearnButton.Icon:SetWidth(18)
+ SkillDetailStatusBarUnlearnButton.Icon:SetHeight(18)
+ SkillDetailStatusBarUnlearnButton.Icon:SetTexture("Interface\\Buttons\\UI-GroupLoot-Pass-Up")
+
+
+ -- Honor Frame
+ hooksecurefunc("HonorFrame_Update", function()
+ E:StripTextures(HonorFrame)
+
+ HonorFrameProgressBar:SetStatusBarTexture(E.media.normTex)
+ E:RegisterStatusBar(HonorFrameProgressBar)
+ end)
+end
+
+S:AddCallback("Character", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Craft.lua b/ElvUI/Modules/Skins/Blizzard/Craft.lua
new file mode 100644
index 0000000..e8512b3
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Craft.lua
@@ -0,0 +1,165 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local find, match, split = string.find, string.match, string.split
+--WoW API / Variables
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local GetCraftReagentInfo = GetCraftReagentInfo
+local GetCraftItemLink = GetCraftItemLink
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or not E.private.skins.blizzard.craft ~= true then return end
+
+ E:StripTextures(CraftFrame, true)
+ E:CreateBackdrop(CraftFrame, "Transparent")
+ CraftFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ CraftFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 74)
+
+ E:StripTextures(CraftRankFrameBorder)
+ CraftRankFrame:SetWidth(322)
+ CraftRankFrame:SetHeight(16)
+ CraftRankFrame:ClearAllPoints()
+ CraftRankFrame:SetPoint("TOP", -10, -45)
+ E:CreateBackdrop(CraftRankFrame)
+ CraftRankFrame:SetStatusBarTexture(E["media"].normTex)
+ CraftRankFrame:SetStatusBarColor(0.13, 0.35, 0.80)
+ E:RegisterStatusBar(CraftRankFrame)
+
+ E:StripTextures(CraftExpandButtonFrame)
+ E:StripTextures(CraftDetailScrollChildFrame)
+
+ E:StripTextures(CraftListScrollFrame)
+ S:HandleScrollBar(CraftListScrollFrameScrollBar)
+
+ E:StripTextures(CraftDetailScrollFrame)
+ S:HandleScrollBar(CraftDetailScrollFrameScrollBar)
+
+ E:StripTextures(CraftIcon)
+
+ S:HandleButton(CraftCreateButton)
+ S:HandleButton(CraftCancelButton)
+
+ S:HandleCloseButton(CraftFrameCloseButton)
+
+ for i = 1, MAX_CRAFT_REAGENTS do
+ local reagent = _G["CraftReagent"..i]
+ local icon = _G["CraftReagent"..i.."IconTexture"]
+ local count = _G["CraftReagent"..i.."Count"]
+ local nameFrame = _G["CraftReagent"..i.."NameFrame"]
+
+ icon:SetTexCoord(unpack(E.TexCoords))
+ icon:SetDrawLayer("OVERLAY")
+
+ icon.backdrop = CreateFrame("Frame", nil, reagent)
+ icon.backdrop:SetFrameLevel(reagent:GetFrameLevel() - 1)
+ E:SetTemplate(icon.backdrop, "Default")
+ E:SetOutside(icon.backdrop, icon)
+
+ icon:SetParent(icon.backdrop)
+ count:SetParent(icon.backdrop)
+ count:SetDrawLayer("OVERLAY")
+
+ E:Kill(nameFrame)
+ end
+
+ hooksecurefunc("CraftFrame_SetSelection", function(id)
+ E:SetTemplate(CraftIcon, "Default", true)
+ E:StyleButton(CraftIcon, nil, true)
+ if CraftIcon:GetNormalTexture() then
+ CraftIcon:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(CraftIcon:GetNormalTexture())
+ end
+
+ CraftIcon:SetWidth(40)
+ CraftIcon:SetHeight(40)
+ CraftIcon:SetPoint("TOPLEFT", 4, -3)
+
+ CraftRequirements:SetTextColor(1, 0.80, 0.10)
+
+ local skillLink = GetCraftItemLink(id)
+ if skillLink then
+ local _, _, quality = GetItemInfo(match(skillLink, "enchant:(%d+)"))
+ if quality then
+ CraftIcon:SetBackdropBorderColor(GetItemQualityColor(quality))
+ CraftName:SetTextColor(GetItemQualityColor(quality))
+ else
+ CraftIcon:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ CraftName:SetTextColor(1, 1, 1)
+ end
+ end
+
+ local numReagents = GetCraftNumReagents(id)
+ for i = 1, numReagents, 1 do
+ local icon = _G["CraftReagent"..i.."IconTexture"]
+ local name = _G["CraftReagent"..i.."Name"]
+
+ local _, _, reagentCount, playerReagentCount = GetCraftReagentInfo(id, i)
+ local reagentLink = GetCraftReagentItemLink(id, i)
+ if reagentLink then
+ local _, _, quality = GetItemInfo(match(reagentLink, "item:(%d+)"))
+ if quality then
+ icon.backdrop:SetBackdropBorderColor(GetItemQualityColor(quality))
+ if playerReagentCount < reagentCount then
+ name:SetTextColor(0.5, 0.5, 0.5)
+ else
+ name:SetTextColor(GetItemQualityColor(quality))
+ end
+ else
+ icon.backdrop:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end
+ end)
+
+ for i = 1, CRAFTS_DISPLAYED do
+ local craftButton = _G["Craft"..i]
+ craftButton:SetNormalTexture("")
+ craftButton.SetNormalTexture = E.noop
+
+ _G["Craft"..i.."Highlight"]:SetTexture("")
+ _G["Craft"..i.."Highlight"].SetTexture = E.noop
+
+ craftButton.Text = craftButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(craftButton.Text, nil, 22)
+ craftButton.Text:SetPoint("LEFT", 3, 0)
+ craftButton.Text:SetText("+")
+
+ hooksecurefunc(craftButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ elseif find(texture, "PlusButton") then
+ self.Text:SetText("+")
+ else
+ self.Text:SetText("")
+ end
+ end)
+ end
+
+ CraftCollapseAllButton:SetNormalTexture("")
+ CraftCollapseAllButton.SetNormalTexture = E.noop
+ CraftCollapseAllButton:SetHighlightTexture("")
+ CraftCollapseAllButton.SetHighlightTexture = E.noop
+ CraftCollapseAllButton:SetDisabledTexture("")
+ CraftCollapseAllButton.SetDisabledTexture = E.noop
+
+ CraftCollapseAllButton.Text = CraftCollapseAllButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(CraftCollapseAllButton.Text, nil, 22)
+ CraftCollapseAllButton.Text:SetPoint("LEFT", 3, 0)
+ CraftCollapseAllButton.Text:SetText("+")
+
+ hooksecurefunc(CraftCollapseAllButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ else
+ self.Text:SetText("+")
+ end
+ end)
+end
+
+S:AddCallbackForAddon("Blizzard_CraftUI", "Craft", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Debug.lua b/ElvUI/Modules/Skins/Blizzard/Debug.lua
new file mode 100644
index 0000000..a3ecc29
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Debug.lua
@@ -0,0 +1,71 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local getn = table.getn
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.debug ~= true then return end
+
+ -- ScriptErrorsFrame:SetParent(E.UIParent)
+ ScriptErrorsFrame:SetScale(UIParent:GetScale())
+ E:SetTemplate(ScriptErrorsFrame, "Transparent")
+ S:HandleScrollBar(ScriptErrorsFrameScrollFrameScrollBar)
+ S:HandleCloseButton(ScriptErrorsFrameClose)
+ E:FontTemplate(ScriptErrorsFrameScrollFrameText, nil, 13)
+ E:CreateBackdrop(ScriptErrorsFrameScrollFrame, "Default")
+ ScriptErrorsFrameScrollFrame:SetFrameLevel(ScriptErrorsFrameScrollFrame:GetFrameLevel() + 2)
+
+ E:SetTemplate(EventTraceFrame, "Transparent")
+ S:HandleSliderFrame(EventTraceFrameScroll)
+
+ local texs = {
+ "TopLeft",
+ "TopRight",
+ "Top",
+ "BottomLeft",
+ "BottomRight",
+ "Bottom",
+ "Left",
+ "Right",
+ "TitleBG",
+ "DialogBG",
+ }
+
+ for i = 1, getn(texs) do
+ _G["ScriptErrorsFrame"..texs[i]]:SetTexture(nil)
+ _G["EventTraceFrame"..texs[i]]:SetTexture(nil)
+ end
+
+ S:HandleButton(ScriptErrorsFrame.reload)
+ S:HandleNextPrevButton(ScriptErrorsFrame.previous)
+ S:HandleNextPrevButton(ScriptErrorsFrame.next)
+ S:HandleButton(ScriptErrorsFrame.close)
+
+ S:HandleButton(ScriptErrorsFrame.close)
+
+ ScriptErrorsFrame.reload:SetPoint("BOTTOMLEFT", 12, 8)
+ ScriptErrorsFrame.previous:SetPoint("BOTTOM", ScriptErrorsFrame, "BOTTOM", -50, 7)
+ ScriptErrorsFrame.next:SetPoint("BOTTOM", ScriptErrorsFrame, "BOTTOM", 50, 7)
+ ScriptErrorsFrame.close:SetPoint("BOTTOMRIGHT", -12, 8)
+
+ local noscalemult = E.mult * GetCVar("uiScale")
+ HookScript(FrameStackTooltip, "OnShow", function()
+ E:SetTemplate(this, "Transparent")
+ this:SetBackdropColor(unpack(E["media"].backdropfadecolor))
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end)
+
+ HookScript(EventTraceTooltip, "OnShow", function()
+ E:SetTemplate(this, "Transparent")
+ end)
+
+ S:HandleCloseButton(EventTraceFrameCloseButton)
+end
+
+S:AddCallbackForAddon("!DebugTools", "SkinDebugTools", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/DressingRoom.lua b/ElvUI/Modules/Skins/Blizzard/DressingRoom.lua
new file mode 100644
index 0000000..ff718a9
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/DressingRoom.lua
@@ -0,0 +1,43 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+--WoW API / Variables
+local SetDressUpBackground = SetDressUpBackground
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.dressingroom ~= true then return end
+
+ E:StripTextures(DressUpFrame)
+ E:CreateBackdrop(DressUpFrame, "Transparent")
+ DressUpFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ DressUpFrame.backdrop:SetPoint("BOTTOMRIGHT", -33, 73)
+
+ E:Kill(DressUpFramePortrait)
+
+ SetDressUpBackground()
+ DressUpBackgroundTopLeft:SetDesaturated(true)
+ DressUpBackgroundTopRight:SetDesaturated(true)
+ DressUpBackgroundBotLeft:SetDesaturated(true)
+ DressUpBackgroundBotRight:SetDesaturated(true)
+
+ DressUpFrameDescriptionText:SetPoint("CENTER", DressUpFrameTitleText, "BOTTOM", -5, -22)
+
+ S:HandleCloseButton(DressUpFrameCloseButton)
+
+ S:HandleRotateButton(DressUpModelRotateLeftButton)
+ DressUpModelRotateLeftButton:SetPoint("TOPLEFT", DressUpFrame, 25, -79)
+ S:HandleRotateButton(DressUpModelRotateRightButton)
+ DressUpModelRotateRightButton:SetPoint("TOPLEFT", DressUpModelRotateLeftButton, "TOPRIGHT", 3, 0)
+
+ S:HandleButton(DressUpFrameCancelButton)
+ DressUpFrameCancelButton:SetPoint("CENTER", DressUpFrame, "TOPLEFT", 306, -423)
+ S:HandleButton(DressUpFrameResetButton)
+ DressUpFrameResetButton:SetPoint("RIGHT", DressUpFrameCancelButton, "LEFT", -3, 0)
+
+ E:CreateBackdrop(DressUpModel, "Default")
+ E:SetOutside(DressUpModel.backdrop, DressUpBackgroundTopLeft, nil, nil, DressUpModel)
+end
+
+S:AddCallback("DressingRoom", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Friends.lua b/ElvUI/Modules/Skins/Blizzard/Friends.lua
new file mode 100644
index 0000000..54abd87
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Friends.lua
@@ -0,0 +1,434 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local upper = string.upper
+--WoW API / Variables
+local GetWhoInfo = GetWhoInfo
+local GetGuildRosterInfo = GetGuildRosterInfo
+local GUILDMEMBERS_TO_DISPLAY = GUILDMEMBERS_TO_DISPLAY
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS
+local hooksecurefunc = hooksecurefunc
+
+function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.friends ~= true then return end
+
+ -- Friends Frame
+ E:StripTextures(FriendsFrame, true)
+ E:CreateBackdrop(FriendsFrame, "Transparent")
+ FriendsFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ FriendsFrame.backdrop:SetPoint("BOTTOMRIGHT", -33, 76)
+
+ S:HandleCloseButton(FriendsFrameCloseButton)
+
+ for i = 1, 4 do
+ S:HandleTab(_G["FriendsFrameTab"..i])
+ end
+
+ -- Friends List Frame
+ for i = 1, 2 do
+ local tab = _G["FriendsFrameToggleTab"..i]
+ E:StripTextures(tab)
+ E:CreateBackdrop(tab, "Default", true)
+ tab.backdrop:SetPoint("TOPLEFT", 3, -7)
+ tab.backdrop:SetPoint("BOTTOMRIGHT", -2, -1)
+
+ tab:SetScript("OnEnter", S.SetModifiedBackdrop)
+ tab:SetScript("OnLeave", S.SetOriginalBackdrop)
+ end
+
+
+ local r, g, b = 0.8, 0.8, 0.8
+ local function StyleButton(f, scale)
+ f:SetHighlightTexture(nil)
+ local width, height = (f:GetWidth() * (scale or 0.5)), f:GetHeight()
+
+ local leftGrad = f:CreateTexture(nil, "HIGHLIGHT")
+ leftGrad:SetWidth(width)
+ leftGrad:SetHeight(height)
+ leftGrad:SetPoint("LEFT", f, "CENTER")
+ leftGrad:SetTexture(E.media.blankTex)
+ leftGrad:SetGradientAlpha("Horizontal", r, g, b, 0.35, r, g, b, 0)
+
+ local rightGrad = f:CreateTexture(nil, "HIGHLIGHT")
+ rightGrad:SetWidth(width)
+ rightGrad:SetHeight(height)
+ rightGrad:SetPoint("RIGHT", f, "CENTER")
+ rightGrad:SetTexture(E.media.blankTex)
+ rightGrad:SetGradientAlpha("Horizontal", r, g, b, 0, r, g, b, 0.35)
+ end
+
+ for i = 1, 10 do
+ StyleButton(_G["FriendsFrameFriendButton"..i], 0.6)
+ end
+
+ E:StripTextures(FriendsFrameFriendsScrollFrame)
+
+ S:HandleScrollBar(FriendsFrameFriendsScrollFrameScrollBar)
+
+ S:HandleButton(FriendsFrameAddFriendButton)
+ FriendsFrameAddFriendButton:SetPoint("BOTTOMLEFT", 17, 102)
+
+ S:HandleButton(FriendsFrameSendMessageButton)
+
+ S:HandleButton(FriendsFrameRemoveFriendButton)
+ FriendsFrameRemoveFriendButton:SetPoint("TOP", FriendsFrameAddFriendButton, "BOTTOM", 0, -2)
+
+ S:HandleButton(FriendsFrameGroupInviteButton)
+ FriendsFrameGroupInviteButton:SetPoint("TOP", FriendsFrameSendMessageButton, "BOTTOM", 0, -2)
+
+ -- Ignore List Frame
+ for i = 1, 2 do
+ local tab = _G["IgnoreFrameToggleTab"..i]
+ E:StripTextures(tab)
+ E:CreateBackdrop(tab, "Default", true)
+ tab.backdrop:SetPoint("TOPLEFT", 3, -7)
+ tab.backdrop:SetPoint("BOTTOMRIGHT", -2, -1)
+
+ tab:SetScript("OnEnter", function() S:SetModifiedBackdrop(this) end)
+ tab:SetScript("OnLeave", function() S:SetOriginalBackdrop(this) end)
+ end
+
+ S:HandleButton(FriendsFrameIgnorePlayerButton)
+ S:HandleButton(FriendsFrameStopIgnoreButton)
+
+ for i = 1, 20 do
+ StyleButton(_G["FriendsFrameIgnoreButton"..i])
+ end
+
+ -- Who Frame
+ WhoFrameColumnHeader3:ClearAllPoints()
+ WhoFrameColumnHeader3:SetPoint("TOPLEFT", 20, -70)
+
+ WhoFrameColumnHeader4:ClearAllPoints()
+ WhoFrameColumnHeader4:SetPoint("LEFT", WhoFrameColumnHeader3, "RIGHT", -2, -0)
+ WhoFrameColumnHeader4:SetWidth(48)
+
+ WhoFrameColumnHeader1:ClearAllPoints()
+ WhoFrameColumnHeader1:SetPoint("LEFT", WhoFrameColumnHeader4, "RIGHT", -2, -0)
+ WhoFrameColumnHeader1:SetWidth(105)
+
+ WhoFrameColumnHeader2:ClearAllPoints()
+ WhoFrameColumnHeader2:SetPoint("LEFT", WhoFrameColumnHeader1, "RIGHT", -2, -0)
+
+ for i = 1, 4 do
+ E:StripTextures(_G["WhoFrameColumnHeader"..i])
+ E:StyleButton(_G["WhoFrameColumnHeader"..i], nil, true)
+ end
+
+ S:HandleDropDownBox(WhoFrameDropDown)
+
+ for i = 1, 17 do
+ local button = _G["WhoFrameButton"..i]
+ local level = _G["WhoFrameButton"..i.."Level"]
+ local name = _G["WhoFrameButton"..i.."Name"]
+
+ button.icon = button:CreateTexture("$parentIcon", "ARTWORK")
+ button.icon:SetPoint("LEFT", 45, 0)
+ button.icon:SetWidth(15)
+ button.icon:SetHeight(15)
+ button.icon:SetTexture("Interface\\AddOns\\ElvUI\\Media\\Textures\\Icons-Classes")
+
+ E:CreateBackdrop(button, "Default", true)
+ button.backdrop:SetAllPoints(button.icon)
+ StyleButton(button)
+
+ level:ClearAllPoints()
+ level:SetPoint("TOPLEFT", 12, -2)
+
+ name:SetWidth(100)
+ name:SetHeight(14)
+ name:ClearAllPoints()
+ name:SetPoint("LEFT", 85, 0)
+
+ _G["WhoFrameButton"..i.."Class"]:Hide()
+ end
+
+ E:StripTextures(WhoListScrollFrame)
+ S:HandleScrollBar(WhoListScrollFrameScrollBar)
+
+ S:HandleEditBox(WhoFrameEditBox)
+ WhoFrameEditBox:SetPoint("BOTTOMLEFT", 17, 108)
+ WhoFrameEditBox:SetWidth(338)
+ WhoFrameEditBox:SetHeight(18)
+
+ S:HandleButton(WhoFrameWhoButton)
+ WhoFrameWhoButton:ClearAllPoints()
+ WhoFrameWhoButton:SetPoint("BOTTOMLEFT", 16, 82)
+
+ S:HandleButton(WhoFrameAddFriendButton)
+ WhoFrameAddFriendButton:SetPoint("LEFT", WhoFrameWhoButton, "RIGHT", 3, 0)
+ WhoFrameAddFriendButton:SetPoint("RIGHT", WhoFrameGroupInviteButton, "LEFT", -3, 0)
+
+ S:HandleButton(WhoFrameGroupInviteButton)
+
+ hooksecurefunc("WhoList_Update", function()
+ local whoOffset = FauxScrollFrame_GetOffset(WhoListScrollFrame)
+ local playerZone = GetRealZoneText()
+ local playerGuild = GetGuildInfo("player")
+ local playerRace = UnitRace("player")
+
+ for i = 1, WHOS_TO_DISPLAY, 1 do
+ local index = whoOffset + i
+ local button = _G["WhoFrameButton"..i]
+ local nameText = _G["WhoFrameButton"..i.."Name"]
+ local levelText = _G["WhoFrameButton"..i.."Level"]
+ local classText = _G["WhoFrameButton"..i.."Class"]
+ local variableText = _G["WhoFrameButton"..i.."Variable"]
+
+ local _, guild, level, race, class, zone = GetWhoInfo(index)
+ if class == UNKNOWN then return end
+
+ if class then
+ class = strupper(class)
+ end
+
+ local classTextColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+ local levelTextColor = GetQuestDifficultyColor(level)
+
+ if class then
+ button.icon:Show()
+ button.icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[class]))
+
+ nameText:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b)
+ levelText:SetTextColor(levelTextColor.r, levelTextColor.g, levelTextColor.b)
+
+ if zone == playerZone then
+ zone = "|cff00ff00"..zone
+ end
+ if guild == playerGuild then
+ guild = "|cff00ff00"..guild
+ end
+ if race == playerRace then
+ race = "|cff00ff00"..race
+ end
+
+ local columnTable = {zone, guild, race}
+
+ variableText:SetText(columnTable[UIDropDownMenu_GetSelectedID(WhoFrameDropDown)])
+ else
+ button.icon:Hide()
+ end
+ end
+ end)
+
+ -- Guild Frame
+ GuildFrameColumnHeader3:ClearAllPoints()
+ GuildFrameColumnHeader3:SetPoint("TOPLEFT", 20, -70)
+
+ GuildFrameColumnHeader4:ClearAllPoints()
+ GuildFrameColumnHeader4:SetPoint("LEFT", GuildFrameColumnHeader3, "RIGHT", -2, -0)
+ GuildFrameColumnHeader4:SetWidth(48)
+
+ GuildFrameColumnHeader1:ClearAllPoints()
+ GuildFrameColumnHeader1:SetPoint("LEFT", GuildFrameColumnHeader4, "RIGHT", -2, -0)
+ GuildFrameColumnHeader1:SetWidth(105)
+
+ GuildFrameColumnHeader2:ClearAllPoints()
+ GuildFrameColumnHeader2:SetPoint("LEFT", GuildFrameColumnHeader1, "RIGHT", -2, -0)
+ GuildFrameColumnHeader2:SetWidth(127)
+
+ for i = 1, GUILDMEMBERS_TO_DISPLAY do
+ local button = _G["GuildFrameButton"..i]
+
+ StyleButton(button)
+ StyleButton(_G["GuildFrameGuildStatusButton"..i])
+
+ button.icon = button:CreateTexture("$parentIcon", "ARTWORK")
+ button.icon:SetPoint("LEFT", 48, -3)
+ button.icon:SetWidth(15)
+ button.icon:SetHeight(15)
+ button.icon:SetTexture("Interface\\AddOns\\ElvUI\\Media\\Textures\\Icons-Classes")
+
+ E:CreateBackdrop(button, "Default", true)
+ button.backdrop:SetAllPoints(button.icon)
+
+ _G["GuildFrameButton"..i.."Level"]:ClearAllPoints()
+ _G["GuildFrameButton"..i.."Level"]:SetPoint("TOPLEFT", 10, -3)
+
+ _G["GuildFrameButton"..i.."Name"]:SetWidth(100)
+ _G["GuildFrameButton"..i.."Name"]:SetHeight(14)
+ _G["GuildFrameButton"..i.."Name"]:ClearAllPoints()
+ _G["GuildFrameButton"..i.."Name"]:SetPoint("LEFT", 85, -3)
+
+ _G["GuildFrameButton"..i.."Class"]:Hide()
+ end
+
+ hooksecurefunc("GuildStatus_Update", function()
+ if FriendsFrame.playerStatusFrame then
+ for i = 1, GUILDMEMBERS_TO_DISPLAY, 1 do
+ local button = _G["GuildFrameButton"..i]
+ local _, _, _, level, class, _, _, _, online = GetGuildRosterInfo(button.guildIndex)
+ if class == UNKNOWN then return end
+
+ if class then
+ class = upper(class)
+ end
+
+ if class then
+ if online then
+ classTextColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+ levelTextColor = GetQuestDifficultyColor(level)
+ buttonText = _G["GuildFrameButton"..i.."Name"]
+ buttonText:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b)
+ buttonText = _G["GuildFrameButton"..i.."Level"]
+ buttonText:SetTextColor(levelTextColor.r, levelTextColor.g, levelTextColor.b)
+ end
+ button.icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[class]))
+ end
+ end
+ else
+ local classFileName
+ for i = 1, GUILDMEMBERS_TO_DISPLAY, 1 do
+ button = _G["GuildFrameGuildStatusButton"..i]
+ _, _, _, _, class, _, _, _, online = GetGuildRosterInfo(button.guildIndex)
+ if class == UNKNOWN then return end
+
+ if class then
+ class = upper(class)
+ end
+
+ if class then
+ if online then
+ classTextColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+ _G["GuildFrameGuildStatusButton"..i.."Name"]:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b)
+ _G["GuildFrameGuildStatusButton"..i.."Online"]:SetTextColor(1.0, 1.0, 1.0)
+ end
+ end
+ end
+ end
+ end)
+
+ E:StripTextures(GuildFrameLFGFrame)
+ E:SetTemplate(GuildFrameLFGFrame, "Transparent")
+
+ S:HandleCheckBox(GuildFrameLFGButton)
+
+ for i = 1, 4 do
+ E:StripTextures(_G["GuildFrameColumnHeader"..i])
+ E:StyleButton(_G["GuildFrameColumnHeader"..i], nil, true)
+ E:StripTextures(_G["GuildFrameGuildStatusColumnHeader"..i])
+ E:StyleButton(_G["GuildFrameGuildStatusColumnHeader"..i], nil, true)
+ end
+
+ E:StripTextures(GuildListScrollFrame)
+ S:HandleScrollBar(GuildListScrollFrameScrollBar)
+
+ S:HandleNextPrevButton(GuildFrameGuildListToggleButton)
+
+ S:HandleButton(GuildFrameGuildInformationButton)
+ S:HandleButton(GuildFrameAddMemberButton)
+ S:HandleButton(GuildFrameControlButton)
+
+ -- Member Detail Frame
+ E:StripTextures(GuildMemberDetailFrame)
+ E:CreateBackdrop(GuildMemberDetailFrame, "Transparent")
+ GuildMemberDetailFrame:SetPoint("TOPLEFT", GuildFrame, "TOPRIGHT", -31, -13)
+
+ S:HandleCloseButton(GuildMemberDetailCloseButton)
+ GuildMemberDetailCloseButton:SetPoint("TOPRIGHT", 2, 2)
+
+ S:HandleButton(GuildFrameControlButton)
+ S:HandleButton(GuildMemberRemoveButton)
+ GuildMemberRemoveButton:SetPoint("BOTTOMLEFT", 8, 7)
+ S:HandleButton(GuildMemberGroupInviteButton)
+ GuildMemberGroupInviteButton:SetPoint("LEFT", GuildMemberRemoveButton, "RIGHT", 3, 0)
+
+ S:HandleNextPrevButton(GuildFramePromoteButton, true)
+ S:HandleNextPrevButton(GuildFrameDemoteButton, true)
+ GuildFrameDemoteButton:SetPoint("LEFT", GuildFramePromoteButton, "RIGHT", 2, 0)
+
+ E:SetTemplate(GuildMemberNoteBackground, "Default")
+ E:SetTemplate(GuildMemberOfficerNoteBackground, "Default")
+
+ -- Info Frame
+ E:StripTextures(GuildInfoFrame)
+ E:CreateBackdrop(GuildInfoFrame, "Transparent")
+ GuildInfoFrame.backdrop:SetPoint("TOPLEFT", 3, -6)
+ GuildInfoFrame.backdrop:SetPoint("BOTTOMRIGHT", -2, 3)
+
+ E:SetTemplate(GuildInfoTextBackground, "Default")
+ S:HandleScrollBar(GuildInfoFrameScrollFrameScrollBar)
+
+ S:HandleCloseButton(GuildInfoCloseButton)
+
+ S:HandleButton(GuildInfoSaveButton)
+ GuildInfoSaveButton:SetPoint("BOTTOMLEFT", 8, 11)
+ S:HandleButton(GuildInfoCancelButton)
+ GuildInfoCancelButton:SetPoint("LEFT", GuildInfoSaveButton, "RIGHT", 3, 0)
+
+ -- Control Frame
+ E:StripTextures(GuildControlPopupFrame)
+ E:CreateBackdrop(GuildControlPopupFrame, "Transparent")
+ GuildControlPopupFrame.backdrop:SetPoint("TOPLEFT", 3, -6)
+ GuildControlPopupFrame.backdrop:SetPoint("BOTTOMRIGHT", -27, 27)
+
+ S:HandleDropDownBox(GuildControlPopupFrameDropDown, 185)
+ GuildControlPopupFrameDropDownButton:SetWidth(16)
+ GuildControlPopupFrameDropDownButton:SetHeight(16)
+
+ local function SkinPlusMinus(f, minus)
+ f:SetNormalTexture("")
+ f.SetNormalTexture = E.noop
+ f:SetPushedTexture("")
+ f.SetPushedTexture = E.noop
+ f:SetHighlightTexture("")
+ f.SetHighlightTexture = E.noop
+ f:SetDisabledTexture("")
+ f.SetDisabledTexture = E.noop
+
+ f.Text = f:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(f.Text, nil, 22)
+ f.Text:SetPoint("LEFT", 5, 0)
+ if minus then
+ f.Text:SetText("-")
+ else
+ f.Text:SetText("+")
+ end
+ end
+
+ GuildControlPopupFrameAddRankButton:SetPoint("LEFT", GuildControlPopupFrameDropDown, "RIGHT", -8, 3)
+ SkinPlusMinus(GuildControlPopupFrameAddRankButton)
+ SkinPlusMinus(GuildControlPopupFrameRemoveRankButton, true)
+
+ S:HandleEditBox(GuildControlPopupFrameEditBox)
+ GuildControlPopupFrameEditBox.backdrop:SetPoint("TOPLEFT", 0, -5)
+ GuildControlPopupFrameEditBox.backdrop:SetPoint("BOTTOMRIGHT", 0, 5)
+
+ for i = 1, 17 do
+ local Checkbox = _G["GuildControlPopupFrameCheckbox"..i]
+ if Checkbox then
+ S:HandleCheckBox(Checkbox)
+ end
+ end
+
+ S:HandleButton(GuildControlPopupAcceptButton)
+ S:HandleButton(GuildControlPopupFrameCancelButton)
+
+ -- Raid Frame
+ S:HandleButton(RaidFrameConvertToRaidButton)
+ S:HandleButton(RaidFrameRaidInfoButton)
+
+ -- Raid Info Frame
+ E:StripTextures(RaidInfoFrame, true)
+ E:SetTemplate(RaidInfoFrame, "Transparent")
+
+ HookScript(RaidInfoFrame, "OnShow", function()
+ if GetNumRaidMembers() > 0 then
+ RaidInfoFrame:SetPoint("TOPLEFT", RaidFrame, "TOPRIGHT", -14, -12)
+ else
+ RaidInfoFrame:SetPoint("TOPLEFT", RaidFrame, "TOPRIGHT", -34, -12)
+ end
+ end)
+
+ S:HandleCloseButton(RaidInfoCloseButton, RaidInfoFrame)
+
+ E:StripTextures(RaidInfoScrollFrame)
+ S:HandleScrollBar(RaidInfoScrollFrameScrollBar)
+end
+
+S:AddCallback("Friends", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Gossip.lua b/ElvUI/Modules/Skins/Blizzard/Gossip.lua
new file mode 100644
index 0000000..d362362
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Gossip.lua
@@ -0,0 +1,58 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.gossip ~= true then return end
+
+ -- ItemTextFrame
+ E:StripTextures(ItemTextFrame, true)
+ E:StripTextures(ItemTextScrollFrame)
+
+ S:HandleScrollBar(ItemTextScrollFrameScrollBar)
+
+ E:CreateBackdrop(ItemTextFrame, "Transparent")
+ ItemTextFrame.backdrop:SetPoint("TOPLEFT", 13, -13)
+ ItemTextFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 74)
+
+ S:HandleNextPrevButton(ItemTextPrevPageButton)
+ S:HandleNextPrevButton(ItemTextNextPageButton)
+ ItemTextPrevPageButton:ClearAllPoints()
+ ItemTextNextPageButton:ClearAllPoints()
+ ItemTextPrevPageButton:SetPoint("TOPLEFT", ItemTextFrame, "TOPLEFT", 30, -50)
+ ItemTextNextPageButton:SetPoint("TOPRIGHT", ItemTextFrame, "TOPRIGHT", -48, -50)
+
+ S:HandleCloseButton(ItemTextCloseButton)
+
+ ItemTextPageText:SetTextColor(1, 1, 1)
+ ItemTextPageText.SetTextColor = E.noop
+
+ -- GossipFrame
+ E:StripTextures(GossipFrameGreetingPanel)
+
+ S:HandleScrollBar(GossipGreetingScrollFrameScrollBar, 5)
+
+ E:Kill(GossipFramePortrait)
+
+ E:CreateBackdrop(GossipFrame, "Transparent")
+ GossipFrame.backdrop:SetPoint("TOPLEFT", 15, -19)
+ GossipFrame.backdrop:SetPoint("BOTTOMRIGHT", -30, 67)
+
+ S:HandleButton(GossipFrameGreetingGoodbyeButton)
+ GossipFrameGreetingGoodbyeButton:SetPoint("BOTTOMRIGHT", GossipFrame, -34, 71)
+
+ S:HandleCloseButton(GossipFrameCloseButton)
+
+ GossipGreetingText:SetTextColor(1, 1, 1)
+
+ for i = 1, NUMGOSSIPBUTTONS do
+ local button = _G["GossipTitleButton"..i]
+ button:SetTextColor(1, 1, 1)
+ end
+end
+
+S:AddCallback("Gossip", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Greeting.lua b/ElvUI/Modules/Skins/Blizzard/Greeting.lua
new file mode 100644
index 0000000..9f09c41
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Greeting.lua
@@ -0,0 +1,30 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.greeting ~= true then return end
+
+ E:StripTextures(QuestFrameGreetingPanel)
+
+ E:Kill(QuestGreetingFrameHorizontalBreak)
+
+ S:HandleScrollBar(QuestGreetingScrollFrameScrollBar)
+
+ S:HandleButton(QuestFrameGreetingGoodbyeButton, true)
+
+ GreetingText:SetTextColor(1, 1, 1)
+ CurrentQuestsText:SetTextColor(1, 1, 0)
+ AvailableQuestsText:SetTextColor(1, 1, 0)
+
+ for i = 1, MAX_NUM_QUESTS do
+ local button = _G["QuestTitleButton"..i]
+ button:SetTextColor(1, 1, 0)
+ end
+end
+
+S:AddCallback("Greeting", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/GuildRegistrar.lua b/ElvUI/Modules/Skins/Blizzard/GuildRegistrar.lua
new file mode 100644
index 0000000..071c324
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/GuildRegistrar.lua
@@ -0,0 +1,35 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.guildregistrar ~= true then return end
+
+ E:StripTextures(GuildRegistrarFrame, true)
+ E:CreateBackdrop(GuildRegistrarFrame, "Transparent")
+ GuildRegistrarFrame.backdrop:SetPoint("TOPLEFT", 12, -17)
+ GuildRegistrarFrame.backdrop:SetPoint("BOTTOMRIGHT", -28, 65)
+ E:StripTextures(GuildRegistrarGreetingFrame)
+ S:HandleButton(GuildRegistrarFrameGoodbyeButton)
+ S:HandleButton(GuildRegistrarFrameCancelButton)
+ S:HandleButton(GuildRegistrarFramePurchaseButton)
+ S:HandleCloseButton(GuildRegistrarFrameCloseButton)
+ S:HandleEditBox(GuildRegistrarFrameEditBox)
+
+ GuildRegistrarFrameEditBox:DisableDrawLayer("BACKGROUND")
+
+ GuildRegistrarFrameEditBox:SetHeight(20)
+
+ for i = 1, 2 do
+ _G["GuildRegistrarButton"..i]:GetFontString():SetTextColor(1, 1, 1)
+ end
+
+ GuildRegistrarPurchaseText:SetTextColor(1, 1, 1)
+ AvailableServicesText:SetTextColor(1, 1, 0)
+end
+
+S:AddCallback("GuildRegistrar", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Help.lua b/ElvUI/Modules/Skins/Blizzard/Help.lua
new file mode 100644
index 0000000..612d7ca
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Help.lua
@@ -0,0 +1,72 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local getn = table.getn
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.help ~= true then return end
+
+ local helpFrameButtons = {
+ "GeneralBack",
+ "GeneralButton",
+ "GeneralButton2",
+ "GeneralCancel",
+ "GMBack",
+ "GMCancel",
+ "HarassmentBack",
+ "HarassmentCancel",
+ "HomeIssues",
+ "HomeCancel",
+ "OpenTicketSubmit",
+ "OpenTicketCancel",
+ "PhysicalHarassmentButton",
+ "VerbalHarassmentButton",
+ }
+
+ E:StripTextures(HelpFrame)
+ E:CreateBackdrop(HelpFrame, "Transparent")
+ HelpFrame.backdrop:SetPoint("TOPLEFT", 6, -2)
+ HelpFrame.backdrop:SetPoint("BOTTOMRIGHT", -45, 14)
+
+ S:HandleCloseButton(HelpFrameCloseButton)
+ HelpFrameCloseButton:SetPoint("TOPRIGHT", -42, 0)
+
+ for i = 1, getn(helpFrameButtons) do
+ local helpButton = _G["HelpFrame"..helpFrameButtons[i]]
+ S:HandleButton(helpButton)
+ end
+
+ -- hide header textures and move text/buttons.
+ local BlizzardHeader = {
+ "KnowledgeBaseFrame"
+ }
+
+ for i = 1, getn(BlizzardHeader) do
+ local title = _G[BlizzardHeader[i].."Header"]
+ if title then
+ title:SetTexture("")
+ title:ClearAllPoints()
+ if title == _G["GameMenuFrameHeader"] then
+ title:SetPoint("TOP", GameMenuFrame, 0, 0)
+ else
+ title:SetPoint("TOP", BlizzardHeader[i], -22, -8)
+ end
+ end
+ end
+
+ E:StripTextures(HelpFrameOpenTicketDivider)
+
+ S:HandleScrollBar(HelpFrameOpenTicketScrollFrame)
+ S:HandleScrollBar(HelpFrameOpenTicketScrollFrameScrollBar)
+
+ HelpFrameOpenTicketSubmit:SetPoint("RIGHT", HelpFrameOpenTicketCancel, "LEFT", -2, 0)
+
+ E:Kill(HelpFrameHarassmentDivider)
+ E:Kill(HelpFrameHarassmentDivider2)
+end
+
+S:AddCallback("Help", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Inspect.lua b/ElvUI/Modules/Skins/Blizzard/Inspect.lua
new file mode 100644
index 0000000..985f924
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Inspect.lua
@@ -0,0 +1,99 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local pairs = pairs
+local find, match, split = string.find, string.match, string.split
+--WoW API / Variables
+local GetInventoryItemLink = GetInventoryItemLink
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if not E.private.skins.blizzard.enable or not E.private.skins.blizzard.inspect then return end
+
+ E:StripTextures(InspectFrame, true)
+ E:CreateBackdrop(InspectFrame, "Transparent")
+ InspectFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ InspectFrame.backdrop:SetPoint("BOTTOMRIGHT", -31, 75)
+
+ S:HandleCloseButton(InspectFrameCloseButton)
+
+ for i = 1, 2 do
+ S:HandleTab(_G["InspectFrameTab"..i])
+ end
+
+ E:StripTextures(InspectPaperDollFrame)
+
+ local slots = {
+ "HeadSlot",
+ "NeckSlot",
+ "ShoulderSlot",
+ "BackSlot",
+ "ChestSlot",
+ "ShirtSlot",
+ "TabardSlot",
+ "WristSlot",
+ "HandsSlot",
+ "WaistSlot",
+ "LegsSlot",
+ "FeetSlot",
+ "Finger0Slot",
+ "Finger1Slot",
+ "Trinket0Slot",
+ "Trinket1Slot",
+ "MainHandSlot",
+ "SecondaryHandSlot",
+ "RangedSlot"
+ }
+
+ for _, slot in pairs(slots) do
+ local icon = _G["Inspect"..slot.."IconTexture"]
+ local slot = _G["Inspect"..slot]
+
+ E:StripTextures(slot)
+ E:StyleButton(slot, false)
+ E:SetTemplate(slot, "Default", true)
+
+ icon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(icon)
+ end
+
+ hooksecurefunc("InspectPaperDollItemSlotButton_Update", function(button)
+ if button.hasItem then
+ local itemLink = GetInventoryItemLink(InspectFrame.unit, button:GetID())
+ if itemLink then
+ local _, _, quality = GetItemInfo(match(itemLink, "item:(%d+)"))
+ if not quality then
+ E:Delay(0.1, function()
+ if InspectFrame.unit then
+ InspectPaperDollItemSlotButton_Update(button)
+ end
+ end)
+ return
+ elseif quality then
+ button:SetBackdropBorderColor(GetItemQualityColor(quality))
+ return
+ end
+ end
+ end
+ button:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end)
+
+ S:HandleRotateButton(InspectModelRotateLeftButton)
+ InspectModelRotateLeftButton:SetPoint("TOPLEFT", 3, -3)
+
+ S:HandleRotateButton(InspectModelRotateRightButton)
+ InspectModelRotateRightButton:SetPoint("TOPLEFT", InspectModelRotateLeftButton, "TOPRIGHT", 3, 0)
+
+ E:StripTextures(InspectHonorFrame)
+
+ InspectHonorFrameProgressBar:SetStatusBarTexture(E.media.normTex)
+ E:RegisterStatusBar(InspectHonorFrameProgressBar)
+end
+
+S:AddCallbackForAddon("Blizzard_InspectUI", "Inspect", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Load_Blizzard.xml b/ElvUI/Modules/Skins/Blizzard/Load_Blizzard.xml
new file mode 100644
index 0000000..fbd7127
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Load_Blizzard.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Loot.lua b/ElvUI/Modules/Skins/Blizzard/Loot.lua
new file mode 100644
index 0000000..a708203
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Loot.lua
@@ -0,0 +1,142 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local match = string.match
+--WoW API / Variables
+local UnitName = UnitName
+local IsFishingLoot = IsFishingLoot
+local GetLootRollItemInfo = GetLootRollItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local LOOTFRAME_NUMBUTTONS = LOOTFRAME_NUMBUTTONS
+local NUM_GROUP_LOOT_FRAMES = NUM_GROUP_LOOT_FRAMES
+local LOOT = LOOT
+
+local function LoadSkin()
+ if E.private.general.loot then return end
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.loot ~= true then return end
+
+ E:StripTextures(LootFrame)
+
+ E:CreateBackdrop(LootFrame, "Transparent")
+ LootFrame.backdrop:SetPoint("TOPLEFT", 13, -14)
+ LootFrame.backdrop:SetPoint("BOTTOMRIGHT", -68, 5)
+
+ LootFramePortraitOverlay:SetParent(E.HiddenFrame)
+
+ S:HandleCloseButton(LootCloseButton)
+
+ --[[for i = 1, LootFrame:GetNumRegions() do
+ local region = select(i, LootFrame:GetRegions())
+ if region:GetObjectType() == "FontString" then
+ if region:GetText() == ITEMS then
+ LootFrame.Title = region
+ end
+ end
+ end]]
+
+ --[[LootFrame.Title:ClearAllPoints()
+ LootFrame.Title:SetPoint("TOPLEFT", LootFrame.backdrop, "TOPLEFT", 4, -4)
+ LootFrame.Title:SetJustifyH("LEFT")]]
+
+ S:HandleNextPrevButton(LootFrameDownButton)
+ S:HandleNextPrevButton(LootFrameUpButton)
+ S:SquareButton_SetIcon(LootFrameUpButton, "UP")
+ S:SquareButton_SetIcon(LootFrameDownButton, "DOWN")
+
+ LootFrameDownButton:ClearAllPoints()
+ LootFrameDownButton:SetPoint("RIGHT", LootFrameNext, "RIGHT", 32, 0)
+ LootFramePrev:SetPoint("BOTTOMLEFT", 57, 22)
+
+ hooksecurefunc("LootFrame_Update", function()
+ local numLootItems = LootFrame.numLootItems
+ local numLootToShow = LOOTFRAME_NUMBUTTONS
+ if numLootItems > LOOTFRAME_NUMBUTTONS then
+ numLootToShow = numLootToShow - 1
+ end
+ for i = 1, LOOTFRAME_NUMBUTTONS do
+ local slot = (((LootFrame.page - 1) * numLootToShow) + i)
+ local lootButton = _G["LootButton"..i]
+ local lootButtonIcon = _G["LootButton"..i.."IconTexture"]
+
+ S:HandleItemButton(lootButton, true)
+
+ if slot <= numLootItems then
+ local itemLink = GetLootSlotLink(slot)
+ if itemLink then
+ local _, _, quality = GetItemInfo(match(itemLink, "item:(%d+)"))
+ if quality then
+ lootButton.backdrop:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ lootButton.backdrop:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ else
+ lootButton.backdrop:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end
+ end)
+
+ --[[HookScript(LootFrame, "OnShow", function()
+ if IsFishingLoot() then
+ this.Title:SetText(L["Fishy Loot"])
+ elseif not UnitIsFriend("player", "target") and UnitIsDead("target") then
+ this.Title:SetText(UnitName("target"))
+ else
+ this.Title:SetText(LOOT)
+ end
+ end)--]]
+end
+
+local function LoadRollSkin()
+ if E.private.general.lootRoll then return end
+ if not E.private.skins.blizzard.enable or not E.private.skins.blizzard.lootRoll then return end
+
+ local function OnShow(self)
+ E:SetTemplate(self, "Transparent")
+
+ local cornerTexture = _G[self:GetName().."Corner"]
+ cornerTexture:SetTexture()
+
+ local iconFrame = _G[self:GetName().."IconFrame"]
+ local _, _, _, quality = GetLootRollItemInfo(self.rollID)
+ iconFrame:SetBackdropBorderColor(GetItemQualityColor(quality))
+ end
+
+ for i = 1, NUM_GROUP_LOOT_FRAMES do
+ local frame = _G["GroupLootFrame"..i]
+ frame:SetParent(UIParent)
+ E:StripTextures(frame)
+
+ local frameName = frame:GetName()
+ local iconFrame = _G[frameName.."IconFrame"]
+ E:SetTemplate(iconFrame, "Default")
+
+ local icon = _G[frameName.."IconFrameIcon"]
+ E:SetInside(icon)
+ icon:SetTexCoord(unpack(E.TexCoords))
+
+ local statusBar = _G[frameName.."Timer"]
+ E:StripTextures(statusBar)
+ E:CreateBackdrop(statusBar, "Default")
+ statusBar:SetStatusBarTexture(E["media"].normTex)
+ E:RegisterStatusBar(statusBar)
+
+ local decoration = _G[frameName.."Decoration"]
+ decoration:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Gold-Dragon")
+ decoration:SetWidth(130)
+ decoration:SetHeight(130)
+ decoration:SetPoint("TOPLEFT", -37, 20)
+
+ local pass = _G[frameName.."PassButton"]
+ S:HandleCloseButton(pass, frame)
+
+ HookScript(_G["GroupLootFrame"..i], "OnShow", OnShow)
+ end
+end
+
+S:AddCallback("Loot", LoadSkin)
+S:AddCallback("LootRoll", LoadRollSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Macro.lua b/ElvUI/Modules/Skins/Blizzard/Macro.lua
new file mode 100644
index 0000000..0f9493f
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Macro.lua
@@ -0,0 +1,100 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local getn = table.getn
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.macro ~= true then return end
+
+ E:StripTextures(MacroFrame)
+ E:CreateBackdrop(MacroFrame, "Transparent")
+ MacroFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ MacroFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 71)
+
+ MacroFrame.bg = CreateFrame("Frame", nil, MacroFrame)
+ E:SetTemplate(MacroFrame.bg, "Transparent", true)
+ MacroFrame.bg:SetPoint("TOPLEFT", MacroButton1, -10, 10)
+ MacroFrame.bg:SetPoint("BOTTOMRIGHT", MacroButton18, 10, -10)
+
+ E:StripTextures(MacroFrameTextBackground)
+ E:CreateBackdrop(MacroFrameTextBackground, "Default")
+ MacroFrameTextBackground.backdrop:SetPoint("TOPLEFT", 6, -3)
+ MacroFrameTextBackground.backdrop:SetPoint("BOTTOMRIGHT", -2, 3)
+
+ local Buttons = {
+ "MacroFrameTab1",
+ "MacroFrameTab2",
+ "MacroDeleteButton",
+ "MacroNewButton",
+ "MacroExitButton",
+ "MacroEditButton",
+ "MacroPopupOkayButton",
+ "MacroPopupCancelButton"
+ }
+
+ for i = 1, getn(Buttons) do
+ E:StripTextures(_G[Buttons[i]])
+ S:HandleButton(_G[Buttons[i]])
+ end
+
+ for i = 1, 2 do
+ local tab = _G["MacroFrameTab"..i]
+
+ tab:SetHeight(22)
+ end
+
+ MacroFrameTab1:SetPoint("TOPLEFT", MacroFrame, "TOPLEFT", 85, -39)
+ MacroFrameTab2:SetPoint("LEFT", MacroFrameTab1, "RIGHT", 4, 0)
+
+ S:HandleCloseButton(MacroFrameCloseButton)
+
+ S:HandleScrollBar(MacroFrameScrollFrameScrollBar)
+ S:HandleScrollBar(MacroPopupScrollFrameScrollBar)
+
+ MacroEditButton:ClearAllPoints()
+ MacroEditButton:SetPoint("BOTTOMLEFT", MacroFrameSelectedMacroButton, "BOTTOMRIGHT", 10, 0)
+
+ MacroFrameSelectedMacroName:SetPoint("TOPLEFT", MacroFrameSelectedMacroBackground, "TOPRIGHT", -4, -10)
+
+ E:StripTextures(MacroFrameSelectedMacroButton)
+ E:SetTemplate(MacroFrameSelectedMacroButton, "Transparent")
+ E:StyleButton(MacroFrameSelectedMacroButton, true)
+ MacroFrameSelectedMacroButton:GetNormalTexture():SetTexture(nil)
+
+ MacroFrameSelectedMacroButtonIcon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(MacroFrameSelectedMacroButtonIcon)
+
+ MacroFrameCharLimitText:ClearAllPoints()
+ MacroFrameCharLimitText:SetPoint("BOTTOM", MacroFrameTextBackground, 0, -9)
+
+ for i = 1, MAX_MACROS do
+ local Button = _G["MacroButton"..i]
+ local ButtonIcon = _G["MacroButton"..i.."Icon"]
+
+ if Button then
+ E:StripTextures(Button)
+ E:SetTemplate(Button, "Default", true)
+ E:StyleButton(Button, nil, true)
+ end
+
+ if ButtonIcon then
+ ButtonIcon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(ButtonIcon)
+ end
+ end
+
+ S:HandleIconSelectionFrame(MacroPopupFrame, NUM_MACRO_ICONS_SHOWN, "MacroPopupButton", "MacroPopup")
+
+ E:CreateBackdrop(MacroPopupScrollFrame, "Transparent")
+ MacroPopupScrollFrame.backdrop:SetPoint("TOPLEFT", 51, 2)
+ MacroPopupScrollFrame.backdrop:SetPoint("BOTTOMRIGHT", 0, 4)
+
+ MacroPopupFrame:SetPoint("TOPLEFT", MacroFrame, "TOPRIGHT", -41, 1)
+end
+
+S:AddCallbackForAddon("Blizzard_MacroUI", "Macro", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Mail.lua b/ElvUI/Modules/Skins/Blizzard/Mail.lua
new file mode 100644
index 0000000..ab144f3
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Mail.lua
@@ -0,0 +1,229 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+--WoW API / Variables
+local GetInboxItem = GetInboxItem
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local GetSendMailItem = GetSendMailItem
+local hooksecurefunc = hooksecurefunc
+local INBOXITEMS_TO_DISPLAY = INBOXITEMS_TO_DISPLAY
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.mail ~= true then return end
+
+ -- Inbox Frame
+ E:StripTextures(MailFrame, true)
+ E:CreateBackdrop(MailFrame, "Transparent")
+ MailFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ MailFrame.backdrop:SetPoint("BOTTOMRIGHT", -30, 74)
+
+ for i = 1, INBOXITEMS_TO_DISPLAY do
+ local mail = _G["MailItem"..i]
+ local button = _G["MailItem"..i.."Button"]
+ local icon = _G["MailItem"..i.."ButtonIcon"]
+
+ E:StripTextures(mail)
+ E:CreateBackdrop(mail, "Default")
+ mail.backdrop:SetPoint("TOPLEFT", 2, 1)
+ mail.backdrop:SetPoint("BOTTOMRIGHT", -2, 2)
+
+ E:StripTextures(button)
+ E:SetTemplate(button, "Default", true)
+ E:StyleButton(button)
+
+ icon:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(icon)
+ end
+
+ hooksecurefunc("InboxFrame_Update", function()
+ local numItems = GetInboxNumItems()
+ local index = ((InboxFrame.pageNum - 1) * INBOXITEMS_TO_DISPLAY) + 1
+
+ for i = 1, INBOXITEMS_TO_DISPLAY do
+ if index <= numItems then
+ local packageIcon, _, _, _, _, _, _, _, _, _, _, _, isGM = GetInboxHeaderInfo(index)
+ local button = _G["MailItem"..i.."Button"]
+
+ button:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ if packageIcon and not isGM then
+ local itemName = GetInboxItem(index)
+ if itemName then
+ local _, itemString = GetItemInfoByName(itemName)
+ local _, _, quality = GetItemInfo(itemString, "item:(%d+)")
+ if quality then
+ button:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ button:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ elseif isGM then
+ button:SetBackdropBorderColor(0, 0.56, 0.94)
+ end
+ end
+
+ index = index + 1
+ end
+ end)
+
+ S:HandleNextPrevButton(InboxPrevPageButton)
+ S:HandleNextPrevButton(InboxNextPageButton)
+
+ S:HandleCloseButton(InboxCloseButton)
+
+ for i = 1, 2 do
+ local tab = _G["MailFrameTab"..i]
+
+ E:StripTextures(tab)
+ S:HandleTab(tab)
+ end
+
+ -- Send Mail Frame
+ E:StripTextures(SendMailFrame)
+
+ E:StripTextures(SendMailScrollFrame, true)
+ E:SetTemplate(SendMailScrollFrame, "Default")
+
+ hooksecurefunc("SendMailFrame_Update", function()
+ if not SendMailPackageButton.skinned then
+ E:StripTextures(SendMailPackageButton)
+ E:SetTemplate(SendMailPackageButton, "Default", true)
+ E:StyleButton(SendMailPackageButton, nil, true)
+
+ SendMailPackageButton.skinned = true
+ end
+
+ local itemName = GetSendMailItem()
+ if itemName then
+ local _, _, _, quality = GetSendMailItem()
+ if quality then
+ SendMailPackageButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ SendMailPackageButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ SendMailPackageButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(SendMailPackageButton:GetNormalTexture())
+ else
+ SendMailPackageButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end)
+
+ SendMailBodyEditBox:SetTextColor(1, 1, 1)
+
+ S:HandleScrollBar(SendMailScrollFrameScrollBar)
+
+ S:HandleEditBox(SendMailNameEditBox)
+ SendMailNameEditBox.backdrop:SetPoint("BOTTOMRIGHT", 2, 0)
+ SendMailNameEditBox:SetPoint("TOPLEFT", 79, -46)
+
+ S:HandleEditBox(SendMailSubjectEditBox)
+ SendMailSubjectEditBox.backdrop:SetPoint("BOTTOMRIGHT", 2, 0)
+
+ S:HandleEditBox(SendMailMoneyGold)
+ S:HandleEditBox(SendMailMoneySilver)
+ S:HandleEditBox(SendMailMoneyCopper)
+
+ S:HandleButton(SendMailMailButton)
+ SendMailMailButton:SetPoint("RIGHT", SendMailCancelButton, "LEFT", -2, 0)
+
+ S:HandleButton(SendMailCancelButton)
+ SendMailCancelButton:SetPoint("BOTTOMRIGHT", -45, 80)
+
+ SendMailMoneyFrame:SetPoint("BOTTOMLEFT", 170, 84)
+
+ -- Open Mail Frame
+ E:StripTextures(OpenMailFrame, true)
+ E:CreateBackdrop(OpenMailFrame, "Transparent")
+ OpenMailFrame.backdrop:SetPoint("TOPLEFT", 12, -12)
+ OpenMailFrame.backdrop:SetPoint("BOTTOMRIGHT", -34, 74)
+
+ E:StripTextures(OpenMailPackageButton)
+ E:StyleButton(OpenMailPackageButton)
+ E:SetTemplate(OpenMailPackageButton, "Default", true)
+
+ for _, region in ipairs({OpenMailPackageButton:GetRegions()}) do
+ if region:GetObjectType() == "Texture" then
+ region:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(region)
+ end
+ end
+
+ --[[for i = 1, OpenMailPackageButton:GetNumRegions() do
+ local region = select(i, OpenMailPackageButton:GetRegions())
+ if region:GetObjectType() == "Texture" then
+ region:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(region)
+ end
+ end]]
+
+ hooksecurefunc("OpenMail_Update", function()
+ local index = InboxFrame.openMailID
+ if not index then return end
+
+ local _, stationeryIcon, _, _, _, _, _, hasItem = GetInboxHeaderInfo(index)
+
+ if hasItem then
+ local itemName = GetInboxItem(index)
+ if itemName then
+ local _, itemString = GetItemInfoByName(itemName)
+ local _, _, quality = GetItemInfo(itemString, "item:(%d+)")
+ if quality then
+ OpenMailPackageButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ OpenMailPackageButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ OpenMailPackageButton:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(OpenMailPackageButton:GetNormalTexture())
+ else
+ OpenMailPackageButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end)
+
+ S:HandleCloseButton(OpenMailCloseButton)
+
+ S:HandleButton(OpenMailReplyButton)
+ OpenMailReplyButton:SetPoint("RIGHT", OpenMailDeleteButton, "LEFT", -2, 0)
+
+ S:HandleButton(OpenMailDeleteButton)
+ OpenMailDeleteButton:SetPoint("RIGHT", OpenMailCancelButton, "LEFT", -2, 0)
+
+ S:HandleButton(OpenMailCancelButton)
+
+ E:StripTextures(OpenMailScrollFrame, true)
+ E:SetTemplate(OpenMailScrollFrame, "Default")
+
+ S:HandleScrollBar(OpenMailScrollFrameScrollBar)
+
+ OpenMailBodyText:SetTextColor(1, 1, 1)
+ InvoiceTextFontNormal:SetTextColor(1, 1, 1)
+ OpenMailInvoiceBuyMode:SetTextColor(1, 0.80, 0.10)
+
+ E:Kill(OpenMailArithmeticLine)
+
+ E:StripTextures(OpenMailLetterButton)
+ E:SetTemplate(OpenMailLetterButton, "Default", true)
+ E:StyleButton(OpenMailLetterButton)
+
+ OpenMailLetterButtonIconTexture:SetTexCoord(unpack(E.TexCoords))
+ OpenMailLetterButtonIconTexture:SetDrawLayer("ARTWORK")
+ E:SetInside(OpenMailLetterButtonIconTexture)
+
+ OpenMailLetterButtonCount:SetDrawLayer("OVERLAY")
+
+ E:StripTextures(OpenMailMoneyButton)
+ E:SetTemplate(OpenMailMoneyButton, "Default", true)
+ E:StyleButton(OpenMailMoneyButton)
+
+ OpenMailMoneyButtonIconTexture:SetTexCoord(unpack(E.TexCoords))
+ OpenMailMoneyButtonIconTexture:SetDrawLayer("ARTWORK")
+ E:SetInside(OpenMailMoneyButtonIconTexture)
+
+ OpenMailMoneyButtonCount:SetDrawLayer("OVERLAY")
+end
+
+S:AddCallback("Mail", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Merchant.lua b/ElvUI/Modules/Skins/Blizzard/Merchant.lua
new file mode 100644
index 0000000..aae9be9
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Merchant.lua
@@ -0,0 +1,151 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local match, split = string.match, string.split
+--WoW API / Variables
+local GetBuybackItemInfo = GetBuybackItemInfo
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local GetMerchantItemLink = GetMerchantItemLink
+local GetItemLinkByName = GetItemLinkByName
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.merchant ~= true then return end
+
+ E:StripTextures(MerchantFrame, true)
+ E:CreateBackdrop(MerchantFrame, "Transparent")
+ MerchantFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ MerchantFrame.backdrop:SetPoint("BOTTOMRIGHT", -28, 60)
+
+ S:HandleCloseButton(MerchantFrameCloseButton, MerchantFrame.backdrop)
+
+ for i = 1, 12 do
+ local item = _G["MerchantItem"..i]
+ local itemButton = _G["MerchantItem"..i.."ItemButton"]
+ local iconTexture = _G["MerchantItem"..i.."ItemButtonIconTexture"]
+ local altCurrencyTex1 = _G["MerchantItem"..i.."AltCurrencyFrameItem1Texture"]
+ local altCurrencyTex2 = _G["MerchantItem"..i.."AltCurrencyFrameItem2Texture"]
+
+ E:StripTextures(item, true)
+ E:CreateBackdrop(item, "Default")
+
+ E:StripTextures(itemButton)
+ E:StyleButton(itemButton)
+ E:SetTemplate(itemButton, "Default", true)
+ itemButton:SetPoint("TOPLEFT", item, "TOPLEFT", 4, -4)
+
+ iconTexture:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(iconTexture)
+
+ _G["MerchantItem"..i.."MoneyFrame"]:ClearAllPoints()
+ _G["MerchantItem"..i.."MoneyFrame"]:SetPoint("BOTTOMLEFT", itemButton, "BOTTOMRIGHT", 3, 0)
+ end
+
+ S:HandleNextPrevButton(MerchantNextPageButton)
+ S:HandleNextPrevButton(MerchantPrevPageButton)
+
+ E:StyleButton(MerchantRepairItemButton)
+ E:SetTemplate(MerchantRepairItemButton, "Default", true)
+
+ for _, region in ipairs({MerchantRepairItemButton:GetRegions()}) do
+ if region:GetObjectType() == "Texture" then
+ region:SetTexCoord(0.04, 0.24, 0.06, 0.5)
+ E:SetInside(region)
+ end
+ end
+
+ --[[for i = 1, MerchantRepairItemButton:GetNumRegions() do
+ local region = select(i, MerchantRepairItemButton:GetRegions())
+ if region:GetObjectType() == "Texture" then
+ region:SetTexCoord(0.04, 0.24, 0.06, 0.5)
+ E:SetInside(region)
+ end
+ end--]]
+
+ E:StyleButton(MerchantRepairAllButton)
+ E:SetTemplate(MerchantRepairAllButton, "Default", true)
+ MerchantRepairAllIcon:SetTexCoord(0.34, 0.1, 0.34, 0.535, 0.535, 0.1, 0.535, 0.535)
+ E:SetInside(MerchantRepairAllIcon)
+
+ E:StripTextures(MerchantBuyBackItem, true)
+ E:CreateBackdrop(MerchantBuyBackItem, "Transparent")
+ MerchantBuyBackItem.backdrop:SetPoint("TOPLEFT", -6, 6)
+ MerchantBuyBackItem.backdrop:SetPoint("BOTTOMRIGHT", 6, -6)
+
+ E:StripTextures(MerchantBuyBackItemItemButton)
+ E:StyleButton(MerchantBuyBackItemItemButton)
+ E:SetTemplate(MerchantBuyBackItemItemButton, "Default", true)
+ MerchantBuyBackItemItemButtonIconTexture:SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(MerchantBuyBackItemItemButtonIconTexture)
+
+ for i = 1, 2 do
+ S:HandleTab(_G["MerchantFrameTab"..i])
+ end
+
+ hooksecurefunc("MerchantFrame_UpdateMerchantInfo", function()
+ local numMerchantItems = GetMerchantNumItems()
+ for i = 1, MERCHANT_ITEMS_PER_PAGE do
+ local index = (((MerchantFrame.page - 1) * MERCHANT_ITEMS_PER_PAGE) + i)
+ local itemButton = _G["MerchantItem"..i.."ItemButton"]
+ local itemName = _G["MerchantItem"..i.."Name"]
+
+ if index <= numMerchantItems then
+ local itemLink = GetMerchantItemLink(index)
+ if itemLink then
+ local _, _, quality = GetItemInfo(match(itemLink, "item:(%d+)"))
+ if quality then
+ itemName:SetTextColor(GetItemQualityColor(quality))
+ itemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ itemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ else
+ itemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+
+ HookScript(MerchantBuyBackItemItemButton, "OnEvent", function()
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end)
+
+ local buybackName = GetBuybackItemInfo(GetNumBuybackItems())
+ if buybackName then
+ local _, _, quality = GetItemInfoByName(buybackName)
+ if quality then
+ MerchantBuyBackItemName:SetTextColor(GetItemQualityColor(quality))
+ MerchantBuyBackItemItemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ MerchantBuyBackItemItemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end
+ end)
+
+ hooksecurefunc("MerchantFrame_UpdateBuybackInfo", function()
+ local numBuybackItems = GetNumBuybackItems()
+ for i = 1, BUYBACK_ITEMS_PER_PAGE do
+ local itemButton = _G["MerchantItem"..i.."ItemButton"]
+ local itemName = _G["MerchantItem"..i.."Name"]
+
+ if i <= numBuybackItems then
+ local buybackName = GetBuybackItemInfo(i)
+ if buybackName then
+ local _, _, quality = GetItemInfoByName(buybackName)
+ if quality then
+ itemName:SetTextColor(GetItemQualityColor(quality))
+ itemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ else
+ itemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end
+ end
+ end)
+end
+
+S:AddCallback("Merchant", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/MirrorTimers.lua b/ElvUI/Modules/Skins/Blizzard/MirrorTimers.lua
new file mode 100644
index 0000000..a69b216
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/MirrorTimers.lua
@@ -0,0 +1,62 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local floor, format = math.floor, string.format
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.mirrorTimers ~= true then return end
+
+ hooksecurefunc("MirrorTimerFrame_OnUpdate", function(frame, elapsed)
+ if frame.paused then
+ return
+ end
+
+ if frame.timeSinceUpdate >= 0.3 then
+ local minutes = frame.value / 60
+ local seconds = frame.value - floor(frame.value / 60) * 60
+ local text = frame.label:GetText()
+
+ if frame.value > 0 then
+ frame.TimerText:SetText(format("%s (%d:%02d)", text, minutes, seconds))
+ else
+ frame.TimerText:SetText(format("%s (0:00)", text))
+ end
+ frame.timeSinceUpdate = 0
+ else
+ frame.timeSinceUpdate = frame.timeSinceUpdate + elapsed
+ end
+ end)
+
+ for i = 1, MIRRORTIMER_NUMTIMERS do
+ local mirrorTimer = _G["MirrorTimer"..i]
+ local statusBar = _G["MirrorTimer"..i.."StatusBar"]
+ local text = _G["MirrorTimer"..i.."Text"]
+
+ E:StripTextures(mirrorTimer)
+ mirrorTimer:SetWidth(222)
+ mirrorTimer:SetHeight(18)
+ mirrorTimer.label = text
+ statusBar:SetStatusBarTexture(E["media"].normTex)
+ E:RegisterStatusBar(statusBar)
+ E:CreateBackdrop(statusBar)
+ statusBar:SetWidth(222)
+ statusBar:SetHeight(18)
+ text:Hide()
+
+ local TimerText = mirrorTimer:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(TimerText)
+ TimerText:SetPoint("CENTER", statusBar, "CENTER", 0, 0)
+ mirrorTimer.TimerText = TimerText
+
+ mirrorTimer.timeSinceUpdate = 0.3
+
+ E:CreateMover(mirrorTimer, "MirrorTimer"..i.."Mover", L["MirrorTimer"]..i, nil, nil, nil, "ALL,SOLO")
+ end
+end
+
+S:AddCallback("MirrorTimers", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Misc.lua b/ElvUI/Modules/Skins/Blizzard/Misc.lua
new file mode 100644
index 0000000..c1e28a6
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Misc.lua
@@ -0,0 +1,456 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local find, getn = string.find, table.getn
+--WoW API / Variables
+local IsAddOnLoaded = IsAddOnLoaded
+local UnitIsUnit = UnitIsUnit
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.misc ~= true then return end
+
+ -- Blizzard frame we want to reskin
+ local skins = {
+ "GameMenuFrame",
+ "UIOptionsFrame",
+ "OptionsFrame",
+ "OptionsFrameDisplay",
+ "OptionsFrameBrightness",
+ "OptionsFrameWorldAppearance",
+ "OptionsFramePixelShaders",
+ "OptionsFrameMiscellaneous",
+ "SoundOptionsFrame",
+ "TicketStatusFrame",
+ "StackSplitFrame"
+ }
+
+ for i = 1, getn(skins) do
+ E:SetTemplate(_G[skins[i]], "Transparent")
+ end
+
+ -- ChatMenus
+ local ChatMenus = {
+ "ChatMenu",
+ "EmoteMenu",
+ "LanguageMenu",
+ "VoiceMacroMenu",
+ }
+
+ for i = 1, getn(ChatMenus) do
+ if _G[ChatMenus[i]] == _G["ChatMenu"] then
+ HookScript(_G[ChatMenus[i]], "OnShow", function()
+ E:SetTemplate(this, "Transparent", true)
+ this:SetBackdropColor(unpack(E["media"].backdropfadecolor))
+ this:ClearAllPoints()
+ this:SetPoint("BOTTOMLEFT", ChatFrame1, "TOPLEFT", 0, 35)
+ end)
+ else
+ HookScript(_G[ChatMenus[i]], "OnShow", function()
+ E:SetTemplate(this, "Transparent", true)
+ this:SetBackdropColor(unpack(E["media"].backdropfadecolor))
+ end)
+ end
+ end
+
+ local function StyleButton(f)
+ local width, height = (f:GetWidth() * .54), f:GetHeight()
+
+ local left = f:CreateTexture(nil, "HIGHLIGHT")
+ left:SetWidth(width)
+ left:SetHeight(height)
+ left:SetPoint("LEFT", f, "CENTER")
+ left:SetTexture(1, 1, 1, 0.3)
+ left:SetHeight(16)
+
+ local right = f:CreateTexture(nil, "HIGHLIGHT")
+ right:SetWidth(width)
+ right:SetHeight(height)
+ right:SetPoint("RIGHT", f, "CENTER")
+ right:SetTexture(1, 1, 1, 0.3)
+ right:SetHeight(16)
+ end
+
+ for i = 1, UIDROPDOWNMENU_MAXBUTTONS do
+ StyleButton(_G["ChatMenuButton"..i])
+ StyleButton(_G["EmoteMenuButton"..i])
+ StyleButton(_G["LanguageMenuButton"..i])
+ StyleButton(_G["VoiceMacroMenuButton"..i])
+ end
+
+ -- UIDropDownMenu
+ hooksecurefunc("UIDropDownMenu_Initialize", function()
+ for i = 1, UIDROPDOWNMENU_MAXLEVELS do
+ local buttonBackdrop = _G["DropDownList"..i.."Backdrop"]
+ local buttonBackdropMenu = _G["DropDownList"..i.."MenuBackdrop"]
+
+ E:SetTemplate(buttonBackdrop, "Transparent")
+ E:SetTemplate(buttonBackdropMenu, "Transparent")
+
+ for j = 1, UIDROPDOWNMENU_MAXBUTTONS do
+ local button = _G["DropDownList"..i.."Button"..j]
+ local buttonHighlight = _G["DropDownList"..i.."Button"..j.."Highlight"]
+
+ button:SetFrameLevel(buttonBackdrop:GetFrameLevel() + 1)
+ buttonHighlight:SetTexture(1, 1, 1, 0.3)
+ buttonHighlight:SetAllPoints(button)
+
+ if i == 1 then
+ buttonHighlight:SetPoint("TOPLEFT", button, "TOPLEFT", -8, 0)
+ buttonHighlight:SetPoint("TOPRIGHT", button, "TOPRIGHT", -8, 0)
+ else
+ buttonHighlight:SetPoint("TOPLEFT", button, "TOPLEFT", -4, 0)
+ buttonHighlight:SetPoint("TOPRIGHT", button, "TOPRIGHT", -4, 0)
+ end
+ end
+ end
+ end)
+
+ -- L_UIDropDownMenu
+ hooksecurefunc("L_UIDropDownMenu_Initialize", function()
+ for i = 1, 2 do
+ local buttonBackdrop = _G["L_DropDownList"..i.."Backdrop"]
+ local buttonBackdropMenu = _G["L_DropDownList"..i.."MenuBackdrop"]
+
+ E:SetTemplate(buttonBackdrop, "Transparent")
+ E:SetTemplate(buttonBackdropMenu, "Transparent")
+
+ if i == 2 then
+ buttonBackdropMenu:SetPoint("TOPRIGHT", -4, 0)
+ end
+
+ for j = 1, UIDROPDOWNMENU_MAXBUTTONS do
+ local button = _G["L_DropDownList"..i.."Button"..j]
+ local buttonHighlight = _G["L_DropDownList"..i.."Button"..j.."Highlight"]
+
+ button:SetFrameLevel(buttonBackdrop:GetFrameLevel() + 1)
+ buttonHighlight:SetTexture(1, 1, 1, 0.3)
+ buttonHighlight:SetAllPoints(button)
+
+ if i == 2 then
+ buttonHighlight:SetPoint("TOPLEFT", button, "TOPLEFT", -8, 0)
+ buttonHighlight:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0)
+ end
+ end
+ end
+ end)
+
+ -- Kill the nVidia logo
+ local _, _, nVidiaLogo = OptionsFrame:GetRegions()
+ if nVidiaLogo:GetObjectType() == "Texture" then
+ E:Kill(nVidiaLogo)
+ end
+
+ -- Static Popups
+ for i = 1, STATICPOPUP_NUMDIALOGS do
+ local staticPopup = _G["StaticPopup"..i]
+ local itemFrameBox = _G["StaticPopup"..i.."EditBox"]
+ local closeButton = _G["StaticPopup"..i.."CloseButton"]
+ local wideBox = _G["StaticPopup"..i.."WideEditBox"]
+
+ E:SetTemplate(staticPopup, "Transparent")
+
+ itemFrameBox:DisableDrawLayer("BACKGROUND")
+
+ S:HandleEditBox(itemFrameBox)
+ itemFrameBox.backdrop:SetPoint("TOPLEFT", -2, -4)
+ itemFrameBox.backdrop:SetPoint("BOTTOMRIGHT", 2, 4)
+
+ E:StripTextures(closeButton)
+ S:HandleCloseButton(closeButton)
+
+ local _, _, _, _, _, _, _, region = wideBox:GetRegions()
+ if region then
+ region:Hide()
+ end
+ --select(8, wideBox:GetRegions()):Hide()
+ S:HandleEditBox(wideBox)
+ wideBox:SetHeight(22)
+
+ for j = 1, 2 do
+ S:HandleButton(_G["StaticPopup"..i.."Button"..j])
+ end
+ end
+
+ -- reskin all esc/menu buttons
+ local BlizzardMenuButtons = {
+ "Options",
+ "SoundOptions",
+ "UIOptions",
+ "Keybindings",
+ "Macros",
+ "Logout",
+ "Quit",
+ "Continue",
+ }
+
+ for i = 1, getn(BlizzardMenuButtons) do
+ local ElvuiMenuButtons = _G["GameMenuButton"..BlizzardMenuButtons[i]]
+ if ElvuiMenuButtons then
+ S:HandleButton(ElvuiMenuButtons)
+ end
+ end
+
+ -- hide header textures and move text/buttons.
+ local BlizzardHeader = {
+ "GameMenuFrame",
+ "SoundOptionsFrame",
+ "OptionsFrame",
+ }
+
+ for i = 1, getn(BlizzardHeader) do
+ local title = _G[BlizzardHeader[i].."Header"]
+ if title then
+ title:SetTexture("")
+ title:ClearAllPoints()
+ if title == _G["GameMenuFrameHeader"] then
+ title:SetPoint("TOP", GameMenuFrame, 0, 7)
+ else
+ title:SetPoint("TOP", BlizzardHeader[i], 0, 0)
+ end
+ end
+ end
+
+ -- here we reskin all "normal" buttons
+ local BlizzardButtons = {
+ "OptionsFrameOkay",
+ "OptionsFrameCancel",
+ "OptionsFrameDefaults",
+ "SoundOptionsFrameOkay",
+ "SoundOptionsFrameCancel",
+ "SoundOptionsFrameDefaults",
+ "UIOptionsFrameDefaults",
+ "UIOptionsFrameOkay",
+ "UIOptionsFrameCancel",
+ "StackSplitOkayButton",
+ "StackSplitCancelButton",
+ "RolePollPopupAcceptButton"
+ }
+
+ for i = 1, getn(BlizzardButtons) do
+ local ElvuiButtons = _G[BlizzardButtons[i]]
+ if ElvuiButtons then
+ S:HandleButton(ElvuiButtons)
+ end
+ end
+
+ -- if a button position is not really where we want, we move it here
+ OptionsFrameCancel:ClearAllPoints()
+ OptionsFrameCancel:SetPoint("BOTTOMLEFT",OptionsFrame,"BOTTOMRIGHT",-105,15)
+ OptionsFrameOkay:ClearAllPoints()
+ OptionsFrameOkay:SetPoint("RIGHT",OptionsFrameCancel,"LEFT",-4,0)
+ SoundOptionsFrameOkay:ClearAllPoints()
+ SoundOptionsFrameOkay:SetPoint("RIGHT",SoundOptionsFrameCancel,"LEFT",-4,0)
+ UIOptionsFrameOkay:ClearAllPoints()
+ UIOptionsFrameOkay:SetPoint("RIGHT",UIOptionsFrameCancel,"LEFT", -4,0)
+
+ -- others
+ ZoneTextFrame:ClearAllPoints()
+ ZoneTextFrame:SetPoint("TOP", UIParent, 0, -128)
+
+ E:StripTextures(CoinPickupFrame)
+ E:SetTemplate(CoinPickupFrame, "Transparent")
+
+ S:HandleButton(CoinPickupOkayButton)
+ S:HandleButton(CoinPickupCancelButton)
+
+ -- Stack Split Frame
+ StackSplitFrame:GetRegions():Hide()
+
+ StackSplitFrame.bg1 = CreateFrame("Frame", nil, StackSplitFrame)
+ E:SetTemplate(StackSplitFrame.bg1, "Transparent")
+ StackSplitFrame.bg1:SetPoint("TOPLEFT", 10, -15)
+ StackSplitFrame.bg1:SetPoint("BOTTOMRIGHT", -10, 55)
+ StackSplitFrame.bg1:SetFrameLevel(StackSplitFrame.bg1:GetFrameLevel() - 1)
+
+ -- Declension frame
+ if GetLocale() == "ruRU" then
+ DeclensionFrame:SetTemplate("Transparent")
+
+ S:HandleNextPrevButton(DeclensionFrameSetPrev)
+ S:HandleNextPrevButton(DeclensionFrameSetNext)
+ S:HandleButton(DeclensionFrameOkayButton)
+ S:HandleButton(DeclensionFrameCancelButton)
+
+ for i = 1, RUSSIAN_DECLENSION_PATTERNS do
+ local editBox = _G["DeclensionFrameDeclension"..i.."Edit"]
+ if editBox then
+ E:StripTextures(editBox)
+ S:HandleEditBox(editBox)
+ end
+ end
+ end
+
+ if GetLocale() == "koKR" then
+ S:HandleButton(GameMenuButtonRatings)
+
+ RatingMenuFrame:SetTemplate("Transparent")
+ RatingMenuFrameHeader:Kill()
+ S:HandleButton(RatingMenuButtonOkay)
+ end
+
+ E:StripTextures(OpacityFrame)
+ E:SetTemplate(OpacityFrame, "Transparent")
+
+ S:HandleSliderFrame(OpacityFrameSlider)
+
+ -- Interface Options
+ UIOptionsFrame:SetParent(E.UIParent)
+ UIOptionsFrame:EnableMouse(false)
+
+ hooksecurefunc("UIOptionsFrame_Load", function()
+ E:StripTextures(UIOptionsFrame)
+ end)
+
+ local UIOptions = {
+ "BasicOptions",
+ "BasicOptionsGeneral",
+ "BasicOptionsDisplay",
+ "BasicOptionsCamera",
+ "BasicOptionsHelp",
+ "AdvancedOptions",
+ "AdvancedOptionsActionBars",
+ "AdvancedOptionsChat",
+ "AdvancedOptionsRaid",
+ "AdvancedOptionsCombatText",
+ }
+
+ for i = 1, getn(UIOptions) do
+ local options = _G[UIOptions[i]]
+ E:SetTemplate(options, "Transparent")
+ end
+
+ BasicOptions.backdrop = CreateFrame("Frame", nil, BasicOptions)
+ BasicOptions.backdrop:SetPoint("TOPLEFT", BasicOptionsGeneral, -20, 35)
+ BasicOptions.backdrop:SetPoint("BOTTOMRIGHT", BasicOptionsHelp, 20, -130)
+ E:SetTemplate(BasicOptions.backdrop, "Transparent")
+
+ AdvancedOptions.backdrop = CreateFrame("Frame", nil, AdvancedOptions)
+ AdvancedOptions.backdrop:SetPoint("TOPLEFT", BasicOptionsGeneral, -20, 35)
+ AdvancedOptions.backdrop:SetPoint("BOTTOMRIGHT", BasicOptionsHelp, 20, -130)
+ E:SetTemplate(AdvancedOptions.backdrop, "Transparent")
+
+ for i = 1, 2 do
+ local tab = _G["UIOptionsFrameTab"..i]
+ E:StripTextures(tab, true)
+ E:CreateBackdrop(tab, "Transparent")
+
+ tab:SetFrameLevel(tab:GetParent():GetFrameLevel() + 2)
+ tab.backdrop:SetFrameLevel(tab:GetParent():GetFrameLevel() + 1)
+
+ tab.backdrop:SetPoint("TOPLEFT", 5, E.PixelMode and -14 or -16)
+ tab.backdrop:SetPoint("BOTTOMRIGHT", -5, E.PixelMode and -4 or -6)
+
+ tab:SetScript("OnClick", function()
+ PanelTemplates_Tab_OnClick(UIOptionsFrame)
+ if AdvancedOptions:IsShown() then
+ BasicOptions:Show()
+ AdvancedOptions:Hide()
+ else
+ BasicOptions:Hide()
+ AdvancedOptions:Show()
+ end
+ PlaySound("igCharacterInfoTab")
+ end)
+
+ HookScript(tab, "OnEnter", S.SetModifiedBackdrop)
+ HookScript(tab, "OnLeave", S.SetOriginalBackdrop)
+ end
+
+ for _, child in ipairs({UIOptionsFrame:GetChildren()}) do
+ if child.GetPushedTexture and child:GetPushedTexture() and not child:GetName() then
+ child:SetFrameLevel(UIOptionsFrame:GetFrameLevel() + 2)
+ S:HandleCloseButton(child, UIOptionsFrame.backdrop)
+ end
+ end
+
+ --[[for i = 1, UIOptionsFrame:GetNumChildren() do
+ local child = select(i, UIOptionsFrame:GetChildren())
+ if child.GetPushedTexture and child:GetPushedTexture() and not child:GetName() then
+ child:SetFrameLevel(UIOptionsFrame:GetFrameLevel() + 2)
+ S:HandleCloseButton(child, UIOptionsFrame.backdrop)
+ end
+ end--]]
+
+ OptionsFrameDefaults:ClearAllPoints()
+ OptionsFrameDefaults:SetPoint("TOPLEFT", OptionsFrame, "BOTTOMLEFT", 15, 36)
+
+ S:HandleButton(UIOptionsFrameResetTutorials)
+
+ SoundOptionsFrameCheckButton1:SetPoint("TOPLEFT", "SoundOptionsFrame", "TOPLEFT", 16, -15)
+
+ -- Interface Options Frame Dropdown
+ local interfacedropdown ={
+ "CombatTextDropDown",
+ "TargetofTargetDropDown",
+ "CameraDropDown",
+ "ClickCameraDropDown"
+ }
+
+ for i = 1, getn(interfacedropdown) do
+ local idropdown = _G["UIOptionsFrame"..interfacedropdown[i]]
+ if idropdown then
+ S:HandleDropDownBox(idropdown)
+ end
+ end
+
+ -- Video Options Frame Dropdown
+ local optiondropdown = {
+ "OptionsFrameResolutionDropDown",
+ "OptionsFrameRefreshDropDown",
+ "OptionsFrameMultiSampleDropDown",
+ "SoundOptionsOutputDropDown",
+ }
+
+ for i = 1, getn(optiondropdown) do
+ local odropdown = _G[optiondropdown[i]]
+ if odropdown then
+ S:HandleDropDownBox(odropdown, i == 3 and 195 or 165)
+ end
+ end
+
+ -- Interface Options Checkboxes
+ for index, value in UIOptionsFrameCheckButtons do
+ local UIOptionsFrameCheckBox = _G["UIOptionsFrameCheckButton"..value.index]
+ if UIOptionsFrameCheckBox then
+ S:HandleCheckBox(UIOptionsFrameCheckBox)
+ end
+ end
+
+ -- Video Options Checkboxes
+ for index, value in OptionsFrameCheckButtons do
+ local OptionsFrameCheckButton = _G["OptionsFrameCheckButton"..value.index]
+ if OptionsFrameCheckButton then
+ S:HandleCheckBox(OptionsFrameCheckButton)
+ end
+ end
+
+ -- Sound Options Checkboxes
+ for index, value in SoundOptionsFrameCheckButtons do
+ local SoundOptionsFrameCheckButton = _G["SoundOptionsFrameCheckButton"..value.index]
+ if SoundOptionsFrameCheckButton then
+ S:HandleCheckBox(SoundOptionsFrameCheckButton)
+ end
+ end
+
+ -- Interface Options Sliders
+ for i, v in UIOptionsFrameSliders do
+ S:HandleSliderFrame(_G["UIOptionsFrameSlider"..i])
+ end
+
+ -- Video Options Sliders
+ for i, v in OptionsFrameSliders do
+ S:HandleSliderFrame(_G["OptionsFrameSlider"..i])
+ end
+
+ -- Sound Options Sliders
+ for i, v in SoundOptionsFrameSliders do
+ S:HandleSliderFrame(_G["SoundOptionsFrameSlider"..i])
+ end
+end
+
+S:AddCallback("SkinMisc", LoadSkin)
diff --git a/ElvUI/Modules/Skins/Blizzard/Petition.lua b/ElvUI/Modules/Skins/Blizzard/Petition.lua
new file mode 100644
index 0000000..a2781ac
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Petition.lua
@@ -0,0 +1,39 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.petition ~= true then return end
+
+ E:StripTextures(PetitionFrame, true)
+ E:CreateBackdrop(PetitionFrame, "Transparent")
+ PetitionFrame.backdrop:SetPoint("TOPLEFT", 12, -17)
+ PetitionFrame.backdrop:SetPoint("BOTTOMRIGHT", -28, 65)
+
+ S:HandleButton(PetitionFrameSignButton)
+ S:HandleButton(PetitionFrameRequestButton)
+ S:HandleButton(PetitionFrameRenameButton)
+ S:HandleButton(PetitionFrameCancelButton)
+ S:HandleCloseButton(PetitionFrameCloseButton)
+
+ PetitionFrameCharterTitle:SetTextColor(1, 1, 0)
+ PetitionFrameCharterName:SetTextColor(1, 1, 1)
+ PetitionFrameMasterTitle:SetTextColor(1, 1, 0)
+ PetitionFrameMasterName:SetTextColor(1, 1, 1)
+ PetitionFrameMemberTitle:SetTextColor(1, 1, 0)
+
+ for i = 1, 9 do
+ _G["PetitionFrameMemberName"..i]:SetTextColor(1, 1, 1)
+ end
+
+ PetitionFrameInstructions:SetTextColor(1, 1, 1)
+
+ PetitionFrameRenameButton:SetPoint("LEFT", PetitionFrameRequestButton, "RIGHT", 3, 0)
+ PetitionFrameRenameButton:SetPoint("RIGHT", PetitionFrameCancelButton, "LEFT", -3, 0)
+end
+
+S:AddCallback("Petition", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Quest.lua b/ElvUI/Modules/Skins/Blizzard/Quest.lua
new file mode 100644
index 0000000..ef7e96d
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Quest.lua
@@ -0,0 +1,439 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs = pairs
+local unpack = unpack
+local find, format, match, split = string.find, string.format, string.match, string.split
+--WoW API / Variables
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.quest ~= true then return end
+
+ local QuestStrip = {
+ "QuestFrame",
+ "QuestLogFrame",
+ "EmptyQuestLogFrame",
+ "QuestFrameDetailPanel",
+ "QuestDetailScrollFrame",
+ "QuestDetailScrollChildFrame",
+ "QuestRewardScrollFrame",
+ "QuestRewardScrollChildFrame",
+ "QuestFrameProgressPanel",
+ "QuestFrameRewardPanel",
+ "QuestFrameRewardPanel"
+ }
+
+ for _, object in pairs(QuestStrip) do
+ E:StripTextures(_G[object], true)
+ end
+
+ local QuestButtons = {
+ "QuestLogFrameAbandonButton",
+ "QuestFrameExitButton",
+ "QuestFramePushQuestButton",
+ "QuestFrameCompleteButton",
+ "QuestFrameGoodbyeButton",
+ "QuestFrameCompleteQuestButton",
+ "QuestFrameCancelButton",
+ "QuestFrameGreetingGoodbyeButton",
+ "QuestFrameAcceptButton",
+ "QuestFrameDeclineButton"
+ }
+
+ for _, button in pairs(QuestButtons) do
+ E:StripTextures(_G[button])
+ S:HandleButton(_G[button])
+ end
+
+ for i = 1, MAX_NUM_ITEMS do
+ local item = _G["QuestLogItem"..i]
+ local icon = _G["QuestLogItem"..i.."IconTexture"]
+ local count = _G["QuestLogItem"..i.."Count"]
+
+ E:StripTextures(item)
+ E:SetTemplate(item, "Default")
+ E:StyleButton(item)
+ item:SetWidth(item:GetWidth() - 4)
+ item:SetFrameLevel(item:GetFrameLevel() + 2)
+
+ icon:SetDrawLayer("OVERLAY")
+ icon:SetWidth(icon:GetWidth() -(E.Spacing*2))
+ icon:SetHeight(icon:GetHeight() -(E.Spacing*2))
+ icon:SetPoint("TOPLEFT", E.Border, -E.Border)
+ S:HandleIcon(icon)
+
+ count:SetParent(item.backdrop)
+ count:SetDrawLayer("OVERLAY")
+ end
+
+ for i = 1, 6 do
+ local item = _G["QuestDetailItem"..i]
+ local icon = _G["QuestDetailItem"..i.."IconTexture"]
+ local count = _G["QuestDetailItem"..i.."Count"]
+
+ E:StripTextures(item)
+ E:SetTemplate(item, "Default")
+ E:StyleButton(item)
+ item:SetWidth(item:GetWidth() - 4)
+ item:SetFrameLevel(item:GetFrameLevel() + 2)
+
+ icon:SetDrawLayer("OVERLAY")
+ icon:SetWidth(icon:GetWidth() -(E.Spacing*2))
+ icon:SetHeight(icon:GetHeight() -(E.Spacing*2))
+ icon:SetPoint("TOPLEFT", E.Border, -E.Border)
+ S:HandleIcon(icon)
+
+ count:SetParent(item.backdrop)
+ count:SetDrawLayer("OVERLAY")
+ end
+
+ for i = 1, 6 do
+ local item = _G["QuestRewardItem"..i]
+ local icon = _G["QuestRewardItem"..i.."IconTexture"]
+ local count = _G["QuestRewardItem"..i.."Count"]
+
+ E:StripTextures(item)
+ E:SetTemplate(item, "Default")
+ E:StyleButton(item)
+ item:SetWidth(item:GetWidth() - 4)
+ item:SetFrameLevel(item:GetFrameLevel() + 2)
+
+ icon:SetDrawLayer("OVERLAY")
+ icon:SetWidth(icon:GetWidth() -(E.Spacing*2))
+ icon:SetHeight(icon:GetHeight() -(E.Spacing*2))
+ icon:SetPoint("TOPLEFT", E.Border, -E.Border)
+ S:HandleIcon(icon)
+
+ count:SetParent(item.backdrop)
+ count:SetDrawLayer("OVERLAY")
+ end
+
+ local function QuestQualityColors(frame, text, quality, link)
+ if link and not quality then
+ _, _, quality = GetItemInfo(match(link, "item:(%d+)"))
+ end
+
+ if quality then
+ if frame then
+ frame:SetBackdropBorderColor(GetItemQualityColor(quality))
+ frame.backdrop:SetBackdropBorderColor(GetItemQualityColor(quality))
+ end
+ text:SetTextColor(GetItemQualityColor(quality))
+ else
+ if frame then
+ frame:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ frame.backdrop:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ text:SetTextColor(1, 1, 1)
+ end
+ end
+
+ E:StripTextures(QuestRewardItemHighlight)
+ E:SetTemplate(QuestRewardItemHighlight, "Default", nil, true)
+ QuestRewardItemHighlight:SetBackdropBorderColor(1, 1, 0)
+ QuestRewardItemHighlight:SetBackdropColor(0, 0, 0, 0)
+ QuestRewardItemHighlight:SetWidth(142)
+ QuestRewardItemHighlight:SetHeight(40)
+
+ hooksecurefunc("QuestRewardItem_OnClick", function()
+ QuestRewardItemHighlight:ClearAllPoints();
+ E:SetOutside(QuestRewardItemHighlight, this:GetName() .. "IconTexture")
+ _G[this:GetName() .. "Name"]:SetTextColor(1, 1, 0)
+
+ for i = 1, MAX_NUM_ITEMS do
+ local questItem = _G["QuestRewardItem"..i]
+ local questName = _G["QuestRewardItem"..i.."Name"]
+ local link = questItem.type and GetQuestItemLink(questItem.type, questItem:GetID())
+
+ if questItem ~= this then
+ QuestQualityColors(nil, questName, nil, link)
+ end
+ end
+ end)
+
+ local function QuestObjectiveTextColor()
+ local numObjectives = GetNumQuestLeaderBoards()
+ local objective
+ local _, type, finished;
+ local numVisibleObjectives = 0
+ for i = 1, numObjectives do
+ _, type, finished = GetQuestLogLeaderBoard(i)
+ if type ~= "spell" then
+ numVisibleObjectives = numVisibleObjectives + 1
+ objective = _G["QuestLogObjective"..numVisibleObjectives]
+ if finished then
+ objective:SetTextColor(1, 0.80, 0.10)
+ else
+ objective:SetTextColor(0.6, 0.6, 0.6)
+ end
+ end
+ end
+ end
+
+ hooksecurefunc("QuestLog_UpdateQuestDetails", function()
+ local requiredMoney = GetQuestLogRequiredMoney()
+ if requiredMoney > 0 then
+ if requiredMoney > GetMoney() then
+ QuestLogRequiredMoneyText:SetTextColor(0.6, 0.6, 0.6)
+ else
+ QuestLogRequiredMoneyText:SetTextColor(1, 0.80, 0.10)
+ end
+ end
+ end)
+
+ hooksecurefunc("QuestFrameItems_Update", function(questState)
+ local titleTextColor = {1, 0.80, 0.10}
+ local textColor = {1, 1, 1}
+
+ QuestDetailObjectiveTitleText:SetTextColor(unpack(titleTextColor))
+ QuestDetailRewardTitleText:SetTextColor(unpack(titleTextColor))
+ QuestLogDescriptionTitle:SetTextColor(unpack(titleTextColor))
+ QuestLogQuestTitle:SetTextColor(unpack(titleTextColor))
+ QuestLogTitleText:SetTextColor(unpack(titleTextColor))
+ QuestLogRewardTitleText:SetTextColor(unpack(titleTextColor))
+ QuestRewardRewardTitleText:SetTextColor(unpack(titleTextColor))
+ QuestRewardTitleText:SetTextColor(unpack(titleTextColor))
+ QuestTitleText:SetTextColor(unpack(titleTextColor))
+ QuestTitleFont:SetTextColor(unpack(titleTextColor))
+ QuestTitleFont:SetFont("Fonts\\MORPHEUS.TTF", E.db.general.fontSize + 6)
+ QuestTitleFont.SetFont = E.noop
+
+ QuestDescription:SetTextColor(unpack(textColor))
+ QuestDetailItemReceiveText:SetTextColor(unpack(textColor))
+ QuestDetailSpellLearnText:SetTextColor(unpack(textColor))
+ QuestDetailItemChooseText:SetTextColor(unpack(textColor))
+ QuestFont:SetTextColor(unpack(textColor))
+ QuestFontNormalSmall:SetTextColor(unpack(textColor))
+ QuestLogObjectivesText:SetTextColor(unpack(textColor))
+ QuestLogQuestDescription:SetTextColor(unpack(textColor))
+ QuestLogItemChooseText:SetTextColor(unpack(textColor))
+ QuestLogItemReceiveText:SetTextColor(unpack(textColor))
+ QuestLogSpellLearnText:SetTextColor(unpack(textColor))
+ QuestObjectiveText:SetTextColor(unpack(textColor))
+ QuestRewardItemChooseText:SetTextColor(unpack(textColor))
+ QuestRewardItemReceiveText:SetTextColor(unpack(textColor))
+ QuestRewardSpellLearnText:SetTextColor(unpack(textColor))
+ QuestRewardText:SetTextColor(unpack(textColor))
+
+ QuestObjectiveTextColor()
+
+ local numQuestRewards, numQuestChoices
+ if questState == "QuestLog" then
+ numQuestRewards, numQuestChoices = GetNumQuestLogRewards(), GetNumQuestLogChoices()
+ else
+ numQuestRewards, numQuestChoices = GetNumQuestRewards(), GetNumQuestChoices()
+ end
+
+ local rewardsCount = numQuestChoices + numQuestRewards
+ if rewardsCount > 0 then
+ local questItem, itemName, link
+ local questItemName = questState.."Item"
+
+ for i = 1, rewardsCount do
+ questItem = _G[questItemName..i]
+ itemName = _G[questItemName..i.."Name"]
+ link = questItem.type and (questState == "QuestLog" and GetQuestLogItemLink or GetQuestItemLink)(questItem.type, questItem:GetID())
+
+ QuestQualityColors(questItem, itemName, nil, link)
+ end
+ end
+ end)
+
+ QuestLogTimerText:SetTextColor(1, 1, 1)
+
+ HookScript(QuestFrameGreetingPanel, "OnShow", function()
+ GreetingText:SetTextColor(1, 0.80, 0.10)
+ CurrentQuestsText:SetTextColor(1, 1, 1)
+ AvailableQuestsText:SetTextColor(1, 1, 1)
+ end)
+
+ E:CreateBackdrop(QuestFrame, "Transparent")
+ QuestFrame.backdrop:SetPoint("TOPLEFT", 15, -19)
+ QuestFrame.backdrop:SetPoint("BOTTOMRIGHT", -30, 67)
+
+ E:CreateBackdrop(QuestLogFrame, "Transparent")
+ QuestLogFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ QuestLogFrame.backdrop:SetPoint("BOTTOMRIGHT", -1, 8)
+
+ E:StripTextures(QuestLogListScrollFrame)
+ E:CreateBackdrop(QuestLogListScrollFrame, "Default", true)
+ QuestLogListScrollFrame:SetWidth(334)
+
+ E:StripTextures(QuestLogDetailScrollFrame)
+ E:CreateBackdrop(QuestLogDetailScrollFrame, "Default", true)
+ QuestLogDetailScrollFrame:SetWidth(334)
+ QuestLogDetailScrollFrame:SetHeight(296)
+ QuestLogDetailScrollFrame:ClearAllPoints()
+ QuestLogDetailScrollFrame:SetPoint("TOPRIGHT", QuestLogListScrollFrame, "BOTTOMRIGHT", 0, -6)
+
+ QuestLogNoQuestsText:ClearAllPoints()
+ QuestLogNoQuestsText:SetPoint("CENTER", EmptyQuestLogFrame, "CENTER", -45, 65)
+
+ QuestLogFrameAbandonButton:SetPoint("BOTTOMLEFT", 18, 15)
+ QuestLogFrameAbandonButton:SetWidth(126)
+
+ QuestFramePushQuestButton:ClearAllPoints()
+ QuestFramePushQuestButton:SetPoint("BOTTOM", QuestFrame, "BOTTOM", 18, 15)
+ QuestFramePushQuestButton:SetWidth(118)
+
+ QuestFrameExitButton:SetPoint("BOTTOMRIGHT", -8, 15)
+ QuestFrameExitButton:SetWidth(100)
+
+ S:HandleScrollBar(QuestLogDetailScrollFrameScrollBar)
+ S:HandleScrollBar(QuestDetailScrollFrameScrollBar)
+ S:HandleScrollBar(QuestLogListScrollFrameScrollBar)
+ S:HandleScrollBar(QuestProgressScrollFrameScrollBar)
+ S:HandleScrollBar(QuestRewardScrollFrameScrollBar)
+
+ S:HandleCloseButton(QuestFrameCloseButton)
+
+ S:HandleCloseButton(QuestLogFrameCloseButton)
+ QuestLogFrameCloseButton:ClearAllPoints()
+ QuestLogFrameCloseButton:SetPoint("TOPRIGHT", 2, -9)
+
+ QuestLogTrack:Hide()
+
+ local QuestTrack = CreateFrame("Button", "QuestTrack", QuestLogFrame, "UIPanelButtonTemplate")
+
+ S:HandleButton(QuestTrack)
+ QuestTrack:SetText(TRACK_QUEST)
+ QuestTrack:SetPoint("TOP", QuestLogFrame, "TOP", -64, -42)
+ QuestTrack:SetWidth(110)
+ QuestTrack:SetHeight(21)
+
+ HookScript(QuestTrack, "OnClick", function()
+ if IsQuestWatched(GetQuestLogSelection()) then
+ RemoveQuestWatch(GetQuestLogSelection())
+
+ QuestWatch_Update()
+ else
+ if GetNumQuestLeaderBoards(GetQuestLogSelection()) == 0 then
+ UIErrorsFrame:AddMessage(QUEST_WATCH_NO_OBJECTIVES, 1.0, 0.1, 0.1, 1.0)
+ return
+ end
+
+ if GetNumQuestWatches() >= MAX_WATCHABLE_QUESTS then
+ UIErrorsFrame:AddMessage(format(QUEST_WATCH_TOO_MANY, MAX_WATCHABLE_QUESTS), 1.0, 0.1, 0.1, 1.0)
+ return
+ end
+
+ AddQuestWatch(GetQuestLogSelection())
+
+ QuestLog_Update()
+ QuestWatch_Update()
+ end
+
+ QuestLog_Update()
+ end)
+
+ hooksecurefunc("QuestLog_Update", function()
+ local numEntries = GetNumQuestLogEntries()
+ if numEntries == 0 then
+ QuestTrack:Disable()
+ else
+ QuestTrack:Enable()
+ end
+ if EmptyQuestLogFrame:IsVisible() then
+ QuestLogListScrollFrame:Hide()
+ else
+ QuestLogListScrollFrame:Show()
+ end
+ end)
+
+ for i = 1, 6 do
+ local item = _G["QuestProgressItem"..i]
+ local icon = _G["QuestProgressItem"..i.."IconTexture"]
+ local count = _G["QuestProgressItem"..i.."Count"]
+
+ E:StripTextures(item)
+ E:SetTemplate(item, "Default")
+ E:StyleButton(item)
+ item:SetWidth(item:GetWidth() - 4)
+ item:SetFrameLevel(item:GetFrameLevel() + 2)
+
+ icon:SetDrawLayer("OVERLAY")
+ icon:SetWidth(icon:GetWidth() -(E.Spacing*2))
+ icon:SetHeight(icon:GetHeight() -(E.Spacing*2))
+ icon:SetPoint("TOPLEFT", E.Border, -E.Border)
+ S:HandleIcon(icon)
+
+ count:SetParent(item.backdrop)
+ count:SetDrawLayer("OVERLAY")
+ end
+
+ hooksecurefunc("QuestFrameProgressItems_Update", function()
+ QuestProgressTitleText:SetTextColor(1, 0.80, 0.10)
+ QuestProgressText:SetTextColor(1, 1, 1)
+
+ QuestProgressRequiredItemsText:SetTextColor(1, 0.80, 0.10)
+
+ if GetQuestMoneyToGet() > GetMoney() then
+ QuestProgressRequiredMoneyText:SetTextColor(0.6, 0.6, 0.6)
+ else
+ QuestProgressRequiredMoneyText:SetTextColor(1, 0.80, 0.10)
+ end
+
+ for i = 1, MAX_REQUIRED_ITEMS do
+ local item = _G["QuestProgressItem"..i]
+ local name = _G["QuestProgressItem"..i.."Name"]
+ local link = item.type and GetQuestItemLink(item.type, item:GetID())
+
+ QuestQualityColors(item, name, nil, link)
+ end
+ end)
+
+ for i = 1, QUESTS_DISPLAYED do
+ local questLogTitle = _G["QuestLogTitle"..i]
+
+ questLogTitle:SetNormalTexture("")
+ questLogTitle.SetNormalTexture = E.noop
+
+ _G["QuestLogTitle"..i.."Highlight"]:SetTexture("")
+ _G["QuestLogTitle"..i.."Highlight"].SetTexture = E.noop
+
+ questLogTitle.Text = questLogTitle:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(questLogTitle.Text, nil, 22)
+ questLogTitle.Text:SetPoint("LEFT", 3, 0)
+ questLogTitle.Text:SetText("+")
+
+ hooksecurefunc(questLogTitle, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ elseif find(texture, "PlusButton") then
+ self.Text:SetText("+")
+ else
+ self.Text:SetText("")
+ end
+ end)
+ end
+
+ E:StripTextures(QuestLogCollapseAllButton)
+ QuestLogCollapseAllButton:SetNormalTexture("")
+ QuestLogCollapseAllButton.SetNormalTexture = E.noop
+ QuestLogCollapseAllButton:SetHighlightTexture("")
+ QuestLogCollapseAllButton.SetHighlightTexture = E.noop
+ QuestLogCollapseAllButton:SetDisabledTexture("")
+ QuestLogCollapseAllButton.SetDisabledTexture = E.noop
+ QuestLogCollapseAllButton:SetPoint("TOPLEFT", -45, 7)
+
+ QuestLogCollapseAllButton.Text = QuestLogCollapseAllButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(QuestLogCollapseAllButton.Text, nil, 22)
+ QuestLogCollapseAllButton.Text:SetPoint("LEFT", 3, 0)
+ QuestLogCollapseAllButton.Text:SetText("+")
+
+ hooksecurefunc(QuestLogCollapseAllButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ else
+ self.Text:SetText("+")
+ end
+ end)
+end
+
+S:AddCallback("Quest", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/QuestTimers.lua b/ElvUI/Modules/Skins/Blizzard/QuestTimers.lua
new file mode 100644
index 0000000..8754d59
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/QuestTimers.lua
@@ -0,0 +1,35 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.questtimers ~= true then return end
+
+ E:StripTextures(QuestTimerFrame)
+ E:SetTemplate(QuestTimerFrame, "Transparent")
+
+ QuestTimerHeader:SetPoint("TOP", 1, 8)
+
+ E:CreateMover(QuestTimerFrame, "QuestTimerFrameMover", QUEST_TIMERS)
+
+ QuestTimerFrame:ClearAllPoints()
+ QuestTimerFrame:SetAllPoints(QuestTimerFrameMover)
+
+ local QuestTimerFrameHolder = CreateFrame("Frame", "QuestTimerFrameHolder", E.UIParent)
+ QuestTimerFrameHolder:SetWidth(150)
+ QuestTimerFrameHolder:SetHeight(22)
+ QuestTimerFrameHolder:SetPoint("TOP", QuestTimerFrameMover, "TOP")
+
+ hooksecurefunc(QuestTimerFrame, "SetPoint", function(_, _, parent)
+ if parent ~= QuestTimerFrameHolder then
+ QuestTimerFrame:ClearAllPoints()
+ QuestTimerFrame:SetPoint("TOP", QuestTimerFrameHolder, "TOP")
+ end
+ end)
+end
+
+S:AddCallback("QuestTimer", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Raid.lua b/ElvUI/Modules/Skins/Blizzard/Raid.lua
new file mode 100644
index 0000000..5679d03
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Raid.lua
@@ -0,0 +1,107 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local pairs = pairs
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.raid ~= true then return end
+
+ -- RaidFrame
+ local StripAllTextures = {
+ "RaidGroup1",
+ "RaidGroup2",
+ "RaidGroup3",
+ "RaidGroup4",
+ "RaidGroup5",
+ "RaidGroup6",
+ "RaidGroup7",
+ "RaidGroup8"
+ }
+
+ for _, object in pairs(StripAllTextures) do
+ if _G[object] then
+ E:StripTextures(_G[object])
+ end
+ end
+
+ S:HandleButton(RaidFrameAddMemberButton)
+ S:HandleButton(RaidFrameReadyCheckButton)
+ S:HandleButton(RaidFrameRaidInfoButton)
+
+ for i = 1, NUM_RAID_GROUPS*5 do
+ S:HandleButton(_G["RaidGroupButton"..i], true)
+ end
+
+ for i = 1, 8 do
+ for j = 1, 5 do
+ E:StripTextures(_G["RaidGroup"..i.."Slot"..j])
+ E:SetTemplate(_G["RaidGroup"..i.."Slot"..j], "Transparent")
+ end
+ end
+
+ local function skinPulloutFrames()
+ for i = 1, NUM_RAID_PULLOUT_FRAMES do
+ local rp = _G["RaidPullout"..i]
+ if not rp.backdrop then
+ _G["RaidPullout"..i.."MenuBackdrop"]:SetBackdrop(nil)
+ E:CreateBackdrop(rp, "Transparent")
+ rp.backdrop:SetPoint("TOPLEFT", 9, -17)
+ rp.backdrop:SetPoint("BOTTOMRIGHT", -7, 10)
+ end
+ end
+ end
+
+ hooksecurefunc("RaidPullout_GetFrame", function()
+ skinPulloutFrames()
+ end)
+
+ --[[hooksecurefunc("RaidPullout_Update", function(pullOutFrame)
+ local pfName = pullOutFrame:GetName()
+ for i = 1, pullOutFrame.numPulloutButtons do
+ local pfBName = pfName.."Button"..i
+ local pfBObj = _G[pfBName]
+ if not pfBObj.backdrop then
+ for _, v in pairs{"HealthBar", "ManaBar", "Target", "TargetTarget"} do
+ local sBar = pfBName..v
+ E:StripTextures(_G[sBar])
+ _G[sBar]:SetStatusBarTexture(E["media"].normTex)
+ end
+
+ _G[pfBName.."ManaBar"]:SetPoint("TOP", "$parentHealthBar", "BOTTOM", 0, 0)
+ _G[pfBName.."Target"]:SetPoint("TOP", "$parentManaBar", "BOTTOM", 0, -1)
+
+ E:CreateBackdrop(pfBObj, "Default")
+ pfBObj.backdrop:SetPoint("TOPLEFT", E.PixelMode and 0 or -1, -(E.PixelMode and 10 or 9))
+ pfBObj.backdrop:SetPoint("BOTTOMRIGHT", E.PixelMode and 0 or 1, E.PixelMode and 1 or 0)
+ end
+
+ if not _G[pfBName.."TargetTargetFrame"].backdrop then
+ E:StripTextures(_G[pfBName.."TargetTargetFrame"])
+ E:CreateBackdrop(_G[pfBName.."TargetTargetFrame"], "Default")
+ _G[pfBName.."TargetTargetFrame"].backdrop:SetPoint("TOPLEFT", E.PixelMode and 10 or 9, -(E.PixelMode and 15 or 14))
+ _G[pfBName.."TargetTargetFrame"].backdrop:SetPoint("BOTTOMRIGHT", -(E.PixelMode and 10 or 9), E.PixelMode and 8 or 7)
+ end
+ end
+ end)]]
+
+ -- ReadyCheckFrame
+ E:StripTextures(ReadyCheckFrame)
+ E:SetTemplate(ReadyCheckFrame, "Transparent")
+
+ E:Kill(ReadyCheckPortrait)
+
+ S:HandleButton(ReadyCheckFrameYesButton)
+ S:HandleButton(ReadyCheckFrameNoButton)
+
+ ReadyCheckFrameYesButton:SetPoint("RIGHT", ReadyCheckFrame, "CENTER", -1, 0)
+ ReadyCheckFrameNoButton:SetPoint("LEFT", ReadyCheckFrameYesButton, "RIGHT", 3, 0)
+ ReadyCheckFrameText:SetPoint("TOP", ReadyCheckFrame, "TOP", 0, -18)
+end
+
+S:AddCallbackForAddon("Blizzard_RaidUI", "RaidUI", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/SpellBook.lua b/ElvUI/Modules/Skins/Blizzard/SpellBook.lua
new file mode 100644
index 0000000..cc6ae83
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/SpellBook.lua
@@ -0,0 +1,70 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.spellbook ~= true then return end
+
+ E:StripTextures(SpellBookFrame, true)
+ E:CreateBackdrop(SpellBookFrame, "Transparent")
+ SpellBookFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ SpellBookFrame.backdrop:SetPoint("BOTTOMRIGHT", -31, 75)
+
+ for i = 1, 3 do
+ local tab = _G["SpellBookFrameTabButton"..i]
+
+ tab:GetNormalTexture():SetTexture("")
+ tab:GetDisabledTexture():SetTexture("")
+
+ S:HandleTab(tab)
+
+ tab.backdrop:SetPoint("TOPLEFT", 14, E.PixelMode and -17 or -19)
+ tab.backdrop:SetPoint("BOTTOMRIGHT", -14, 19)
+ end
+
+ S:HandleNextPrevButton(SpellBookPrevPageButton)
+ S:HandleNextPrevButton(SpellBookNextPageButton)
+
+ S:HandleCloseButton(SpellBookCloseButton)
+
+ for i = 1, SPELLS_PER_PAGE do
+ local button = _G["SpellButton"..i]
+ E:StripTextures(button)
+
+ _G["SpellButton"..i.."AutoCastable"]:SetTexture("Interface\\Buttons\\UI-AutoCastableOverlay")
+ E:SetOutside(_G["SpellButton"..i.."AutoCastable"], button, 16, 16)
+
+ E:CreateBackdrop(button, "Default", true)
+
+ _G["SpellButton"..i.."IconTexture"]:SetTexCoord(unpack(E.TexCoords))
+
+ E:RegisterCooldown(_G["SpellButton"..i.."Cooldown"])
+ end
+
+ hooksecurefunc("SpellButton_UpdateButton", function()
+ local name = this:GetName()
+ _G[name.."SpellName"]:SetTextColor(1, 0.80, 0.10)
+ _G[name.."SubSpellName"]:SetTextColor(1, 1, 1)
+ _G[name.."Highlight"]:SetTexture(1, 1, 1, 0.3)
+ end)
+
+ for i = 1, MAX_SKILLLINE_TABS do
+ local tab = _G["SpellBookSkillLineTab"..i]
+
+ E:StripTextures(tab)
+ E:StyleButton(tab, nil, true)
+ E:SetTemplate(tab, "Default", true)
+
+ E:SetInside(tab:GetNormalTexture())
+ tab:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ end
+
+ SpellBookPageText:SetTextColor(1, 1, 1)
+end
+
+S:AddCallback("SpellBook", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Stable.lua b/ElvUI/Modules/Skins/Blizzard/Stable.lua
new file mode 100644
index 0000000..381cffd
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Stable.lua
@@ -0,0 +1,58 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+local GetPetHappiness = GetPetHappiness
+local HasPetUI = HasPetUI
+local hooksecurefunc = hooksecurefunc
+local UnitExists = UnitExists
+
+function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.stable ~= true then return end
+
+ E:StripTextures(PetStableFrame)
+ E:Kill(PetStableFramePortrait)
+ E:CreateBackdrop(PetStableFrame, "Transparent")
+ PetStableFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ PetStableFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 71)
+
+ S:HandleButton(PetStablePurchaseButton)
+ S:HandleCloseButton(PetStableFrameCloseButton)
+ S:HandleRotateButton(PetStableModelRotateRightButton)
+ S:HandleRotateButton(PetStableModelRotateLeftButton)
+
+ S:HandleItemButton(_G["PetStableCurrentPet"], true)
+ _G["PetStableCurrentPetIconTexture"]:SetDrawLayer("OVERLAY")
+
+ for i = 1, NUM_PET_STABLE_SLOTS do
+ S:HandleItemButton(_G["PetStableStabledPet"..i], true)
+ _G["PetStableStabledPet"..i.."IconTexture"]:SetDrawLayer("OVERLAY")
+ end
+
+ PetStablePetInfo:GetRegions():SetTexCoord(0.04, 0.15, 0.06, 0.30)
+ PetStablePetInfo:SetFrameLevel(PetModelFrame:GetFrameLevel() + 2)
+ E:CreateBackdrop(PetStablePetInfo, "Default")
+ PetStablePetInfo:SetWidth(24)
+ PetStablePetInfo:SetHeight(24)
+
+ hooksecurefunc("PetStable_Update", function()
+ local happiness = GetPetHappiness()
+ local hasPetUI, isHunterPet = HasPetUI()
+ if UnitExists("pet") and hasPetUI and not isHunterPet then
+ return
+ end
+ local texture = PetStablePetInfo:GetRegions()
+ if happiness == 1 then
+ texture:SetTexCoord(0.41, 0.53, 0.06, 0.30)
+ elseif happiness == 2 then
+ texture:SetTexCoord(0.22, 0.345, 0.06, 0.30)
+ elseif happiness == 3 then
+ texture:SetTexCoord(0.04, 0.15, 0.06, 0.30)
+ end
+ end)
+end
+
+S:AddCallback("Stable", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Tabard.lua b/ElvUI/Modules/Skins/Blizzard/Tabard.lua
new file mode 100644
index 0000000..811c76c
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Tabard.lua
@@ -0,0 +1,57 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.tabard ~= true then return end
+
+ E:StripTextures(TabardFrame)
+ E:Kill(TabardFramePortrait)
+ E:CreateBackdrop(TabardFrame, "Transparent")
+ TabardFrame.backdrop:SetPoint("TOPLEFT", 10, -12)
+ TabardFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 74)
+ E:CreateBackdrop(TabardModel, "Default")
+ S:HandleButton(TabardFrameCancelButton)
+ S:HandleButton(TabardFrameAcceptButton)
+ S:HandleCloseButton(TabardFrameCloseButton)
+ S:HandleRotateButton(TabardCharacterModelRotateLeftButton)
+ S:HandleRotateButton(TabardCharacterModelRotateRightButton)
+ E:StripTextures(TabardFrameCostFrame)
+ E:StripTextures(TabardFrameCustomizationFrame)
+
+ for i = 1, 5 do
+ local custom = "TabardFrameCustomization"..i
+ E:StripTextures(_G[custom])
+ S:HandleNextPrevButton(_G[custom.."LeftButton"])
+ S:HandleNextPrevButton(_G[custom.."RightButton"])
+
+ if(i > 1) then
+ _G[custom]:ClearAllPoints()
+ _G[custom]:SetPoint("TOP", _G["TabardFrameCustomization"..i-1], "BOTTOM", 0, -6)
+ else
+ local point, anchor, point2, x, y = _G[custom]:GetPoint()
+ _G[custom]:SetPoint(point, anchor, point2, x, y+4)
+ end
+ end
+
+ TabardCharacterModelRotateLeftButton:SetPoint("BOTTOMLEFT", 4, 4)
+ TabardCharacterModelRotateRightButton:SetPoint("TOPLEFT", TabardCharacterModelRotateLeftButton, "TOPRIGHT", 4, 0)
+ hooksecurefunc(TabardCharacterModelRotateLeftButton, "SetPoint", function(self, point, _, _, xOffset, yOffset)
+ if point ~= "BOTTOMLEFT" or xOffset ~= 4 or yOffset ~= 4 then
+ self:SetPoint("BOTTOMLEFT", 4, 4)
+ end
+ end)
+
+ hooksecurefunc(TabardCharacterModelRotateRightButton, "SetPoint", function(self, point, _, _, xOffset, yOffset)
+ if point ~= "TOPLEFT" or xOffset ~= 4 or yOffset ~= 0 then
+ self:SetPoint("TOPLEFT", TabardCharacterModelRotateLeftButton, "TOPRIGHT", 4, 0)
+ end
+ end)
+end
+
+S:AddCallback("Tabard", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Talent.lua b/ElvUI/Modules/Skins/Blizzard/Talent.lua
new file mode 100644
index 0000000..e477c9a
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Talent.lua
@@ -0,0 +1,58 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.talent ~= true then return end
+
+ E:StripTextures(TalentFrame)
+ E:CreateBackdrop(TalentFrame, "Transparent")
+ TalentFrame.backdrop:SetPoint("TOPLEFT", 13, -12)
+ TalentFrame.backdrop:SetPoint("BOTTOMRIGHT", -31, 76)
+
+ TalentFramePortrait:Hide()
+
+ S:HandleCloseButton(TalentFrameCloseButton)
+
+ E:Kill(TalentFrameCancelButton)
+
+ for i = 1, 5 do
+ S:HandleTab(_G["TalentFrameTab"..i])
+ end
+
+ E:StripTextures(TalentFrameScrollFrame)
+ E:CreateBackdrop(TalentFrameScrollFrame, "Default")
+ TalentFrameScrollFrame.backdrop:SetPoint("TOPLEFT", -1, 2)
+ TalentFrameScrollFrame.backdrop:SetPoint("BOTTOMRIGHT", 6, -2)
+
+ S:HandleScrollBar(TalentFrameScrollFrameScrollBar)
+ TalentFrameScrollFrameScrollBar:SetPoint("TOPLEFT", TalentFrameScrollFrame, "TOPRIGHT", 10, -16)
+
+ TalentFrameSpentPoints:SetPoint("TOP", 0, -42)
+ TalentFrameTalentPointsText:SetPoint("BOTTOMRIGHT", TalentFrame, "BOTTOMLEFT", 220, 84)
+
+ for i = 1, MAX_NUM_TALENTS do
+ local talent = _G["TalentFrameTalent"..i]
+ local icon = _G["TalentFrameTalent"..i.."IconTexture"]
+ local rank = _G["TalentFrameTalent"..i.."Rank"]
+
+ if talent then
+ E:StripTextures(talent)
+ E:SetTemplate(talent, "Default")
+ E:StyleButton(talent)
+
+ E:SetInside(icon)
+ icon:SetTexCoord(unpack(E.TexCoords))
+ icon:SetDrawLayer("ARTWORK")
+
+ rank:SetFont(E.LSM:Fetch("font", E.db["general"].font), 12, "OUTLINE")
+ end
+ end
+end
+
+S:AddCallbackForAddon("Blizzard_TalentUI", "Talent", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Taxi.lua b/ElvUI/Modules/Skins/Blizzard/Taxi.lua
new file mode 100644
index 0000000..811f1b8
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Taxi.lua
@@ -0,0 +1,20 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.taxi ~= true then return end
+
+ E:CreateBackdrop(TaxiFrame, "Transparent")
+ TaxiFrame.backdrop:SetPoint("TOPLEFT", 11, -12)
+ TaxiFrame.backdrop:SetPoint("BOTTOMRIGHT", -34, 75)
+
+ E:StripTextures(TaxiFrame)
+
+ E:Kill(TaxiPortrait)
+
+ S:HandleCloseButton(TaxiCloseButton)
+
+ E:CreateBackdrop(TaxiRouteMap, "Default")
+end
+
+S:AddCallback("Taxi", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Tooltip.lua b/ElvUI/Modules/Skins/Blizzard/Tooltip.lua
new file mode 100644
index 0000000..43f4bf9
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Tooltip.lua
@@ -0,0 +1,51 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+local TT = E:GetModule("Tooltip");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local pairs = pairs
+--WoW API / Variables
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.tooltip ~= true then return end
+
+ S:HandleCloseButton(ItemRefCloseButton)
+
+ local GameTooltip = _G["GameTooltip"]
+ local GameTooltipStatusBar = _G["GameTooltipStatusBar"]
+ local tooltips = {
+ GameTooltip,
+ ItemRefTooltip,
+ ItemRefShoppingTooltip1,
+ ItemRefShoppingTooltip2,
+ ItemRefShoppingTooltip3,
+ AutoCompleteBox,
+ FriendsTooltip,
+ ConsolidatedBuffsTooltip,
+ ShoppingTooltip1,
+ ShoppingTooltip2,
+ ShoppingTooltip3,
+ WorldMapTooltip,
+ WorldMapCompareTooltip1,
+ WorldMapCompareTooltip2,
+ WorldMapCompareTooltip3
+ }
+ for _, tt in pairs(tooltips) do
+ TT:SecureHookScript(tt, "OnShow", "SetStyle")
+ end
+
+ GameTooltipStatusBar:SetStatusBarTexture(E["media"].normTex)
+ E:RegisterStatusBar(GameTooltipStatusBar)
+ E:CreateBackdrop(GameTooltipStatusBar, "Transparent")
+ GameTooltipStatusBar:ClearAllPoints()
+ GameTooltipStatusBar:SetPoint("TOPLEFT", GameTooltip, "BOTTOMLEFT", E.Border, -(E.Spacing * 3))
+ GameTooltipStatusBar:SetPoint("TOPRIGHT", GameTooltip, "BOTTOMRIGHT", -E.Border, -(E.Spacing * 3))
+
+ TT:SecureHookScript(GameTooltip, "OnSizeChanged", "CheckBackdropColor")
+ TT:SecureHookScript(GameTooltip, "OnUpdate", "CheckBackdropColor")
+ TT:RegisterEvent("CURSOR_UPDATE", "CheckBackdropColor")
+end
+
+S:AddCallback("SkinTooltip", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Trade.lua b/ElvUI/Modules/Skins/Blizzard/Trade.lua
new file mode 100644
index 0000000..da66ca7
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Trade.lua
@@ -0,0 +1,125 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+--WoW API / Variables
+local GetItemQualityColor = GetItemQualityColor
+local GetTradePlayerItemInfo = GetTradePlayerItemInfo
+local GetTradeTargetItemInfo = GetTradeTargetItemInfo
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.trade ~= true then return end
+
+ E:StripTextures(TradeFrame, true)
+ TradeFrame:SetWidth(400)
+ E:CreateBackdrop(TradeFrame, "Transparent")
+ TradeFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ TradeFrame.backdrop:SetPoint("BOTTOMRIGHT", -28, 48)
+
+ S:HandleCloseButton(TradeFrameCloseButton, TradeFrame.backdrop)
+
+ S:HandleEditBox(TradePlayerInputMoneyFrameGold)
+ S:HandleEditBox(TradePlayerInputMoneyFrameSilver)
+ S:HandleEditBox(TradePlayerInputMoneyFrameCopper)
+
+ for i = 1, MAX_TRADE_ITEMS do
+ local player = _G["TradePlayerItem"..i]
+ local recipient = _G["TradeRecipientItem"..i]
+ local playerButton = _G["TradePlayerItem"..i.."ItemButton"]
+ local playerButtonIcon = _G["TradePlayerItem"..i.."ItemButtonIconTexture"]
+ local recipientButton = _G["TradeRecipientItem"..i.."ItemButton"]
+ local recipientButtonIcon = _G["TradeRecipientItem"..i.."ItemButtonIconTexture"]
+ local playerNameFrame = _G["TradePlayerItem"..i.."NameFrame"]
+ local recipientNameFrame = _G["TradeRecipientItem"..i.."NameFrame"]
+
+ E:StripTextures(player)
+ E:StripTextures(recipient)
+
+ E:StripTextures(playerButton)
+ E:StyleButton(playerButton)
+ E:SetTemplate(playerButton, "Default", true)
+
+ E:SetInside(playerButtonIcon)
+ playerButtonIcon:SetTexCoord(unpack(E.TexCoords))
+
+ E:StripTextures(recipientButton)
+ E:StyleButton(recipientButton)
+ E:SetTemplate(recipientButton, "Default", true)
+
+ E:SetInside(recipientButtonIcon)
+ recipientButtonIcon:SetTexCoord(unpack(E.TexCoords))
+
+ playerButton.bg = CreateFrame("Frame", nil, playerButton)
+ E:SetTemplate(playerButton.bg, "Default")
+ playerButton.bg:SetPoint("TOPLEFT", playerButton, "TOPRIGHT", 4, 0)
+ playerButton.bg:SetPoint("BOTTOMRIGHT", playerNameFrame, "BOTTOMRIGHT", -5, 14)
+ playerButton.bg:SetFrameLevel(playerButton:GetFrameLevel() - 4)
+
+ recipientButton.bg = CreateFrame("Frame", nil, recipientButton)
+ E:SetTemplate(recipientButton.bg, "Default")
+ recipientButton.bg:SetPoint("TOPLEFT", recipientButton, "TOPRIGHT", 4, 0)
+ recipientButton.bg:SetPoint("BOTTOMRIGHT", recipientNameFrame, "BOTTOMRIGHT", -5, 14)
+ recipientButton.bg:SetFrameLevel(recipientButton:GetFrameLevel() - 4)
+ end
+
+ TradePlayerItem1:SetPoint("TOPLEFT", 24, -104)
+
+ TradeHighlightPlayerTop:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightPlayerBottom:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightPlayerMiddle:SetTexture(0, 1, 0, 0.2)
+
+ TradeHighlightPlayerEnchantTop:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightPlayerEnchantBottom:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightPlayerEnchantMiddle:SetTexture(0, 1, 0, 0.2)
+
+ TradeHighlightRecipientTop:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightRecipientBottom:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightRecipientMiddle:SetTexture(0, 1, 0, 0.2)
+
+ TradeHighlightRecipientEnchantTop:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightRecipientEnchantBottom:SetTexture(0, 1, 0, 0.2)
+ TradeHighlightRecipientEnchantMiddle:SetTexture(0, 1, 0, 0.2)
+
+ S:HandleButton(TradeFrameTradeButton)
+ TradeFrameTradeButton:SetPoint("BOTTOMRIGHT", -120, 55)
+
+ S:HandleButton(TradeFrameCancelButton)
+
+ hooksecurefunc("TradeFrame_UpdatePlayerItem", function(id)
+ local tradeItemButton = _G["TradePlayerItem"..id.."ItemButton"]
+ local tradeItemName = _G["TradePlayerItem"..id.."Name"]
+
+ local name = GetTradePlayerItemInfo(id)
+ if name then
+ local _, _, _, quality = GetTradePlayerItemInfo(id)
+ tradeItemName:SetTextColor(GetItemQualityColor(quality))
+ if quality then
+ tradeItemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ end
+ else
+ tradeItemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end)
+
+ hooksecurefunc("TradeFrame_UpdateTargetItem", function(id)
+ local tradeItemButton = _G["TradeRecipientItem"..id.."ItemButton"]
+ local tradeItemName = _G["TradeRecipientItem"..id.."Name"]
+
+ local name = GetTradeTargetItemInfo(id)
+ if name then
+ local _, _, _, quality = GetTradeTargetItemInfo(id)
+ tradeItemName:SetTextColor(GetItemQualityColor(quality))
+ if quality then
+ tradeItemButton:SetBackdropBorderColor(GetItemQualityColor(quality))
+ end
+ else
+ tradeItemButton:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end)
+end
+
+S:AddCallback("Trade", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/TradeSkill.lua b/ElvUI/Modules/Skins/Blizzard/TradeSkill.lua
new file mode 100644
index 0000000..7241513
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/TradeSkill.lua
@@ -0,0 +1,182 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local find, match, split = string.find, string.match, string.split
+--WoW API / Variables
+local GetItemInfo = GetItemInfo
+local GetItemQualityColor = GetItemQualityColor
+local GetTradeSkillItemLink = GetTradeSkillItemLink
+local GetTradeSkillReagentInfo = GetTradeSkillReagentInfo
+local GetTradeSkillReagentItemLink = GetTradeSkillReagentItemLink
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.tradeskill ~= true then return end
+
+ E:StripTextures(TradeSkillFrame, true)
+ E:CreateBackdrop(TradeSkillFrame, "Transparent")
+ TradeSkillFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ TradeSkillFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 74)
+
+ E:StripTextures(TradeSkillRankFrameBorder)
+ TradeSkillRankFrame:SetWidth(322)
+ TradeSkillRankFrame:SetHeight(16)
+ TradeSkillRankFrame:ClearAllPoints()
+ TradeSkillRankFrame:SetPoint("TOP", -10, -45)
+ E:CreateBackdrop(TradeSkillRankFrame)
+ TradeSkillRankFrame:SetStatusBarTexture(E["media"].normTex)
+ TradeSkillRankFrame:SetStatusBarColor(0.13, 0.35, 0.80)
+ E:RegisterStatusBar(TradeSkillRankFrame)
+
+ E:StripTextures(TradeSkillExpandButtonFrame)
+
+ TradeSkillCollapseAllButton:SetNormalTexture("")
+ TradeSkillCollapseAllButton.SetNormalTexture = E.noop
+ TradeSkillCollapseAllButton:SetHighlightTexture("")
+ TradeSkillCollapseAllButton.SetHighlightTexture = E.noop
+ TradeSkillCollapseAllButton:SetDisabledTexture("")
+ TradeSkillCollapseAllButton.SetDisabledTexture = E.noop
+
+ TradeSkillCollapseAllButton.Text = TradeSkillCollapseAllButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(TradeSkillCollapseAllButton.Text, nil, 22)
+ TradeSkillCollapseAllButton.Text:SetPoint("LEFT", 3, 0)
+ TradeSkillCollapseAllButton.Text:SetText("+")
+
+ hooksecurefunc(TradeSkillCollapseAllButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ else
+ self.Text:SetText("+")
+ end
+ end)
+
+ S:HandleDropDownBox(TradeSkillInvSlotDropDown, 140)
+ TradeSkillSubClassDropDown:ClearAllPoints()
+ TradeSkillInvSlotDropDown:SetPoint("TOPRIGHT", TradeSkillFrame, "TOPRIGHT", -32, -68)
+
+ S:HandleDropDownBox(TradeSkillSubClassDropDown, 140)
+ TradeSkillSubClassDropDown:ClearAllPoints()
+ TradeSkillSubClassDropDown:SetPoint("RIGHT", TradeSkillInvSlotDropDown, "RIGHT", -120, 0)
+
+ TradeSkillFrameTitleText:ClearAllPoints()
+ TradeSkillFrameTitleText:SetPoint("TOP", TradeSkillFrame, "TOP", 0, -18)
+
+ for i = 1, TRADE_SKILLS_DISPLAYED do
+ local skillButton = _G["TradeSkillSkill"..i]
+ skillButton:SetNormalTexture("")
+ skillButton.SetNormalTexture = E.noop
+
+ _G["TradeSkillSkill"..i.."Highlight"]:SetTexture("")
+ _G["TradeSkillSkill"..i.."Highlight"].SetTexture = E.noop
+
+ skillButton.Text = skillButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(skillButton.Text, nil, 22)
+ skillButton.Text:SetPoint("LEFT", 3, 0)
+ skillButton.Text:SetText("+")
+
+ hooksecurefunc(skillButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ elseif find(texture, "PlusButton") then
+ self.Text:SetText("+")
+ else
+ self.Text:SetText("")
+ end
+ end)
+ end
+
+ E:StripTextures(TradeSkillDetailScrollFrame)
+ E:StripTextures(TradeSkillListScrollFrame)
+ E:StripTextures(TradeSkillDetailScrollChildFrame)
+
+ S:HandleScrollBar(TradeSkillListScrollFrameScrollBar)
+ S:HandleScrollBar(TradeSkillDetailScrollFrameScrollBar)
+
+ E:StyleButton(TradeSkillSkillIcon, nil, true)
+ E:SetTemplate(TradeSkillSkillIcon, "Default")
+
+ for i = 1, MAX_TRADE_SKILL_REAGENTS do
+ local reagent = _G["TradeSkillReagent"..i]
+ local icon = _G["TradeSkillReagent"..i.."IconTexture"]
+ local count = _G["TradeSkillReagent"..i.."Count"]
+ local nameFrame = _G["TradeSkillReagent"..i.."NameFrame"]
+
+ icon:SetTexCoord(unpack(E.TexCoords))
+ icon:SetDrawLayer("OVERLAY")
+
+ icon.backdrop = CreateFrame("Frame", nil, reagent)
+ icon.backdrop:SetFrameLevel(reagent:GetFrameLevel() - 1)
+ E:SetTemplate(icon.backdrop, "Default")
+ E:SetOutside(icon.backdrop, icon)
+
+ icon:SetParent(icon.backdrop)
+ count:SetParent(icon.backdrop)
+ count:SetDrawLayer("OVERLAY")
+
+ E:Kill(nameFrame)
+ end
+
+ S:HandleButton(TradeSkillCancelButton)
+ S:HandleButton(TradeSkillCreateButton)
+ S:HandleButton(TradeSkillCreateAllButton)
+
+ S:HandleNextPrevButton(TradeSkillDecrementButton)
+ TradeSkillInputBox:SetHeight(16)
+ S:HandleEditBox(TradeSkillInputBox)
+ S:HandleNextPrevButton(TradeSkillIncrementButton)
+
+ S:HandleCloseButton(TradeSkillFrameCloseButton)
+
+ hooksecurefunc("TradeSkillFrame_SetSelection", function(id)
+ E:SetTemplate(TradeSkillSkillIcon, "Default", true)
+ E:StyleButton(TradeSkillSkillIcon, nil, true)
+ if TradeSkillSkillIcon:GetNormalTexture() then
+ TradeSkillSkillIcon:GetNormalTexture():SetTexCoord(unpack(E.TexCoords))
+ E:SetInside(TradeSkillSkillIcon:GetNormalTexture())
+ end
+
+ TradeSkillSkillIcon:SetWidth(40)
+ TradeSkillSkillIcon:SetHeight(40)
+ TradeSkillSkillIcon:SetPoint("TOPLEFT", 2, -3)
+
+ local skillLink = GetTradeSkillItemLink(id)
+ if skillLink then
+ local _, _, quality = GetItemInfo(match(skillLink, "item:(%d+)"))
+ if quality then
+ TradeSkillSkillIcon:SetBackdropBorderColor(GetItemQualityColor(quality))
+ TradeSkillSkillName:SetTextColor(GetItemQualityColor(quality))
+ else
+ TradeSkillSkillIcon:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ TradeSkillSkillName:SetTextColor(1, 1, 1)
+ end
+ end
+
+ local numReagents = GetTradeSkillNumReagents(id)
+ for i = 1, numReagents, 1 do
+ local _, _, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(id, i)
+ local reagentLink = GetTradeSkillReagentItemLink(id, i)
+ local icon = _G["TradeSkillReagent"..i.."IconTexture"]
+ local name = _G["TradeSkillReagent"..i.."Name"]
+
+ if reagentLink then
+ local _, _, quality = GetItemInfo(match(reagentLink, "item:(%d+)"))
+ if quality then
+ icon.backdrop:SetBackdropBorderColor(GetItemQualityColor(quality))
+ if playerReagentCount < reagentCount then
+ name:SetTextColor(0.5, 0.5, 0.5)
+ else
+ name:SetTextColor(GetItemQualityColor(quality))
+ end
+ else
+ icon.backdrop:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+ end
+ end
+ end
+ end)
+end
+
+S:AddCallbackForAddon("Blizzard_TradeSkillUI", "TradeSkill", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Trainer.lua b/ElvUI/Modules/Skins/Blizzard/Trainer.lua
new file mode 100644
index 0000000..2f84dbe
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Trainer.lua
@@ -0,0 +1,94 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local find = string.find
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.trainer ~= true then return end
+
+ E:CreateBackdrop(ClassTrainerFrame, "Transparent")
+ ClassTrainerFrame.backdrop:SetPoint("TOPLEFT", 10, -11)
+ ClassTrainerFrame.backdrop:SetPoint("BOTTOMRIGHT", -32, 74)
+
+ E:StripTextures(ClassTrainerFrame, true)
+
+ E:StripTextures(ClassTrainerExpandButtonFrame)
+
+ S:HandleDropDownBox(ClassTrainerFrameFilterDropDown)
+ ClassTrainerFrameFilterDropDown:SetPoint("TOPRIGHT", -40, -64)
+
+ E:StripTextures(ClassTrainerListScrollFrame)
+ S:HandleScrollBar(ClassTrainerListScrollFrameScrollBar)
+
+ E:StripTextures(ClassTrainerDetailScrollFrame)
+ S:HandleScrollBar(ClassTrainerDetailScrollFrameScrollBar)
+
+ E:StripTextures(ClassTrainerSkillIcon)
+
+ S:HandleButton(ClassTrainerTrainButton)
+ S:HandleButton(ClassTrainerCancelButton)
+
+ S:HandleCloseButton(ClassTrainerFrameCloseButton)
+
+ hooksecurefunc("ClassTrainer_SetSelection", function()
+ local skillIcon = ClassTrainerSkillIcon:GetNormalTexture()
+ if skillIcon then
+ E:SetInside(skillIcon)
+ skillIcon:SetTexCoord(unpack(E.TexCoords))
+
+ E:SetTemplate(ClassTrainerSkillIcon, "Default")
+ end
+ end)
+
+ for i = 1, CLASS_TRAINER_SKILLS_DISPLAYED do
+ local skillButton = _G["ClassTrainerSkill"..i]
+ skillButton:SetNormalTexture("")
+ skillButton.SetNormalTexture = E.noop
+
+ _G["ClassTrainerSkill"..i.."Highlight"]:SetTexture("")
+ _G["ClassTrainerSkill"..i.."Highlight"].SetTexture = E.noop
+
+ skillButton.Text = skillButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(skillButton.Text, nil, 22)
+ skillButton.Text:SetPoint("LEFT", 3, 0)
+ skillButton.Text:SetText("+")
+
+ hooksecurefunc(skillButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ elseif find(texture, "PlusButton") then
+ self.Text:SetText("+")
+ else
+ self.Text:SetText("")
+ end
+ end)
+ end
+
+ ClassTrainerCollapseAllButton:SetNormalTexture("")
+ ClassTrainerCollapseAllButton.SetNormalTexture = E.noop
+ ClassTrainerCollapseAllButton:SetHighlightTexture("")
+ ClassTrainerCollapseAllButton.SetHighlightTexture = E.noop
+ ClassTrainerCollapseAllButton:SetDisabledTexture("")
+ ClassTrainerCollapseAllButton.SetDisabledTexture = E.noop
+
+ ClassTrainerCollapseAllButton.Text = ClassTrainerCollapseAllButton:CreateFontString(nil, "OVERLAY")
+ E:FontTemplate(ClassTrainerCollapseAllButton.Text, nil, 22)
+ ClassTrainerCollapseAllButton.Text:SetPoint("LEFT", 3, 0)
+ ClassTrainerCollapseAllButton.Text:SetText("+")
+
+ hooksecurefunc(ClassTrainerCollapseAllButton, "SetNormalTexture", function(self, texture)
+ if find(texture, "MinusButton") then
+ self.Text:SetText("-")
+ else
+ self.Text:SetText("+")
+ end
+ end)
+end
+
+S:AddCallbackForAddon("Blizzard_TrainerUI", "Trainer", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/Tutorial.lua b/ElvUI/Modules/Skins/Blizzard/Tutorial.lua
new file mode 100644
index 0000000..e164195
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/Tutorial.lua
@@ -0,0 +1,33 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+--WoW API / Variables
+local MAX_TUTORIAL_ALERTS = MAX_TUTORIAL_ALERTS
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.tutorial ~= true then return end
+
+ for i = 1, MAX_TUTORIAL_ALERTS do
+ local button = _G["TutorialFrameAlertButton"..i]
+ local icon = button:GetNormalTexture()
+
+ button:SetWidth(35)
+ button:SetHeight(45)
+ E:SetTemplate(button, "Default", true)
+ E:StyleButton(button, nil, true)
+
+ E:SetInside(icon)
+ icon:SetTexCoord(0.09, 0.40, 0.11, 0.56)
+ end
+
+ E:SetTemplate(TutorialFrame, "Transparent")
+
+ S:HandleCheckBox(TutorialFrameCheckButton)
+
+ S:HandleButton(TutorialFrameOkayButton)
+end
+
+S:AddCallback("Tutorial", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Blizzard/WorldMap.lua b/ElvUI/Modules/Skins/Blizzard/WorldMap.lua
new file mode 100644
index 0000000..3884cf4
--- /dev/null
+++ b/ElvUI/Modules/Skins/Blizzard/WorldMap.lua
@@ -0,0 +1,23 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:GetModule("Skins");
+
+local function LoadSkin()
+ if E.private.skins.blizzard.enable ~= true or E.private.skins.blizzard.worldmap ~= true then return end
+
+ E:StripTextures(WorldMapFrame)
+ E:CreateBackdrop(WorldMapPositioningGuide, "Transparent")
+
+ S:HandleDropDownBox(WorldMapContinentDropDown, 170)
+ S:HandleDropDownBox(WorldMapZoneDropDown, 170)
+
+ WorldMapZoneDropDown:SetPoint("LEFT", WorldMapContinentDropDown, "RIGHT", -24, 0)
+ WorldMapZoomOutButton:SetPoint("LEFT", WorldMapZoneDropDown, "RIGHT", -4, 3)
+
+ S:HandleButton(WorldMapZoomOutButton)
+
+ S:HandleCloseButton(WorldMapFrameCloseButton)
+
+ E:CreateBackdrop(WorldMapDetailFrame, "Default")
+end
+
+S:AddCallback("SkinWorldMap", LoadSkin)
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Load_Skins.xml b/ElvUI/Modules/Skins/Load_Skins.xml
new file mode 100644
index 0000000..21ca4aa
--- /dev/null
+++ b/ElvUI/Modules/Skins/Load_Skins.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Skins/Skins.lua b/ElvUI/Modules/Skins/Skins.lua
new file mode 100644
index 0000000..e163a2b
--- /dev/null
+++ b/ElvUI/Modules/Skins/Skins.lua
@@ -0,0 +1,602 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local S = E:NewModule("Skins", "AceHook-3.0", "AceEvent-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack, assert, pairs, ipairs, type, pcall = unpack, assert, pairs, ipairs, type, pcall
+local tinsert, wipe = table.insert, table.wipe
+local find, gfind, lower = string.find, string.gfind, string.lower
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local SetDesaturation = SetDesaturation
+local hooksecurefunc = hooksecurefunc
+local IsAddOnLoaded = IsAddOnLoaded
+local GetCVarBool = GetCVarBool
+
+E.Skins = S
+S.addonsToLoad = {}
+S.nonAddonsToLoad = {}
+S.allowBypass = {}
+S.addonCallbacks = {}
+S.nonAddonCallbacks = {["CallPriority"] = {}}
+
+S.SQUARE_BUTTON_TEXCOORDS = {
+ ["UP"] = { 0.45312500, 0.64062500, 0.01562500, 0.20312500};
+ ["DOWN"] = { 0.45312500, 0.64062500, 0.20312500, 0.01562500};
+ ["LEFT"] = { 0.23437500, 0.42187500, 0.01562500, 0.20312500};
+ ["RIGHT"] = { 0.42187500, 0.23437500, 0.01562500, 0.20312500};
+ ["DELETE"] = { 0.01562500, 0.20312500, 0.01562500, 0.20312500}
+}
+
+function S:SquareButton_SetIcon(self, name)
+ local coords = S.SQUARE_BUTTON_TEXCOORDS[strupper(name)]
+ if coords then
+ self.icon:SetTexCoord(coords[1], coords[2], coords[3], coords[4])
+ end
+end
+
+function S:SetModifiedBackdrop()
+ if this.backdrop then this = this.backdrop end
+ this:SetBackdropBorderColor(unpack(E["media"].rgbvaluecolor))
+end
+
+function S:SetOriginalBackdrop()
+ if this.backdrop then this = this.backdrop end
+ this:SetBackdropBorderColor(unpack(E["media"].bordercolor))
+end
+
+function S:HandleButton(f, strip)
+ local name = f:GetName()
+ if name then
+ local left = _G[name .."Left"]
+ local middle = _G[name .."Middle"]
+ local right = _G[name .."Right"]
+
+ if left then E:Kill(left) end
+ if middle then E:Kill(middle) end
+ if right then E:Kill(right) end
+ end
+
+ if f.Left then E:Kill(f.Left) end
+ if f.Middle then E:Kill(f.Middle) end
+ if f.Right then E:Kill(f.Right) end
+
+ if f.SetNormalTexture then f:SetNormalTexture("") end
+ if f.SetHighlightTexture then f:SetHighlightTexture("") end
+ if f.SetPushedTexture then f:SetPushedTexture("") end
+ if f.SetDisabledTexture then f:SetDisabledTexture("") end
+
+ if strip then E:StripTextures(f) end
+
+ E:SetTemplate(f, "Default", true)
+ HookScript(f, "OnEnter", S.SetModifiedBackdrop)
+ HookScript(f, "OnLeave", S.SetOriginalBackdrop)
+end
+
+function S:HandleScrollBar(frame, thumbTrim)
+ local name = frame:GetName()
+ if _G[name.."BG"] then _G[name.."BG"]:SetTexture(nil) end
+ if _G[name.."Track"] then _G[name.."Track"]:SetTexture(nil) end
+ if _G[name.."Top"] then _G[name.."Top"]:SetTexture(nil) end
+ if _G[name.."Bottom"] then _G[name.."Bottom"]:SetTexture(nil) end
+ if _G[name.."Middle"] then _G[name.."Middle"]:SetTexture(nil) end
+
+ if _G[name.."ScrollUpButton"] and _G[name.."ScrollDownButton"] then
+ E:StripTextures(_G[name.."ScrollUpButton"])
+ if not _G[name.."ScrollUpButton"].icon then
+ S:HandleNextPrevButton(_G[name.."ScrollUpButton"])
+ S:SquareButton_SetIcon(_G[name.."ScrollUpButton"], "UP")
+ _G[name.."ScrollUpButton"]:SetWidth(_G[name.."ScrollUpButton"]:GetWidth() + 7)
+ _G[name.."ScrollUpButton"]:SetHeight(_G[name.."ScrollUpButton"]:GetHeight() + 7)
+ end
+
+ E:StripTextures(_G[name .."ScrollDownButton"])
+ if not _G[name.."ScrollDownButton"].icon then
+ S:HandleNextPrevButton(_G[name.."ScrollDownButton"])
+ S:SquareButton_SetIcon(_G[name.."ScrollDownButton"], "DOWN")
+ _G[name.."ScrollDownButton"]:SetWidth(_G[name.."ScrollDownButton"]:GetWidth() + 7)
+ _G[name.."ScrollDownButton"]:SetHeight(_G[name.."ScrollDownButton"]:GetHeight() + 7)
+ end
+
+ if not frame.trackbg then
+ frame.trackbg = CreateFrame("Frame", nil, frame)
+ frame.trackbg:SetPoint("TOPLEFT", _G[name .."ScrollUpButton"], "BOTTOMLEFT", 0, -1)
+ frame.trackbg:SetPoint("BOTTOMRIGHT", _G[name .."ScrollDownButton"], "TOPRIGHT", 0, 1)
+ E:SetTemplate(frame.trackbg, "Transparent")
+ end
+
+ if frame:GetThumbTexture() then
+ if not thumbTrim then thumbTrim = 3 end
+ frame:GetThumbTexture():SetTexture(nil)
+ if not frame.thumbbg then
+ frame.thumbbg = CreateFrame("Frame", nil, frame)
+ frame:GetThumbTexture():SetHeight(24)
+ frame.thumbbg:SetPoint("TOPLEFT", frame:GetThumbTexture(), "TOPLEFT", 1, -thumbTrim)
+ frame.thumbbg:SetPoint("BOTTOMRIGHT", frame:GetThumbTexture(), "BOTTOMRIGHT", -1, thumbTrim)
+ E:SetTemplate(frame.thumbbg, "Default", true, true)
+ frame.thumbbg:SetBackdropColor(0.6, 0.6, 0.6)
+ if frame.trackbg then
+ frame.thumbbg:SetFrameLevel(frame.trackbg:GetFrameLevel() + 1)
+ end
+ end
+ end
+ end
+end
+
+local tabs = {
+ "LeftDisabled",
+ "MiddleDisabled",
+ "RightDisabled",
+ "Left",
+ "Middle",
+ "Right"
+}
+
+function S:HandleTab(tab)
+ local name = tab:GetName()
+ for _, object in pairs(tabs) do
+ local tex = _G[name..object]
+ if tex then
+ tex:SetTexture(nil)
+ end
+ end
+
+ if tab.GetHighlightTexture and tab:GetHighlightTexture() then
+ tab:GetHighlightTexture():SetTexture(nil)
+ else
+ E:StripTextures(tab)
+ end
+
+ tab.backdrop = CreateFrame("Frame", nil, tab)
+ E:SetTemplate(tab.backdrop, "Default")
+ tab.backdrop:SetFrameLevel(tab:GetFrameLevel() - 1)
+ tab.backdrop:SetPoint("TOPLEFT", 10, E.PixelMode and -1 or -3)
+ tab.backdrop:SetPoint("BOTTOMRIGHT", -10, 3)
+end
+
+function S:HandleNextPrevButton(btn, buttonOverride)
+ local inverseDirection = btn:GetName() and (find(lower(btn:GetName()), "left") or find(lower(btn:GetName()), "prev") or find(lower(btn:GetName()), "decrement") or find(lower(btn:GetName()), "promote"))
+
+ E:StripTextures(btn)
+ btn:SetNormalTexture(nil)
+ btn:SetPushedTexture(nil)
+ btn:SetHighlightTexture(nil)
+ btn:SetDisabledTexture(nil)
+
+ if not btn.icon then
+ btn.icon = btn:CreateTexture(nil, "ARTWORK")
+ btn.icon:SetWidth(13)
+ btn.icon:SetHeight(13)
+ btn.icon:SetPoint("CENTER", 0, 0)
+ btn.icon:SetTexture("Interface\\AddOns\\ElvUI\\Media\\Textures\\SquareButtonTextures.blp")
+ btn.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
+
+ btn:SetScript("OnMouseDown", function()
+ if btn:IsEnabled() == 1 then
+ this.icon:SetPoint("CENTER", -1, -1)
+ end
+ end)
+ btn:SetScript("OnMouseUp", function()
+ this.icon:SetPoint("CENTER", 0, 0)
+ end)
+
+ hooksecurefunc(btn, "Disable", function(self)
+ SetDesaturation(self.icon, true)
+ self.icon:SetAlpha(0.5)
+ end)
+ hooksecurefunc(btn, "Enable", function(self)
+ SetDesaturation(self.icon, false)
+ self.icon:SetAlpha(1.0)
+ end)
+
+ if btn:IsEnabled() == 0 then
+ SetDesaturation(btn.icon, true)
+ btn.icon:SetAlpha(0.5)
+ end
+ end
+
+ if buttonOverride then
+ if inverseDirection then
+ S:SquareButton_SetIcon(btn, "UP")
+ else
+ S:SquareButton_SetIcon(btn, "DOWN")
+ end
+ else
+ if inverseDirection then
+ S:SquareButton_SetIcon(btn, "LEFT")
+ else
+ S:SquareButton_SetIcon(btn, "RIGHT")
+ end
+ end
+
+ S:HandleButton(btn)
+ btn:SetWidth(btn:GetWidth() - 7)
+ btn:SetHeight(btn:GetHeight() - 7)
+end
+
+function S:HandleRotateButton(btn)
+ E:SetTemplate(btn, "Default")
+ btn:SetWidth(btn:GetWidth() - 14)
+ btn:SetHeight(btn:GetHeight() - 14)
+
+ btn:GetNormalTexture():SetTexCoord(0.27, 0.73, 0.27, 0.68)
+ btn:GetPushedTexture():SetTexCoord(0.27, 0.73, 0.27, 0.68)
+
+ btn:GetHighlightTexture():SetTexture(1, 1, 1, 0.3)
+
+ E:SetInside(btn:GetNormalTexture())
+ btn:GetPushedTexture():SetAllPoints(btn:GetNormalTexture())
+ btn:GetHighlightTexture():SetAllPoints(btn:GetNormalTexture())
+end
+
+function S:HandleEditBox(frame)
+ if not frame then return end
+
+ E:CreateBackdrop(frame, "Default")
+ frame.backdrop:SetFrameLevel(frame:GetFrameLevel())
+
+ if frame:GetName() then
+ if _G[frame:GetName() .."Left"] then E:Kill(_G[frame:GetName() .."Left"]) end
+ if _G[frame:GetName() .."Middle"] then E:Kill(_G[frame:GetName() .."Middle"]) end
+ if _G[frame:GetName() .."Right"] then E:Kill(_G[frame:GetName() .."Right"]) end
+ if _G[frame:GetName() .."Mid"] then E:Kill(_G[frame:GetName() .."Mid"]) end
+
+ if gfind(frame:GetName(), "Silver") or gfind(frame:GetName(), "Copper") then
+ frame.backdrop:SetPoint("BOTTOMRIGHT", -12, -2)
+ end
+ end
+end
+
+function S:HandleDropDownBox(frame, width)
+ local button = _G[frame:GetName().."Button"]
+ if not button then return end
+
+ if not width then width = 155 end
+
+ E:StripTextures(frame)
+ frame:SetWidth(width)
+
+ if _G[frame:GetName().."Text"] then
+ _G[frame:GetName().."Text"]:ClearAllPoints()
+ _G[frame:GetName().."Text"]:SetPoint("RIGHT", button, "LEFT", -2, 0)
+ end
+
+ if button then
+ button:ClearAllPoints()
+ button:SetPoint("RIGHT", frame, "RIGHT", -10, 3)
+
+ self:HandleNextPrevButton(button, true)
+ end
+ E:CreateBackdrop(frame, "Default")
+ frame.backdrop:SetPoint("TOPLEFT", 20, -2)
+ frame.backdrop:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 2, -2)
+ frame.backdrop:SetFrameLevel(frame:GetFrameLevel())
+end
+
+function S:HandleCheckBox(frame, noBackdrop)
+ frame:SetNormalTexture(nil)
+ frame:SetPushedTexture(nil)
+ frame:SetHighlightTexture(nil)
+ frame:SetDisabledTexture(nil)
+
+ if noBackdrop then
+ E:SetTemplate(frame, "Default")
+ frame:SetWidth(16)
+ frame:SetHeight(16)
+ else
+ E:CreateBackdrop(frame, "Default")
+ E:SetInside(frame.backdrop, nil, 4, 4)
+ frame.backdrop:SetFrameLevel(frame:GetFrameLevel())
+ end
+end
+
+function S:HandleIcon(icon, parent)
+ parent = parent or icon:GetParent()
+
+ icon:SetTexCoord(unpack(E.TexCoords))
+ E:CreateBackdrop(parent, "Default")
+ icon:SetParent(parent.backdrop)
+ E:SetOutside(parent.backdrop, icon)
+end
+
+function S:HandleItemButton(b, shrinkIcon)
+ if b.isSkinned then return end
+
+ local icon = b.icon or b.IconTexture or b.iconTexture
+ local texture
+ if b:GetName() and _G[b:GetName() .."IconTexture"] then
+ icon = _G[b:GetName() .."IconTexture"]
+ elseif b:GetName() and _G[b:GetName() .."Icon"] then
+ icon = _G[b:GetName() .."Icon"]
+ end
+
+ if icon and icon:GetTexture() then
+ texture = icon:GetTexture()
+ end
+
+ E:StripTextures(b)
+ E:CreateBackdrop(b, "Default", true)
+ E:StyleButton(b)
+
+ if icon then
+ icon:SetTexCoord(unpack(E.TexCoords))
+
+ if shrinkIcon then
+ b.backdrop:SetAllPoints()
+ E:SetInside(icon, b)
+ else
+ E:SetOutside(b.backdrop, icon)
+ end
+ icon:SetParent(b.backdrop)
+
+ if texture then
+ icon:SetTexture(texture)
+ end
+ end
+ b.isSkinned = true
+end
+
+function S:HandleCloseButton(f, point, text)
+ E:StripTextures(f)
+
+ if f:GetNormalTexture() then f:SetNormalTexture("") f.SetNormalTexture = E.noop end
+ if f:GetPushedTexture() then f:SetPushedTexture("") f.SetPushedTexture = E.noop end
+
+ if not f.backdrop then
+ E:CreateBackdrop(f, "Default", true)
+ f.backdrop:SetPoint("TOPLEFT", 7, -8)
+ f.backdrop:SetPoint("BOTTOMRIGHT", -8, 8)
+
+ HookScript(f, "OnEnter", function() S:SetModifiedBackdrop(this) end)
+ HookScript(f, "OnLeave", function() S:SetOriginalBackdrop(this) end)
+ end
+ if not text then text = "x" end
+ if not f.text then
+ f.text = f:CreateFontString(nil, "OVERLAY")
+ f.text:SetFont([[Interface\AddOns\ElvUI\Media\Fonts\PT_Sans_Narrow.ttf]], 16, "OUTLINE")
+ f.text:SetText(text)
+ f.text:SetJustifyH("CENTER")
+ f.text:SetPoint("CENTER", f, "CENTER", -1, 1)
+ end
+
+ if point then
+ f:SetPoint("TOPRIGHT", point, "TOPRIGHT", 2, 2)
+ end
+end
+
+function S:HandleSliderFrame(frame)
+ local orientation = frame:GetOrientation()
+ local SIZE = 12
+ E:StripTextures(frame)
+ E:CreateBackdrop(frame, "Default")
+ frame.backdrop:SetAllPoints()
+ hooksecurefunc(frame, "SetBackdrop", function(_, backdrop)
+ if backdrop ~= nil then
+ frame:SetBackdrop(nil)
+ end
+ end)
+ frame:SetThumbTexture(E["media"].blankTex)
+ frame:GetThumbTexture():SetVertexColor(0.3, 0.3, 0.3)
+ frame:GetThumbTexture():SetWidth(SIZE-2)
+ frame:GetThumbTexture():SetHeight(SIZE-2)
+ if orientation == "VERTICAL" then
+ frame:SetWidth(SIZE)
+ else
+ frame:SetHeight(SIZE)
+
+ for _, region in ipairs({frame:GetRegions()}) do
+ if region and region:GetObjectType() == "FontString" then
+ local point, anchor, anchorPoint, x, y = region:GetPoint()
+ if find(anchorPoint, "BOTTOM") then
+ region:SetPoint(point, anchor, anchorPoint, x, y - 4)
+ end
+ end
+ end
+
+ --[[for i = 1, frame:GetNumRegions() do
+ local region = select(i, frame:GetRegions())
+ if region and region:GetObjectType() == "FontString" then
+ local point, anchor, anchorPoint, x, y = region:GetPoint()
+ if anchorPoint:find("BOTTOM") then
+ region:SetPoint(point, anchor, anchorPoint, x, y - 4)
+ end
+ end
+ end]]
+ end
+end
+
+function S:HandleIconSelectionFrame(frame, numIcons, buttonNameTemplate, frameNameOverride)
+ assert(frame, "HandleIconSelectionFrame: frame argument missing")
+ assert(numIcons and type(numIcons) == "number", "HandleIconSelectionFrame: numIcons argument missing or not a number")
+ assert(buttonNameTemplate and type(buttonNameTemplate) == "string", "HandleIconSelectionFrame: buttonNameTemplate argument missing or not a string")
+
+ local frameName = frameNameOverride or frame:GetName() --We need override in case Blizzard fucks up the naming (guild bank)
+ local scrollFrame = _G[frameName.."ScrollFrame"]
+ local editBox = _G[frameName.."EditBox"]
+ local okayButton = _G[frameName.."OkayButton"] or _G[frameName.."Okay"]
+ local cancelButton = _G[frameName.."CancelButton"] or _G[frameName.."Cancel"]
+
+ E:StripTextures(frame)
+ E:StripTextures(scrollFrame)
+ editBox:DisableDrawLayer("BACKGROUND") --Removes textures around it
+
+ E:CreateBackdrop(frame, "Transparent")
+ frame.backdrop:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -12)
+ frame.backdrop:SetPoint("BOTTOMRIGHT", cancelButton, "BOTTOMRIGHT", 5, -5)
+
+ S:HandleButton(okayButton)
+ S:HandleButton(cancelButton)
+ S:HandleEditBox(editBox)
+
+ for i = 1, numIcons do
+ local button = _G[buttonNameTemplate..i]
+ local icon = _G[button:GetName().."Icon"]
+ E:StripTextures(button)
+ E:SetTemplate(button, "Default")
+ E:StyleButton(button, nil, true)
+ E:SetInside(icon)
+ icon:SetTexCoord(unpack(E.TexCoords))
+ end
+end
+
+function S:ADDON_LOADED()
+ if self.allowBypass[arg1] then
+ if self.addonsToLoad[arg1] then
+ --Load addons using the old deprecated register method
+ self.addonsToLoad[arg1]()
+ self.addonsToLoad[arg1] = nil
+ elseif self.addonCallbacks[arg1] then
+ --Fire events to the skins that rely on this addon
+ for index, event in ipairs(self.addonCallbacks[arg1]["CallPriority"]) do
+ self.addonCallbacks[arg1][event] = nil
+ self.addonCallbacks[arg1]["CallPriority"][index] = nil
+ E.callbacks:Fire(event)
+ end
+ end
+ return
+ end
+
+ if not E.initialized then return end
+
+ if self.addonsToLoad[arg1] then
+ self.addonsToLoad[arg1]()
+ self.addonsToLoad[arg1] = nil
+ elseif self.addonCallbacks[arg1] then
+ for index, event in ipairs(self.addonCallbacks[arg1]["CallPriority"]) do
+ self.addonCallbacks[arg1][event] = nil
+ self.addonCallbacks[arg1]["CallPriority"][index] = nil
+ E.callbacks:Fire(event)
+ end
+ end
+end
+
+--Old deprecated register function. Keep it for the time being for any plugins that may need it.
+function S:RegisterSkin(name, loadFunc, forceLoad, bypass)
+ if bypass then
+ self.allowBypass[name] = true
+ end
+
+ if forceLoad then
+ loadFunc()
+ self.addonsToLoad[name] = nil
+ elseif name == "ElvUI" then
+ tinsert(self.nonAddonsToLoad, loadFunc)
+ else
+ self.addonsToLoad[name] = loadFunc
+ end
+end
+
+--Add callback for skin that relies on another addon.
+--These events will be fired when the addon is loaded.
+function S:AddCallbackForAddon(addonName, eventName, loadFunc, forceLoad, bypass)
+ if not addonName or type(addonName) ~= "string" then
+ E:Print("Invalid argument #1 to S:AddCallbackForAddon (string expected)")
+ return
+ elseif not eventName or type(eventName) ~= "string" then
+ E:Print("Invalid argument #2 to S:AddCallbackForAddon (string expected)")
+ return
+ elseif not loadFunc or type(loadFunc) ~= "function" then
+ E:Print("Invalid argument #3 to S:AddCallbackForAddon (function expected)")
+ return
+ end
+
+ if bypass then
+ self.allowBypass[addonName] = true
+ end
+
+ --Create an event registry for this addon, so that we can fire multiple events when this addon is loaded
+ if not self.addonCallbacks[addonName] then
+ self.addonCallbacks[addonName] = {["CallPriority"] = {}}
+ end
+
+ if self.addonCallbacks[addonName][eventName] or E.ModuleCallbacks[eventName] or E.InitialModuleCallbacks[eventName] then
+ --Don't allow a registered callback to be overwritten
+ E:Print("Invalid argument #2 to S:AddCallbackForAddon (event name:", eventName, "is already registered, please use a unique event name)")
+ return
+ end
+
+ --Register loadFunc to be called when event is fired
+ E.RegisterCallback(E, eventName, loadFunc)
+
+ if forceLoad then
+ E.callbacks:Fire(eventName)
+ else
+ --Insert eventName in this addons' registry
+ self.addonCallbacks[addonName][eventName] = true
+ self.addonCallbacks[addonName]["CallPriority"][getn(self.addonCallbacks[addonName]["CallPriority"]) + 1] = eventName
+ end
+end
+
+--Add callback for skin that does not rely on a another addon.
+--These events will be fired when the Skins module is initialized.
+function S:AddCallback(eventName, loadFunc)
+ if not eventName or type(eventName) ~= "string" then
+ E:Print("Invalid argument #1 to S:AddCallback (string expected)")
+ return
+ elseif not loadFunc or type(loadFunc) ~= "function" then
+ E:Print("Invalid argument #2 to S:AddCallback (function expected)")
+ return
+ end
+
+ if self.nonAddonCallbacks[eventName] or E.ModuleCallbacks[eventName] or E.InitialModuleCallbacks[eventName] then
+ --Don't allow a registered callback to be overwritten
+ E:Print("Invalid argument #1 to S:AddCallback (event name:", eventName, "is already registered, please use a unique event name)")
+ return
+ end
+
+ --Add event name to registry
+ self.nonAddonCallbacks[eventName] = true
+ self.nonAddonCallbacks["CallPriority"][getn(self.nonAddonCallbacks["CallPriority"]) + 1] = eventName
+
+ --Register loadFunc to be called when event is fired
+ E.RegisterCallback(E, eventName, loadFunc)
+end
+
+function S:Initialize()
+ self.db = E.private.skins
+
+ --Fire events for Blizzard addons that are already loaded
+ for addon in pairs(self.addonCallbacks) do
+ if IsAddOnLoaded(addon) then
+ for index, event in ipairs(self.addonCallbacks[addon]["CallPriority"]) do
+ self.addonCallbacks[addon][event] = nil
+ self.addonCallbacks[addon]["CallPriority"][index] = nil
+ E.callbacks:Fire(event)
+ end
+ end
+ end
+ --Fire event for all skins that doesn't rely on a Blizzard addon
+ for index, event in ipairs(self.nonAddonCallbacks["CallPriority"]) do
+ self.nonAddonCallbacks[event] = nil
+ self.nonAddonCallbacks["CallPriority"][index] = nil
+ E.callbacks:Fire(event)
+ end
+
+ --Old deprecated load functions. We keep this for the time being in case plugins make use of it.
+ for addon, loadFunc in pairs(self.addonsToLoad) do
+ if IsAddOnLoaded(addon) then
+ self.addonsToLoad[addon] = nil
+ local _, catch = pcall(loadFunc)
+ if catch and GetCVarBool("ShowErrors") == "1" then
+ ScriptErrorsFrame_OnError(catch, false)
+ end
+ end
+ end
+
+ for _, loadFunc in pairs(self.nonAddonsToLoad) do
+ local _, catch = pcall(loadFunc)
+ if catch and GetCVarBool("ShowErrors") == "1" then
+ ScriptErrorsFrame_OnError(catch, false)
+ end
+ end
+ wipe(self.nonAddonsToLoad)
+end
+
+S:RegisterEvent("ADDON_LOADED")
+
+local function InitializeCallback()
+ S:Initialize()
+end
+
+E:RegisterModule(S:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/Tooltip/Load_Tooltip.xml b/ElvUI/Modules/Tooltip/Load_Tooltip.xml
new file mode 100644
index 0000000..1e62dbe
--- /dev/null
+++ b/ElvUI/Modules/Tooltip/Load_Tooltip.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/Tooltip/Tooltip.lua b/ElvUI/Modules/Tooltip/Tooltip.lua
new file mode 100644
index 0000000..380feae
--- /dev/null
+++ b/ElvUI/Modules/Tooltip/Tooltip.lua
@@ -0,0 +1,332 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local TT = E:NewModule("Tooltip", "AceHook-3.0", "AceEvent-3.0");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local unpack = unpack
+local twipe, tinsert, tconcat = table.wipe, table.insert, table.concat
+local floor = math.floor
+local find, format, match = string.find, string.format, string.match
+--WoW API / Variables
+local IsShiftKeyDown = IsShiftKeyDown
+local UnitExists = UnitExists
+local UnitLevel = UnitLevel
+local UnitIsPlayer = UnitIsPlayer
+local UnitClass = UnitClass
+local UnitName = UnitName
+local GetGuildInfo = GetGuildInfo
+local UnitPVPName = UnitPVPName
+local GetQuestDifficultyColor = GetQuestDifficultyColor
+local UnitRace = UnitRace
+local UnitIsTapped = UnitIsTapped
+local UnitIsTappedByPlayer = UnitIsTappedByPlayer
+local UnitReaction = UnitReaction
+local UnitClassification = UnitClassification
+local UnitCreatureType = UnitCreatureType
+local UnitIsPVP = UnitIsPVP
+local GetNumPartyMembers = GetNumPartyMembers
+local GetNumRaidMembers = GetNumRaidMembers
+local UnitIsUnit = UnitIsUnit
+local SetTooltipMoney = SetTooltipMoney
+
+local targetList = {}
+local TAPPED_COLOR = {r = 0.6, g = 0.6, b = 0.6}
+
+local classification = {
+ worldboss = format("|cffAF5050 %s|r", BOSS),
+ rareelite = format("|cffAF5050+ %s|r", ITEM_QUALITY3_DESC),
+ elite = "|cffAF5050+|r",
+ rare = format("|cffAF5050 %s|r", ITEM_QUALITY3_DESC)
+}
+
+function TT:GameTooltip_SetDefaultAnchor(tt, parent)
+ if E.private.tooltip.enable ~= true then return end
+ if tt:GetAnchorType() ~= "ANCHOR_NONE" then return end
+
+ if parent then
+ if self.db.healthBar.statusPosition == "BOTTOM" then
+ if GameTooltipStatusBar.anchoredToTop then
+ GameTooltipStatusBar:ClearAllPoints()
+ E:Point(GameTooltipStatusBar, "TOPLEFT", GameTooltip, "BOTTOMLEFT", E.Border, -(E.Spacing * 3))
+ E:Point(GameTooltipStatusBar, "TOPRIGHT", GameTooltip, "BOTTOMRIGHT", -E.Border, -(E.Spacing * 3))
+ E:Point(GameTooltipStatusBar.text, "CENTER", GameTooltipStatusBar, 0, -3)
+ GameTooltipStatusBar.anchoredToTop = nil
+ end
+ else
+ if not GameTooltipStatusBar.anchoredToTop then
+ GameTooltipStatusBar:ClearAllPoints()
+ E:Point(GameTooltipStatusBar, "BOTTOMLEFT", GameTooltip, "TOPLEFT", E.Border, (E.Spacing * 3))
+ E:Point(GameTooltipStatusBar, "BOTTOMRIGHT", GameTooltip, "TOPRIGHT", -E.Border, (E.Spacing * 3))
+ E:Point(GameTooltipStatusBar.text, "CENTER", GameTooltipStatusBar, 0, 3)
+ GameTooltipStatusBar.anchoredToTop = true
+ end
+ end
+ if self.db.cursorAnchor then
+ tt:SetOwner(parent, "ANCHOR_CURSOR")
+ return;
+ else
+ tt:SetOwner(parent, "ANCHOR_NONE")
+ end
+ end
+
+ if not E:HasMoverBeenMoved("TooltipMover") then
+ if ElvUI_ContainerFrame and ElvUI_ContainerFrame:IsShown() then
+ tt:SetPoint("BOTTOMRIGHT", ElvUI_ContainerFrame, "TOPRIGHT", 0, 18)
+ elseif RightChatPanel:GetAlpha() == 1 and RightChatPanel:IsShown() then
+ tt:SetPoint("BOTTOMRIGHT", RightChatPanel, "TOPRIGHT", 0, 18)
+ else
+ tt:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", 0, 18)
+ end
+ else
+ local point = E:GetScreenQuadrant(TooltipMover)
+ if point == "TOPLEFT" then
+ tt:SetPoint("TOPLEFT", TooltipMover)
+ elseif point == "TOPRIGHT" then
+ tt:SetPoint("TOPRIGHT", TooltipMover)
+ elseif point == "BOTTOMLEFT" or point == "LEFT" then
+ tt:SetPoint("BOTTOMLEFT", TooltipMover)
+ else
+ tt:SetPoint("BOTTOMRIGHT", TooltipMover)
+ end
+ end
+end
+
+function TT:SetStyle(tt)
+ E:SetTemplate(this, "Transparent", nil, true)
+ local r, g, b = this:GetBackdropColor()
+ this:SetBackdropColor(r, g, b, self.db.colorAlpha)
+end
+
+function TT:RemoveTrashLines(tt)
+ for i = 2, tt:NumLines() do
+ local tiptext = _G["GameTooltipTextLeft"..i]
+ local linetext = tiptext:GetText()
+
+ if linetext == HELPFRAME_HOME_ISSUE3_HEADER or linetext == FACTION_ALLIANCE or linetext == FACTION_HORDE then
+ tiptext:SetText(nil)
+ tiptext:Hide()
+ end
+ end
+end
+
+function TT:GetLevelLine(tt, offset)
+ for i = offset, tt:NumLines() do
+ local tipText = _G["GameTooltipTextLeft"..i]
+ if tipText:GetText() and find(tipText:GetText(), LEVEL) then
+ return tipText
+ end
+ end
+end
+
+function TT:UPDATE_MOUSEOVER_UNIT(_, unit)
+ if not unit then unit = "mouseover" end
+ if not UnitExists(unit) then return end
+
+ TT:RemoveTrashLines(GameTooltip)
+ local level = UnitLevel(unit)
+ local isShiftKeyDown = IsShiftKeyDown()
+
+ local color
+ if UnitIsPlayer(unit) then
+ local localeClass, class = UnitClass(unit)
+ local name = UnitName(unit)
+ local guildName, guildRankName = GetGuildInfo(unit)
+ local pvpName = UnitPVPName(unit)
+ if not localeClass or not class then return end
+
+ color = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+
+ GameTooltipTextLeft1:SetText(format("%s%s", E:RGBToHex(color.r, color.g, color.b), name))
+
+ local diffColor = GetQuestDifficultyColor(level)
+ local race = UnitRace(unit)
+
+ if guildName then
+ if self.db.guildRanks then
+ GameTooltipTextLeft2:SetText(format("<|cff00ff10%s|r> [|cff00ff10%s|r]", guildName, guildRankName))
+ else
+ GameTooltipTextLeft2:SetText(format("<|cff00ff10%s|r>", guildName))
+ end
+ GameTooltip:AddLine(format("|cff%02x%02x%02x%s|r %s %s%s|r", diffColor.r * 255, diffColor.g * 255, diffColor.b * 255, level > 0 and level or "??", race or "", E:RGBToHex(color.r, color.g, color.b), localeClass), 1, 1, 1)
+ else
+ GameTooltipTextLeft2:SetText(format("|cff%02x%02x%02x%s|r %s %s%s|r", diffColor.r * 255, diffColor.g * 255, diffColor.b * 255, level > 0 and level or "??", race or "", E:RGBToHex(color.r, color.g, color.b), localeClass))
+ end
+ else
+ if UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) then
+ color = TAPPED_COLOR
+ else
+ color = E.db.tooltip.useCustomFactionColors and E.db.tooltip.factionColors[UnitReaction(unit, "player")] or FACTION_BAR_COLORS[UnitReaction(unit, "player")]
+ end
+
+ local levelLine = self:GetLevelLine(GameTooltip, 2)
+ if levelLine then
+ local creatureClassification = UnitClassification(unit)
+ local creatureType = UnitCreatureType(unit)
+ local pvpFlag = ""
+ local diffColor = GetQuestDifficultyColor(level)
+
+ if UnitIsPVP(unit) then
+ pvpFlag = format(" (%s)", HELPFRAME_HOME_ISSUE3_HEADER)
+ end
+
+ levelLine:SetText(format("|cff%02x%02x%02x%s|r%s %s%s", diffColor.r * 255, diffColor.g * 255, diffColor.b * 255, level > 0 and level or "??", classification[creatureClassification] or "", creatureType or "", pvpFlag))
+ end
+ end
+
+ local unitTarget = unit.."target"
+ if self.db.targetInfo and unit ~= "player" and UnitExists(unitTarget) then
+ local targetColor;
+ if UnitIsPlayer(unitTarget) then
+ local _, class = UnitClass(unitTarget);
+ targetColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class];
+ else
+ local reaction = UnitReaction(unitTarget, "player") or 4
+ targetColor = E.db.tooltip.useCustomFactionColors and E.db.tooltip.factionColors[reaction] or FACTION_BAR_COLORS[reaction]
+ end
+
+ GameTooltip:AddDoubleLine(format("%s:", TARGET), format("|cff%02x%02x%02x%s|r", targetColor.r * 255, targetColor.g * 255, targetColor.b * 255, UnitName(unitTarget)))
+ end
+
+ local numParty, numRaid = GetNumPartyMembers(), GetNumRaidMembers()
+ if self.db.targetInfo and (numParty > 0 or numRaid > 0) then
+ for i = 1, (numRaid > 0 and numRaid or numParty) do
+ local groupUnit = (numRaid > 0 and "raid"..i or "party"..i)
+ if UnitIsUnit(groupUnit.."target", unit) and (not UnitIsUnit(groupUnit,"player")) then
+ local _, class = UnitClass(groupUnit)
+ local color = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]
+ tinsert(targetList, format("%s%s", E:RGBToHex(color.r, color.g, color.b), UnitName(groupUnit)))
+ end
+ end
+ local numList = getn(targetList)
+ if numList > 0 then
+ GameTooltip:AddLine(format("%s (|cffffffff%d|r): %s", L["Targeted By:"], numList, tconcat(targetList, ", ")), nil, nil, nil, true)
+ twipe(targetList)
+ end
+ end
+
+ if color then
+ GameTooltipStatusBar:SetStatusBarColor(color.r, color.g, color.b)
+ else
+ GameTooltipStatusBar:SetStatusBarColor(0.6, 0.6, 0.6)
+ end
+
+ GameTooltip:Show()
+
+ local textWidth = GameTooltipStatusBar.text:GetStringWidth()
+ if textWidth then
+ GameTooltip:SetMinimumWidth(textWidth)
+ end
+end
+
+function TT:SetUnit(tt, unit)
+ self:UPDATE_MOUSEOVER_UNIT(nil, unit)
+end
+
+function TT:GameTooltipStatusBar_OnValueChanged()
+ if not arg1 or not self.db.healthBar.text or not this.text then return end
+
+ local _, max = this:GetMinMaxValues()
+ if arg1 > 0 and max == 1 then
+ this.text:SetText(format("%d%%", floor(arg1 * 100)))
+ this:SetStatusBarColor(TAPPED_COLOR.r, TAPPED_COLOR.g, TAPPED_COLOR.b) --most effeciant?
+ elseif arg1 == 0 then
+ this.text:SetText(DEAD)
+ else
+ this.text:SetText(E:ShortValue(arg1).." / "..E:ShortValue(max))
+ end
+end
+
+function TT:SetItemRef(link)
+ if find(link, "^item:") then
+ local id = tonumber(match(link, "(%d+)"))
+ ItemRefTooltip:AddLine(format("|cFFCA3C3C%s|r %d", ID, id))
+ ItemRefTooltip:Show()
+ end
+end
+
+function TT:CheckBackdropColor()
+ if not GameTooltip:IsShown() then return end
+
+ local r, g, b = GameTooltip:GetBackdropColor()
+ if r and g and b then
+ r = E:Round(r, 1)
+ g = E:Round(g, 1)
+ b = E:Round(b, 1)
+ local red, green, blue = unpack(E.media.backdropfadecolor)
+ if r ~= red or g ~= green or b ~= blue then
+ GameTooltip:SetBackdropColor(red, green, blue, self.db.colorAlpha)
+ end
+ end
+end
+
+function TT:SetTooltipFonts()
+ local font = E.LSM:Fetch("font", E.db.tooltip.font)
+ local fontOutline = E.db.tooltip.fontOutline
+ local headerSize = E.db.tooltip.headerFontSize
+ local textSize = E.db.tooltip.textFontSize
+ local smallTextSize = E.db.tooltip.smallTextFontSize
+
+ GameTooltipHeaderText:SetFont(font, headerSize, fontOutline)
+ GameTooltipText:SetFont(font, textSize, fontOutline)
+ GameTooltipTextSmall:SetFont(font, smallTextSize, fontOutline)
+ if GameTooltip.hasMoney then
+ for i = 1, GameTooltip.numMoneyFrames do
+ _G["GameTooltipMoneyFrame"..i.."PrefixText"]:SetFont(font, textSize, fontOutline)
+ _G["GameTooltipMoneyFrame"..i.."SuffixText"]:SetFont(font, textSize, fontOutline)
+ _G["GameTooltipMoneyFrame"..i.."GoldButtonText"]:SetFont(font, textSize, fontOutline)
+ _G["GameTooltipMoneyFrame"..i.."SilverButtonText"]:SetFont(font, textSize, fontOutline)
+ _G["GameTooltipMoneyFrame"..i.."CopperButtonText"]:SetFont(font, textSize, fontOutline)
+ end
+ end
+
+ ShoppingTooltip1TextLeft1:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextLeft2:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextLeft3:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextLeft4:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextRight1:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextRight2:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextRight3:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip1TextRight4:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextLeft1:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextLeft2:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextLeft3:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextLeft4:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextRight1:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextRight2:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextRight3:SetFont(font, headerSize, fontOutline)
+ ShoppingTooltip2TextRight4:SetFont(font, headerSize, fontOutline)
+end
+
+function TT:Initialize()
+ self.db = E.db.tooltip
+
+ if E.private.tooltip.enable ~= true then return end
+ E.Tooltip = TT
+
+ GameTooltipStatusBar:SetHeight(self.db.healthBar.height)
+ GameTooltipStatusBar:SetScript("OnValueChanged", nil)
+ GameTooltipStatusBar.text = GameTooltipStatusBar:CreateFontString(nil, "OVERLAY")
+ GameTooltipStatusBar.text:SetPoint("CENTER", GameTooltipStatusBar, 0, -3)
+ E:FontTemplate(GameTooltipStatusBar.text, E.LSM:Fetch("font", self.db.healthBar.font), self.db.healthBar.fontSize, self.db.healthBar.fontOutline)
+
+ if not GameTooltip.hasMoney then
+ SetTooltipMoney(GameTooltip, 1, nil, "", "")
+ SetTooltipMoney(GameTooltip, 1, nil, "", "")
+ GameTooltipMoneyFrame:Hide()
+ end
+ self:SetTooltipFonts()
+
+ self:SecureHook("GameTooltip_SetDefaultAnchor")
+ self:SecureHook("SetItemRef")
+ self:SecureHook(GameTooltip, "SetUnit")
+ self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
+
+ self:HookScript(GameTooltipStatusBar, "OnValueChanged", "GameTooltipStatusBar_OnValueChanged")
+end
+
+local function InitializeCallback()
+ TT:Initialize()
+end
+
+E:RegisterModule(TT:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Config_Enviroment.lua b/ElvUI/Modules/UnitFrames/Config_Enviroment.lua
new file mode 100644
index 0000000..4d6070f
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Config_Enviroment.lua
@@ -0,0 +1,297 @@
+local E, L, V, P, G = unpack(ElvUI)
+local UF = E:GetModule("UnitFrames");
+local ns = oUF
+local ElvUF = ns.oUF
+
+local _G = _G;
+local setmetatable, getfenv, setfenv = setmetatable, getfenv, setfenv;
+local type, unpack, select, pairs = type, unpack, select, pairs;
+local min, random = math.min, math.random;
+local format = string.format;
+
+local UnitMana = UnitMana;
+local UnitManaMax = UnitManaMax;
+local UnitHealth = UnitHealth;
+local UnitHealthMax = UnitHealthMax;
+local UnitName = UnitName;
+local UnitClass = UnitClass;
+local InCombatLockdown = InCombatLockdown;
+local UnregisterUnitWatch = UnregisterUnitWatch;
+local RegisterUnitWatch = RegisterUnitWatch;
+local RegisterStateDriver = RegisterStateDriver;
+local LOCALIZED_CLASS_NAMES_MALE = LOCALIZED_CLASS_NAMES_MALE;
+local CLASS_SORT_ORDER = CLASS_SORT_ORDER;
+local MAX_RAID_MEMBERS = MAX_RAID_MEMBERS;
+
+local attributeBlacklist = {["showRaid"] = true, ["showParty"] = true, ["showSolo"] = true}
+local configEnv
+local originalEnvs = {}
+local overrideFuncs = {}
+
+local function createConfigEnv()
+ if( configEnv ) then return end
+ configEnv = setmetatable({
+ UnitMana = function (unit, displayType)
+ if(unit:find("target") or unit:find("focus")) then
+ return UnitMana(unit, displayType);
+ end
+
+ return random(1, UnitManaMax(unit, displayType) or 1);
+ end,
+ UnitHealth = function(unit)
+ if(unit:find("target") or unit:find("focus")) then
+ return UnitHealth(unit);
+ end
+
+ return random(1, UnitHealthMax(unit));
+ end,
+ UnitName = function(unit)
+ if(unit:find("target") or unit:find("focus")) then
+ return UnitName(unit);
+ end
+ if(E.CreditsList) then
+ local max = #E.CreditsList;
+ return E.CreditsList[random(1, max)];
+ end
+ return "Test Name";
+ end,
+ UnitClass = function(unit)
+ if(unit:find("target") or unit:find("focus")) then
+ return UnitClass(unit);
+ end
+
+ local classToken = CLASS_SORT_ORDER[random(1, #(CLASS_SORT_ORDER))];
+ return LOCALIZED_CLASS_NAMES_MALE[classToken], classToken;
+ end,
+ Hex = function(r, g, b)
+ if(type(r) == "table") then
+ if(r.r) then r, g, b = r.r, r.g, r.b; else r, g, b = unpack(r); end
+ end
+ return format("|cff%02x%02x%02x", r*255, g*255, b*255);
+ end,
+ ColorGradient = ElvUF.ColorGradient,
+ }, {
+ __index = _G,
+ __newindex = function(_, key, value) _G[key] = value end,
+ })
+
+ overrideFuncs["namecolor"] = ElvUF.Tags.Methods["namecolor"]
+ overrideFuncs["name:veryshort"] = ElvUF.Tags.Methods["name:veryshort"]
+ overrideFuncs["name:short"] = ElvUF.Tags.Methods["name:short"]
+ overrideFuncs["name:medium"] = ElvUF.Tags.Methods["name:medium"]
+ overrideFuncs["name:long"] = ElvUF.Tags.Methods["name:long"]
+
+ overrideFuncs["healthcolor"] = ElvUF.Tags.Methods["healthcolor"]
+ overrideFuncs["health:current"] = ElvUF.Tags.Methods["health:current"]
+ overrideFuncs["health:deficit"] = ElvUF.Tags.Methods["health:deficit"]
+ overrideFuncs["health:current-percent"] = ElvUF.Tags.Methods["health:current-percent"]
+ overrideFuncs["health:current-max"] = ElvUF.Tags.Methods["health:current-max"]
+ overrideFuncs["health:current-max-percent"] = ElvUF.Tags.Methods["health:current-max-percent"]
+ overrideFuncs["health:max"] = ElvUF.Tags.Methods["health:max"]
+ overrideFuncs["health:percent"] = ElvUF.Tags.Methods["health:percent"]
+
+ overrideFuncs["powercolor"] = ElvUF.Tags.Methods["powercolor"]
+ overrideFuncs["power:current"] = ElvUF.Tags.Methods["power:current"]
+ overrideFuncs["power:deficit"] = ElvUF.Tags.Methods["power:deficit"]
+ overrideFuncs["power:current-percent"] = ElvUF.Tags.Methods["power:current-percent"]
+ overrideFuncs["power:current-max"] = ElvUF.Tags.Methods["power:current-max"]
+ overrideFuncs["power:current-max-percent"] = ElvUF.Tags.Methods["power:current-max-percent"]
+ overrideFuncs["power:max"] = ElvUF.Tags.Methods["power:max"]
+ overrideFuncs["power:percent"] = ElvUF.Tags.Methods["power:percent"]
+end
+
+function UF:ForceShow(frame)
+ if InCombatLockdown() then return; end
+ if not frame.isForced then
+ frame.oldUnit = frame.unit
+ frame.unit = "player"
+ frame.isForced = true;
+ frame.oldOnUpdate = frame:GetScript("OnUpdate")
+ end
+
+ frame:SetScript("OnUpdate", nil)
+ frame.forceShowAuras = true
+ UnregisterUnitWatch(frame)
+ RegisterUnitWatch(frame, true)
+
+ frame:Show()
+ if frame:IsVisible() and frame.Update then
+ frame:Update()
+ end
+
+ if(_G[frame:GetName().."Target"]) then
+ self:ForceShow(_G[frame:GetName().."Target"]);
+ end
+
+ if(_G[frame:GetName().."Pet"]) then
+ self:ForceShow(_G[frame:GetName().."Pet"]);
+ end
+end
+
+function UF:UnforceShow(frame)
+ if InCombatLockdown() then return; end
+ if not frame.isForced then
+ return
+ end
+ frame.forceShowAuras = nil
+ frame.isForced = nil
+
+ -- Ask the SecureStateDriver to show/hide the frame for us
+ UnregisterUnitWatch(frame)
+ RegisterUnitWatch(frame)
+
+ if frame.oldOnUpdate then
+ frame:SetScript("OnUpdate", frame.oldOnUpdate)
+ frame.oldOnUpdate = nil
+ end
+
+ frame.unit = frame.oldUnit or frame.unit
+ -- If we're visible force an update so everything is properly in a
+ -- non-config mode state
+ if frame:IsVisible() and frame.Update then
+ frame:Update()
+ end
+
+ if(_G[frame:GetName().."Target"]) then
+ self:UnforceShow(_G[frame:GetName().."Target"])
+ end
+
+ if(_G[frame:GetName().."Pet"]) then
+ self:UnforceShow(_G[frame:GetName().."Pet"])
+ end
+end
+
+function UF:ShowChildUnits(header, ...)
+ header.isForced = true
+
+ for i=1, select("#", ...) do
+ local frame = select(i, ...)
+ frame:RegisterForClicks(nil)
+ frame:SetID(i)
+ frame.TargetGlow:SetAlpha(0)
+ self:ForceShow(frame)
+ end
+end
+
+function UF:UnshowChildUnits(header, ...)
+ header.isForced = nil
+
+ for i=1, select("#", ...) do
+ local frame = select(i, ...)
+ frame:RegisterForClicks(self.db.targetOnMouseDown and "AnyDown" or "AnyUp")
+ frame.TargetGlow:SetAlpha(1)
+ self:UnforceShow(frame)
+ end
+end
+
+local function OnAttributeChanged(self)
+ if not self:GetParent().forceShow and not self.forceShow then return; end
+ if not self:IsShown() then return end
+
+ local db = self.db or self:GetParent().db
+ local maxUnits = MAX_RAID_MEMBERS
+
+ local startingIndex = db.raidWideSorting and -(min(db.numGroups * (db.groupsPerRowCol * 5), maxUnits) + 1) or -4
+ if self:GetAttribute("startingIndex") ~= startingIndex then
+ self:SetAttribute("startingIndex", startingIndex)
+ UF:ShowChildUnits(self, self:GetChildren())
+ end
+end
+
+function UF:HeaderConfig(header, configMode)
+ if InCombatLockdown() then return; end
+
+ createConfigEnv()
+ header.forceShow = configMode
+ header.forceShowAuras = configMode
+ header.isForced = configMode
+
+ if configMode then
+ for _, func in pairs(overrideFuncs) do
+ if type(func) == "function" then
+ if not originalEnvs[func] then
+ originalEnvs[func] = getfenv(func)
+ setfenv(func, configEnv)
+ end
+ end
+ end
+
+ RegisterStateDriver(header, "visibility", "show")
+ else
+ for func, env in pairs(originalEnvs) do
+ setfenv(func, env)
+ originalEnvs[func] = nil
+ end
+
+ RegisterStateDriver(header, "visibility", header.db.visibility)
+
+ if(header:GetScript("OnEvent")) then
+ header:GetScript("OnEvent")(header, "PLAYER_ENTERING_WORLD");
+ end
+ end
+
+ for i=1, #header.groups do
+ local group = header.groups[i]
+
+ if group:IsShown() then
+ group.forceShow = header.forceShow
+ group.forceShowAuras = header.forceShowAuras
+ group:HookScript("OnAttributeChanged", OnAttributeChanged)
+ if configMode then
+ for key in pairs(attributeBlacklist) do
+ group:SetAttribute(key, nil)
+ end
+
+ OnAttributeChanged(group)
+
+ group:Update()
+ else
+ for key in pairs(attributeBlacklist) do
+ group:SetAttribute(key, true)
+ end
+
+ UF:UnshowChildUnits(group, group:GetChildren())
+ group:SetAttribute("startingIndex", 1)
+
+ group:Update()
+ end
+ end
+ end
+
+ UF["headerFunctions"][header.groupName]:AdjustVisibility(header);
+end
+
+function UF:PLAYER_REGEN_DISABLED()
+ for _, header in pairs(UF["headers"]) do
+ if header.forceShow then
+ self:HeaderConfig(header)
+ end
+ end
+
+ for _, unit in pairs(UF["units"]) do
+ local frame = self[unit]
+ if frame and frame.forceShow then
+ self:UnforceShow(frame)
+ end
+ end
+
+ for i=1, 5 do
+ if self["arena"..i] and self["arena"..i].isForced then
+ self:UnforceShow(self["arena"..i])
+ end
+ end
+
+ for i=1, 4 do
+ if self["boss"..i] and self["boss"..i].isForced then
+ self:UnforceShow(self["boss"..i])
+ end
+ end
+
+ for i=1, 4 do
+ if self["party"..i] and self["party"..i].isForced then
+ self:UnforceShow(self["party"..i])
+ end
+ end
+end
+
+UF:RegisterEvent("PLAYER_REGEN_DISABLED")
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/CombatIndicator.lua b/ElvUI/Modules/UnitFrames/Elements/CombatIndicator.lua
new file mode 100644
index 0000000..e5ba971
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/CombatIndicator.lua
@@ -0,0 +1,26 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+
+--WoW API / Variables
+
+function UF:Construct_CombatIndicator(frame)
+ local combat = frame.RaisedElementParent.TextureParent:CreateTexture(nil, "OVERLAY")
+ combat:SetWidth(19)
+ combat:SetHeight(19)
+ combat:SetPoint("CENTER", frame.Health, "CENTER", 0, 6)
+ combat:SetVertexColor(0.69, 0.31, 0.31)
+
+ return combat
+end
+
+function UF:Configure_CombatIndicator(frame)
+ if frame.db.combatIcon and not frame:IsElementEnabled('CombatIndicator') then
+ frame:EnableElement("CombatIndicator")
+ elseif not frame.db.combatIcon and frame:IsElementEnabled('CombatIndicator') then
+ frame:DisableElement("CombatIndicator")
+ frame.CombatIndicator:Hide()
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/Health.lua b/ElvUI/Modules/UnitFrames/Elements/Health.lua
new file mode 100644
index 0000000..4d5ead8
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/Health.lua
@@ -0,0 +1,238 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+local random = random
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local UnitIsTapped = UnitIsTapped
+local UnitIsTappedByPlayer = UnitIsTappedByPlayer
+local UnitReaction = UnitReaction
+local UnitIsPlayer = UnitIsPlayer
+local UnitClass = UnitClass
+local UnitIsDeadOrGhost = UnitIsDeadOrGhost
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+function UF:Construct_HealthBar(frame, bg, text, textPos)
+ local health = CreateFrame("StatusBar", nil, frame)
+ UF["statusbars"][health] = true
+
+ health:SetFrameLevel(10) --Make room for Portrait and Power which should be lower by default
+ health.PostUpdate = self.PostUpdateHealth
+
+ CreateStatusBarTexturePointer(health)
+
+ if bg then
+ health.bg = health:CreateTexture(nil, "BORDER")
+ health.bg:SetAllPoints()
+ health.bg:SetTexture(E["media"].blankTex)
+ health.bg.multiplier = 0.25
+ end
+
+ if text then
+ health.value = frame.RaisedElementParent:CreateFontString(nil, "OVERLAY")
+ UF:Configure_FontString(health.value)
+
+ local x = -2
+ if textPos == "LEFT" then
+ x = 2
+ end
+
+ health.value:SetPoint(textPos, health, textPos, x, 0)
+ end
+
+ health.colorTapping = true
+ health.colorDisconnected = true
+ E:CreateBackdrop(health, "Default", nil, nil, self.thinBorders, true)
+
+ return health
+end
+
+function UF:Configure_HealthBar(frame)
+ if not frame.VARIABLES_SET then return end
+ local db = frame.db
+ local health = frame.Health
+
+ health.Smooth = self.db.smoothbars
+ health.SmoothSpeed = self.db.smoothSpeed * 10
+
+ --Text
+ if db.health and health.value then
+ local attachPoint = self:GetObjectAnchorPoint(frame, db.health.attachTextTo)
+ health.value:ClearAllPoints()
+ health.value:SetPoint(db.health.position, attachPoint, db.health.position, db.health.xOffset, db.health.yOffset)
+ frame:Tag(health.value, db.health.text_format)
+ end
+
+ --Colors
+ health.colorSmooth = nil
+ health.colorHealth = nil
+ health.colorClass = nil
+ health.colorReaction = nil
+
+ if db.colorOverride and db.colorOverride == "FORCE_ON" then
+ health.colorClass = true
+ health.colorReaction = true
+ elseif db.colorOverride and db.colorOverride == "FORCE_OFF" then
+ if self.db["colors"].colorhealthbyvalue == true then
+ health.colorSmooth = true
+ else
+ health.colorHealth = true
+ end
+ else
+ if self.db.colors.healthclass ~= true then
+ if self.db.colors.colorhealthbyvalue == true then
+ health.colorSmooth = true
+ else
+ health.colorHealth = true
+ end
+ else
+ health.colorClass = (not self.db.colors.forcehealthreaction)
+ health.colorReaction = true
+ end
+ end
+
+ --Position
+ health:ClearAllPoints()
+ if frame.ORIENTATION == "LEFT" then
+ health:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -frame.BORDER - frame.SPACING, -frame.BORDER - frame.SPACING - frame.CLASSBAR_YOFFSET)
+
+ if frame.USE_POWERBAR_OFFSET then
+ health:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -frame.BORDER - frame.SPACING - frame.POWERBAR_OFFSET, -frame.BORDER - frame.SPACING - frame.CLASSBAR_YOFFSET)
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET) - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET))
+ elseif frame.POWERBAR_DETACHED or not frame.USE_POWERBAR or frame.USE_INSET_POWERBAR then
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.BORDER + frame.SPACING + frame.BOTTOM_OFFSET))
+ elseif frame.USE_MINI_POWERBAR then
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.SPACING + (frame.POWERBAR_HEIGHT/2)))
+ else
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.BORDER + frame.SPACING + frame.BOTTOM_OFFSET))
+ end
+ elseif frame.ORIENTATION == "RIGHT" then
+ health:SetPoint("TOPLEFT", frame, "TOPLEFT", frame.BORDER + frame.SPACING, -frame.BORDER - frame.SPACING - frame.CLASSBAR_YOFFSET)
+
+ if frame.USE_POWERBAR_OFFSET then
+ health:SetPoint("TOPLEFT", frame, "TOPLEFT", frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET, -frame.BORDER - frame.SPACING - frame.CLASSBAR_YOFFSET)
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET) - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET))
+ elseif frame.POWERBAR_DETACHED or not frame.USE_POWERBAR or frame.USE_INSET_POWERBAR then
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.BORDER + frame.SPACING + frame.BOTTOM_OFFSET))
+ elseif frame.USE_MINI_POWERBAR then
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.SPACING + (frame.POWERBAR_HEIGHT/2)))
+ else
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.BORDER + frame.SPACING + frame.BOTTOM_OFFSET))
+ end
+ elseif frame.ORIENTATION == "MIDDLE" then
+ health:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -frame.BORDER - frame.SPACING, -frame.BORDER - frame.SPACING - frame.CLASSBAR_YOFFSET)
+
+ if frame.USE_POWERBAR_OFFSET then
+ health:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -frame.BORDER - frame.SPACING - frame.POWERBAR_OFFSET, -frame.BORDER - frame.SPACING - frame.CLASSBAR_YOFFSET)
+ health:SetWidth(frame.UNIT_WIDTH - (frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING + (frame.POWERBAR_OFFSET*2)))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET) - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET))
+ elseif frame.POWERBAR_DETACHED or not frame.USE_POWERBAR or frame.USE_INSET_POWERBAR then
+ health:SetWidth(frame.UNIT_WIDTH - (frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.BORDER + frame.SPACING + frame.BOTTOM_OFFSET))
+ elseif frame.USE_MINI_POWERBAR then
+ health:SetWidth(frame.UNIT_WIDTH - (frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.SPACING + (frame.POWERBAR_HEIGHT/2)))
+ else
+ health:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ health:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET) - (frame.BORDER + frame.SPACING + frame.BOTTOM_OFFSET))
+ end
+ end
+
+ health.bg:ClearAllPoints()
+ if not frame.USE_PORTRAIT_OVERLAY then
+ health.bg:SetParent(health)
+ health.bg:SetAllPoints()
+ else
+ health.bg:SetPoint("BOTTOMLEFT", health.texturePointer, "BOTTOMRIGHT")
+ health.bg:SetPoint("TOPRIGHT", health)
+ health.bg:SetParent(frame.Portrait.overlay)
+ end
+
+ if db.health then
+ --Party/Raid Frames allow to change statusbar orientation
+ if db.health.orientation then
+ health:SetOrientation(db.health.orientation)
+ end
+
+ --Party/Raid Frames can toggle frequent updates
+ if db.health.frequentUpdates then
+ health.frequentUpdates = db.health.frequentUpdates
+ end
+ end
+
+ --Transparency Settings
+ UF:ToggleTransparentStatusBar(UF.db.colors.transparentHealth, frame.Health, frame.Health.bg, (frame.USE_PORTRAIT and frame.USE_PORTRAIT_OVERLAY) ~= true)
+
+ frame:UpdateElement("Health")
+end
+
+function UF:GetHealthBottomOffset(frame)
+ local bottomOffset = 0
+ if frame.USE_POWERBAR and not frame.POWERBAR_DETACHED and not frame.USE_INSET_POWERBAR then
+ bottomOffset = bottomOffset + frame.POWERBAR_HEIGHT - (frame.BORDER-frame.SPACING)
+ end
+ if frame.USE_INFO_PANEL then
+ bottomOffset = bottomOffset + frame.INFO_PANEL_HEIGHT - (frame.BORDER-frame.SPACING)
+ end
+
+ return bottomOffset
+end
+
+function UF:PostUpdateHealth(unit, min, max)
+ local parent = self:GetParent()
+ if parent.isForced then
+ min = random(1, max)
+ self:SetValue(min)
+ end
+
+ local r, g, b = self:GetStatusBarColor()
+ local colors = E.db["unitframe"]["colors"]
+ if ((colors.healthclass == true and colors.colorhealthbyvalue == true) or (colors.colorhealthbyvalue and parent.isForced)) and not (UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit)) then
+ local newr, newg, newb = ElvUF.ColorGradient(min, max, 1, 0, 0, 1, 1, 0, r, g, b)
+
+ self:SetStatusBarColor(newr, newg, newb)
+ if self.bg and self.bg.multiplier then
+ local mu = self.bg.multiplier
+ self.bg:SetVertexColor(newr * mu, newg * mu, newb * mu)
+ end
+ end
+
+ if colors.classbackdrop then
+ local reaction = UnitReaction(unit, "player")
+ local t
+ if UnitIsPlayer(unit) then
+ local _, class = UnitClass(unit)
+ t = parent.colors.class[class]
+ elseif(reaction) then
+ t = parent.colors.reaction[reaction]
+ end
+
+ if t then
+ self.bg:SetVertexColor(t[1], t[2], t[3])
+ end
+ end
+
+ --Backdrop
+ if colors.customhealthbackdrop then
+ local backdrop = colors.health_backdrop
+ self.bg:SetVertexColor(backdrop.r, backdrop.g, backdrop.b)
+ end
+
+ if colors.useDeadBackdrop and UnitIsDeadOrGhost(unit) then
+ local backdrop = colors.health_backdrop_dead
+ self.bg:SetVertexColor(backdrop.r, backdrop.g, backdrop.b)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/InfoPanel.lua b/ElvUI/Modules/UnitFrames/Elements/InfoPanel.lua
new file mode 100644
index 0000000..fe2a8da
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/InfoPanel.lua
@@ -0,0 +1,49 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+function UF:Construct_InfoPanel(frame)
+ local infoPanel = CreateFrame("Frame", nil, frame)
+
+ infoPanel:SetFrameLevel(7) --Health is 10 and filled power is 5 by default
+ local thinBorders = self.thinBorders
+ E:CreateBackdrop(infoPanel, "Default", true, nil, thinBorders, true)
+
+ return infoPanel
+end
+
+function UF:Configure_InfoPanel(frame, noTemplateChange)
+ if not frame.VARIABLES_SET then return end
+ local db = frame.db
+
+ if frame.USE_INFO_PANEL then
+ frame.InfoPanel:Show()
+ frame.InfoPanel:ClearAllPoints()
+
+ if frame.ORIENTATION == "RIGHT" then
+ frame.InfoPanel:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -frame.BORDER - frame.SPACING, frame.BORDER + frame.SPACING)
+ if frame.USE_POWERBAR and not frame.USE_INSET_POWERBAR and not frame.POWERBAR_DETACHED then
+ frame.InfoPanel:SetPoint("TOPLEFT", frame.Power.backdrop, "BOTTOMLEFT", frame.BORDER, -(frame.SPACING*3))
+ else
+ frame.InfoPanel:SetPoint("TOPLEFT", frame.Health.backdrop, "BOTTOMLEFT", frame.BORDER, -(frame.SPACING*3))
+ end
+ else
+ frame.InfoPanel:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", frame.BORDER + frame.SPACING, frame.BORDER + frame.SPACING)
+ if frame.USE_POWERBAR and not frame.USE_INSET_POWERBAR and not frame.POWERBAR_DETACHED then
+ frame.InfoPanel:SetPoint("TOPRIGHT", frame.Power.backdrop, "BOTTOMRIGHT", -frame.BORDER, -(frame.SPACING*3))
+ else
+ frame.InfoPanel:SetPoint("TOPRIGHT", frame.Health.backdrop, "BOTTOMRIGHT", -frame.BORDER, -(frame.SPACING*3))
+ end
+ end
+
+ if not noTemplateChange then
+ local thinBorders = self.thinBorders
+ if db.infoPanel.transparent then
+ E:SetTemplate(frame.InfoPanel.backdrop, "Transparent", nil, nil, thinBorders, true)
+ else
+ E:SetTemplate(frame.InfoPanel.backdrop, "Default", true, nil, thinBorders, true)
+ end
+ end
+ else
+ frame.InfoPanel:Hide()
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml b/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml
new file mode 100644
index 0000000..c380c5b
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/Name.lua b/ElvUI/Modules/UnitFrames/Elements/Name.lua
new file mode 100644
index 0000000..c5b6d33
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/Name.lua
@@ -0,0 +1,48 @@
+local E, L, V, P, G = unpack(ElvUI);
+local UF = E:GetModule("UnitFrames");
+
+local UnitIsPlayer = UnitIsPlayer
+
+function UF:Construct_NameText(frame)
+ local name = frame.RaisedElementParent:CreateFontString(nil, "OVERLAY")
+ UF:Configure_FontString(name)
+ name:SetPoint("CENTER", frame.Health)
+
+ return name
+end
+
+function UF:UpdateNameSettings(frame, childType)
+ local db = frame.db
+ if childType == "pet" then
+ db = frame.db.petsGroup
+ elseif childType == "target" then
+ db = frame.db.targetsGroup
+ end
+
+ local name = frame.Name
+ if not db.power or not db.power.enable or not db.power.hideonnpc then
+ local attachPoint = self:GetObjectAnchorPoint(frame, db.name.attachTextTo)
+ name:ClearAllPoints()
+ name:SetPoint(db.name.position, attachPoint, db.name.position, db.name.xOffset, db.name.yOffset)
+ end
+
+ frame:Tag(name, db.name.text_format)
+end
+
+function UF:PostNamePosition(frame, unit)
+ if not frame.Power.value:IsShown() then return end
+ local db = frame.db
+ if UnitIsPlayer(unit) or (db.power and not db.power.enable) then
+ local position = db.name.position
+ local attachPoint = self:GetObjectAnchorPoint(frame, db.name.attachTextTo)
+ frame.Power.value:SetAlpha(1)
+
+ frame.Name:ClearAllPoints()
+ frame.Name:SetPoint(position, attachPoint, position, db.name.xOffset, db.name.yOffset)
+ else
+ frame.Power.value:SetAlpha(db.power.hideonnpc and 0 or 1)
+
+ frame.Name:ClearAllPoints()
+ frame.Name:SetPoint(frame.Power.value:GetPoint())
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/Portrait.lua b/ElvUI/Modules/UnitFrames/Elements/Portrait.lua
new file mode 100644
index 0000000..997169b
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/Portrait.lua
@@ -0,0 +1,119 @@
+local E, L, V, P, G = unpack(ElvUI);
+local UF = E:GetModule("UnitFrames");
+
+local CreateFrame = CreateFrame;
+
+function UF:Construct_Portrait(frame, type)
+ local portrait;
+ if(type == "texture") then
+ local backdrop = CreateFrame("Frame", nil, frame);
+ portrait = frame:CreateTexture(nil, "OVERLAY");
+ portrait:SetTexCoord(0.15, 0.85, 0.15, 0.85);
+ E:SetOutside(backdrop, portrait);
+ backdrop:SetFrameLevel(frame:GetFrameLevel());
+ E:SetTemplate(backdrop, "Default");
+ portrait.backdrop = backdrop;
+ else
+ portrait = CreateFrame("PlayerModel", nil, frame);
+ E:CreateBackdrop(portrait, "Default", nil, nil, self.thinBorders, true)
+ end
+
+ portrait.PostUpdate = self.PortraitUpdate;
+
+ portrait.overlay = CreateFrame("Frame", nil, frame);
+ portrait.overlay:SetFrameLevel(frame.Health:GetFrameLevel() + 5);
+
+ return portrait;
+end
+
+function UF:Configure_Portrait(frame, dontHide)
+ if(not frame.VARIABLES_SET) then return; end
+ local db = frame.db;
+ if(frame.Portrait and not dontHide) then
+ frame.Portrait:Hide();
+ frame.Portrait:ClearAllPoints();
+ frame.Portrait.backdrop:Hide();
+ end
+ frame.Portrait = db.portrait.style == "2D" and frame.Portrait2D or frame.Portrait3D;
+
+ local portrait = frame.Portrait;
+ if(frame.USE_PORTRAIT) then
+ if(not frame:IsElementEnabled("Portrait")) then
+ frame:EnableElement("Portrait", frame.unit);
+ end
+
+ local color = E.db.unitframe.colors.borderColor
+ portrait.backdrop:SetBackdropBorderColor(color.r, color.g, color.b)
+
+ portrait:ClearAllPoints();
+ portrait.backdrop:ClearAllPoints();
+ if(frame.USE_PORTRAIT_OVERLAY) then
+ if(db.portrait.style == "3D") then
+ portrait:SetFrameLevel(frame.Health:GetFrameLevel() + 1);
+ else
+ portrait:SetParent(frame.Health);
+ end
+
+ portrait:SetAllPoints(frame.Health);
+
+ portrait:SetPoint("TOPLEFT", frame.Health, "TOPLEFT", - frame.BORDER - frame.SPACING, -(frame.BORDER + frame.SPACING))
+ portrait:SetPoint("BOTTOMLEFT", frame.Health, "BOTTOMLEFT", - frame.BORDER - frame.SPACING, -(frame.BORDER + frame.SPACING))
+
+ portrait:SetAlpha(0.35);
+ if(not dontHide) then
+ portrait:Show();
+ end
+ portrait.backdrop:Hide();
+ else
+ portrait:SetAlpha(1);
+ if(not dontHide) then
+ portrait:Show();
+ end
+ portrait.backdrop:Show();
+ if(db.portrait.style == "3D") then
+ portrait:SetFrameLevel(frame.Health:GetFrameLevel() - 4);
+ else
+ portrait:SetParent(frame.Health);
+ end
+
+ if(frame.ORIENTATION == "LEFT") then
+ portrait.backdrop:SetPoint("TOPLEFT", frame, "TOPLEFT", frame.SPACING, frame.USE_MINI_CLASSBAR and -(frame.CLASSBAR_YOFFSET+frame.SPACING) or -frame.SPACING);
+
+ if(frame.USE_MINI_POWERBAR or frame.USE_POWERBAR_OFFSET or not frame.USE_POWERBAR or frame.USE_INSET_POWERBAR or frame.POWERBAR_DETACHED) then
+ portrait.backdrop:SetPoint("BOTTOMRIGHT", frame.Health.backdrop, "BOTTOMLEFT", frame.BORDER - frame.SPACING*3, 0);
+ else
+ portrait.backdrop:SetPoint("BOTTOMRIGHT", frame.Power.backdrop, "BOTTOMLEFT", frame.BORDER - frame.SPACING*3, 0);
+ end
+ elseif(frame.ORIENTATION == "RIGHT") then
+ portrait.backdrop:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -frame.SPACING, frame.USE_MINI_CLASSBAR and -(frame.CLASSBAR_YOFFSET+frame.SPACING) or -frame.SPACING);
+
+ if(frame.USE_MINI_POWERBAR or frame.USE_POWERBAR_OFFSET or not frame.USE_POWERBAR or frame.USE_INSET_POWERBAR or frame.POWERBAR_DETACHED) then
+ portrait.backdrop:SetPoint("BOTTOMLEFT", frame.Health.backdrop, "BOTTOMRIGHT", -frame.BORDER + frame.SPACING*3, 0);
+ else
+ portrait.backdrop:SetPoint("BOTTOMLEFT", frame.Power.backdrop, "BOTTOMRIGHT", -frame.BORDER + frame.SPACING*3, 0);
+ end
+ end
+
+ E:SetInside(portrait, portrait.backdrop, frame.BORDER);
+ end
+ else
+ if(frame:IsElementEnabled("Portrait")) then
+ frame:DisableElement("Portrait");
+ portrait:Hide();
+ portrait.backdrop:Hide();
+ end
+ end
+end
+
+function UF:PortraitUpdate()
+ local db = self:GetParent().db;
+ if(not db) then return; end
+
+ local portrait = db.portrait;
+ if(portrait.enable and self:GetParent().USE_PORTRAIT_OVERLAY) then
+ self:SetAlpha(0);
+ self:SetAlpha(0.35);
+ else
+ self:SetAlpha(1)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/Power.lua b/ElvUI/Modules/UnitFrames/Elements/Power.lua
new file mode 100644
index 0000000..288e642
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/Power.lua
@@ -0,0 +1,244 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+local random = random
+--WoW API / Variables
+local CreateFrame = CreateFrame
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+function UF:Construct_PowerBar(frame, bg, text, textPos)
+ local power = CreateFrame("StatusBar", nil, frame)
+ UF["statusbars"][power] = true
+
+ power.PostUpdate = self.PostUpdatePower
+
+ CreateStatusBarTexturePointer(power)
+
+ if bg then
+ power.bg = power:CreateTexture(nil, "BORDER")
+ power.bg:SetAllPoints()
+ power.bg:SetTexture(E["media"].blankTex)
+ power.bg.multiplier = 0.2
+ end
+
+ if text then
+ power.value = frame.RaisedElementParent:CreateFontString(nil, "OVERLAY")
+ power.value.frequentUpdates = true
+
+ UF:Configure_FontString(power.value)
+
+ local x = -2
+ if textPos == "LEFT" then
+ x = 2
+ end
+
+ power.value:SetPoint(textPos, frame.Health, textPos, x, 0)
+ end
+
+ power.colorDisconnected = false
+ power.colorTapping = false
+ E:CreateBackdrop(power, "Default", nil, nil, self.thinBorders)
+
+ return power
+end
+
+function UF:Configure_Power(frame)
+ if not frame.VARIABLES_SET then return end
+ local db = frame.db
+ local power = frame.Power
+ power.origParent = frame
+
+ if frame.USE_POWERBAR then
+ if not frame:IsElementEnabled("Power") then
+ frame:EnableElement("Power")
+ power:Show()
+ end
+
+ power.Smooth = self.db.smoothbars
+ power.SmoothSpeed = self.db.smoothSpeed * 10
+
+ --Text
+ local attachPoint = self:GetObjectAnchorPoint(frame, db.power.attachTextTo)
+ power.value:ClearAllPoints()
+ power.value:SetPoint(db.power.position, attachPoint, db.power.position, db.power.xOffset, db.power.yOffset)
+ frame:Tag(power.value, db.power.text_format)
+
+ if db.power.attachTextTo == "Power" then
+ power.value:SetParent(power)
+ else
+ power.value:SetParent(frame.RaisedElementParent)
+ end
+
+ --Colors
+ power.colorClass = nil
+ power.colorReaction = nil
+ power.colorPower = nil
+ if self.db["colors"].powerclass then
+ power.colorClass = true
+ power.colorReaction = true
+ else
+ power.colorPower = true
+ end
+
+ --Fix height in case it is lower than the theme allows
+ local heightChanged = false
+ if (not self.thinBorders and not E.PixelMode) and frame.POWERBAR_HEIGHT < 7 then --A height of 7 means 6px for borders and just 1px for the actual power statusbar
+ frame.POWERBAR_HEIGHT = 7
+ if db.power then db.power.height = 7 end
+ heightChanged = true
+ elseif (self.thinBorders or E.PixelMode) and frame.POWERBAR_HEIGHT < 3 then --A height of 3 means 2px for borders and just 1px for the actual power statusbar
+ frame.POWERBAR_HEIGHT = 3
+ if db.power then db.power.height = 3 end
+ heightChanged = true
+ end
+ if heightChanged then
+ --Update health size
+ frame.BOTTOM_OFFSET = UF:GetHealthBottomOffset(frame)
+ UF:Configure_HealthBar(frame)
+ end
+
+ power:ClearAllPoints()
+ if frame.POWERBAR_DETACHED then
+ power:SetWidth(frame.POWERBAR_WIDTH - ((frame.BORDER + frame.SPACING)*2))
+ power:SetHeight(frame.POWERBAR_HEIGHT - ((frame.BORDER + frame.SPACING)*2))
+ if not power.Holder or (power.Holder and not power.Holder.mover) then
+ power.Holder = CreateFrame("Frame", nil, power)
+ power.Holder:SetWidth(frame.POWERBAR_WIDTH)
+ power.Holder:SetHeight(frame.POWERBAR_HEIGHT)
+ power.Holder:SetPoint("BOTTOM", frame, "BOTTOM", 0, -20)
+ power:ClearAllPoints()
+ power:SetPoint("BOTTOMLEFT", power.Holder, "BOTTOMLEFT", frame.BORDER+frame.SPACING, frame.BORDER+frame.SPACING)
+
+ if(frame.unitframeType and frame.unitframeType == "player") then
+ E:CreateMover(power.Holder, "PlayerPowerBarMover", L["Player Powerbar"], nil, nil, nil, "ALL,SOLO")
+ elseif(frame.unitframeType and frame.unitframeType == "target") then
+ E:CreateMover(power.Holder, "TargetPowerBarMover", L["Target Powerbar"], nil, nil, nil, "ALL,SOLO")
+ end
+ else
+ power.Holder:SetWidth(frame.POWERBAR_WIDTH)
+ power.Holder:SetHeight(frame.POWERBAR_HEIGHT)
+ power:ClearAllPoints()
+ power:SetPoint("BOTTOMLEFT", power.Holder, "BOTTOMLEFT", frame.BORDER+frame.SPACING, frame.BORDER+frame.SPACING)
+ power.Holder.mover:SetScale(1)
+ power.Holder.mover:SetAlpha(1)
+ end
+
+ power:SetFrameLevel(50) --RaisedElementParent uses 100, we want lower value to allow certain icons and texts to appear above power
+ power.backdrop:SetFrameLevel(49)
+ elseif frame.USE_POWERBAR_OFFSET then
+ if frame.ORIENTATION == "LEFT" then
+ power:SetPoint("TOPRIGHT", frame.Health, "TOPRIGHT", frame.POWERBAR_OFFSET, -frame.POWERBAR_OFFSET)
+ power:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET))
+ power:SetHeight(frame.UNIT_HEIGHT - (frame.BORDER + frame.SPACING + frame.POWERBAR_OFFSET) - (frame.BORDER + frame.SPACING + frame.CLASSBAR_YOFFSET))
+ elseif frame.ORIENTATION == "MIDDLE" then
+ power:SetWidth(frame.UNIT_WIDTH - frame.PORTRAIT_WIDTH - ((frame.BORDER + frame.SPACING) * 2))
+ power:SetHeight(frame.UNIT_HEIGHT - (frame.POWERBAR_OFFSET + frame.CLASSBAR_YOFFSET) - frame.BORDER)
+ power:SetPoint("TOPLEFT", frame, "TOPLEFT", frame.BORDER + frame.SPACING, -frame.POWERBAR_OFFSET -frame.CLASSBAR_YOFFSET)
+ else
+ power:SetWidth(frame.UNIT_WIDTH - frame.PORTRAIT_WIDTH - frame.POWERBAR_OFFSET)
+ power:SetHeight(frame.UNIT_HEIGHT - frame.POWERBAR_OFFSET)
+ power:SetPoint("TOPLEFT", frame.Health, "TOPLEFT", -frame.POWERBAR_OFFSET, -frame.POWERBAR_OFFSET)
+ end
+ power:SetFrameLevel(frame.Health:GetFrameLevel() -5) --Health uses 10
+ power.backdrop:SetFrameLevel(frame.Health:GetFrameLevel() - 6)
+ elseif frame.USE_INSET_POWERBAR then
+ power:SetWidth(frame.UNIT_WIDTH - frame.PORTRAIT_WIDTH - ((frame.BORDER + (frame.BORDER*2)) * 2) - ((frame.BORDER + frame.SPACING) * 2))
+ power:SetHeight(frame.POWERBAR_HEIGHT - ((frame.BORDER + frame.SPACING)*2))
+ power:SetPoint("BOTTOMLEFT", frame.Health, "BOTTOMLEFT", frame.BORDER + (frame.BORDER*2), frame.BORDER + (frame.BORDER*2))
+
+ power:SetFrameLevel(50)
+ power.backdrop:SetFrameLevel(49)
+ elseif frame.USE_MINI_POWERBAR then
+ power:SetHeight(frame.POWERBAR_HEIGHT - ((frame.BORDER + frame.SPACING)*2))
+
+ if frame.ORIENTATION == "LEFT" then
+ power:SetWidth(frame.POWERBAR_WIDTH - frame.BORDER*2)
+ power:SetPoint("RIGHT", frame, "BOTTOMRIGHT", -(frame.BORDER*2 + 4), ((frame.POWERBAR_HEIGHT-frame.BORDER)/2))
+ elseif frame.ORIENTATION == "RIGHT" then
+ power:SetWidth(frame.POWERBAR_WIDTH - frame.BORDER*2)
+ power:SetPoint("LEFT", frame, "BOTTOMLEFT", (frame.BORDER*2 + 4), ((frame.POWERBAR_HEIGHT-frame.BORDER)/2))
+ else
+ power:SetWidth(frame.UNIT_WIDTH - ((frame.BORDER*2 + 4) * 2))
+ power:SetHeight(frame.POWERBAR_HEIGHT - frame.BORDER*2)
+ power:SetPoint("LEFT", frame, "BOTTOMLEFT", (frame.BORDER*2 + 4), ((frame.POWERBAR_HEIGHT-frame.BORDER)/2))
+ end
+
+ power:SetFrameLevel(50)
+ power.backdrop:SetFrameLevel(49)
+ else
+ power:SetPoint("TOPLEFT", frame.Health.backdrop, "BOTTOMLEFT", frame.BORDER, -frame.SPACING*3)
+ power:SetWidth(frame.UNIT_WIDTH - (frame.PORTRAIT_WIDTH + frame.BORDER + frame.SPACING) - (frame.BORDER + frame.SPACING))
+ power:SetHeight(frame.POWERBAR_HEIGHT - ((frame.BORDER + frame.SPACING)*2))
+
+ power:SetFrameLevel(frame.Health:GetFrameLevel() - 5)
+ power.backdrop:SetFrameLevel(frame.Health:GetFrameLevel() - 6)
+ end
+
+ --Hide mover until we detach again
+ if not frame.POWERBAR_DETACHED then
+ if power.Holder and power.Holder.mover then
+ power.Holder.mover:SetScale(0.0001)
+ power.Holder.mover:SetAlpha(0)
+ end
+ end
+
+ if db.power.strataAndLevel and db.power.strataAndLevel.useCustomStrata then
+ power:SetFrameStrata(db.power.strataAndLevel.frameStrata)
+ else
+ power:SetFrameStrata("LOW")
+ end
+ if db.power.strataAndLevel and db.power.strataAndLevel.useCustomLevel then
+ power:SetFrameLevel(db.power.strataAndLevel.frameLevel)
+ power.backdrop:SetFrameLevel(power:GetFrameLevel() - 1)
+ end
+
+ if frame.POWERBAR_DETACHED and db.power.parent == "UIPARENT" then
+ power:SetParent(E.UIParent)
+ else
+ power:SetParent(frame)
+ end
+ elseif frame:IsElementEnabled("Power") then
+ frame:DisableElement("Power")
+ power:Hide()
+ frame:Tag(power.value, "")
+ end
+
+ if frame.DruidAltMana then
+ if db.power.druidMana then
+ frame:EnableElement("DruidAltMana")
+ else
+ frame:DisableElement("DruidAltMana")
+ frame.DruidAltMana:Hide()
+ end
+ end
+
+ --Transparency Settings
+ UF:ToggleTransparentStatusBar(UF.db.colors.transparentPower, frame.Power, frame.Power.bg)
+end
+
+function UF:PostUpdatePower(unit, cur, max)
+ local parent = self:GetParent()
+
+ if parent.isForced then
+ local pType = random(0, 3)
+ local color = ElvUF["colors"].power[pType]
+ cur = random(1, max)
+ self:SetValue(cur)
+
+ if not self.colorClass then
+ self:SetStatusBarColor(color[1], color[2], color[3])
+ local mu = self.bg.multiplier or 1
+ self.bg:SetVertexColor(color[1] * mu, color[2] * mu, color[3] * mu)
+ end
+ end
+
+ local db = parent.db
+ if db and db.power and db.power.hideonnpc then
+ UF:PostNamePosition(parent, unit)
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/RaidIcon.lua b/ElvUI/Modules/UnitFrames/Elements/RaidIcon.lua
new file mode 100644
index 0000000..7d0e527
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/RaidIcon.lua
@@ -0,0 +1,32 @@
+local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+function UF:Construct_RaidIcon(frame)
+ local tex = frame.RaisedElementParent.TextureParent:CreateTexture(nil, "OVERLAY")
+ tex:SetTexture([[Interface\AddOns\ElvUI\media\textures\raidicons]])
+ tex:SetWidth(18)
+ tex:SetHeight(18)
+ tex:SetPoint("CENTER", frame.Health, "TOP", 0, 2)
+ tex.SetTexture = E.noop
+
+ return tex
+end
+
+function UF:Configure_RaidIcon(frame)
+ local RI = frame.RaidTargetIndicator
+ local db = frame.db
+
+ if db.raidicon.enable then
+ frame:EnableElement("RaidTargetIndicator")
+ RI:Show()
+ RI:SetWidth(db.raidicon.size)
+ RI:SetHeight(db.raidicon.size)
+
+ local attachPoint = self:GetObjectAnchorPoint(frame, db.raidicon.attachToObject)
+ RI:ClearAllPoints()
+ RI:SetPoint(db.raidicon.attachTo, attachPoint, db.raidicon.attachTo, db.raidicon.xOffset, db.raidicon.yOffset)
+ else
+ frame:DisableElement("RaidTargetIndicator")
+ RI:Hide()
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/RaidRoleIcons.lua b/ElvUI/Modules/UnitFrames/Elements/RaidRoleIcons.lua
new file mode 100644
index 0000000..a031d0e
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/RaidRoleIcons.lua
@@ -0,0 +1,94 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+
+--WoW API / Variables
+local CreateFrame = CreateFrame
+
+function UF:Construct_RaidRoleFrames(frame)
+ local anchor = CreateFrame("Frame", nil, frame.RaisedElementParent)
+ frame.LeaderIndicator = anchor:CreateTexture(nil, "OVERLAY")
+ frame.AssistantIndicator = anchor:CreateTexture(nil, "OVERLAY")
+ frame.MasterLooterIndicator = anchor:CreateTexture(nil, "OVERLAY")
+
+ anchor:SetWidth(24)
+ anchor:SetHeight(12)
+ frame.LeaderIndicator:SetWidth(12)
+ frame.LeaderIndicator:SetHeight(12)
+ frame.AssistantIndicator:SetWidth(12)
+ frame.AssistantIndicator:SetHeight(12)
+ frame.MasterLooterIndicator:SetWidth(11)
+ frame.MasterLooterIndicator:SetHeight(11)
+
+ frame.LeaderIndicator.PostUpdate = UF.RaidRoleUpdate
+ frame.AssistantIndicator.PostUpdate = UF.RaidRoleUpdate
+ frame.MasterLooterIndicator.PostUpdate = UF.RaidRoleUpdate
+
+ return anchor
+end
+
+function UF:Configure_RaidRoleIcons(frame)
+ local raidRoleFrameAnchor = frame.RaidRoleFramesAnchor
+
+ if frame.db.raidRoleIcons.enable then
+ raidRoleFrameAnchor:Show()
+ if not frame:IsElementEnabled("LeaderIndicator") then
+ frame:EnableElement("LeaderIndicator")
+ frame:EnableElement("MasterLooterIndicator")
+ frame:EnableElement("AssistantIndicator")
+ end
+
+ raidRoleFrameAnchor:ClearAllPoints()
+ if frame.db.raidRoleIcons.position == "TOPLEFT" then
+ raidRoleFrameAnchor:SetPoint("LEFT", frame.Health, "TOPLEFT", 2, 0)
+ else
+ raidRoleFrameAnchor:SetPoint("RIGHT", frame, "TOPRIGHT", -2, 0)
+ end
+ elseif frame:IsElementEnabled("LeaderIndicator") then
+ raidRoleFrameAnchor:Hide()
+ frame:DisableElement("LeaderIndicator")
+ frame:DisableElement("MasterLooterIndicator")
+ frame:DisableElement("AssistantIndicator")
+ end
+end
+
+function UF:RaidRoleUpdate()
+ local anchor = self:GetParent()
+ local frame = anchor:GetParent():GetParent()
+ local leader = frame.LeaderIndicator
+ local assistant = frame.AssistantIndicator
+ local masterLooter = frame.MasterLooterIndicator
+
+ if not leader or not masterLooter or not assistant then return; end
+
+ local db = frame.db
+ local isLeader = leader:IsShown()
+ local isMasterLooter = masterLooter:IsShown()
+ local isAssist = assistant:IsShown()
+
+ leader:ClearAllPoints()
+ assistant:ClearAllPoints()
+ masterLooter:ClearAllPoints()
+
+ if db and db.raidRoleIcons then
+ if isLeader and db.raidRoleIcons.position == "TOPLEFT" then
+ leader:SetPoint("LEFT", anchor, "LEFT")
+ masterLooter:SetPoint("RIGHT", anchor, "RIGHT")
+ elseif isLeader and db.raidRoleIcons.position == "TOPRIGHT" then
+ leader:SetPoint("RIGHT", anchor, "RIGHT")
+ masterLooter:SetPoint("LEFT", anchor, "LEFT")
+ elseif isAssist and db.raidRoleIcons.position == "TOPLEFT" then
+ assistant:SetPoint("LEFT", anchor, "LEFT")
+ masterLooter:SetPoint("RIGHT", anchor, "RIGHT")
+ elseif isAssist and db.raidRoleIcons.position == "TOPRIGHT" then
+ assistant:SetPoint("RIGHT", anchor, "RIGHT")
+ masterLooter:SetPoint("LEFT", anchor, "LEFT")
+ elseif isMasterLooter and db.raidRoleIcons.position == "TOPLEFT" then
+ masterLooter:SetPoint("LEFT", anchor, "LEFT")
+ else
+ masterLooter:SetPoint("RIGHT", anchor, "RIGHT")
+ end
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Elements/RestingIndicator.lua b/ElvUI/Modules/UnitFrames/Elements/RestingIndicator.lua
new file mode 100644
index 0000000..26f964d
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Elements/RestingIndicator.lua
@@ -0,0 +1,40 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+
+--WoW API / Variables
+
+function UF:Construct_RestingIndicator(frame)
+ local resting = frame.RaisedElementParent.TextureParent:CreateTexture(nil, "OVERLAY")
+ resting:SetWidth(22)
+ resting:SetHeight(22)
+
+ return resting
+end
+
+function UF:Configure_RestingIndicator(frame)
+ if not frame.VARIABLES_SET then return end
+ local rIcon = frame.RestingIndicator
+ local db = frame.db
+ if db.restIcon then
+ if not frame:IsElementEnabled("RestingIndicator") then
+ frame:EnableElement("RestingIndicator")
+ end
+
+ rIcon:ClearAllPoints()
+ if frame.ORIENTATION == "RIGHT" then
+ rIcon:SetPoint("CENTER", frame.Health, "TOPLEFT", -3, 6)
+ else
+ if frame.USE_PORTRAIT and not frame.USE_PORTRAIT_OVERLAY then
+ rIcon:SetPoint("CENTER", frame.Portrait, "TOPLEFT", -3, 6)
+ else
+ rIcon:SetPoint("CENTER", frame.Health, "TOPLEFT", -3, 6)
+ end
+ end
+ elseif frame:IsElementEnabled("RestingIndicator") then
+ frame:DisableElement("RestingIndicator")
+ rIcon:Hide()
+ end
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Groups/Load_Groups.xml b/ElvUI/Modules/UnitFrames/Groups/Load_Groups.xml
new file mode 100644
index 0000000..22ccc83
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Groups/Load_Groups.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Groups/Party.lua b/ElvUI/Modules/UnitFrames/Groups/Party.lua
new file mode 100644
index 0000000..440f5bf
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Groups/Party.lua
@@ -0,0 +1,122 @@
+local E, L, V, P, G = unpack(ElvUI)
+local UF = E:GetModule("UnitFrames")
+
+local _G = _G
+local tinsert = table.insert
+
+local CreateFrame = CreateFrame
+local InCombatLockdown = InCombatLockdown
+local UnregisterStateDriver = UnregisterStateDriver
+local RegisterStateDriver = RegisterStateDriver
+local IsInInstance = IsInInstance
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+function UF:Construct_PartyFrames()
+ self:SetScript("OnEnter", UnitFrame_OnEnter)
+ self:SetScript("OnLeave", UnitFrame_OnLeave)
+
+ self.RaisedElementParent = CreateFrame("Frame", nil, self)
+ self.RaisedElementParent:SetFrameLevel(self:GetFrameLevel() + 100)
+ self.RaisedElementParent.TextureParent = CreateFrame("Frame", nil, self.RaisedElementParent)
+ self.RaisedElementParent.TextureParent:SetFrameLevel(self.RaisedElementParent:GetFrameLevel() + 1)
+
+ self.Health = UF:Construct_HealthBar(self, true, true, "RIGHT")
+ self.Power = UF:Construct_PowerBar(self, true, true, "LEFT")
+ self.Power.frequentUpdates = false
+ self.Portrait3D = UF:Construct_Portrait(self, "model")
+ self.Portrait2D = UF:Construct_Portrait(self, "texture")
+ self.InfoPanel = UF:Construct_InfoPanel(self)
+ self.Name = UF:Construct_NameText(self)
+ self.RaidRoleFramesAnchor = UF:Construct_RaidRoleFrames(self)
+ self.RaidTargetIndicator = UF:Construct_RaidIcon(self)
+
+ self.unitframeType = "party"
+
+ UF:Update_StatusBars()
+ UF:Update_FontStrings()
+
+ UF:Update_PartyFrames(self, UF.db["units"]["party"])
+
+ return self;
+end
+
+function UF:Update_PartyHeader(header)
+ if not header.positioned then
+ header:ClearAllPoints()
+ header:SetPoint("BOTTOMLEFT", E.UIParent, "BOTTOMLEFT", 4, 195)
+
+ E:CreateMover(header, header:GetName().."Mover", L["Party Frames"], nil, nil, nil, "ALL,PARTY,ARENA")
+ header.positioned = true
+ end
+end
+
+
+function UF:Update_PartyFrames(frame, db)
+ frame.db = db
+
+ frame.Portrait = db.portrait.style == "2D" and frame.Portrait2D or frame.Portrait3D
+ frame.colors = ElvUF.colors
+ frame:RegisterForClicks(self.db.targetOnMouseDown and "LeftButtonDown" or "LeftButtonUp", self.db.targetOnMouseDown and "RightButtonDown" or "RightButtonUp")
+
+ do
+ if self.thinBorders then
+ frame.SPACING = 0
+ frame.BORDER = E.mult
+ else
+ frame.BORDER = E.Border
+ frame.SPACING = E.Spacing
+ end
+
+ frame.ORIENTATION = db.orientation
+ frame.UNIT_WIDTH = db.width
+ frame.UNIT_HEIGHT = db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height
+
+ frame.USE_POWERBAR = db.power.enable
+ frame.POWERBAR_DETACHED = db.power.detachFromFrame
+ frame.USE_INSET_POWERBAR = not frame.POWERBAR_DETACHED and db.power.width == "inset" and frame.USE_POWERBAR
+ frame.USE_MINI_POWERBAR = (not frame.POWERBAR_DETACHED and db.power.width == "spaced" and frame.USE_POWERBAR)
+ frame.USE_POWERBAR_OFFSET = db.power.offset ~= 0 and frame.USE_POWERBAR and not frame.POWERBAR_DETACHED
+ frame.POWERBAR_OFFSET = frame.USE_POWERBAR_OFFSET and db.power.offset or 0
+
+ frame.POWERBAR_HEIGHT = not frame.USE_POWERBAR and 0 or db.power.height
+ frame.POWERBAR_WIDTH = frame.USE_MINI_POWERBAR and (frame.UNIT_WIDTH - (frame.BORDER*2))/2 or (frame.POWERBAR_DETACHED and db.power.detachedWidth or (frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2)))
+
+ frame.USE_PORTRAIT = db.portrait and db.portrait.enable
+ frame.USE_PORTRAIT_OVERLAY = frame.USE_PORTRAIT and (db.portrait.overlay or frame.ORIENTATION == "MIDDLE")
+ frame.PORTRAIT_WIDTH = (frame.USE_PORTRAIT_OVERLAY or not frame.USE_PORTRAIT) and 0 or db.portrait.width
+
+ frame.CLASSBAR_WIDTH = 0
+ frame.CLASSBAR_YOFFSET = 0
+
+ frame.USE_INFO_PANEL = not frame.USE_MINI_POWERBAR and not frame.USE_POWERBAR_OFFSET and db.infoPanel.enable
+ frame.INFO_PANEL_HEIGHT = frame.USE_INFO_PANEL and db.infoPanel.height or 0
+
+ frame.BOTTOM_OFFSET = UF:GetHealthBottomOffset(frame)
+
+ frame.VARIABLES_SET = true
+ end
+
+ frame:SetWidth(frame.UNIT_WIDTH)
+ frame:SetHeight(frame.UNIT_HEIGHT)
+
+ UF:Configure_InfoPanel(frame)
+
+ UF:Configure_HealthBar(frame)
+
+ UF:UpdateNameSettings(frame)
+
+ UF:Configure_Power(frame)
+
+ UF:Configure_Portrait(frame)
+
+ UF:Configure_RaidIcon(frame)
+
+ UF:Configure_RaidRoleIcons(frame)
+
+ frame:UpdateAllElements("ElvUI_UpdateAllElements")
+end
+
+UF["headerstoload"]["party"] = true
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Groups/Raid.lua b/ElvUI/Modules/UnitFrames/Groups/Raid.lua
new file mode 100644
index 0000000..2eb9a74
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Groups/Raid.lua
@@ -0,0 +1,122 @@
+local E, L, V, P, G = unpack(ElvUI)
+local UF = E:GetModule("UnitFrames")
+
+local tinsert = table.insert
+
+local CreateFrame = CreateFrame
+local InCombatLockdown = InCombatLockdown
+local IsInInstance = IsInInstance
+local GetInstanceInfo = GetInstanceInfo
+local UnregisterStateDriver = UnregisterStateDriver
+local RegisterStateDriver = RegisterStateDriver
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+function UF:Construct_RaidFrames()
+ self:SetScript("OnEnter", UnitFrame_OnEnter)
+ self:SetScript("OnLeave", UnitFrame_OnLeave)
+
+ self.RaisedElementParent = CreateFrame("Frame", nil, self)
+ self.RaisedElementParent:SetFrameLevel(self:GetFrameLevel() + 100)
+ self.RaisedElementParent.TextureParent = CreateFrame("Frame", nil, self.RaisedElementParent)
+ self.RaisedElementParent.TextureParent:SetFrameLevel(self.RaisedElementParent:GetFrameLevel() + 1)
+
+ self.Health = UF:Construct_HealthBar(self, true, true, "RIGHT")
+ self.Power = UF:Construct_PowerBar(self, true, true, "LEFT")
+ self.Power.frequentUpdates = false
+ self.Portrait3D = UF:Construct_Portrait(self, "model")
+ self.Portrait2D = UF:Construct_Portrait(self, "texture")
+ self.Name = UF:Construct_NameText(self)
+ self.RaidRoleFramesAnchor = UF:Construct_RaidRoleFrames(self)
+ self.RaidTargetIndicator = UF:Construct_RaidIcon(self);
+
+ self.InfoPanel = UF:Construct_InfoPanel(self)
+ UF:Update_StatusBars()
+ UF:Update_FontStrings()
+ self.unitframeType = "raid"
+
+ UF:Update_RaidFrames(self, UF.db["units"]["raid"])
+
+ return self
+end
+
+function UF:Update_RaidHeader(header)
+ if not header.positioned then
+ header:ClearAllPoints()
+ header:SetPoint("BOTTOMLEFT", E.UIParent, "BOTTOMLEFT", 4, 195)
+
+ E:CreateMover(header, header:GetName().."Mover", L["Raid Frames"], nil, nil, nil, "ALL,RAID")
+ header.positioned = true
+ end
+end
+
+function UF:Update_RaidFrames(frame, db)
+ frame.db = db
+
+ frame.Portrait = frame.Portrait or (db.portrait.style == "2D" and frame.Portrait2D or frame.Portrait3D)
+ frame.colors = ElvUF.colors
+ frame:RegisterForClicks(self.db.targetOnMouseDown and "LeftButtonDown" or "LeftButtonUp", self.db.targetOnMouseDown and "RightButtonDown" or "RightButtonUp")
+
+ do
+ if self.thinBorders then
+ frame.SPACING = 0
+ frame.BORDER = E.mult
+ else
+ frame.BORDER = E.Border
+ frame.SPACING = E.Spacing
+ end
+
+ frame.SHADOW_SPACING = 3
+ frame.ORIENTATION = db.orientation
+
+ frame.UNIT_WIDTH = db.width
+ frame.UNIT_HEIGHT = db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height
+
+ frame.USE_POWERBAR = db.power.enable
+ frame.POWERBAR_DETACHED = db.power.detachFromFrame
+ frame.USE_INSET_POWERBAR = not frame.POWERBAR_DETACHED and db.power.width == "inset" and frame.USE_POWERBAR
+ frame.USE_MINI_POWERBAR = (not frame.POWERBAR_DETACHED and db.power.width == "spaced" and frame.USE_POWERBAR)
+ frame.USE_POWERBAR_OFFSET = db.power.offset ~= 0 and frame.USE_POWERBAR and not frame.POWERBAR_DETACHED
+ frame.POWERBAR_OFFSET = frame.USE_POWERBAR_OFFSET and db.power.offset or 0
+
+ frame.POWERBAR_HEIGHT = not frame.USE_POWERBAR and 0 or db.power.height
+ frame.POWERBAR_WIDTH = frame.USE_MINI_POWERBAR and (frame.UNIT_WIDTH - (frame.BORDER*2))/2 or (frame.POWERBAR_DETACHED and db.power.detachedWidth or (frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2)))
+
+ frame.USE_PORTRAIT = db.portrait and db.portrait.enable
+ frame.USE_PORTRAIT_OVERLAY = frame.USE_PORTRAIT and (db.portrait.overlay or frame.ORIENTATION == "MIDDLE")
+ frame.PORTRAIT_WIDTH = (frame.USE_PORTRAIT_OVERLAY or not frame.USE_PORTRAIT) and 0 or db.portrait.width
+
+ frame.CLASSBAR_WIDTH = 0
+ frame.CLASSBAR_YOFFSET = 0
+
+ frame.USE_INFO_PANEL = not frame.USE_MINI_POWERBAR and not frame.USE_POWERBAR_OFFSET and db.infoPanel.enable
+ frame.INFO_PANEL_HEIGHT = frame.USE_INFO_PANEL and db.infoPanel.height or 0
+
+ frame.BOTTOM_OFFSET = UF:GetHealthBottomOffset(frame)
+
+ frame.VARIABLES_SET = true
+ end
+
+ frame:SetWidth(frame.UNIT_WIDTH)
+ frame:SetHeight(frame.UNIT_HEIGHT)
+
+ UF:Configure_InfoPanel(frame)
+
+ UF:Configure_HealthBar(frame)
+
+ UF:UpdateNameSettings(frame)
+
+ UF:Configure_Power(frame)
+
+ UF:Configure_Portrait(frame)
+
+ UF:Configure_RaidIcon(frame)
+
+ UF:Configure_RaidRoleIcons(frame)
+
+ frame:UpdateAllElements("ElvUI_UpdateAllElements")
+end
+
+UF["headerstoload"]["raid"] = true
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml b/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml
new file mode 100644
index 0000000..ecbb659
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Tags.lua b/ElvUI/Modules/UnitFrames/Tags.lua
new file mode 100644
index 0000000..aaf4e0d
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Tags.lua
@@ -0,0 +1,552 @@
+local E, L, V, P, G = unpack(ElvUI)
+
+local _G = _G;
+local floor = math.floor;
+local format = string.format;
+
+local GetPVPTimer = GetPVPTimer;
+local GetTime = GetTime;
+local UnitClass = UnitClass;
+local UnitClassification = UnitClassification;
+local UnitGUID = UnitGUID;
+local UnitIsAFK = UnitIsAFK;
+local UnitIsConnected = UnitIsConnected;
+local UnitIsDND = UnitIsDND;
+local UnitIsDead = UnitIsDead;
+local UnitIsDeadOrGhost = UnitIsDeadOrGhost;
+local UnitIsGhost = UnitIsGhost;
+local UnitIsPVP = UnitIsPVP;
+local UnitIsPVPFreeForAll = UnitIsPVPFreeForAll;
+local UnitIsPlayer = UnitIsPlayer;
+local UnitLevel = UnitLevel;
+local UnitMana = UnitMana;
+local UnitManaMax = UnitManaMax;
+local UnitPowerType = UnitPowerType;
+local UnitReaction = UnitReaction;
+local DEFAULT_AFK_MESSAGE = DEFAULT_AFK_MESSAGE;
+local PVP = PVP;
+
+------------------------------------------------------------------------
+-- Tags
+------------------------------------------------------------------------
+
+ElvUF.Tags.Events["afk"] = "PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["afk"] = function(unit)
+ local isAFK = UnitIsAFK(unit)
+ if isAFK then
+ return ("|cffFFFFFF[|r|cffFF0000%s|r|cFFFFFFFF]|r"):format(DEFAULT_AFK_MESSAGE)
+ else
+ return ""
+ end
+end
+
+ElvUF.Tags.Events["healthcolor"] = "UNIT_HEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["healthcolor"] = function(unit)
+ if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
+ return Hex(0.84, 0.75, 0.65)
+ else
+ local r, g, b = ElvUF.ColorGradient(UnitHealth(unit), UnitHealthMax(unit), 0.69, 0.31, 0.31, 0.65, 0.63, 0.35, 0.33, 0.59, 0.33)
+ return Hex(r, g, b)
+ end
+end
+
+ElvUF.Tags.Events["health:current"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["health:current"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+ if (status) then
+ return status
+ else
+ return E:GetFormattedText("CURRENT", UnitHealth(unit), UnitHealthMax(unit))
+ end
+end
+
+ElvUF.Tags.Events["health:deficit"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["health:deficit"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+
+ if (status) then
+ return status
+ else
+ return E:GetFormattedText("DEFICIT", UnitHealth(unit), UnitHealthMax(unit))
+ end
+end
+
+ElvUF.Tags.Events["health:current-percent"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["health:current-percent"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+
+ if (status) then
+ return status
+ else
+ return E:GetFormattedText("CURRENT_PERCENT", UnitHealth(unit), UnitHealthMax(unit))
+ end
+end
+
+ElvUF.Tags.Events["health:current-max"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["health:current-max"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+
+ if (status) then
+ return status
+ else
+ return E:GetFormattedText("CURRENT_MAX", UnitHealth(unit), UnitHealthMax(unit))
+ end
+end
+
+ElvUF.Tags.Events["health:current-max-percent"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["health:current-max-percent"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+
+ if (status) then
+ return status
+ else
+ return E:GetFormattedText("CURRENT_MAX_PERCENT", UnitHealth(unit), UnitHealthMax(unit))
+ end
+end
+
+ElvUF.Tags.Events["health:max"] = "UNIT_MAXHEALTH"
+ElvUF.Tags.Methods["health:max"] = function(unit)
+ local max = UnitHealthMax(unit)
+
+ return E:GetFormattedText("CURRENT", max, max)
+end
+
+ElvUF.Tags.Events["health:percent"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
+ElvUF.Tags.Methods["health:percent"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+
+ if (status) then
+ return status
+ else
+ return E:GetFormattedText("PERCENT", UnitHealth(unit), UnitHealthMax(unit))
+ end
+end
+
+ElvUF.Tags.Events["health:current-nostatus"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:current-nostatus"] = function(unit)
+ return E:GetFormattedText("CURRENT", UnitHealth(unit), UnitHealthMax(unit));
+end
+
+ElvUF.Tags.Events["health:deficit-nostatus"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:deficit-nostatus"] = function(unit)
+ return E:GetFormattedText("DEFICIT", UnitHealth(unit), UnitHealthMax(unit));
+end
+
+ElvUF.Tags.Events["health:current-percent-nostatus"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:current-percent-nostatus"] = function(unit)
+ return E:GetFormattedText("CURRENT_PERCENT", UnitHealth(unit), UnitHealthMax(unit));
+end
+
+ElvUF.Tags.Events["health:current-max-nostatus"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:current-max-nostatus"] = function(unit)
+ return E:GetFormattedText("CURRENT_MAX", UnitHealth(unit), UnitHealthMax(unit));
+end
+
+ElvUF.Tags.Events["health:current-max-percent-nostatus"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:current-max-percent-nostatus"] = function(unit)
+ return E:GetFormattedText("CURRENT_MAX_PERCENT", UnitHealth(unit), UnitHealthMax(unit));
+end
+
+ElvUF.Tags.Events["health:percent-nostatus"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:percent-nostatus"] = function(unit)
+ return E:GetFormattedText("PERCENT", UnitHealth(unit), UnitHealthMax(unit));
+end
+
+ElvUF.Tags.Events["health:deficit-percent:name"] = "UNIT_HEALTH UNIT_MAXHEALTH";
+ElvUF.Tags.Methods["health:deficit-percent:name"] = function(unit)
+ local currentHealth = UnitHealth(unit)
+ local deficit = UnitHealthMax(unit) - currentHealth;
+
+ if (deficit > 0 and currentHealth > 0) then
+ return _TAGS["health:percent-nostatus"](unit);
+ else
+ return _TAGS["name"](unit);
+ end
+end
+
+ElvUF.Tags.Events["health:deficit-percent:name-long"] = "UNIT_HEALTH UNIT_MAXHEALTH"
+ElvUF.Tags.Methods["health:deficit-percent:name-long"] = function(unit)
+ local currentHealth = UnitHealth(unit)
+ local deficit = UnitHealthMax(unit) - currentHealth
+
+ if (deficit > 0 and currentHealth > 0) then
+ return _TAGS["health:percent-nostatus"](unit)
+ else
+ return _TAGS["name:long"](unit)
+ end
+end
+
+ElvUF.Tags.Events["health:deficit-percent:name-medium"] = "UNIT_HEALTH UNIT_MAXHEALTH"
+ElvUF.Tags.Methods["health:deficit-percent:name-medium"] = function(unit)
+ local currentHealth = UnitHealth(unit)
+ local deficit = UnitHealthMax(unit) - currentHealth
+
+ if (deficit > 0 and currentHealth > 0) then
+ return _TAGS["health:percent-nostatus"](unit)
+ else
+ return _TAGS["name:medium"](unit)
+ end
+end
+
+ElvUF.Tags.Events["health:deficit-percent:name-short"] = "UNIT_HEALTH UNIT_MAXHEALTH"
+ElvUF.Tags.Methods["health:deficit-percent:name-short"] = function(unit)
+ local currentHealth = UnitHealth(unit)
+ local deficit = UnitHealthMax(unit) - currentHealth
+
+ if (deficit > 0 and currentHealth > 0) then
+ return _TAGS["health:percent-nostatus"](unit)
+ else
+ return _TAGS["name:short"](unit)
+ end
+end
+
+ElvUF.Tags.Events["health:deficit-percent:name-veryshort"] = "UNIT_HEALTH UNIT_MAXHEALTH"
+ElvUF.Tags.Methods["health:deficit-percent:name-veryshort"] = function(unit)
+ local currentHealth = UnitHealth(unit)
+ local deficit = UnitHealthMax(unit) - currentHealth
+
+ if (deficit > 0 and currentHealth > 0) then
+ return _TAGS["health:percent-nostatus"](unit)
+ else
+ return _TAGS["name:veryshort"](unit)
+ end
+end
+
+ElvUF.Tags.Events["powercolor"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["powercolor"] = function(unit)
+ local color = ElvUF["colors"].power[UnitPowerType(unit)]
+ if color then
+ return Hex(color[1], color[2], color[3])
+ else
+ return Hex(unpack(ElvUF["colors"].power[0]))
+ end
+end
+
+ElvUF.Tags.Events["power:current"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["power:current"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["power:current-max"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["power:current-max"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT_MAX", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["power:current-percent"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["power:current-percent"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT_PERCENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["power:current-max-percent"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["power:current-max-percent"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT_MAX_PERCENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["power:percent"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["power:percent"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("PERCENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["power:deficit"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_MAXPOWER"
+ElvUF.Tags.Methods["power:deficit"] = function(unit)
+ return E:GetFormattedText("DEFICIT", UnitMana(unit), UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["power:max"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER"
+ElvUF.Tags.Methods["power:max"] = function(unit)
+ local max = UnitManaMax(unit)
+
+ return E:GetFormattedText("CURRENT", max, max)
+end
+
+ElvUF.Tags.Methods["manacolor"] = function()
+ local altR, altG, altB = PowerBarColor["MANA"].r, PowerBarColor["MANA"].g, PowerBarColor["MANA"].b
+ local color = ElvUF["colors"].power["MANA"]
+ if color then
+ return Hex(color[1], color[2], color[3])
+ else
+ return Hex(altR, altG, altB)
+ end
+end
+
+ElvUF.Tags.Events["mana:current"] = "UNIT_MANA UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:current"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["mana:current-max"] = "UNIT_MANA UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:current-max"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT_MAX", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["mana:current-percent"] = "UNIT_MANA UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:current-percent"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT_PERCENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["mana:current-max-percent"] = "UNIT_MANA UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:current-max-percent"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("CURRENT_MAX_PERCENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["mana:percent"] = "UNIT_MANA UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:percent"] = function(unit)
+ local min = UnitMana(unit)
+
+ return min == 0 and " " or E:GetFormattedText("PERCENT", min, UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["mana:deficit"] = "UNIT_MANA UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:deficit"] = function(unit)
+ return E:GetFormattedText("DEFICIT", UnitMana(unit), UnitManaMax(unit))
+end
+
+ElvUF.Tags.Events["mana:max"] = "UNIT_MAXMANA"
+ElvUF.Tags.Methods["mana:max"] = function(unit)
+ local max = UnitManaMax(unit)
+
+ return E:GetFormattedText("CURRENT", max, max)
+end
+
+ElvUF.Tags.Events["difficultycolor"] = "UNIT_LEVEL PLAYER_LEVEL_UP"
+ElvUF.Tags.Methods["difficultycolor"] = function(unit)
+ local r, g, b = 0.69, 0.31, 0.31
+ local level = UnitLevel(unit)
+ if (level > 1) then
+ local DiffColor = UnitLevel(unit) - UnitLevel("player")
+ if (DiffColor >= 5) then
+ r, g, b = 0.69, 0.31, 0.31
+ elseif (DiffColor >= 3) then
+ r, g, b = 0.71, 0.43, 0.27
+ elseif (DiffColor >= -2) then
+ r, g, b = 0.84, 0.75, 0.65
+ elseif (-DiffColor <= GetQuestGreenRange()) then
+ r, g, b = 0.33, 0.59, 0.33
+ else
+ r, g, b = 0.55, 0.57, 0.61
+ end
+ end
+
+ return Hex(r, g, b)
+end
+
+ElvUF.Tags.Events["namecolor"] = "UNIT_NAME_UPDATE"
+ElvUF.Tags.Methods["namecolor"] = function(unit)
+ local unitReaction = UnitReaction(unit, "player")
+ local _, unitClass = UnitClass(unit)
+ if (UnitIsPlayer(unit)) then
+ local class = ElvUF.colors.class[unitClass]
+ if not class then return "" end
+ return Hex(class[1], class[2], class[3])
+ elseif (unitReaction) then
+ local reaction = ElvUF["colors"].reaction[unitReaction]
+ return Hex(reaction[1], reaction[2], reaction[3])
+ else
+ return "|cFFC2C2C2"
+ end
+end
+
+ElvUF.Tags.Events["smartlevel"] = "UNIT_LEVEL PLAYER_LEVEL_UP"
+ElvUF.Tags.Methods["smartlevel"] = function(unit)
+ local level = UnitLevel(unit)
+ if level == UnitLevel("player") then
+ return ""
+ elseif(level > 0) then
+ return level
+ else
+ return "??"
+ end
+end
+
+ElvUF.Tags.Events["name:veryshort"] = "UNIT_NAME_UPDATE"
+ElvUF.Tags.Methods["name:veryshort"] = function(unit)
+ local name = UnitName(unit)
+ return name ~= nil and E:ShortenString(name, 5) or ""
+end
+
+ElvUF.Tags.Events["name:short"] = "UNIT_NAME_UPDATE"
+ElvUF.Tags.Methods["name:short"] = function(unit)
+ local name = UnitName(unit)
+ return name ~= nil and E:ShortenString(name, 10) or ""
+end
+
+ElvUF.Tags.Events["name:medium"] = "UNIT_NAME_UPDATE"
+ElvUF.Tags.Methods["name:medium"] = function(unit)
+ local name = UnitName(unit)
+ return name ~= nil and E:ShortenString(name, 15) or ""
+end
+
+ElvUF.Tags.Events["name:long"] = "UNIT_NAME_UPDATE"
+ElvUF.Tags.Methods["name:long"] = function(unit)
+ local name = UnitName(unit)
+ return name ~= nil and E:ShortenString(name, 20) or ""
+end
+
+ElvUF.Tags.Events["name:veryshort:status"] = "UNIT_NAME_UPDATE UNIT_CONNECTION PLAYER_FLAGS_CHANGED UNIT_HEALTH"
+ElvUF.Tags.Methods["name:veryshort:status"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+ local name = UnitName(unit)
+ if (status) then
+ return status
+ else
+ return name ~= nil and E:ShortenString(name, 5) or ""
+ end
+end
+
+ElvUF.Tags.Events["name:short:status"] = "UNIT_NAME_UPDATE UNIT_CONNECTION PLAYER_FLAGS_CHANGED UNIT_HEALTH"
+ElvUF.Tags.Methods["name:short:status"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+ local name = UnitName(unit)
+ if (status) then
+ return status
+ else
+ return name ~= nil and E:ShortenString(name, 10) or ""
+ end
+end
+
+ElvUF.Tags.Events["name:medium:status"] = "UNIT_NAME_UPDATE UNIT_CONNECTION PLAYER_FLAGS_CHANGED UNIT_HEALTH"
+ElvUF.Tags.Methods["name:medium:status"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+ local name = UnitName(unit)
+ if (status) then
+ return status
+ else
+ return name ~= nil and E:ShortenString(name, 15) or ""
+ end
+end
+
+ElvUF.Tags.Events["name:long:status"] = "UNIT_NAME_UPDATE UNIT_CONNECTION PLAYER_FLAGS_CHANGED UNIT_HEALTH"
+ElvUF.Tags.Methods["name:long:status"] = function(unit)
+ local status = UnitIsDead(unit) and L["Dead"] or UnitIsGhost(unit) and L["Ghost"] or not UnitIsConnected(unit) and L["Offline"]
+ local name = UnitName(unit)
+ if (status) then
+ return status
+ else
+ return name ~= nil and E:ShortenString(name, 20) or ""
+ end
+end
+
+local unitStatus = {}
+ElvUF.Tags.OnUpdateThrottle["statustimer"] = 1
+ElvUF.Tags.Methods["statustimer"] = function(unit)
+ if not UnitIsPlayer(unit) then return; end
+ local guid = UnitGUID(unit)
+ if (UnitIsAFK(unit)) then
+ if not unitStatus[guid] or unitStatus[guid] and unitStatus[guid][1] ~= "AFK" then
+ unitStatus[guid] = {"AFK", GetTime()}
+ end
+ elseif(UnitIsDND(unit)) then
+ if not unitStatus[guid] or unitStatus[guid] and unitStatus[guid][1] ~= "DND" then
+ unitStatus[guid] = {"DND", GetTime()}
+ end
+ elseif(UnitIsDead(unit)) or (UnitIsGhost(unit))then
+ if not unitStatus[guid] or unitStatus[guid] and unitStatus[guid][1] ~= "Dead" then
+ unitStatus[guid] = {"Dead", GetTime()}
+ end
+ elseif(not UnitIsConnected(unit)) then
+ if not unitStatus[guid] or unitStatus[guid] and unitStatus[guid][1] ~= "Offline" then
+ unitStatus[guid] = {"Offline", GetTime()}
+ end
+ else
+ unitStatus[guid] = nil
+ end
+
+ if unitStatus[guid] ~= nil then
+ local status = unitStatus[guid][1]
+ local timer = GetTime() - unitStatus[guid][2]
+ local mins = floor(timer / 60)
+ local secs = floor(timer - (mins * 60))
+ return ("%s (%01.f:%02.f)"):format(status, mins, secs)
+ else
+ return ""
+ end
+end
+
+ElvUF.Tags.OnUpdateThrottle["pvptimer"] = 1
+ElvUF.Tags.Methods["pvptimer"] = function(unit)
+ if (UnitIsPVPFreeForAll(unit) or UnitIsPVP(unit)) then
+ local timer = GetPVPTimer()
+
+ if timer ~= 301000 and timer ~= -1 then
+ local mins = floor((timer / 1000) / 60)
+ local secs = floor((timer / 1000) - (mins * 60))
+ return ("%s (%01.f:%02.f)"):format(PVP, mins, secs)
+ else
+ return PVP
+ end
+ else
+ return ""
+ end
+end
+
+ElvUF.Tags.Events["classificationcolor"] = "UNIT_CLASSIFICATION_CHANGED";
+ElvUF.Tags.Methods["classificationcolor"] = function(unit)
+ local c = UnitClassification(unit);
+ if(c == "rare" or c == "elite") then
+ return Hex(1, 0.5, 0.25); -- Orange
+ elseif(c == "rareelite" or c == "worldboss") then
+ return Hex(1, 0, 0); -- Red
+ end
+end
+
+ElvUF.Tags.Events["guild"] = "PLAYER_GUILD_UPDATE"
+ElvUF.Tags.Methods["guild"] = function(unit)
+ local guildName = GetGuildInfo(unit)
+
+ return guildName or ""
+end
+
+ElvUF.Tags.Events["guild:brackets"] = "PLAYER_GUILD_UPDATE"
+ElvUF.Tags.Methods["guild:brackets"] = function(unit)
+ local guildName = GetGuildInfo(unit)
+
+ return guildName and format("<%s>", guildName) or ""
+end
+
+ElvUF.Tags.Events["target:veryshort"] = "UNIT_TARGET"
+ElvUF.Tags.Methods["target:veryshort"] = function(unit)
+ local targetName = UnitName(unit.."target")
+ return targetName ~= nil and E:ShortenString(targetName, 5) or ""
+end
+
+ElvUF.Tags.Events["target:short"] = "UNIT_TARGET"
+ElvUF.Tags.Methods["target:short"] = function(unit)
+ local targetName = UnitName(unit.."target")
+ return targetName ~= nil and E:ShortenString(targetName, 10) or ""
+end
+
+ElvUF.Tags.Events["target:medium"] = "UNIT_TARGET"
+ElvUF.Tags.Methods["target:medium"] = function(unit)
+ local targetName = UnitName(unit.."target")
+ return targetName ~= nil and E:ShortenString(targetName, 15) or ""
+end
+
+ElvUF.Tags.Events["target:long"] = "UNIT_TARGET"
+ElvUF.Tags.Methods["target:long"] = function(unit)
+ local targetName = UnitName(unit.."target")
+ return targetName ~= nil and E:ShortenString(targetName, 20) or ""
+end
+
+ElvUF.Tags.Events["target"] = "UNIT_TARGET"
+ElvUF.Tags.Methods["target"] = function(unit)
+ local targetName = UnitName(unit.."target")
+ return targetName or ""
+end
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/UnitFrames.lua b/ElvUI/Modules/UnitFrames/UnitFrames.lua
new file mode 100644
index 0000000..c63457f
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/UnitFrames.lua
@@ -0,0 +1,1099 @@
+local E, L, V, P, G = unpack(ElvUI)
+local UF = E:NewModule("UnitFrames", "AceTimer-3.0", "AceEvent-3.0", "AceHook-3.0")
+local LSM = LibStub("LibSharedMedia-3.0")
+UF.LSM = LSM
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local select, pairs, type, unpack, assert, tostring = select, pairs, type, unpack, assert, tostring
+local min = math.min
+local tinsert = table.insert
+local find, gsub, format = string.find, string.gsub, string.format
+--WoW API / Variables
+local hooksecurefunc = hooksecurefunc
+local CreateFrame = CreateFrame
+local UnitFrame_OnEnter = UnitFrame_OnEnter
+local UnitFrame_OnLeave = UnitFrame_OnLeave
+local IsInInstance = IsInInstance
+local InCombatLockdown = InCombatLockdown
+local GetInstanceInfo = GetInstanceInfo
+local UnregisterStateDriver = UnregisterStateDriver
+local RegisterStateDriver = RegisterStateDriver
+local MAX_RAID_MEMBERS = MAX_RAID_MEMBERS
+local MAX_BOSS_FRAMES = MAX_BOSS_FRAMES
+
+local ns = oUF
+ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+UF["headerstoload"] = {}
+UF["unitstoload"] = {}
+
+UF["groupPrototype"] = {}
+UF["headerPrototype"] = {}
+UF["headers"] = {}
+UF["units"] = {}
+
+UF["statusbars"] = {}
+UF["fontstrings"] = {}
+UF["badHeaderPoints"] = {
+ ["TOP"] = "BOTTOM",
+ ["LEFT"] = "RIGHT",
+ ["BOTTOM"] = "TOP",
+ ["RIGHT"] = "LEFT"
+}
+
+UF["headerFunctions"] = {}
+
+UF["classMaxResourceBar"] = {
+ ["DRUID"] = 1
+}
+
+UF["mapIDs"] = {
+ [443] = 10, -- Warsong Gulch
+ [461] = 15, -- Arathi Basin
+ [401] = 40, -- Alterac Valley
+ [566] = 15, -- Eye of the Storm
+}
+
+UF["headerGroupBy"] = {
+ ["CLASS"] = function(header)
+ header:SetAttribute("groupingOrder", "DRUID,HUNTER,MAGE,PALADIN,PRIEST,SHAMAN,WARLOCK,WARRIOR")
+ header:SetAttribute("sortMethod", "NAME")
+ header:SetAttribute("groupBy", "CLASS")
+ end,
+ ["NAME"] = function(header)
+ header:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8")
+ header:SetAttribute("sortMethod", "NAME")
+ header:SetAttribute("groupBy", nil)
+ end,
+ ["GROUP"] = function(header)
+ header:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8")
+ header:SetAttribute("sortMethod", "INDEX")
+ header:SetAttribute("groupBy", "GROUP")
+ end,
+ ["PETNAME"] = function(header)
+ header:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8")
+ header:SetAttribute("sortMethod", "NAME")
+ header:SetAttribute("groupBy", nil)
+ header:SetAttribute("filterOnPet", true) --This is the line that matters. Without this, it sorts based on the owners name
+ end,
+}
+
+local POINT_COLUMN_ANCHOR_TO_DIRECTION = {
+ ["TOPTOP"] = "UP_RIGHT",
+ ["BOTTOMBOTTOM"] = "TOP_RIGHT",
+ ["LEFTLEFT"] = "RIGHT_UP",
+ ["RIGHTRIGHT"] = "LEFT_UP",
+ ["RIGHTTOP"] = "LEFT_DOWN",
+ ["LEFTTOP"] = "RIGHT_DOWN",
+ ["LEFTBOTTOM"] = "RIGHT_UP",
+ ["RIGHTBOTTOM"] = "LEFT_UP",
+ ["BOTTOMRIGHT"] = "UP_LEFT",
+ ["BOTTOMLEFT"] = "UP_RIGHT",
+ ["TOPRIGHT"] = "DOWN_LEFT",
+ ["TOPLEFT"] = "DOWN_RIGHT"
+}
+
+local DIRECTION_TO_POINT = {
+ DOWN_RIGHT = "TOP",
+ DOWN_LEFT = "TOP",
+ UP_RIGHT = "BOTTOM",
+ UP_LEFT = "BOTTOM",
+ RIGHT_DOWN = "LEFT",
+ RIGHT_UP = "LEFT",
+ LEFT_DOWN = "RIGHT",
+ LEFT_UP = "RIGHT",
+ UP = "BOTTOM",
+ DOWN = "TOP"
+}
+
+local DIRECTION_TO_GROUP_ANCHOR_POINT = {
+ DOWN_RIGHT = "TOPLEFT",
+ DOWN_LEFT = "TOPRIGHT",
+ UP_RIGHT = "BOTTOMLEFT",
+ UP_LEFT = "BOTTOMRIGHT",
+ RIGHT_DOWN = "TOPLEFT",
+ RIGHT_UP = "BOTTOMLEFT",
+ LEFT_DOWN = "TOPRIGHT",
+ LEFT_UP = "BOTTOMRIGHT",
+ OUT_RIGHT_UP = "BOTTOM",
+ OUT_LEFT_UP = "BOTTOM",
+ OUT_RIGHT_DOWN = "TOP",
+ OUT_LEFT_DOWN = "TOP",
+ OUT_UP_RIGHT = "LEFT",
+ OUT_UP_LEFT = "RIGHT",
+ OUT_DOWN_RIGHT = "LEFT",
+ OUT_DOWN_LEFT = "RIGHT"
+}
+
+local INVERTED_DIRECTION_TO_COLUMN_ANCHOR_POINT = {
+ DOWN_RIGHT = "RIGHT",
+ DOWN_LEFT = "LEFT",
+ UP_RIGHT = "RIGHT",
+ UP_LEFT = "LEFT",
+ RIGHT_DOWN = "BOTTOM",
+ RIGHT_UP = "TOP",
+ LEFT_DOWN = "BOTTOM",
+ LEFT_UP = "TOP",
+ UP = "TOP",
+ DOWN = "BOTTOM"
+}
+
+local DIRECTION_TO_COLUMN_ANCHOR_POINT = {
+ DOWN_RIGHT = "LEFT",
+ DOWN_LEFT = "RIGHT",
+ UP_RIGHT = "LEFT",
+ UP_LEFT = "RIGHT",
+ RIGHT_DOWN = "TOP",
+ RIGHT_UP = "BOTTOM",
+ LEFT_DOWN = "TOP",
+ LEFT_UP = "BOTTOM"
+}
+
+local DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER = {
+ DOWN_RIGHT = 1,
+ DOWN_LEFT = -1,
+ UP_RIGHT = 1,
+ UP_LEFT = -1,
+ RIGHT_DOWN = 1,
+ RIGHT_UP = 1,
+ LEFT_DOWN = -1,
+ LEFT_UP = -1
+}
+
+local DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER = {
+ DOWN_RIGHT = -1,
+ DOWN_LEFT = -1,
+ UP_RIGHT = 1,
+ UP_LEFT = 1,
+ RIGHT_DOWN = -1,
+ RIGHT_UP = 1,
+ LEFT_DOWN = -1,
+ LEFT_UP = 1
+}
+
+function UF:ConvertGroupDB(group)
+ local db = self.db.units[group.groupName]
+ if db.point and db.columnAnchorPoint then
+ db.growthDirection = POINT_COLUMN_ANCHOR_TO_DIRECTION[db.point..db.columnAnchorPoint];
+ db.point = nil;
+ db.columnAnchorPoint = nil;
+ end
+
+ if db.growthDirection == "UP" then
+ db.growthDirection = "UP_RIGHT"
+ end
+
+ if db.growthDirection == "DOWN" then
+ db.growthDirection = "DOWN_RIGHT"
+ end
+end
+
+function UF:Construct_UF(frame, unit)
+ frame:SetFrameStrata("LOW")
+ frame:SetScript("OnEnter", UnitFrame_OnEnter)
+ frame:SetScript("OnLeave", UnitFrame_OnLeave)
+
+ if(self.thinBorders) then
+ frame.SPACING = 0
+ frame.BORDER = E.mult
+ else
+ frame.BORDER = E.Border
+ frame.SPACING = E.Spacing
+ end
+
+ frame.SHADOW_SPACING = 3
+ frame.CLASSBAR_YOFFSET = 0 --placeholder
+ frame.BOTTOM_OFFSET = 0 --placeholder
+
+ frame.RaisedElementParent = CreateFrame("Frame", nil, frame)
+ frame.RaisedElementParent:SetFrameLevel(frame:GetFrameLevel() + 100)
+ frame.RaisedElementParent.TextureParent = CreateFrame("Frame", nil, frame.RaisedElementParent)
+ frame.RaisedElementParent.TextureParent:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 1)
+
+ local stringTitle = E:StringTitle(unit)
+ if string.find(stringTitle, "target") then
+ stringTitle = gsub(stringTitle, "target", "Target")
+ end
+ self["Construct_"..stringTitle.."Frame"](self, frame, unit)
+
+ self:Update_StatusBars()
+ self:Update_FontStrings()
+ return frame
+end
+
+function UF:GetObjectAnchorPoint(frame, point)
+ if not frame[point] or point == "Frame" then
+ return frame
+ elseif frame[point] and not frame[point]:IsShown() then
+ return frame.Health
+ else
+ return frame[point]
+ end
+end
+
+function UF:GetPositionOffset(position, offset)
+ if not offset then offset = 2; end
+ local x, y = 0, 0
+ if find(position, "LEFT") then
+ x = offset
+ elseif find(position, "RIGHT") then
+ x = -offset
+ end
+
+ if find(position, "TOP") then
+ y = -offset
+ elseif find(position, "BOTTOM") then
+ y = offset
+ end
+
+ return x, y
+end
+
+function UF:GetAuraOffset(p1, p2)
+ local x, y = 0, 0
+ if p1 == "RIGHT" and p2 == "LEFT" then
+ x = -3
+ elseif p1 == "LEFT" and p2 == "RIGHT" then
+ x = 3
+ end
+
+ if find(p1, "TOP") and find(p2, "BOTTOM") then
+ y = -1
+ elseif find(p1, "BOTTOM") and find(p2, "TOP") then
+ y = 1
+ end
+
+ return E:Scale(x), E:Scale(y)
+end
+
+function UF:GetAuraAnchorFrame(frame, attachTo, isConflict)
+ if isConflict then
+ E:Print(format(L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."], E:StringTitle(frame:GetName())))
+ end
+
+ if isConflict or attachTo == "FRAME" then
+ return frame
+ elseif attachTo == "BUFFS" then
+ return frame.Buffs
+ elseif attachTo == "DEBUFFS" then
+ return frame.Debuffs
+ elseif attachTo == "HEALTH" then
+ return frame.Health
+ elseif attachTo == "POWER" and frame.Power then
+ return frame.Power
+ else
+ return frame
+ end
+end
+
+function UF:UpdateColors()
+ local db = self.db.colors
+
+ local good = E:GetColorTable(db.reaction.GOOD)
+ local bad = E:GetColorTable(db.reaction.BAD)
+ local neutral = E:GetColorTable(db.reaction.NEUTRAL)
+
+ ElvUF.colors.tapped = E:GetColorTable(db.tapped);
+ ElvUF.colors.disconnected = E:GetColorTable(db.disconnected);
+ ElvUF.colors.health = E:GetColorTable(db.health);
+ ElvUF.colors.power[0] = E:GetColorTable(db.power.MANA);
+ ElvUF.colors.power[1] = E:GetColorTable(db.power.RAGE);
+ ElvUF.colors.power[2] = E:GetColorTable(db.power.FOCUS);
+ ElvUF.colors.power[3] = E:GetColorTable(db.power.ENERGY);
+
+ --[[ElvUF.colors.ComboPoints = {}
+ ElvUF.colors.ComboPoints[1] = E:GetColorTable(db.classResources.comboPoints[1])
+ ElvUF.colors.ComboPoints[2] = E:GetColorTable(db.classResources.comboPoints[2])
+ ElvUF.colors.ComboPoints[3] = E:GetColorTable(db.classResources.comboPoints[3])
+ ElvUF.colors.ComboPoints[4] = E:GetColorTable(db.classResources.comboPoints[4])
+ ElvUF.colors.ComboPoints[5] = E:GetColorTable(db.classResources.comboPoints[5])]]
+
+ ElvUF.colors.reaction[1] = bad
+ ElvUF.colors.reaction[2] = bad
+ ElvUF.colors.reaction[3] = bad
+ ElvUF.colors.reaction[4] = neutral
+ ElvUF.colors.reaction[5] = good
+ ElvUF.colors.reaction[6] = good
+ ElvUF.colors.reaction[7] = good
+ ElvUF.colors.reaction[8] = good
+ ElvUF.colors.smooth = {1, 0, 0,
+ 1, 1, 0,
+ unpack(E:GetColorTable(db.health))}
+
+ ElvUF.colors.castColor = E:GetColorTable(db.castColor);
+end
+
+function UF:Update_StatusBars()
+ local statusBarTexture = LSM:Fetch("statusbar", self.db.statusbar)
+ for statusbar in pairs(UF["statusbars"]) do
+ if statusbar and statusbar:GetObjectType() == "StatusBar" and not statusbar.isTransparent then
+ statusbar:SetStatusBarTexture(statusBarTexture)
+ elseif statusbar and statusbar:GetObjectType() == "Texture" then
+ statusbar:SetTexture(statusBarTexture)
+ end
+ end
+end
+
+function UF:Update_StatusBar(bar)
+ bar:SetStatusBarTexture(LSM:Fetch("statusbar", self.db.statusbar))
+end
+
+function UF:Update_FontString(object)
+ E:FontTemplate(object, LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
+end
+
+function UF:Update_FontStrings()
+ local stringFont = LSM:Fetch("font", self.db.font)
+ for font in pairs(UF["fontstrings"]) do
+ E:FontTemplate(font, stringFont, self.db.fontSize, self.db.fontOutline)
+ end
+end
+
+function UF:Configure_FontString(obj)
+ UF["fontstrings"][obj] = true
+ E:FontTemplate(obj) --This is temporary.
+end
+
+function UF:Update_AllFrames()
+ if E.private["unitframe"].enable ~= true then return; end
+ self:UpdateColors()
+ self:Update_FontStrings()
+ self:Update_StatusBars()
+
+ for unit in pairs(self["units"]) do
+ if self.db["units"][unit].enable then
+ self[unit]:Enable()
+ self[unit]:Update()
+ E:EnableMover(self[unit].mover:GetName())
+ else
+ self[unit]:Disable()
+ E:DisableMover(self[unit].mover:GetName())
+ end
+ end
+
+ self:UpdateAllHeaders()
+end
+
+function UF:HeaderUpdateSpecificElement(group, elementName)
+ assert(self[group], "Invalid group specified.")
+ for i = 1, self[group]:GetNumChildren() do
+ local frame = select(i, self[group]:GetChildren())
+ if frame and frame.Health then
+ frame:UpdateElement(elementName)
+ end
+ end
+end
+
+--Keep an eye on this one, it may need to be changed too
+--Reference: http://www.tukui.org/forums/topic.php?id=35332
+function UF.groupPrototype:GetAttribute(name)
+ return self.groups[1]:GetAttribute(name)
+end
+
+function UF.groupPrototype:Configure_Groups(self)
+ local db = UF.db.units[self.groupName]
+
+ local point
+ local width, height, newCols, newRows = 0, 0, 0, 0
+ local direction = db.growthDirection
+ local xMult, yMult = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[direction], DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[direction]
+ local UNIT_HEIGHT = db.infoPanel and db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height
+
+ local numGroups = self.numGroups
+ for i = 1, numGroups do
+ local group = self.groups[i]
+
+ point = DIRECTION_TO_POINT[direction]
+
+ if group then
+ UF:ConvertGroupDB(group)
+ if point == "LEFT" or point == "RIGHT" then
+ group:SetAttribute("xOffset", db.horizontalSpacing * DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[direction])
+ group:SetAttribute("yOffset", 0)
+ group:SetAttribute("columnSpacing", db.verticalSpacing)
+ else
+ group:SetAttribute("xOffset", 0)
+ group:SetAttribute("yOffset", db.verticalSpacing * DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[direction])
+ group:SetAttribute("columnSpacing", db.horizontalSpacing)
+ end
+
+ --[[if not group.isForced then
+ if not group.initialized then
+ group:SetAttribute("startingIndex", db.raidWideSorting and (-min(numGroups * (db.groupsPerRowCol * 5), MAX_RAID_MEMBERS) + 1) or -4)
+ group:Show()
+ group.initialized = true
+ end
+ group:SetAttribute("startingIndex", 1)
+ end]]
+
+ group:ClearAllPoints()
+ if db.raidWideSorting and db.invertGroupingOrder then
+ group:SetAttribute("columnAnchorPoint", INVERTED_DIRECTION_TO_COLUMN_ANCHOR_POINT[direction])
+ else
+ group:SetAttribute("columnAnchorPoint", DIRECTION_TO_COLUMN_ANCHOR_POINT[direction])
+ end
+
+ group:ClearChildPoints()
+ group:SetAttribute("point", point)
+
+ if not group.isForced then
+ group:SetAttribute("maxColumns", db.raidWideSorting and numGroups or 1)
+ group:SetAttribute("unitsPerColumn", db.raidWideSorting and (db.groupsPerRowCol * 5) or 5)
+ UF.headerGroupBy[db.groupBy](group)
+ group:SetAttribute("sortDir", db.sortDir)
+ group:SetAttribute("showPlayer", db.showPlayer)
+ end
+
+ if i == 1 and db.raidWideSorting then
+ group:SetAttribute("groupFilter", "1,2,3,4,5,6,7,8")
+ else
+ group:SetAttribute("groupFilter", tostring(i))
+ end
+ end
+
+ --MATH!! WOOT
+ point = DIRECTION_TO_GROUP_ANCHOR_POINT[direction]
+ if db.raidWideSorting and db.startFromCenter then
+ point = DIRECTION_TO_GROUP_ANCHOR_POINT["OUT_"..direction]
+ end
+ if math.mod(i - 1, db.groupsPerRowCol) == 0 then
+ if DIRECTION_TO_POINT[direction] == "LEFT" or DIRECTION_TO_POINT[direction] == "RIGHT" then
+ if group then
+ group:SetPoint(point, self, point, 0, height * yMult)
+ end
+ height = height + UNIT_HEIGHT + db.verticalSpacing
+ newRows = newRows + 1
+ else
+ if group then
+ group:SetPoint(point, self, point, width * xMult, 0)
+ end
+ width = width + db.width + db.horizontalSpacing
+
+ newCols = newCols + 1
+ end
+ else
+ if DIRECTION_TO_POINT[direction] == "LEFT" or DIRECTION_TO_POINT[direction] == "RIGHT" then
+ if newRows == 1 then
+ if group then
+ group:SetPoint(point, self, point, width * xMult, 0)
+ end
+ width = width + ((db.width + db.horizontalSpacing) * 5)
+ newCols = newCols + 1
+ elseif group then
+ group:SetPoint(point, self, point, (((db.width + db.horizontalSpacing) * 5) * (math.mod(i-1, db.groupsPerRowCol))) * xMult, ((UNIT_HEIGHT + db.verticalSpacing) * (newRows - 1)) * yMult)
+ end
+ else
+ if newCols == 1 then
+ if group then
+ group:SetPoint(point, self, point, 0, height * yMult)
+ end
+ height = height + ((UNIT_HEIGHT + db.verticalSpacing) * 5)
+ newRows = newRows + 1
+ elseif group then
+ group:SetPoint(point, self, point, ((db.width + db.horizontalSpacing) * (newCols - 1)) * xMult, (((UNIT_HEIGHT + db.verticalSpacing) * 5) * (math.mod(i-1, db.groupsPerRowCol))) * yMult)
+ end
+ end
+ end
+
+ if height == 0 then
+ height = height + ((UNIT_HEIGHT + db.verticalSpacing) * 5)
+ elseif width == 0 then
+ width = width + ((db.width + db.horizontalSpacing) * 5)
+ end
+ end
+
+ if not self.isInstanceForced then
+ self.dirtyWidth = width - db.horizontalSpacing
+ self.dirtyHeight = height - db.verticalSpacing
+ end
+
+ if self.mover then
+ self.mover.positionOverride = DIRECTION_TO_GROUP_ANCHOR_POINT[direction]
+ E:UpdatePositionOverride(self.mover:GetName())
+ self:GetScript("OnSizeChanged")(self) --Mover size is not updated if frame is hidden, so call an update manually
+ end
+
+ self:SetWidth(width - db.horizontalSpacing)
+ self:SetHeight(height - db.verticalSpacing)
+end
+
+function UF.groupPrototype:Update(self)
+ local group = self.groupName
+
+ UF[group].db = UF.db["units"][group]
+ for i = 1, getn(self.groups) do
+ self.groups[i].db = UF.db["units"][group]
+ self.groups[i]:Update()
+ end
+end
+
+function UF.groupPrototype:AdjustVisibility(self)
+ if not self.isForced then
+ local numGroups = self.numGroups
+ for i = 1, getn(self.groups) do
+ local group = self.groups[i]
+ if (i <= numGroups) and ((self.db.raidWideSorting and i <= 1) or not self.db.raidWideSorting) then
+ group:Show()
+ else
+ if group.forceShow then
+ group:Hide()
+ UF:UnshowChildUnits(group, group:GetChildren())
+ group:SetAttribute("startingIndex", 1)
+ else
+ group:Reset()
+ end
+ end
+ end
+ end
+end
+
+function UF.groupPrototype:UpdateHeader(self)
+ local group = self.groupName;
+ UF["Update_"..E:StringTitle(group).."Header"](UF, self, UF.db["units"][group]);
+end
+
+function UF.headerPrototype:ClearChildPoints()
+ for i = 1, self:GetNumChildren() do
+ local child = select(i, self:GetChildren())
+ child:ClearAllPoints()
+ end
+end
+
+function UF.headerPrototype:Update(isForced)
+ local group = self.groupName
+ local db = UF.db["units"][group]
+
+ local i = 1
+ local child = self:GetAttribute("child" .. i)
+
+ while child do
+ UF["Update_"..E:StringTitle(group).."Frames"](UF, child, db)
+
+ if _G[child:GetName().."Pet"] then
+ UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Pet"], db)
+ end
+
+ if _G[child:GetName().."Target"] then
+ UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Target"], db)
+ end
+
+ i = i + 1
+ child = self:GetAttribute("child" .. i)
+ end
+end
+
+function UF.headerPrototype:Reset()
+ self:Hide()
+
+ self:SetAttribute("showPlayer", true)
+
+ self:SetAttribute("showSolo", true)
+ self:SetAttribute("showParty", true)
+ self:SetAttribute("showRaid", true)
+
+ self:SetAttribute("columnSpacing", nil)
+ self:SetAttribute("columnAnchorPoint", nil)
+ self:SetAttribute("groupBy", nil)
+ self:SetAttribute("groupFilter", nil)
+ self:SetAttribute("groupingOrder", nil)
+ self:SetAttribute("maxColumns", nil)
+ self:SetAttribute("nameList", nil)
+ self:SetAttribute("point", nil)
+ self:SetAttribute("sortDir", nil)
+ self:SetAttribute("sortMethod", "NAME")
+ self:SetAttribute("startingIndex", nil)
+ self:SetAttribute("strictFiltering", nil)
+ self:SetAttribute("unitsPerColumn", nil)
+ self:SetAttribute("xOffset", nil)
+ self:SetAttribute("yOffset", nil)
+end
+
+function UF:CreateHeader(parent, groupFilter, overrideName, template, groupName, headerTemplate)
+ local group = parent.groupName or groupName
+ local db = UF.db["units"][group]
+ ElvUF:SetActiveStyle("ElvUF_"..E:StringTitle(group))
+ local header = ElvUF:SpawnHeader(overrideName, headerTemplate, nil,
+ "groupFilter", groupFilter,
+ "showParty", true,
+ "showRaid", true,
+ "showSolo", false,
+ template and "template", template)
+
+ header.groupName = group
+ header:SetParent(parent)
+ header:Show()
+
+ for k, v in pairs(self.headerPrototype) do
+ header[k] = v
+ end
+
+ return header
+end
+
+function UF:CreateAndUpdateHeaderGroup(group, groupFilter, template, headerUpdate, headerTemplate)
+ local db = self.db["units"][group]
+ local numGroups = db.numGroups
+
+ if not self[group] then
+ local stringTitle = E:StringTitle(group)
+ ElvUF:RegisterStyle("ElvUF_"..stringTitle, UF["Construct_"..stringTitle.."Frames"])
+ ElvUF:SetActiveStyle("ElvUF_"..stringTitle)
+
+ if db.numGroups then
+ self[group] = CreateFrame("Frame", "ElvUF_"..stringTitle, E.UIParent)
+ self[group]:SetFrameStrata("LOW")
+ self[group].groups = {}
+ self[group].groupName = group
+ self[group].template = self[group].template or template
+ self[group].headerTemplate = self[group].headerTemplate or headerTemplate
+ if not UF["headerFunctions"][group] then UF["headerFunctions"][group] = {} end
+ for k, v in pairs(self.groupPrototype) do
+ UF["headerFunctions"][group][k] = v
+ end
+ else
+ self[group] = self:CreateHeader(E.UIParent, groupFilter, "ElvUF_"..E:StringTitle(group), template, group, headerTemplate)
+ end
+
+ self[group].db = db
+ self["headers"][group] = self[group]
+ self[group]:Show()
+ end
+
+ self[group].numGroups = numGroups
+ if numGroups then
+ if db.raidWideSorting then
+ if not self[group].groups[1] then
+ self[group].groups[1] = self:CreateHeader(self[group], nil, "ElvUF_"..E:StringTitle(self[group].groupName).."Group1", template or self[group].template, nil, headerTemplate or self[group].headerTemplate)
+ end
+ else
+ while numGroups > getn(self[group].groups) do
+ local index = tostring(getn(self[group].groups) + 1)
+ tinsert(self[group].groups, self:CreateHeader(self[group], index, "ElvUF_"..E:StringTitle(self[group].groupName).."Group"..index, template or self[group].template, nil, headerTemplate or self[group].headerTemplate))
+ end
+ end
+
+ UF["headerFunctions"][group]:AdjustVisibility(self[group])
+
+ if headerUpdate or not self[group].mover then
+ UF["headerFunctions"][group]:Configure_Groups(self[group])
+ if not self[group].isForced and not self[group].blockVisibilityChanges then
+ -- RegisterStateDriver(self[group], "visibility", db.visibility)
+ end
+ else
+ UF["headerFunctions"][group]:Configure_Groups(self[group])
+ UF["headerFunctions"][group]:UpdateHeader(self[group])
+ UF["headerFunctions"][group]:Update(self[group])
+ end
+
+ if db.enable then
+ self[group]:Show()
+ if self[group].mover then
+ E:EnableMover(self[group].mover:GetName())
+ end
+ else
+ -- UnregisterStateDriver(self[group], "visibility")
+ self[group]:Hide()
+ if self[group].mover then
+ E:DisableMover(self[group].mover:GetName())
+ end
+ return
+ end
+ else
+ self[group].db = db
+
+ if not UF["headerFunctions"][group] then UF["headerFunctions"][group] = {} end
+ UF["headerFunctions"][group]["Update"] = function()
+ local db = UF.db["units"][group]
+ if db.enable ~= true then
+ UnregisterStateDriver(UF[group], "visibility")
+ --UF[group]:Hide()
+ if(UF[group].mover) then
+ E:DisableMover(UF[group].mover:GetName())
+ end
+ return
+ end
+ UF["Update_"..E:StringTitle(group).."Header"](UF, UF[group], db)
+
+ for i = 1, UF[group]:GetNumChildren() do
+ local child = select(i, UF[group]:GetChildren())
+ UF["Update_"..E:StringTitle(group).."Frames"](UF, child, UF.db["units"][group])
+
+ if _G[child:GetName().."Target"] then
+ UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Target"], UF.db["units"][group])
+ end
+
+ if _G[child:GetName().."Pet"] then
+ UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Pet"], UF.db["units"][group])
+ end
+ end
+
+ E:EnableMover(UF[group].mover:GetName())
+ end
+
+ if headerUpdate then
+ UF["Update_"..E:StringTitle(group).."Header"](self, self[group], db)
+ else
+ UF["headerFunctions"][group]:Update(self[group])
+ end
+ end
+end
+
+function UF:PLAYER_REGEN_ENABLED()
+ self:Update_AllFrames()
+ self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+end
+
+function UF:CreateAndUpdateUF(unit)
+ assert(unit, "No unit provided to create or update.")
+
+ local frameName = E:StringTitle(unit)
+ frameName = gsub(frameName, "t(arget)", "T%1")
+ if not self[unit] then
+ self[unit] = ElvUF:Spawn(unit, "ElvUF_"..frameName)
+ self["units"][unit] = unit
+ end
+
+ self[unit].Update = function()
+ UF["Update_"..frameName.."Frame"](self, self[unit], self.db["units"][unit])
+ end
+
+ if self.db["units"][unit].enable then
+ self[unit]:Enable()
+ self[unit].Update()
+ E:EnableMover(self[unit].mover:GetName())
+ else
+ self[unit]:Disable()
+ E:DisableMover(self[unit].mover:GetName())
+ end
+end
+
+function UF:LoadUnits()
+ for _, unit in pairs(self["unitstoload"]) do
+ self:CreateAndUpdateUF(unit)
+ end
+ self["unitstoload"] = nil
+
+ for group, groupOptions in pairs(self["headerstoload"]) do
+ local groupFilter, template, headerTemplate
+ if type(groupOptions) == "table" then
+ groupFilter, template, headerTemplate = unpack(groupOptions)
+ end
+
+ self:CreateAndUpdateHeaderGroup(group, groupFilter, template, nil, headerTemplate)
+ end
+ self["headerstoload"] = nil
+end
+
+function UF:UpdateAllHeaders(event)
+ local _, instanceType = IsInInstance()
+ local ORD = ns.oUF_RaidDebuffs or oUF_RaidDebuffs
+ if ORD then
+ ORD:ResetDebuffData()
+
+ if instanceType == "party" or instanceType == "raid" then
+ ORD:RegisterDebuffs(E.global.unitframe.aurafilters.RaidDebuffs.spells)
+ else
+ ORD:RegisterDebuffs(E.global.unitframe.aurafilters.CCDebuffs.spells)
+ end
+ end
+
+ if E.private["unitframe"]["disabledBlizzardFrames"].party then
+ ElvUF:DisableBlizzard("party")
+ end
+
+ for group, header in pairs(self["headers"]) do
+ if header.numGroups then
+ UF["headerFunctions"][group]:UpdateHeader(header)
+ end
+ UF["headerFunctions"][group]:Update(header)
+
+ if group == "party" or group == "raid" then
+ --Update BuffIndicators on profile change as they might be using profile specific data
+ --self:UpdateAuraWatchFromHeader(group)
+ end
+ end
+end
+
+local hiddenParent = CreateFrame("Frame")
+hiddenParent:Hide()
+
+local HandleFrame = function(baseName)
+ local frame
+ if(type(baseName) == "string") then
+ frame = _G[baseName]
+ else
+ frame = baseName
+ end
+
+ if(frame) then
+ frame:UnregisterAllEvents()
+ frame:Hide()
+
+ -- Keep frame hidden without causing taint
+ frame:SetParent(hiddenParent)
+
+ local health = frame.healthbar
+ if(health) then
+ health:UnregisterAllEvents()
+ end
+
+ local power = frame.manabar
+ if(power) then
+ power:UnregisterAllEvents()
+ end
+
+ local spell = frame.spellbar
+ if(spell) then
+ spell:UnregisterAllEvents()
+ end
+ end
+end
+
+function ElvUF:DisableBlizzard(unit)
+ if not unit then return end
+
+ if(unit == "player") and E.private["unitframe"]["disabledBlizzardFrames"].player then
+ HandleFrame(PlayerFrame)
+ elseif(unit == "pet") and E.private["unitframe"]["disabledBlizzardFrames"].player then
+ HandleFrame(PetFrame)
+ elseif(unit == "target") and E.private["unitframe"]["disabledBlizzardFrames"].target then
+ HandleFrame(TargetFrame)
+ HandleFrame(ComboFrame)
+-- elseif(unit == "focus") and E.private["unitframe"]["disabledBlizzardFrames"].focus then
+-- HandleFrame(FocusFrame)
+-- HandleFrame(FocusFrameToT)
+ elseif(unit == "targettarget") and E.private["unitframe"]["disabledBlizzardFrames"].target then
+ HandleFrame(TargetofTargetFrame)
+ elseif string.match(unit, "(party)%d?$") == "party" and E.private["unitframe"]["disabledBlizzardFrames"].party then
+ local id = string.match(unit, "party(%d)")
+ if(id) then
+ HandleFrame("PartyMemberFrame"..id)
+ else
+ for i = 1, 4 do
+ HandleFrame(format("PartyMemberFrame%d", i))
+ end
+ end
+ HandleFrame(PartyMemberBackground)
+ end
+end
+
+local hasEnteredWorld = false
+function UF:PLAYER_ENTERING_WORLD()
+ if not hasEnteredWorld then
+ --We only want to run Update_AllFrames once when we first log in or /reload
+ self:Update_AllFrames()
+ hasEnteredWorld = true
+ else
+ local _, instanceType = IsInInstance()
+ if instanceType ~= "none" then
+ --We need to update headers when we zone into an instance
+ UF:UpdateAllHeaders()
+ end
+ end
+end
+
+function UF:Initialize()
+ self.db = E.db["unitframe"]
+ self.thinBorders = self.db.thinBorders or E.PixelMode
+ if E.private["unitframe"].enable ~= true then return; end
+ E.UnitFrames = UF
+
+ self:UpdateColors()
+ ElvUF:RegisterStyle("ElvUF", function(frame, unit)
+ self:Construct_UF(frame, unit)
+ end)
+
+ self:LoadUnits()
+ self:RegisterEvent("PLAYER_ENTERING_WORLD")
+
+ local ORD = ns.oUF_RaidDebuffs or oUF_RaidDebuffs
+ if not ORD then return end
+ ORD.ShowDispelableDebuff = true
+ ORD.FilterDispellableDebuff = true
+
+ self:UpdateRangeCheckSpells()
+ self:RegisterEvent("LEARNED_SPELL_IN_TAB", "UpdateRangeCheckSpells")
+end
+
+function UF:ResetUnitSettings(unit)
+ E:CopyTable(self.db["units"][unit], P["unitframe"]["units"][unit])
+
+ if self.db["units"][unit].buffs and self.db["units"][unit].buffs.sizeOverride then
+ self.db["units"][unit].buffs.sizeOverride = P.unitframe.units[unit].buffs.sizeOverride or 0
+ end
+
+ if self.db["units"][unit].debuffs and self.db["units"][unit].debuffs.sizeOverride then
+ self.db["units"][unit].debuffs.sizeOverride = P.unitframe.units[unit].debuffs.sizeOverride or 0
+ end
+
+ self:Update_AllFrames()
+end
+
+function UF:ToggleForceShowGroupFrames(unitGroup, numGroup)
+ for i = 1, numGroup do
+ if self[unitGroup..i] and not self[unitGroup..i].isForced then
+ UF:ForceShow(self[unitGroup..i])
+ elseif self[unitGroup..i] then
+ UF:UnforceShow(self[unitGroup..i])
+ end
+ end
+end
+
+local ignoreSettings = {
+ ["position"] = true,
+ ["playerOnly"] = true,
+ ["noConsolidated"] = true,
+ ["useBlacklist"] = true,
+ ["useWhitelist"] = true,
+ ["noDuration"] = true,
+ ["onlyDispellable"] = true,
+ ["useFilter"] = true
+}
+
+local ignoreSettingsGroup = {
+ ["visibility"] = true
+}
+
+local allowPass = {
+ ["sizeOverride"] = true
+}
+
+function UF:MergeUnitSettings(fromUnit, toUnit, isGroupUnit)
+ local db = self.db["units"]
+ local filter = ignoreSettings
+ if isGroupUnit then
+ filter = ignoreSettingsGroup
+ end
+ if fromUnit ~= toUnit then
+ for option, value in pairs(db[fromUnit]) do
+ if type(value) ~= "table" and not filter[option] then
+ if db[toUnit][option] ~= nil then
+ db[toUnit][option] = value
+ end
+ elseif not filter[option] then
+ if type(value) == "table" then
+ for opt, val in pairs(db[fromUnit][option]) do
+ --local val = db[fromUnit][option][opt]
+ if type(val) ~= "table" and not filter[opt] then
+ if db[toUnit][option] ~= nil and (db[toUnit][option][opt] ~= nil or allowPass[opt]) then
+ db[toUnit][option][opt] = val
+ end
+ elseif not filter[opt] then
+ if type(val) == "table" then
+ for o, v in pairs(db[fromUnit][option][opt]) do
+ if not filter[o] then
+ if db[toUnit][option] ~= nil and db[toUnit][option][opt] ~= nil and db[toUnit][option][opt][o] ~= nil then
+ db[toUnit][option][opt][o] = v
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ E:Print(L["You cannot copy settings from the same unit."])
+ end
+
+ self:Update_AllFrames()
+end
+
+local function updateColor(self, r, g, b)
+ if not self.isTransparent then return end
+ if self.backdrop then
+ local _, _, _, a = self.backdrop:GetBackdropColor()
+ self.backdrop:SetBackdropColor(r * 0.58, g * 0.58, b * 0.58, a)
+ elseif self:GetParent().template then
+ local _, _, _, a = self:GetParent():GetBackdropColor()
+ self:GetParent():SetBackdropColor(r * 0.58, g * 0.58, b * 0.58, a)
+ end
+
+ if self.bg and self.bg:GetObjectType() == "Texture" and not self.bg.multiplier then
+ self.bg:SetTexture(r * 0.35, g * 0.35, b * 0.35)
+ end
+end
+
+function UF:ToggleTransparentStatusBar(isTransparent, statusBar, backdropTex, adjustBackdropPoints, invertBackdropTex)
+ statusBar.isTransparent = isTransparent
+
+ local statusBarTex = statusBar.texturePointer
+ local statusBarOrientation = statusBar:GetOrientation()
+ if isTransparent then
+ if statusBar.backdrop then
+ E:SetTemplate(statusBar.backdrop, "Transparent", nil, nil, nil, true)
+ statusBar.backdrop.ignoreUpdates = true
+ elseif statusBar:GetParent().template then
+ E:SetTemplate(statusBar:GetParent(), "Transparent", nil, nil, nil, true)
+ statusBar:GetParent().ignoreUpdates = true
+ end
+
+ statusBar:SetStatusBarTexture("")
+ if statusBar.texture then statusBar.texture = statusBar:GetStatusBarTexture() end --Needed for Power element
+
+ backdropTex:ClearAllPoints()
+ if statusBarOrientation == "VERTICAL" then
+ backdropTex:SetPoint("TOPLEFT", statusBar, "TOPLEFT")
+ backdropTex:SetPoint("BOTTOMLEFT", statusBarTex, "TOPLEFT")
+ backdropTex:SetPoint("BOTTOMRIGHT", statusBarTex, "TOPRIGHT")
+ else
+ backdropTex:SetPoint("TOPLEFT", statusBarTex, "TOPRIGHT")
+ backdropTex:SetPoint("BOTTOMLEFT", statusBarTex, "BOTTOMRIGHT")
+ backdropTex:SetPoint("BOTTOMRIGHT", statusBar, "BOTTOMRIGHT")
+ end
+
+ if invertBackdropTex then
+ backdropTex:Show()
+ end
+
+ if not invertBackdropTex and not statusBar.hookedColor then
+ hooksecurefunc(statusBar, "SetStatusBarColor", updateColor)
+ statusBar.hookedColor = true
+ end
+
+ if backdropTex.multiplier then
+ backdropTex.multiplier = 0.25
+ end
+ else
+ if statusBar.backdrop then
+ E:SetTemplate(statusBar.backdrop, "Default", nil, nil, not statusBar.PostCastStart and self.thinBorders, true)
+ statusBar.backdrop.ignoreUpdates = nil
+ elseif statusBar:GetParent().template then
+ E:SetTemplate(statusBar:GetParent(), "Default", nil, nil, self.thinBorders, true)
+ statusBar:GetParent().ignoreUpdates = nil
+ end
+ statusBar:SetStatusBarTexture(LSM:Fetch("statusbar", self.db.statusbar))
+ if statusBar.texture then statusBar.texture = statusBar:GetStatusBarTexture() end
+
+ if adjustBackdropPoints then
+ backdropTex:ClearAllPoints()
+ if statusBarOrientation == "VERTICAL" then
+ backdropTex:SetPoint("TOPLEFT", statusBar, "TOPLEFT")
+ backdropTex:SetPoint("BOTTOMLEFT", statusBarTex, "TOPLEFT")
+ backdropTex:SetPoint("BOTTOMRIGHT", statusBarTex, "TOPRIGHT")
+ else
+ backdropTex:SetPoint("TOPLEFT", statusBarTex, "TOPRIGHT")
+ backdropTex:SetPoint("BOTTOMLEFT", statusBarTex, "BOTTOMRIGHT")
+ backdropTex:SetPoint("BOTTOMRIGHT", statusBar, "BOTTOMRIGHT")
+ end
+ end
+
+ if invertBackdropTex then
+ backdropTex:Hide()
+ end
+
+ if backdropTex.multiplier then
+ backdropTex.multiplier = 0.25
+ end
+ end
+end
+
+local function InitializeCallback()
+ UF:Initialize()
+end
+
+E:RegisterInitialModule(UF:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Units/Load_Units.xml b/ElvUI/Modules/UnitFrames/Units/Load_Units.xml
new file mode 100644
index 0000000..ba62950
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Units/Load_Units.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Units/Player.lua b/ElvUI/Modules/UnitFrames/Units/Player.lua
new file mode 100644
index 0000000..9a69105
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Units/Player.lua
@@ -0,0 +1,106 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+local CAN_HAVE_CLASSBAR = E.myclass == "DRUID"
+
+function UF:Construct_PlayerFrame(frame)
+ frame.Health = self:Construct_HealthBar(frame, true, true, "RIGHT")
+ frame.Health.frequentUpdates = true
+
+ frame.Power = self:Construct_PowerBar(frame, true, true, "LEFT")
+ frame.Power.frequentUpdates = true
+
+ frame.Name = self:Construct_NameText(frame)
+
+ frame.Portrait3D = self:Construct_Portrait(frame, "model")
+ frame.Portrait2D = self:Construct_Portrait(frame, "texture")
+ frame.RaidTargetIndicator = UF:Construct_RaidIcon(frame)
+ frame.RestingIndicator = self:Construct_RestingIndicator(frame)
+ frame.CombatIndicator = self:Construct_CombatIndicator(frame)
+ frame.InfoPanel = self:Construct_InfoPanel(frame)
+
+ frame:SetPoint("BOTTOMLEFT", E.UIParent, "BOTTOM", -413, 68)
+ E:CreateMover(frame, frame:GetName().."Mover", L["Player Frame"], nil, nil, nil, "ALL,SOLO")
+ frame.unitframeType = "player"
+end
+
+function UF:Update_PlayerFrame(frame, db)
+ frame.db = db
+
+ do
+ frame.ORIENTATION = db.orientation
+ frame.UNIT_WIDTH = db.width
+ frame.UNIT_HEIGHT = db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height
+
+ frame.USE_POWERBAR = db.power.enable
+ frame.POWERBAR_DETACHED = db.power.detachFromFrame
+ frame.USE_INSET_POWERBAR = not frame.POWERBAR_DETACHED and db.power.width == "inset" and frame.USE_POWERBAR
+ frame.USE_MINI_POWERBAR = (not frame.POWERBAR_DETACHED and db.power.width == "spaced" and frame.USE_POWERBAR)
+ frame.USE_POWERBAR_OFFSET = db.power.offset ~= 0 and frame.USE_POWERBAR and not frame.POWERBAR_DETACHED
+ frame.POWERBAR_OFFSET = frame.USE_POWERBAR_OFFSET and db.power.offset or 0
+
+ frame.POWERBAR_HEIGHT = not frame.USE_POWERBAR and 0 or db.power.height
+ frame.POWERBAR_WIDTH = frame.USE_MINI_POWERBAR and (frame.UNIT_WIDTH - (frame.BORDER*2))/2 or (frame.POWERBAR_DETACHED and db.power.detachedWidth or (frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2)))
+
+ frame.USE_PORTRAIT = db.portrait and db.portrait.enable
+ frame.USE_PORTRAIT_OVERLAY = frame.USE_PORTRAIT and (db.portrait.overlay or frame.ORIENTATION == "MIDDLE")
+ frame.PORTRAIT_WIDTH = (frame.USE_PORTRAIT_OVERLAY or not frame.USE_PORTRAIT) and 0 or db.portrait.width
+
+ frame.CAN_HAVE_CLASSBAR = CAN_HAVE_CLASSBAR
+ frame.MAX_CLASS_BAR = frame.MAX_CLASS_BAR or UF.classMaxResourceBar[E.myclass] or 0
+ frame.USE_CLASSBAR = db.classbar.enable and frame.CAN_HAVE_CLASSBAR
+ frame.CLASSBAR_SHOWN = frame.CAN_HAVE_CLASSBAR and frame[frame.ClassBar]:IsShown()
+ frame.CLASSBAR_DETACHED = db.classbar.detachFromFrame
+ frame.USE_MINI_CLASSBAR = db.classbar.fill == "spaced" and frame.USE_CLASSBAR
+ frame.CLASSBAR_HEIGHT = frame.USE_CLASSBAR and db.classbar.height or 0
+ frame.CLASSBAR_WIDTH = frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2) - frame.PORTRAIT_WIDTH -(frame.ORIENTATION == "MIDDLE" and (frame.POWERBAR_OFFSET*2) or frame.POWERBAR_OFFSET)
+ frame.CLASSBAR_YOFFSET = (not frame.USE_CLASSBAR or not frame.CLASSBAR_SHOWN or frame.CLASSBAR_DETACHED) and 0 or (frame.USE_MINI_CLASSBAR and (frame.SPACING+(frame.CLASSBAR_HEIGHT/2)) or (frame.CLASSBAR_HEIGHT - (frame.BORDER-frame.SPACING)))
+
+ frame.USE_INFO_PANEL = not frame.USE_MINI_POWERBAR and not frame.USE_POWERBAR_OFFSET and db.infoPanel.enable
+ frame.INFO_PANEL_HEIGHT = frame.USE_INFO_PANEL and db.infoPanel.height or 0
+
+ frame.HAPPINESS_WIDTH = 0
+
+ frame.BOTTOM_OFFSET = UF:GetHealthBottomOffset(frame)
+
+ frame.VARIABLES_SET = true
+ end
+
+ frame.colors = ElvUF.colors
+ frame.Portrait = frame.Portrait or (db.portrait.style == "2D" and frame.Portrait2D or frame.Portrait3D)
+ frame:RegisterForClicks(self.db.targetOnMouseDown and "LeftButtonDown" or "LeftButtonUp", self.db.targetOnMouseDown and "RightButtonDown" or "RightButtonUp")
+
+ frame:SetWidth(frame.UNIT_WIDTH)
+ frame:SetHeight(frame.UNIT_HEIGHT)
+ _G[frame:GetName().."Mover"]:SetWidth(frame:GetWidth())
+ _G[frame:GetName().."Mover"]:SetHeight(frame:GetHeight())
+
+ UF:Configure_InfoPanel(frame)
+
+ UF:Configure_RestingIndicator(frame)
+
+ UF:Configure_CombatIndicator(frame)
+
+ UF:Configure_HealthBar(frame)
+
+ UF:UpdateNameSettings(frame)
+
+ UF:Configure_Power(frame)
+
+ UF:Configure_Portrait(frame)
+
+ UF:Configure_RaidIcon(frame)
+
+ E:SetMoverSnapOffset(frame:GetName().."Mover", -(12 + db.castbar.height))
+ frame:UpdateAllElements("ElvUI_UpdateAllElements")
+end
+
+tinsert(UF["unitstoload"], "player")
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Units/Target.lua b/ElvUI/Modules/UnitFrames/Units/Target.lua
new file mode 100644
index 0000000..ce6baf7
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Units/Target.lua
@@ -0,0 +1,96 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+function UF:Construct_TargetFrame(frame)
+ frame.Health = self:Construct_HealthBar(frame, true, true, "RIGHT")
+ frame.Health.frequentUpdates = true
+
+ frame.Power = self:Construct_PowerBar(frame, true, true, "LEFT")
+ frame.Power.frequentUpdates = true
+
+ frame.Name = self:Construct_NameText(frame)
+
+ frame.Portrait3D = self:Construct_Portrait(frame, "model")
+ frame.Portrait2D = self:Construct_Portrait(frame, "texture")
+ frame.RaidTargetIndicator = UF:Construct_RaidIcon(frame)
+ frame.InfoPanel = self:Construct_InfoPanel(frame)
+
+ frame:SetPoint("BOTTOMRIGHT", E.UIParent, "BOTTOM", 413, 68)
+ E:CreateMover(frame, frame:GetName().."Mover", L["Target Frame"], nil, nil, nil, "ALL,SOLO")
+ frame.unitframeType = "target"
+end
+
+function UF:Update_TargetFrame(frame, db)
+ frame.db = db
+
+ do
+ frame.ORIENTATION = db.orientation
+ frame.UNIT_WIDTH = db.width
+ frame.UNIT_HEIGHT = db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height
+
+ frame.USE_POWERBAR = db.power.enable
+ frame.POWERBAR_DETACHED = db.power.detachFromFrame
+ frame.USE_INSET_POWERBAR = not frame.POWERBAR_DETACHED and db.power.width == "inset" and frame.USE_POWERBAR
+ frame.USE_MINI_POWERBAR = (not frame.POWERBAR_DETACHED and db.power.width == "spaced" and frame.USE_POWERBAR)
+ frame.USE_POWERBAR_OFFSET = db.power.offset ~= 0 and frame.USE_POWERBAR and not frame.POWERBAR_DETACHED
+ frame.POWERBAR_OFFSET = frame.USE_POWERBAR_OFFSET and db.power.offset or 0
+
+ frame.POWERBAR_HEIGHT = not frame.USE_POWERBAR and 0 or db.power.height
+ frame.POWERBAR_WIDTH = frame.USE_MINI_POWERBAR and (frame.UNIT_WIDTH - (frame.BORDER*2))/2 or (frame.POWERBAR_DETACHED and db.power.detachedWidth or (frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2)))
+
+ frame.USE_PORTRAIT = db.portrait and db.portrait.enable
+ frame.USE_PORTRAIT_OVERLAY = frame.USE_PORTRAIT and (db.portrait.overlay or frame.ORIENTATION == "MIDDLE")
+ frame.PORTRAIT_WIDTH = (frame.USE_PORTRAIT_OVERLAY or not frame.USE_PORTRAIT) and 0 or db.portrait.width
+
+ frame.CAN_HAVE_CLASSBAR = db.combobar.enable
+ frame.MAX_CLASS_BAR = MAX_COMBO_POINTS
+ frame.USE_CLASSBAR = db.combobar.enable
+ frame.CLASSBAR_SHOWN = frame.CAN_HAVE_CLASSBAR and frame.ComboPoints and frame.ComboPoints:IsShown()
+ frame.CLASSBAR_DETACHED = db.combobar.detachFromFrame
+ frame.USE_MINI_CLASSBAR = db.combobar.fill == "spaced" and frame.USE_CLASSBAR
+ frame.CLASSBAR_HEIGHT = frame.USE_CLASSBAR and db.combobar.height or 0
+ frame.CLASSBAR_WIDTH = frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2) - frame.PORTRAIT_WIDTH - frame.POWERBAR_OFFSET
+ frame.CLASSBAR_YOFFSET = (not frame.USE_CLASSBAR or not frame.CLASSBAR_SHOWN or frame.CLASSBAR_DETACHED) and 0 or (frame.USE_MINI_CLASSBAR and (frame.SPACING+(frame.CLASSBAR_HEIGHT/2)) or (frame.CLASSBAR_HEIGHT + frame.SPACING))
+
+ frame.USE_INFO_PANEL = not frame.USE_MINI_POWERBAR and not frame.USE_POWERBAR_OFFSET and db.infoPanel.enable
+ frame.INFO_PANEL_HEIGHT = frame.USE_INFO_PANEL and db.infoPanel.height or 0
+
+ frame.BOTTOM_OFFSET = UF:GetHealthBottomOffset(frame)
+
+ frame.VARIABLES_SET = true
+ end
+
+ frame.colors = ElvUF.colors
+ frame.Portrait = frame.Portrait or (db.portrait.style == "2D" and frame.Portrait2D or frame.Portrait3D)
+ frame:RegisterForClicks(self.db.targetOnMouseDown and "LeftButtonDown" or "LeftButtonUp", self.db.targetOnMouseDown and "RightButtonDown" or "RightButtonUp")
+
+ frame:SetWidth(frame.UNIT_WIDTH)
+ frame:SetHeight(frame.UNIT_HEIGHT)
+ _G[frame:GetName().."Mover"]:SetWidth(frame:GetWidth())
+ _G[frame:GetName().."Mover"]:SetHeight(frame:GetHeight())
+
+ UF:Configure_InfoPanel(frame)
+
+ UF:Configure_HealthBar(frame)
+
+ UF:UpdateNameSettings(frame)
+
+ UF:Configure_Power(frame)
+
+ UF:Configure_Portrait(frame)
+
+ UF:Configure_RaidIcon(frame)
+
+ E:SetMoverSnapOffset(frame:GetName().."Mover", -(12 + db.castbar.height))
+ frame:UpdateAllElements("ElvUI_UpdateAllElements")
+end
+
+tinsert(UF["unitstoload"], "target")
\ No newline at end of file
diff --git a/ElvUI/Modules/UnitFrames/Units/TargetTarget.lua b/ElvUI/Modules/UnitFrames/Units/TargetTarget.lua
new file mode 100644
index 0000000..0b298e5
--- /dev/null
+++ b/ElvUI/Modules/UnitFrames/Units/TargetTarget.lua
@@ -0,0 +1,81 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+--Cache global variables
+--Lua functions
+local _G = _G
+
+local ns = oUF
+local ElvUF = ns.oUF
+assert(ElvUF, "ElvUI was unable to locate oUF.")
+
+function UF:Construct_TargetTargetFrame(frame)
+ frame.Health = self:Construct_HealthBar(frame, true, true, "RIGHT")
+ frame.Power = self:Construct_PowerBar(frame, true, true, "LEFT")
+ frame.Name = self:Construct_NameText(frame)
+ frame.Portrait3D = self:Construct_Portrait(frame, "model")
+ frame.Portrait2D = self:Construct_Portrait(frame, "texture")
+ frame.RaidTargetIndicator = UF:Construct_RaidIcon(frame)
+ frame.InfoPanel = self:Construct_InfoPanel(frame)
+
+ frame:SetPoint("BOTTOM", E.UIParent, "BOTTOM", 0, 75)
+ E:CreateMover(frame, frame:GetName().."Mover", L["TargetTarget Frame"], nil, nil, nil, "ALL,SOLO")
+ frame.unitframeType = "targettarget";
+end
+
+function UF:Update_TargetTargetFrame(frame, db)
+ frame.db = db
+
+ do
+ frame.ORIENTATION = db.orientation
+ frame.UNIT_WIDTH = db.width
+ frame.UNIT_HEIGHT = db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height
+
+ frame.USE_POWERBAR = db.power.enable
+ frame.POWERBAR_DETACHED = db.power.detachFromFrame
+ frame.USE_INSET_POWERBAR = not frame.POWERBAR_DETACHED and db.power.width == "inset" and frame.USE_POWERBAR
+ frame.USE_MINI_POWERBAR = (not frame.POWERBAR_DETACHED and db.power.width == "spaced" and frame.USE_POWERBAR)
+ frame.USE_POWERBAR_OFFSET = db.power.offset ~= 0 and frame.USE_POWERBAR and not frame.POWERBAR_DETACHED
+ frame.POWERBAR_OFFSET = frame.USE_POWERBAR_OFFSET and db.power.offset or 0
+
+ frame.POWERBAR_HEIGHT = not frame.USE_POWERBAR and 0 or db.power.height
+ frame.POWERBAR_WIDTH = frame.USE_MINI_POWERBAR and (frame.UNIT_WIDTH - (frame.BORDER*2))/2 or (frame.POWERBAR_DETACHED and db.power.detachedWidth or (frame.UNIT_WIDTH - ((frame.BORDER+frame.SPACING)*2)))
+
+ frame.USE_PORTRAIT = db.portrait and db.portrait.enable
+ frame.USE_PORTRAIT_OVERLAY = frame.USE_PORTRAIT and (db.portrait.overlay or frame.ORIENTATION == "MIDDLE")
+ frame.PORTRAIT_WIDTH = (frame.USE_PORTRAIT_OVERLAY or not frame.USE_PORTRAIT) and 0 or db.portrait.width
+
+ frame.USE_INFO_PANEL = not frame.USE_MINI_POWERBAR and not frame.USE_POWERBAR_OFFSET and db.infoPanel.enable
+ frame.INFO_PANEL_HEIGHT = frame.USE_INFO_PANEL and db.infoPanel.height or 0
+
+ frame.BOTTOM_OFFSET = UF:GetHealthBottomOffset(frame)
+
+ frame.VARIABLES_SET = true
+ end
+
+ frame.colors = ElvUF.colors
+ frame.Portrait = frame.Portrait or (db.portrait.style == "2D" and frame.Portrait2D or frame.Portrait3D)
+ frame:RegisterForClicks(self.db.targetOnMouseDown and "LeftButtonDown" or "LeftButtonUp", self.db.targetOnMouseDown and "RightButtonDown" or "RightButtonUp")
+ frame:RegisterForClicks("LeftButtonUp", "RightButtonUp")
+ frame:SetWidth(frame.UNIT_WIDTH)
+ frame:SetHeight(frame.UNIT_HEIGHT)
+ _G[frame:GetName().."Mover"]:SetWidth(frame:GetWidth())
+ _G[frame:GetName().."Mover"]:SetHeight(frame:GetHeight())
+
+ UF:Configure_InfoPanel(frame)
+
+ UF:Configure_HealthBar(frame)
+
+ UF:UpdateNameSettings(frame)
+
+ UF:Configure_Power(frame)
+
+ UF:Configure_Portrait(frame)
+
+ UF:Configure_RaidIcon(frame)
+
+ E:SetMoverSnapOffset(frame:GetName().."Mover", -(12 + self.db["units"].player.castbar.height))
+ frame:UpdateAllElements("ElvUI_UpdateAllElements")
+end
+
+tinsert(UF["unitstoload"], "targettarget")
\ No newline at end of file
diff --git a/ElvUI/Settings/Filters/Load_Filters.xml b/ElvUI/Settings/Filters/Load_Filters.xml
new file mode 100644
index 0000000..dd470ff
--- /dev/null
+++ b/ElvUI/Settings/Filters/Load_Filters.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Settings/Filters/NamePlate.lua b/ElvUI/Settings/Filters/NamePlate.lua
new file mode 100644
index 0000000..bd672f3
--- /dev/null
+++ b/ElvUI/Settings/Filters/NamePlate.lua
@@ -0,0 +1 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
diff --git a/ElvUI/Settings/Filters/UnitFrame.lua b/ElvUI/Settings/Filters/UnitFrame.lua
new file mode 100644
index 0000000..bd672f3
--- /dev/null
+++ b/ElvUI/Settings/Filters/UnitFrame.lua
@@ -0,0 +1 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
diff --git a/ElvUI/Settings/Global.lua b/ElvUI/Settings/Global.lua
new file mode 100644
index 0000000..672e99f
--- /dev/null
+++ b/ElvUI/Settings/Global.lua
@@ -0,0 +1,30 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Global Settings
+G["general"] = {
+ ["autoScale"] = true,
+ ["minUiScale"] = 0.64,
+ ["eyefinity"] = false,
+ ["smallerWorldMap"] = true,
+ ["WorldMapCoordinates"] = {
+ ["enable"] = true,
+ ["position"] = "BOTTOMLEFT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0
+ },
+ ["versionCheck"] = true
+}
+
+G["classCache"] = {}
+
+G["classtimer"] = {}
+
+G["nameplates"] = {}
+
+G["chat"] = {
+ ["classColorMentionExcludedNames"] = {}
+}
+
+G["bags"] = {
+ ["ignoredItems"] = {}
+}
\ No newline at end of file
diff --git a/ElvUI/Settings/Load_Config.xml b/ElvUI/Settings/Load_Config.xml
new file mode 100644
index 0000000..f9136f7
--- /dev/null
+++ b/ElvUI/Settings/Load_Config.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Settings/Private.lua b/ElvUI/Settings/Private.lua
new file mode 100644
index 0000000..03bb53a
--- /dev/null
+++ b/ElvUI/Settings/Private.lua
@@ -0,0 +1,123 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+--Locked Settings, These settings are stored for your character only regardless of profile options.
+
+V["general"] = {
+ ["loot"] = true,
+ ["lootRoll"] = true,
+ ["lootUnderMouse"] = false,
+ ["normTex"] = "ElvUI Norm",
+ ["glossTex"] = "ElvUI Norm",
+ ["dmgfont"] = "PT Sans Narrow",
+ ["namefont"] = "PT Sans Narrow",
+ ["chatBubbles"] = "backdrop",
+ ["chatBubbleFont"] = "PT Sans Narrow",
+ ["chatBubbleFontSize"] = 14,
+ ["chatBubbleFontOutline"] = "NONE",
+ ["pixelPerfect"] = true,
+ ["replaceBlizzFonts"] = true,
+ ["minimap"] = {
+ ["enable"] = true,
+ ["hideCalendar"] = true,
+ ["zoomLevel"] = 0,
+ },
+ ["classCache"] = true,
+ ["classColorMentionsSpeech"] = true,
+}
+
+V["bags"] = {
+ ["enable"] = true,
+ ["bagBar"] = false,
+}
+
+V["nameplates"] = {
+ ["enable"] = true,
+}
+
+V["auras"] = {
+ ["enable"] = true,
+ ["disableBlizzard"] = true,
+ ["lbf"] = {
+ enable = false,
+ skin = "Blizzard"
+ },
+}
+
+V["chat"] = {
+ ["enable"] = true,
+}
+
+V["skins"] = {
+ ["ace3"] = {
+ ["enable"] = true,
+ },
+ ["blizzard"] = {
+ ["enable"] = true,
+ ["alertframes"] = true,
+ ["auctionhouse"] = true,
+ ["bags"] = true,
+ ["battlefield"] = true,
+ ["bgscore"] = true,
+ ["binding"] = true,
+ ["character"] = true,
+ ["debug"] = true,
+ ["dressingroom"] = true,
+ ["friends"] = true,
+ ["gossip"] = true,
+ ["greeting"] = true,
+ ["guildregistrar"] = true,
+ ["help"] = true,
+ ["inspect"] = true,
+ ["loot"] = true,
+ ["lootRoll"] = true,
+ ["macro"] = true,
+ ["mail"] = true,
+ ["merchant"] = true,
+ ["misc"] = true,
+ ["petition"] = true,
+ ["quest"] = true,
+ ["questtimers"] = true,
+ ["raid"] = true,
+ ["spellbook"] = true,
+ ["stable"] = true,
+ ["tabard"] = true,
+ ["talent"] = true,
+ ["taxi"] = true,
+ ["tooltip"] = true,
+ ["trade"] = true,
+ ["tradeskill"] = true,
+ ["trainer"] = true,
+ ["tutorial"] = true,
+ ["watchframe"] = true,
+ ["worldmap"] = true,
+ ["mirrorTimers"] = true
+ },
+}
+
+V["tooltip"] = {
+ ["enable"] = true
+}
+
+V["unitframe"] = {
+ ["enable"] = true,
+ ["disabledBlizzardFrames"] = {
+ ["player"] = true,
+ ["target"] = true,
+ ["focus"] = true,
+ ["boss"] = true,
+ ["arena"] = true,
+ ["party"] = true,
+ },
+}
+
+V["actionbar"] = {
+ ["enable"] = true,
+ ["lbf"] = {
+ enable = false,
+ skin = "Blizzard"
+ },
+}
+
+V["cooldown"] = {
+ enable = true
+}
\ No newline at end of file
diff --git a/ElvUI/Settings/Profile.lua b/ElvUI/Settings/Profile.lua
new file mode 100644
index 0000000..591ea5c
--- /dev/null
+++ b/ElvUI/Settings/Profile.lua
@@ -0,0 +1,2657 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+
+P.gridSize = 64
+P.farmSize = 340
+
+--Core
+P["general"] = {
+ ["taintLog"] = false,
+ ["stickyFrames"] = true,
+ ["loginmessage"] = true,
+ ["autoRepair"] = "NONE",
+ ["autoRoll"] = false,
+ ["vendorGrays"] = false,
+ ["autoAcceptInvite"] = false,
+ ["bottomPanel"] = true,
+ ["hideErrorFrame"] = true,
+ ["watchFrameHeight"] = 480,
+ ["afk"] = true,
+ ["enhancedPvpMessages"] = true,
+ ["numberPrefixStyle"] = "ENGLISH",
+ ["decimalLength"] = 1,
+
+ ["fontSize"] = 12,
+ ["font"] = "PT Sans Narrow",
+
+ ["bordercolor"] = {r = 0, g = 0, b = 0},
+ ["backdropcolor"] = {r = 0.1, g = 0.1, b = 0.1},
+ ["backdropfadecolor"] = {r = .06, g = .06, b = .06, a = 0.8},
+ ["valuecolor"] = {r = 254/255, g = 123/255, b = 44/255},
+
+ ["classCacheStoreInDB"] = true,
+ ["classCacheRequestInfo"] = false,
+
+ ["minimap"] = {
+ ["size"] = 176,
+ ["locationText"] = "MOUSEOVER",
+ ["locationFontSize"] = 12,
+ ["locationFontOutline"] = "OUTLINE",
+ ["locationFont"] = "PT Sans Narrow",
+ ["resetZoom"] = {
+ ["enable"] = false,
+ ["time"] = 3,
+ },
+ ["icons"] = {
+ ["calendar"] = {
+ ["scale"] = 1,
+ ["position"] = "TOPRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["hide"] = true,
+ },
+ ["mail"] = {
+ ["scale"] = 1,
+ ["position"] = "TOPRIGHT",
+ ["xOffset"] = 3,
+ ["yOffset"] = 4,
+ },
+ ["lfgEye"] = {
+ ["scale"] = 1,
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 3,
+ ["yOffset"] = 0,
+ },
+ ["battlefield"] = {
+ ["scale"] = 1,
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 3,
+ ["yOffset"] = 0,
+ },
+ ["difficulty"] = {
+ ["scale"] = 1,
+ ["position"] = "TOPLEFT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["vehicleLeave"] = {
+ ["scale"] = 1,
+ ["position"] = "BOTTOMLEFT",
+ ["xOffset"] = 2,
+ ["yOffset"] = 2,
+ ["hide"] = false,
+ },
+ }
+ },
+}
+
+-- Data Bars
+P["databars"] = {
+ ["experience"] = {
+ ["enable"] = true,
+ ["width"] = 10,
+ ["height"] = 180,
+ ["textFormat"] = "NONE",
+ ["textSize"] = 12,
+ ["font"] = "PT Sans Narrow",
+ ["fontOutline"] = "NONE",
+ ["mouseover"] = false,
+ ["orientation"] = "VERTICAL",
+ ["hideAtMaxLevel"] = true,
+ },
+ ["reputation"] = {
+ ["enable"] = true,
+ ["width"] = 10,
+ ["height"] = 180,
+ ["textFormat"] = "NONE",
+ ["textSize"] = 12,
+ ["font"] = "PT Sans Narrow",
+ ["fontOutline"] = "NONE",
+ ["mouseover"] = false,
+ ["orientation"] = "VERTICAL",
+ },
+}
+
+P["nameplates"] = {
+ ["statusbar"] = "ElvUI Norm",
+ ["font"] = "Homespun",
+ ["fontSize"] = 8,
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["useTargetScale"] = true,
+ ["targetScale"] = 1.15,
+ ["nonTargetTransparency"] = 0.35,
+ ["motionType"] = "OVERLAP",
+ ["lowHealthThreshold"] = 0.4,
+
+ ["showFriendlyCombat"] = "DISABLED",
+ ["showEnemyCombat"] = "DISABLED",
+
+ ["clampToScreen"] = false,
+ ["useTargetGlow"] = true,
+
+ ["castColor"] = {r = 1, g = 208/255, b = 0},
+ ["comboPoints"] = true,
+ ["reactions"] = {
+ ["friendlyPlayer"] = {r = 0.31, g = 0.45, b = 0.63},
+ ["tapped"] = {r = 0.6, g = 0.6, b = 0.6},
+ ["good"] = {r = 75/255, g = 175/255, b = 76/255},
+ ["neutral"] = {r = 218/255, g = 197/255, b = 92/255},
+ ["bad"] = {r = 0.78, g = 0.25, b = 0.25},
+ },
+ ["threat"] = {
+ ["goodColor"] = {r = 75/255, g = 175/255, b = 76/255},
+ ["badColor"] = {r = 0.78, g = 0.25, b = 0.25},
+ ["goodTransition"] = {r = 218/255, g = 197/255, b = 92/255},
+ ["badTransition"] = {r = 235/255, g = 163/255, b = 40/255},
+ ["beingTankedByTankColor"] = {r = .8, g = 0.1,b = 1},
+ ["beingTankedByTank"] = true,
+ ["goodScale"] = 0.8,
+ ["badScale"] = 1.2,
+ ["useThreatColor"] = true,
+ },
+
+ ["units"] = {
+ ["FRIENDLY_PLAYER"] = {
+ ["healthbar"] = {
+ ["enable"] = false,
+ ["height"] = 10,
+ ["width"] = 150,
+ ["glowStyle"] = "TARGET_THREAT",
+ ["text"] = {
+ ["enable"] = false,
+ ["format"] = "CURRENT",
+ },
+ ["useClassColor"] = true,
+ },
+ ["showName"] = true,
+ ["showLevel"] = false,
+ ["castbar"] = {
+ ["enable"] = true,
+ ["height"] = 8,
+ ["offset"] = 1,
+ ["hideSpellName"] = false,
+ ["hideTime"] = false,
+ ["castTimeFormat"] = "CURRENT",
+ ["channelTimeFormat"] = "CURRENT",
+ ["timeToHold"] = 0
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "TurtleBuffs"
+ },
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "CCDebuffs"
+ },
+ },
+ ["name"] = {
+ ["useClassColor"] = true,
+ },
+ },
+ ["ENEMY_PLAYER"] = {
+ ["markHealers"] = true,
+ ["healthbar"] = {
+ ["enable"] = true,
+ ["height"] = 10,
+ ["width"] = 150,
+ ["glowStyle"] = "TARGET_THREAT",
+ ["text"] = {
+ ["enable"] = false,
+ ["format"] = "CURRENT",
+ },
+ ["useClassColor"] = true,
+ },
+ ["showName"] = true,
+ ["showLevel"] = true,
+ ["castbar"] = {
+ ["enable"] = true,
+ ["height"] = 8,
+ ["offset"] = 1,
+ ["hideSpellName"] = false,
+ ["hideTime"] = false,
+ ["castTimeFormat"] = "CURRENT",
+ ["channelTimeFormat"] = "CURRENT",
+ ["timeToHold"] = 0
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "TurtleBuffs"
+ },
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "CCDebuffs"
+ },
+ },
+ ["name"] = {
+ ["useClassColor"] = true,
+ },
+ },
+ ["FRIENDLY_NPC"] = {
+ ["healthbar"] = {
+ ["enable"] = false,
+ ["height"] = 10,
+ ["width"] = 150,
+ ["glowStyle"] = "TARGET_THREAT",
+ ["text"] = {
+ ["enable"] = false,
+ ["format"] = "CURRENT",
+ },
+ },
+ ["showName"] = true,
+ ["showLevel"] = true,
+ ["castbar"] = {
+ ["enable"] = true,
+ ["height"] = 8,
+ ["offset"] = 1,
+ ["hideSpellName"] = false,
+ ["hideTime"] = false,
+ ["castTimeFormat"] = "CURRENT",
+ ["channelTimeFormat"] = "CURRENT",
+ ["timeToHold"] = 0
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "TurtleBuffs"
+ },
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "CCDebuffs"
+ },
+ },
+ ["eliteIcon"] = {
+ ["enable"] = false,
+ ["size"] = 20,
+ ["position"] = "RIGHT",
+ ["xOffset"] = 15,
+ ["yOffset"] = 0,
+ },
+ },
+ ["ENEMY_NPC"] = {
+ ["healthbar"] = {
+ ["enable"] = true,
+ ["height"] = 10,
+ ["width"] = 150,
+ ["glowStyle"] = "TARGET_THREAT",
+ ["text"] = {
+ ["enable"] = false,
+ ["format"] = "CURRENT",
+ },
+ },
+ ["showName"] = true,
+ ["showLevel"] = true,
+ ["castbar"] = {
+ ["enable"] = true,
+ ["height"] = 8,
+ ["offset"] = 1,
+ ["hideSpellName"] = false,
+ ["hideTime"] = false,
+ ["castTimeFormat"] = "CURRENT",
+ ["channelTimeFormat"] = "CURRENT",
+ ["timeToHold"] = 0
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "TurtleBuffs"
+ },
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["numAuras"] = 4,
+ ["baseHeight"] = 18,
+ ["filters"] = {
+ ["personal"] = true,
+ ["maxDuration"] = 120,
+ ["filter"] = "CCDebuffs"
+ },
+ },
+ ["eliteIcon"] = {
+ ["enable"] = false,
+ ["size"] = 20,
+ ["position"] = "RIGHT",
+ ["xOffset"] = 15,
+ ["yOffset"] = 0,
+ },
+ ["detection"] = {
+ ["enable"] = true,
+ }
+ }
+ }
+};
+
+--Auras
+P["auras"] = {
+ ["font"] = "Homespun",
+ ["fontSize"] = 10,
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["countYOffset"] = 0,
+ ["countXOffset"] = 0,
+ ["timeYOffset"] = 0,
+ ["timeXOffset"] = 0,
+ ["fadeThreshold"] = 5,
+ ["buffs"] = {
+ ["growthDirection"] = "LEFT_DOWN",
+ ["wrapAfter"] = 12,
+ ["maxWraps"] = 3,
+ ["horizontalSpacing"] = 6,
+ ["verticalSpacing"] = 16,
+ ["sortMethod"] = "TIME",
+ ["sortDir"] = "-",
+ ["seperateOwn"] = 1,
+ ["size"] = 32,
+ },
+ ["debuffs"] = {
+ ["growthDirection"] = "LEFT_DOWN",
+ ["wrapAfter"] = 12,
+ ["maxWraps"] = 1,
+ ["horizontalSpacing"] = 6,
+ ["verticalSpacing"] = 16,
+ ["sortMethod"] = "TIME",
+ ["sortDir"] = "-",
+ ["seperateOwn"] = 1,
+ ["size"] = 32,
+ },
+}
+
+--Chat
+P["chat"] = {
+ ["lockPositions"] = true,
+ ["url"] = true,
+ ["shortChannels"] = true,
+ ["hyperlinkHover"] = true,
+ ["throttleInterval"] = 45,
+ ["scrollDownInterval"] = 15,
+ ["fade"] = true,
+ ["font"] = "PT Sans Narrow",
+ ["fontOutline"] = "NONE",
+ ["sticky"] = true,
+ ["keywordSound"] = "None",
+ ["whisperSound"] = "Whisper Alert",
+ ["noAlertInCombat"] = false,
+ ["chatHistory"] = true,
+ ["timeStampFormat"] = "NONE",
+ ["keywords"] = "ElvUI",
+ ["separateSizes"] = false,
+ ["panelWidth"] = 412,
+ ["panelHeight"] = 180,
+ ["panelWidthRight"] = 412,
+ ["panelHeightRight"] = 180,
+ ["panelBackdropNameLeft"] = "",
+ ["panelBackdropNameRight"] = "",
+ ["panelBackdrop"] = "SHOWBOTH",
+ ["panelTabBackdrop"] = false,
+ ["panelTabTransparency"] = false,
+ ["editBoxPosition"] = "BELOW_CHAT",
+ ["fadeUndockedTabs"] = true,
+ ["fadeTabsNoBackdrop"] = true,
+ ["useAltKey"] = false,
+ ["classColorMentionsChat"] = true,
+ ["numAllowedCombatRepeat"] = 5,
+ ["useCustomTimeColor"] = true,
+ ["customTimeColor"] = {r = 0.7, g = 0.7, b = 0.7},
+ ["numScrollMessages"] = 3,
+
+ ["tabFont"] = "PT Sans Narrow",
+ ["tabFontSize"] = 12,
+ ["tabFontOutline"] = "NONE",
+}
+
+--Datatexts
+P["datatexts"] = {
+ ["font"] = "PT Sans Narrow",
+ ["fontSize"] = 12,
+ ["fontOutline"] = "NONE",
+ ["wordWrap"] = false,
+
+ ["panels"] = {
+ ["LeftChatDataPanel"] = {
+ ["left"] = "Armor",
+ ["middle"] = "Durability",
+ ["right"] = "Avoidance",
+ },
+ ["RightChatDataPanel"] = {
+ ["left"] = "System",
+ ["middle"] = "Time",
+ ["right"] = "Gold",
+ },
+ ["LeftMiniPanel"] = "Guild",
+ ["RightMiniPanel"] = "Friends",
+ ["BottomMiniPanel"] = "",
+ ["TopMiniPanel"] = "",
+ ["BottomLeftMiniPanel"] = "",
+ ["BottomRightMiniPanel"] = "",
+ ["TopRightMiniPanel"] = "",
+ ["TopLeftMiniPanel"] = "",
+ },
+ ["battleground"] = true,
+ ["panelBackdrop"] = true,
+ ["panelTransparency"] = false,
+
+ --Datatext Options
+ --General
+ ["goldFormat"] = "BLIZZARD",
+ ["goldCoins"] = false,
+
+ --Time Datatext
+ ["timeFormat"] = "%I:%M",
+ ["dateFormat"] = "",
+
+ --Enabled/Disabled Panels
+ ["minimapPanels"] = true,
+ ["leftChatPanel"] = true,
+ ["rightChatPanel"] = true,
+ ["minimapTop"] = false,
+ ["minimapTopLeft"] = false,
+ ["minimapTopRight"] = false,
+ ["minimapBottom"] = false,
+ ["minimapBottomLeft"] = false,
+ ["minimapBottomRight"] = false,
+}
+
+--Tooltip
+P["tooltip"] = {
+ ["cursorAnchor"] = false,
+ ["targetInfo"] = true,
+ ["playerTitles"] = true,
+ ["guildRanks"] = true,
+ ["inspectInfo"] = true,
+ ["itemCount"] = "BAGS_ONLY",
+ ["spellID"] = true,
+ ["font"] = "PT Sans Narrow",
+ ["fontOutline"] = "NONE",
+ ["headerFontSize"] = 12,
+ ["textFontSize"] = 12,
+ ["smallTextFontSize"] = 12,
+ ["colorAlpha"] = 0.8,
+ ["visibility"] = {
+ ["unitFrames"] = "NONE",
+ ["bags"] = "NONE",
+ ["actionbars"] = "NONE",
+ ["combat"] = false
+ },
+ ["healthBar"] = {
+ ["text"] = true,
+ ["height"] = 7,
+ ["font"] = "Homespun",
+ ["fontSize"] = 10,
+ ["fontOutline"] = "OUTLINE",
+ ["statusPosition"] = "BOTTOM",
+ },
+ ["useCustomFactionColors"] = false,
+ ["factionColors"] = {
+ [1] = {r = 0.8, g = 0.3, b = 0.22},
+ [2] = {r = 0.8, g = 0.3, b = 0.22},
+ [3] = {r = 0.75, g = 0.27, b = 0},
+ [4] = {r = 0.9, g = 0.7, b = 0},
+ [5] = {r = 0, g = 0.6, b = 0.1},
+ [6] = {r = 0, g = 0.6, b = 0.1},
+ [7] = {r = 0, g = 0.6, b = 0.1},
+ [8] = {r = 0, g = 0.6, b = 0.1},
+ }
+}
+
+P["bags"] = {
+ ["sortInverted"] = true,
+ ["bagSize"] = 34,
+ ["bankSize"] = 34,
+ ["bagWidth"] = 406,
+ ["bankWidth"] = 406,
+ ["moneyFormat"] = "SMART",
+ ["moneyCoins"] = true,
+ ["ignoredItems"] = {},
+ ["itemLevel"] = true,
+ ["itemLevelThreshold"] = 1,
+ ["itemLevelFont"] = "Homespun",
+ ["itemLevelFontSize"] = 10,
+ ["itemLevelFontOutline"] = "MONOCHROMEOUTLINE",
+ ["countFont"] = "Homespun",
+ ["countFontSize"] = 10,
+ ["countFontOutline"] = "MONOCHROMEOUTLINE",
+ ["countFontColor"] = {r = 1, g = 1, b = 1},
+ ["clearSearchOnClose"] = false,
+ ["disableBagSort"] = false,
+ ["disableBankSort"] = false,
+ ["bagBar"] = {
+ ["growthDirection"] = "VERTICAL",
+ ["sortDirection"] = "ASCENDING",
+ ["size"] = 30,
+ ["spacing"] = 4,
+ ["backdropSpacing"] = 4,
+ ["showBackdrop"] = false,
+ ["mouseover"] = false
+ }
+};
+
+--UnitFrame
+P["unitframe"] = {
+ ["smoothbars"] = false,
+ ["smoothSpeed"] = 0.3,
+ ["statusbar"] = "ElvUI Norm",
+ ["font"] = "Homespun",
+ ["fontSize"] = 10,
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["OORAlpha"] = 0.35,
+ ["debuffHighlighting"] = "FILL",
+ ["targetOnMouseDown"] = false,
+ ["auraBlacklistModifier"] = "SHIFT",
+ ["thinBorders"] = false,
+ ["colors"] = {
+ ["borderColor"] = {r = 0, g = 0, b = 0},
+ ["healthclass"] = false,
+ ["forcehealthreaction"] = false,
+ ["powerclass"] = false,
+ ["colorhealthbyvalue"] = true,
+ ["customhealthbackdrop"] = false,
+ ["useDeadBackdrop"] = false,
+ ["classbackdrop"] = false,
+ ["auraBarByType"] = true,
+ ["auraBarTurtle"] = true,
+ ["auraBarTurtleColor"] = {r = 143/255, g = 101/255, b = 158/255},
+ ["transparentHealth"] = false,
+ ["transparentPower"] = false,
+ ["transparentCastbar"] = false,
+ ["transparentAurabars"] = false,
+ ["castColor"] = {r = .31,g = .31,b = .31},
+ ["castNoInterrupt"] = {r = 0.78, g = 0.25, b = 0.25},
+ ["castClassColor"] = false,
+ ["castReactionColor"] = false,
+
+
+ ["health"] = {r = .31,g = .31,b = .31},
+ ["health_backdrop"] = {r = .8,g = .01,b = .01},
+ ["health_backdrop_dead"] = {r = .8,g = .01,b = .01},
+ ["tapped"] = {r = 0.55, g = 0.57, b = 0.61},
+ ["disconnected"] = {r = 0.84, g = 0.75, b = 0.65},
+ ["auraBarBuff"] = {r = .31,g = .31,b = .31},
+ ["auraBarDebuff"] = {r = 0.8, g = 0.1, b = 0.1},
+ ["power"] = {
+ ["MANA"] = {r = 0.31, g = 0.45, b = 0.63},
+ ["RAGE"] = {r = 0.78, g = 0.25, b = 0.25},
+ ["FOCUS"] = {r = 0.71, g = 0.43, b = 0.27},
+ ["ENERGY"] = {r = 0.65, g = 0.63, b = 0.35},
+ ["RUNIC_POWER"] = {r = 0, g = 0.82, b = 1},
+ },
+ ["reaction"] = {
+ ["BAD"] = {r = 0.78, g = 0.25, b = 0.25},
+ ["NEUTRAL"] = {r = 218/255, g = 197/255, b = 92/255},
+ ["GOOD"] = {r = 75/255, g = 175/255, b = 76/255}
+ },
+ ["healPrediction"] = {
+ ["personal"] = {r = 0, g = 1, b = 0.5, a = 0.25},
+ ["others"] = {r = 0, g = 1, b = 0, a = 0.25},
+ ["maxOverflow"] = 0,
+ },
+ ["classResources"] = {
+ ["bgColor"] = {r = 0.1,g = 0.1,b = 0.1, a = 1},
+ ["comboPoints"] = {
+ [1] = {r = 0.69, g = 0.31, b = 0.31},
+ [2] = {r = 0.65, g = 0.63, b = 0.34},
+ [3] = {r = 0.33, g = 0.59, b = 0.33},
+ },
+ },
+ },
+
+ ["units"] = {
+ ["player"] = {
+ ["enable"] = true,
+ ["orientation"] = "LEFT",
+ ["width"] = 270,
+ ["height"] = 54,
+ ["lowmana"] = 30,
+ ["combatfade"] = false,
+ ["healPrediction"] = true,
+ ["restIcon"] = true,
+ ["combatIcon"] = true,
+ ["threatStyle"] = "GLOW",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:current-percent]",
+ ["position"] = "LEFT",
+ ["xOffset"] = 2,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "[powercolor][power:current]",
+ ["width"] = "fill",
+ ["height"] = 10,
+ ["offset"] = 0,
+ ["position"] = "RIGHT",
+ ["hideonnpc"] = false,
+ ["xOffset"] = -2,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ ["detachFromFrame"] = false,
+ ["detachedWidth"] = 250,
+ ["druidMana"] = true,
+ ["strataAndLevel"] = {
+ ["useCustomStrata"] = false,
+ ["frameStrata"] = "LOW",
+ ["useCustomLevel"] = false,
+ ["frameLevel"] = 1,
+ },
+ ["parent"] = "FRAME",
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 20,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["pvp"] = {
+ ["position"] = "BOTTOM",
+ ["text_format"] = "||cFFB04F4F[pvptimer][mouseover]||r",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["pvpIcon"] = {
+ ["enable"] = false,
+ ["anchorPoint"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["scale"] = 1,
+ },
+ ["portrait"] = {
+ ["enable"] = true,
+ ["width"] = 45,
+ ["overlay"] = true,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 8,
+ ["numrows"] = 1,
+ ["attachTo"] = "DEBUFFS",
+ ["anchorPoint"] = "TOPLEFT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "Blacklist,Personal,PlayerBuffs,Whitelist,blockNoDuration,nonPersonal", --Player Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 8,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "TOPLEFT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "Blacklist,Personal,nonPersonal", --Player Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["castbar"] = {
+ ["enable"] = true,
+ ["width"] = 270,
+ ["height"] = 18,
+ ["icon"] = true,
+ ["latency"] = true,
+ ["format"] = "REMAINING",
+ ["ticks"] = true,
+ ["spark"] = true,
+ ["displayTarget"] = false,
+ ["iconSize"] = 42,
+ ["iconAttached"] = true,
+ ["insideInfoPanel"] = true,
+ ["iconAttachedTo"] = "Frame",
+ ["iconPosition"] = "LEFT",
+ ["iconXOffset"] = -10,
+ ["iconYOffset"] = 0,
+ ["tickWidth"] = 1,
+ ["tickColor"] = {r = 0, g = 0, b = 0, a = 0.8},
+ },
+ ["classbar"] = {
+ ["enable"] = true,
+ ["fill"] = "fill",
+ ["height"] = 10,
+ ["detachFromFrame"] = false,
+ ["detachedWidth"] = 250,
+ ["autoHide"] = false,
+ ["parent"] = "FRAME",
+ ["verticalOrientation"] = false,
+ ["additionalPowerText"] = true,
+ ["strataAndLevel"] = {
+ ["useCustomStrata"] = false,
+ ["frameStrata"] = "LOW",
+ ["useCustomLevel"] = false,
+ ["frameLevel"] = 1,
+ },
+ },
+ ["aurabar"] = {
+ ["enable"] = true,
+ ["anchorPoint"] = "ABOVE",
+ ["attachTo"] = "DEBUFFS",
+ ["maxBars"] = 6,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 120,
+ ["priority"] = "Blacklist,blockNoDuration,Personal,RaidDebuffs,PlayerBuffs", --Player AuraBars
+ ["friendlyAuraType"] = "HELPFUL",
+ ["enemyAuraType"] = "HARMFUL",
+ ["height"] = 20,
+ ["sort"] = "TIME_REMAINING",
+ ["uniformThreshold"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ },
+ ["target"] = {
+ ["enable"] = true,
+ ["width"] = 270,
+ ["height"] = 54,
+ ["orientation"] = "RIGHT",
+ ["threatStyle"] = "GLOW",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["rangeCheck"] = true,
+ ["healPrediction"] = true,
+ ["middleClickFocus"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:current-percent]",
+ ["position"] = "RIGHT",
+ ["xOffset"] = -2,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "[powercolor][power:current]",
+ ["width"] = "fill",
+ ["height"] = 10,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["xOffset"] = 2,
+ ["yOffset"] = 0,
+ ["detachFromFrame"] = false,
+ ["detachedWidth"] = 250,
+ ["attachTextTo"] = "Health",
+ ["strataAndLevel"] = {
+ ["useCustomStrata"] = false,
+ ["frameStrata"] = "LOW",
+ ["useCustomLevel"] = false,
+ ["frameLevel"] = 1,
+ },
+ ["parent"] = "FRAME",
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 20,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium] [difficultycolor][smartlevel] [shortclassification]",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["pvpIcon"] = {
+ ["enable"] = false,
+ ["anchorPoint"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["scale"] = 1,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 8,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "TOPRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,nonPersonal", --Target Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 8,
+ ["numrows"] = 1,
+ ["attachTo"] = "BUFFS",
+ ["anchorPoint"] = "TOPRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,RaidDebuffs,CCDebuffs,Friendly:Dispellable", --Target Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["castbar"] = {
+ ["enable"] = true,
+ ["width"] = 270,
+ ["height"] = 18,
+ ["icon"] = true,
+ ["format"] = "REMAINING",
+ ["spark"] = true,
+ ["iconSize"] = 42,
+ ["iconAttached"] = true,
+ ["insideInfoPanel"] = true,
+ ["iconAttachedTo"] = "Frame",
+ ["iconPosition"] = "LEFT",
+ ["iconXOffset"] = -10,
+ ["iconYOffset"] = 0,
+ },
+ ["combobar"] = {
+ ["enable"] = true,
+ ["fill"] = "fill",
+ ["height"] = 10,
+ ["detachFromFrame"] = false,
+ ["detachedWidth"] = 250,
+ ["autoHide"] = true
+ },
+ ["aurabar"] = {
+ ["enable"] = true,
+ ["anchorPoint"] = "ABOVE",
+ ["attachTo"] = "DEBUFFS",
+ ["maxBars"] = 6,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 120,
+ ["priority"] = "Blacklist,Personal,blockNoDuration,PlayerBuffs,RaidDebuffs", --Target AuraBars
+ ["friendlyAuraType"] = "HELPFUL",
+ ["enemyAuraType"] = "HARMFUL",
+ ["height"] = 20,
+ ["sort"] = "TIME_REMAINING",
+ ["uniformThreshold"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ ["GPSArrow"] = {
+ ["enable"] = false,
+ ["size"] = 45,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["onMouseOver"] = true,
+ ["outOfRange"] = true,
+ },
+ },
+ ["targettarget"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "NONE",
+ ["orientation"] = "MIDDLE",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 130,
+ ["height"] = 36,
+ ["health"] = {
+ ["text_format"] = "",
+ ["position"] = "RIGHT",
+ ["xOffset"] = -2,
+ ["yOffset"] = 0,
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["xOffset"] = 2,
+ ["yOffset"] = 0,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 14,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 7,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMLEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,PlayerBuffs,Dispellable", --TargetTarget Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 5,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,RaidDebuffs,CCDebuffs,Dispellable,Whitelist", --TargetTarget Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ },
+ ["targettargettarget"] = {
+ ["enable"] = false,
+ ["rangeCheck"] = true,
+ ["orientation"] = "MIDDLE",
+ ["threatStyle"] = "NONE",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 130,
+ ["height"] = 36,
+ ["health"] = {
+ ["text_format"] = "",
+ ["position"] = "RIGHT",
+ ["xOffset"] = -2,
+ ["yOffset"] = 0,
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["xOffset"] = 2,
+ ["yOffset"] = 0,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 12,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 7,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMLEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,nonPersonal", --TargetTargetTarget Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 5,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,nonPersonal", --TargetTargetTarget Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ },
+ ["focus"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "GLOW",
+ ["orientation"] = "MIDDLE",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 190,
+ ["height"] = 36,
+ ["healPrediction"] = true,
+ ["health"] = {
+ ["text_format"] = "",
+ ["position"] = "RIGHT",
+ ["xOffset"] = -2,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["xOffset"] = 2,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 14,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 7,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMLEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,PlayerBuffs,CastByUnit,Dispellable", --Focus Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 5,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "TOPRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,RaidDebuffs,Dispellable,Whitelist", --Focus Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["castbar"] = {
+ ["enable"] = true,
+ ["width"] = 190,
+ ["height"] = 18,
+ ["icon"] = true,
+ ["format"] = "REMAINING",
+ ["spark"] = true,
+ ["iconSize"] = 32,
+ ["iconAttached"] = true,
+ ["insideInfoPanel"] = true,
+ ["iconAttachedTo"] = "Frame",
+ ["iconPosition"] = "LEFT",
+ ["iconXOffset"] = -10,
+ ["iconYOffset"] = 0,
+ },
+ ["aurabar"] = {
+ ["enable"] = false,
+ ["anchorPoint"] = "ABOVE",
+ ["attachTo"] = "DEBUFFS",
+ ["maxBars"] = 3,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 120,
+ ["priority"] = "Blacklist,blockNoDuration,Personal,PlayerBuffs,RaidDebuffs", --Focus AuraBars
+ ["friendlyAuraType"] = "HELPFUL",
+ ["enemyAuraType"] = "HARMFUL",
+ ["height"] = 20,
+ ["sort"] = "TIME_REMAINING",
+ ["uniformThreshold"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ ["GPSArrow"] = {
+ ["enable"] = true,
+ ["size"] = 45,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["onMouseOver"] = true,
+ ["outOfRange"] = true,
+ },
+ },
+ ["focustarget"] = {
+ ["enable"] = false,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "NONE",
+ ["orientation"] = "MIDDLE",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 190,
+ ["height"] = 26,
+ ["health"] = {
+ ["text_format"] = "",
+ ["position"] = "RIGHT",
+ ["xOffset"] = -2,
+ ["yOffset"] = 0,
+ },
+ ["power"] = {
+ ["enable"] = false,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["xOffset"] = 2,
+ ["yOffset"] = 0,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 12,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 7,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMLEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,PlayerBuffs,Dispellable,CastByUnit", --FocusTarget Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 5,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,RaidDebuffs,Dispellable,Whitelist", --FocusTarget Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ },
+ ["pet"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["orientation"] = "MIDDLE",
+ ["threatStyle"] = "GLOW",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 130,
+ ["height"] = 36,
+ ["healPrediction"] = true,
+ ["health"] = {
+ ["text_format"] = "",
+ ["position"] = "RIGHT",
+ ["yOffset"] = 0,
+ ["xOffset"] = -2,
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 0,
+ ["xOffset"] = 2,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 12,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 7,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMLEFT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,PlayerBuffs", --Pet Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 5,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMRIGHT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,RaidDebuffs,Dispellable,Whitelist", --Pet Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ },
+ ["castbar"] = {
+ ["enable"] = true,
+ ["width"] = 130,
+ ["height"] = 18,
+ ["icon"] = true,
+ ["format"] = "REMAINING",
+ ["spark"] = true,
+ ["iconSize"] = 26,
+ ["iconAttached"] = true,
+ ["insideInfoPanel"] = true,
+ ["iconAttachedTo"] = "Frame",
+ ["iconPosition"] = "LEFT",
+ ["iconXOffset"] = -10,
+ ["iconYOffset"] = 0,
+ },
+ },
+ ["pettarget"] = {
+ ["enable"] = false,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "NONE",
+ ["orientation"] = "MIDDLE",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 130,
+ ["height"] = 26,
+ ["health"] = {
+ ["text_format"] = "",
+ ["position"] = "RIGHT",
+ ["yOffset"] = 0,
+ ["xOffset"] = -2,
+ },
+ ["power"] = {
+ ["enable"] = false,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "LEFT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 0,
+ ["xOffset"] = 2,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 12,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 7,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMLEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,PlayerBuffs,CastByUnit,Whitelist", --PetTarget Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 5,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "BOTTOMRIGHT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,Personal,RaidDebuffs", --PetTarget Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ },
+ ["boss"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["growthDirection"] = "DOWN",
+ ["orientation"] = "RIGHT",
+ ["smartAuraPosition"] = "DISABLED",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 216,
+ ["height"] = 46,
+ ["spacing"] = 25,
+ ["targetGlow"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:current]",
+ ["position"] = "LEFT",
+ ["yOffset"] = 0,
+ ["xOffset"] = 2,
+ ["attachTextTo"] = "Health",
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "[powercolor][power:current]",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "RIGHT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 0,
+ ["xOffset"] = -2,
+ ["attachTextTo"] = "Health",
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 35,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 16,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "Blacklist,CastByUnit,Whitelist", --Boss Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 20,
+ ["sizeOverride"] = 22,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 3,
+ ["numrows"] = 2,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "Blacklist,Personal,RaidDebuffs,CastByUnit,Whitelist", --Boss Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = -3,
+ ["sizeOverride"] = 22,
+ },
+ ["castbar"] = {
+ ["enable"] = true,
+ ["width"] = 215,
+ ["height"] = 18,
+ ["icon"] = true,
+ ["format"] = "REMAINING",
+ ["spark"] = true,
+ ["iconSize"] = 32,
+ ["iconAttached"] = true,
+ ["insideInfoPanel"] = true,
+ ["iconAttachedTo"] = "Frame",
+ ["iconPosition"] = "LEFT",
+ ["iconXOffset"] = -10,
+ ["iconYOffset"] = 0,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ },
+ ["arena"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["growthDirection"] = "DOWN",
+ ["orientation"] = "RIGHT",
+ ["smartAuraPosition"] = "DISABLED",
+ ["spacing"] = 25,
+ ["width"] = 246,
+ ["height"] = 47,
+ ["healPrediction"] = true,
+ ["colorOverride"] = "USE_DEFAULT",
+ ["targetGlow"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:current]",
+ ["position"] = "LEFT",
+ ["yOffset"] = 0,
+ ["xOffset"] = 2,
+ ["attachTextTo"] = "Health",
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "[powercolor][power:current]",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["attachTextTo"] = "Health",
+ ["position"] = "RIGHT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 0,
+ ["xOffset"] = -2,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 17,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:medium]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,TurtleBuffs,PlayerBuffs,Dispellable", --Arena Buffs
+ ["sizeOverride"] = 27,
+ ["xOffset"] = 0,
+ ["yOffset"] = 16,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["clickThrough"] = false,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,blockNoDuration,Personal,CCDebuffs,Whitelist", --Arena Debuffs
+ ["sizeOverride"] = 27,
+ ["xOffset"] = 0,
+ ["yOffset"] = -16,
+ },
+ ["castbar"] = {
+ ["enable"] = true,
+ ["width"] = 256,
+ ["height"] = 18,
+ ["icon"] = true,
+ ["format"] = "REMAINING",
+ ["spark"] = true,
+ ["iconSize"] = 32,
+ ["iconAttached"] = true,
+ ["insideInfoPanel"] = true,
+ ["iconAttachedTo"] = "Frame",
+ ["iconPosition"] = "LEFT",
+ ["iconXOffset"] = -10,
+ ["iconYOffset"] = 0,
+ },
+ ["pvpTrinket"] = {
+ ["enable"] = true,
+ ["position"] = "RIGHT",
+ ["size"] = 46,
+ ["xOffset"] = 1,
+ ["yOffset"] = 0,
+ },
+ },
+ ["party"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "GLOW",
+ ["orientation"] = "LEFT",
+ ["visibility"] = "[@raid6,exists][nogroup] hide;show",
+ ["growthDirection"] = "UP_RIGHT",
+ ["horizontalSpacing"] = 0,
+ ["verticalSpacing"] = 3,
+ ["numGroups"] = 1,
+ ["groupsPerRowCol"] = 1,
+ ["groupBy"] = "GROUP",
+ ["sortDir"] = "ASC",
+ ["raidWideSorting"] = false,
+ ["invertGroupingOrder"] = false,
+ ["startFromCenter"] = false,
+ ["showPlayer"] = true,
+ ["healPrediction"] = false,
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 184,
+ ["height"] = 54,
+ ["targetGlow"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:current-percent]",
+ ["position"] = "LEFT",
+ ["orientation"] = "HORIZONTAL",
+ ["attachTextTo"] = "Health",
+ ["frequentUpdates"] = false,
+ ["yOffset"] = 0,
+ ["xOffset"] = 2,
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "[powercolor][power:current]",
+ ["attachTextTo"] = "Health",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "RIGHT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 0,
+ ["xOffset"] = -2,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 15,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["attachTextTo"] = "Health",
+ ["text_format"] = "[namecolor][name:medium] [difficultycolor][smartlevel]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 4,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["countFontSize"] = 10,
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,TurtleBuffs", --Party Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = true,
+ ["perrow"] = 4,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "RIGHT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,RaidDebuffs,CCDebuffs,Dispellable,Whitelist", --Party Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["sizeOverride"] = 52,
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ ["profileSpecific"] = false,
+ },
+ ["rdebuffs"] = {
+ ["enable"] = false,
+ ["showDispellableDebuff"] = true,
+ ["onlyMatchSpellID"] = true,
+ ["fontSize"] = 10,
+ ["font"] = "Homespun",
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["size"] = 26,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["duration"] = {
+ ["position"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ ["stack"] = {
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ },
+ ["roleIcon"] = {
+ ["enable"] = true,
+ ["position"] = "TOPRIGHT",
+ ["attachTo"] = "Health",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["size"] = 15,
+ },
+ ["raidRoleIcons"] = {
+ ["enable"] = true,
+ ["position"] = "TOPLEFT",
+ },
+ ["petsGroup"] = {
+ ["enable"] = false,
+ ["width"] = 100,
+ ["height"] = 22,
+ ["anchorPoint"] = "TOPLEFT",
+ ["xOffset"] = -1,
+ ["yOffset"] = 0,
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:short]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ },
+ ["targetsGroup"] = {
+ ["enable"] = false,
+ ["width"] = 100,
+ ["height"] = 22,
+ ["anchorPoint"] = "TOPLEFT",
+ ["xOffset"] = -1,
+ ["yOffset"] = 0,
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:short]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ ["GPSArrow"] = {
+ ["enable"] = true,
+ ["size"] = 45,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["onMouseOver"] = true,
+ ["outOfRange"] = true,
+ },
+ ["readycheckIcon"] = {
+ ["enable"] = true,
+ ["size"] = 12,
+ ["attachTo"] = "Health",
+ ["position"] = "BOTTOM",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ },
+ },
+ ["raid"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "GLOW",
+ ["orientation"] = "MIDDLE",
+ ["visibility"] = "[@raid6,noexists][@raid26,exists] hide;show",
+ ["growthDirection"] = "RIGHT_DOWN",
+ ["horizontalSpacing"] = 3,
+ ["verticalSpacing"] = 3,
+ ["numGroups"] = 5,
+ ["groupsPerRowCol"] = 1,
+ ["groupBy"] = "GROUP",
+ ["sortDir"] = "ASC",
+ ["showPlayer"] = true,
+ ["healPrediction"] = false,
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 80,
+ ["height"] = 44,
+ ["targetGlow"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:deficit]",
+ ["position"] = "BOTTOM",
+ ["orientation"] = "HORIZONTAL",
+ ["attachTextTo"] = "Health",
+ ["frequentUpdates"] = false,
+ ["yOffset"] = 2,
+ ["xOffset"] = 0,
+ },
+ ["power"] = {
+ ["enable"] = true,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "BOTTOMRIGHT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 2,
+ ["xOffset"] = -2,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 12,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["attachTextTo"] = "Health",
+ ["text_format"] = "[namecolor][name:short]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,TurtleBuffs", --Raid Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "RIGHT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,RaidDebuffs,CCDebuffs,Dispellable", --Raid Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ ["profileSpecific"] = false,
+ },
+ ["rdebuffs"] = {
+ ["enable"] = true,
+ ["showDispellableDebuff"] = true,
+ ["onlyMatchSpellID"] = true,
+ ["fontSize"] = 10,
+ ["font"] = "Homespun",
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["size"] = 26,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["duration"] = {
+ ["position"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ ["stack"] = {
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ },
+ ["roleIcon"] = {
+ ["enable"] = true,
+ ["position"] = "TOPLEFT",
+ ["attachTo"] = "Health",
+ ["xOffset"] = 1,
+ ["yOffset"] = -1,
+ ["size"] = 15,
+ },
+ ["raidRoleIcons"] = {
+ ["enable"] = true,
+ ["position"] = "TOPLEFT",
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ ["GPSArrow"] = {
+ ["enable"] = true,
+ ["size"] = 40,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["onMouseOver"] = true,
+ ["outOfRange"] = true,
+ },
+ ["readycheckIcon"] = {
+ ["enable"] = true,
+ ["size"] = 12,
+ ["attachTo"] = "Health",
+ ["position"] = "BOTTOM",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ },
+ },
+ ["raid40"] = {
+ ["enable"] = true,
+ ["rangeCheck"] = true,
+ ["threatStyle"] = "GLOW",
+ ["orientation"] = "MIDDLE",
+ ["visibility"] = "[@raid26,noexists] hide;show",
+ ["growthDirection"] = "RIGHT_DOWN",
+ ["horizontalSpacing"] = 3,
+ ["verticalSpacing"] = 3,
+ ["numGroups"] = 8,
+ ["groupsPerRowCol"] = 1,
+ ["groupBy"] = "GROUP",
+ ["sortDir"] = "ASC",
+ ["showPlayer"] = true,
+ ["healPrediction"] = false,
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 80,
+ ["height"] = 27,
+ ["targetGlow"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:deficit]",
+ ["position"] = "BOTTOM",
+ ["orientation"] = "HORIZONTAL",
+ ["frequentUpdates"] = false,
+ ["attachTextTo"] = "Health",
+ ["yOffset"] = 2,
+ ["xOffset"] = 0,
+ },
+ ["power"] = {
+ ["enable"] = false,
+ ["text_format"] = "",
+ ["width"] = "fill",
+ ["height"] = 7,
+ ["offset"] = 0,
+ ["position"] = "BOTTOMRIGHT",
+ ["hideonnpc"] = false,
+ ["yOffset"] = 2,
+ ["xOffset"] = -2,
+ },
+ ["infoPanel"] = {
+ ["enable"] = false,
+ ["height"] = 12,
+ ["transparent"] = false,
+ },
+ ["name"] = {
+ ["position"] = "CENTER",
+ ["text_format"] = "[namecolor][name:short]",
+ ["yOffset"] = 0,
+ ["xOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,TurtleBuffs", --Raid40 Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "RIGHT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 300,
+ ["priority"] = "Blacklist,RaidDebuffs,CCDebuffs,Dispellable,Whitelist", --Raid40 Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["rdebuffs"] = {
+ ["enable"] = false,
+ ["showDispellableDebuff"] = true,
+ ["onlyMatchSpellID"] = true,
+ ["fontSize"] = 10,
+ ["font"] = "Homespun",
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["size"] = 22,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["duration"] = {
+ ["position"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ ["stack"] = {
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ },
+ ["roleIcon"] = {
+ ["enable"] = false,
+ ["position"] = "BOTTOMRIGHT",
+ ["attachTo"] = "Health",
+ ["xOffset"] = -1,
+ ["yOffset"] = 1,
+ ["size"] = 15,
+ },
+ ["raidRoleIcons"] = {
+ ["enable"] = true,
+ ["position"] = "TOPLEFT",
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ ["profileSpecific"] = false,
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ ["GPSArrow"] = {
+ ["enable"] = true,
+ ["size"] = 45,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["onMouseOver"] = true,
+ ["outOfRange"] = true,
+ },
+ ["readycheckIcon"] = {
+ ["enable"] = true,
+ ["size"] = 12,
+ ["attachTo"] = "Health",
+ ["position"] = "BOTTOM",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ },
+ },
+ ["raidpet"] = {
+ ["enable"] = false,
+ ["rangeCheck"] = true,
+ ["orientation"] = "MIDDLE",
+ ["threatStyle"] = "GLOW",
+ ["visibility"] = "[group:raid] show; hide",
+ ["growthDirection"] = "DOWN_RIGHT",
+ ["horizontalSpacing"] = 3,
+ ["verticalSpacing"] = 3,
+ ["numGroups"] = 2,
+ ["groupsPerRowCol"] = 1,
+ ["groupBy"] = "PETNAME",
+ ["sortDir"] = "ASC",
+ ["raidWideSorting"] = true,
+ ["invertGroupingOrder"] = false,
+ ["startFromCenter"] = false,
+ ["healPrediction"] = true,
+ ["colorOverride"] = "USE_DEFAULT",
+ ["width"] = 80,
+ ["height"] = 30,
+ ["targetGlow"] = true,
+ ["health"] = {
+ ["text_format"] = "[healthcolor][health:deficit]",
+ ["position"] = "BOTTOM",
+ ["orientation"] = "HORIZONTAL",
+ ["frequentUpdates"] = true,
+ ["yOffset"] = 2,
+ ["xOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["name"] = {
+ ["position"] = "TOP",
+ ["text_format"] = "[namecolor][name:short]",
+ ["yOffset"] = -2,
+ ["xOffset"] = 0,
+ ["attachTextTo"] = "Health",
+ },
+ ["portrait"] = {
+ ["enable"] = false,
+ ["width"] = 45,
+ ["overlay"] = false,
+ ["style"] = "3D",
+ },
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "LEFT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "Blacklist,Personal,PlayerBuffs,blockNoDuration,nonPersonal", --RaidPet Buffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 3,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "RIGHT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "Blacklist,Personal,Whitelist,RaidDebuffs,blockNoDuration,nonPersonal", --RaidPet Debuffs
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ },
+ ["rdebuffs"] = {
+ ["enable"] = true,
+ ["showDispellableDebuff"] = true,
+ ["onlyMatchSpellID"] = true,
+ ["fontSize"] = 10,
+ ["font"] = "Homespun",
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["size"] = 26,
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["duration"] = {
+ ["position"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ ["stack"] = {
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ },
+ ["raidicon"] = {
+ ["enable"] = true,
+ ["size"] = 18,
+ ["attachTo"] = "TOP",
+ ["attachToObject"] = "Frame",
+ ["xOffset"] = 0,
+ ["yOffset"] = 8,
+ },
+ },
+ ["tank"] = {
+ ["enable"] = true,
+ ["orientation"] = "LEFT",
+ ["threatStyle"] = "GLOW",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["rangeCheck"] = true,
+ ["width"] = 120,
+ ["height"] = 28,
+ ["disableDebuffHighlight"] = true,
+ ["verticalSpacing"] = 7,
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 6,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "TOPLEFT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 6,
+ ["numrows"] = 1,
+ ["attachTo"] = "BUFFS",
+ ["anchorPoint"] = "TOPRIGHT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "",
+ ["xOffset"] = 0,
+ ["yOffset"] = 1,
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ ["profileSpecific"] = false,
+ },
+ ["rdebuffs"] = {
+ ["enable"] = true,
+ ["showDispellableDebuff"] = true,
+ ["onlyMatchSpellID"] = true,
+ ["fontSize"] = 10,
+ ["font"] = "Homespun",
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["size"] = 26,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["duration"] = {
+ ["position"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ ["stack"] = {
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ },
+ ["targetsGroup"] = {
+ ["enable"] = true,
+ ["anchorPoint"] = "RIGHT",
+ ["xOffset"] = 1,
+ ["yOffset"] = 0,
+ ["width"] = 120,
+ ["height"] = 28,
+ ["colorOverride"] = "USE_DEFAULT",
+ },
+ },
+ ["assist"] = {
+ ["enable"] = true,
+ ["orientation"] = "LEFT",
+ ["threatStyle"] = "GLOW",
+ ["colorOverride"] = "USE_DEFAULT",
+ ["rangeCheck"] = true,
+ ["width"] = 120,
+ ["height"] = 28,
+ ["disableDebuffHighlight"] = true,
+ ["verticalSpacing"] = 7,
+ ["buffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 6,
+ ["numrows"] = 1,
+ ["attachTo"] = "FRAME",
+ ["anchorPoint"] = "TOPLEFT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ },
+ ["debuffs"] = {
+ ["enable"] = false,
+ ["perrow"] = 6,
+ ["numrows"] = 1,
+ ["attachTo"] = "BUFFS",
+ ["anchorPoint"] = "TOPRIGHT",
+ ["fontSize"] = 10,
+ ["countFontSize"] = 10,
+ ["sortMethod"] = "TIME_REMAINING",
+ ["sortDirection"] = "DESCENDING",
+ ["clickThrough"] = false,
+ ["minDuration"] = 0,
+ ["maxDuration"] = 0,
+ ["priority"] = "",
+ ["xOffset"] = 0,
+ ["yOffset"] = 1,
+ },
+ ["buffIndicator"] = {
+ ["enable"] = true,
+ ["size"] = 8,
+ ["fontSize"] = 10,
+ ["profileSpecific"] = false,
+ },
+ ["rdebuffs"] = {
+ ["enable"] = true,
+ ["showDispellableDebuff"] = true,
+ ["onlyMatchSpellID"] = true,
+ ["fontSize"] = 10,
+ ["font"] = "Homespun",
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["size"] = 26,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["duration"] = {
+ ["position"] = "CENTER",
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ ["stack"] = {
+ ["position"] = "BOTTOMRIGHT",
+ ["xOffset"] = 0,
+ ["yOffset"] = 2,
+ ["color"] = {r = 1, g = 0.9, b = 0, a = 1}
+ },
+ },
+ ["targetsGroup"] = {
+ ["enable"] = true,
+ ["anchorPoint"] = "RIGHT",
+ ["xOffset"] = 1,
+ ["yOffset"] = 0,
+ ["width"] = 120,
+ ["height"] = 28,
+ ["colorOverride"] = "USE_DEFAULT",
+ },
+ },
+ },
+}
+
+P["cooldown"] = {
+ threshold = 3,
+ expiringColor = {r = 1, g = 0, b = 0},
+ secondsColor = {r = 1, g = 1, b = 0},
+ minutesColor = {r = 1, g = 1, b = 1},
+ hoursColor = {r = 0.4, g = 1, b = 1},
+ daysColor = {r = 0.4, g = 0.4, b = 1},
+}
+
+--Actionbar
+P["actionbar"] = {
+ ["font"] = "Homespun",
+ ["fontSize"] = 10,
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["fontColor"] = {r = 1, g = 1, b = 1},
+
+ ["macrotext"] = false,
+ ["hotkeytext"] = true,
+
+ ["noRangeColor"] = {r = 0.8, g = 0.1, b = 0.1},
+ ["noPowerColor"] = {r = 0.5, g = 0.5, b = 1},
+ ["usableColor"] = {r = 1, g = 1, b = 1},
+ ["notUsableColor"] = {r = 0.4, g = 0.4, b = 0.4},
+
+ ["keyDown"] = true,
+ ["movementModifier"] = "SHIFT",
+
+ ["microbar"] = {
+ ["enabled"] = false,
+ ["Scale"] = 1,
+ ["xOffset"] = 1,
+ ["yOffset"] = 1,
+ ["buttonsPerRow"] = 10,
+ ["alpha"] = 1,
+ ["mouseover"] = false
+ },
+
+ ["globalFadeAlpha"] = 0,
+ ["lockActionBars"] = true,
+
+ ["bar1"] = {
+ ["enabled"] = true,
+ ["buttons"] = 12,
+ ["mouseover"] = false,
+ ["buttonsPerRow"] = 12,
+ ["point"] = "BOTTOMLEFT",
+ ["backdrop"] = false,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ ["showGrid"] = true,
+ },
+ ["bar2"] = {
+ ["enabled"] = false,
+ ["mouseover"] = false,
+ ["buttons"] = 12,
+ ["buttonsPerRow"] = 12,
+ ["point"] = "BOTTOMLEFT",
+ ["backdrop"] = false,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ ["showGrid"] = true,
+ },
+ ["bar3"] = {
+ ["enabled"] = true,
+ ["mouseover"] = false,
+ ["buttons"] = 6,
+ ["buttonsPerRow"] = 6,
+ ["point"] = "BOTTOMLEFT",
+ ["backdrop"] = false,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ ["showGrid"] = true,
+ },
+ ["bar4"] = {
+ ["enabled"] = true,
+ ["mouseover"] = false,
+ ["buttons"] = 12,
+ ["buttonsPerRow"] = 1,
+ ["point"] = "TOPRIGHT",
+ ["backdrop"] = true,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ ["showGrid"] = true,
+ },
+ ["bar5"] = {
+ ["enabled"] = true,
+ ["mouseover"] = false,
+ ["buttons"] = 6,
+ ["buttonsPerRow"] = 6,
+ ["point"] = "BOTTOMLEFT",
+ ["backdrop"] = false,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ ["showGrid"] = true,
+ },
+ ["bar6"] = {
+ ["enabled"] = true,
+ ["mouseover"] = false,
+ ["buttons"] = 12,
+ ["buttonsPerRow"] = 12,
+ ["point"] = "BOTTOMLEFT",
+ ["backdrop"] = false,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ ["showGrid"] = true,
+ },
+ ["barPet"] = {
+ ["enabled"] = true,
+ ["mouseover"] = false,
+ ["buttons"] = NUM_PET_ACTION_SLOTS,
+ ["buttonsPerRow"] = 1,
+ ["point"] = "TOPRIGHT",
+ ["backdrop"] = true,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ },
+ ["barShapeShift"] = {
+ ["enabled"] = true,
+ ["style"] = "darkenInactive",
+ ["mouseover"] = false,
+ ["buttonsPerRow"] = NUM_SHAPESHIFT_SLOTS,
+ ["buttons"] = NUM_SHAPESHIFT_SLOTS,
+ ["point"] = "TOPLEFT",
+ ["backdrop"] = false,
+ ["heightMult"] = 1,
+ ["widthMult"] = 1,
+ ["buttonsize"] = 32,
+ ["buttonspacing"] = 2,
+ ["backdropSpacing"] = 2,
+ ["alpha"] = 1,
+ },
+}
\ No newline at end of file
diff --git a/ElvUI_Config/ActionBars.lua b/ElvUI_Config/ActionBars.lua
new file mode 100644
index 0000000..c73c06c
--- /dev/null
+++ b/ElvUI_Config/ActionBars.lua
@@ -0,0 +1,453 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local AB = E:GetModule("ActionBars");
+local ACD = LibStub("AceConfigDialog-3.0");
+local group
+
+--Cache global variables
+--Lua functions
+local _G = _G
+local getn = table.getn
+--WoW API / Variables
+local SetCVar = SetCVar
+local GameTooltip = _G["GameTooltip"]
+local NONE, COLOR = NONE, COLOR
+local LOCK_ACTIONBAR_TEXT = LOCK_ACTIONBAR_TEXT
+
+local points = {
+ ["TOPLEFT"] = "TOPLEFT",
+ ["TOPRIGHT"] = "TOPRIGHT",
+ ["BOTTOMLEFT"] = "BOTTOMLEFT",
+ ["BOTTOMRIGHT"] = "BOTTOMRIGHT"
+}
+
+local function BuildABConfig()
+ group["general"] = {
+ order = 1,
+ type = "group",
+ name = L["General Options"],
+ disabled = function() return not E.private.actionbar.enable end,
+ args = {
+ info = {
+ order = 1,
+ type = "header",
+ name = L["General Options"]
+ },
+ toggleKeybind = {
+ order = 2,
+ type = "execute",
+ name = L["Keybind Mode"],
+ func = function()
+ AB:ActivateBindMode()
+ E:ToggleConfig()
+ GameTooltip:Hide()
+ end
+ },
+ cooldownText = {
+ order = 3,
+ type = "execute",
+ name = L["Cooldown Text"],
+ func = function() ACD:SelectGroup("ElvUI", "general", "cooldown") end
+ },
+ spacer = {
+ order = 4,
+ type = "description",
+ name = ""
+ },
+ macrotext = {
+ order = 5,
+ type = "toggle",
+ name = L["Macro Text"],
+ desc = L["Display macro names on action buttons."]
+ },
+ hotkeytext = {
+ order = 6,
+ type = "toggle",
+ name = L["Keybind Text"],
+ desc = L["Display bind names on action buttons."]
+ },
+ keyDown = {
+ order = 8,
+ type = "toggle",
+ name = L["Key Down"],
+ desc = "OPTION_TOOLTIP_ACTION_BUTTON_USE_KEY_DOWN"
+ },
+ lockActionBars = {
+ order = 9,
+ type = "toggle",
+ name = LOCK_ACTIONBAR_TEXT,
+ desc = L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."],
+ set = function(info, value)
+ E.db.actionbar[ info[getn(info)] ] = value
+ AB:UpdateButtonSettings()
+ SetCVar("lockActionBars", (value == true and 1 or 0))
+ LOCK_ACTIONBAR = (value == true and "1" or "0")
+ end
+ },
+ movementModifier = {
+ order = 10,
+ type = "select",
+ name = L["Pick Up Action Key"],
+ desc = L["The button you must hold down in order to drag an ability to another action button."],
+ disabled = function() return (not E.private.actionbar.enable or not E.db.actionbar.lockActionBars) end,
+ values = {
+ ["NONE"] = NONE,
+ ["SHIFT"] = "SHIFT_KEY",
+ ["ALT"] = "ALT_KEY",
+ ["CTRL"] = "CTRL_KEY"
+ }
+ },
+ globalFadeAlpha = {
+ order = 11,
+ type = "range",
+ name = L["Global Fade Transparency"],
+ desc = L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."],
+ min = 0, max = 1, step = 0.01,
+ isPercent = true,
+ set = function(info, value) E.db.actionbar[ info[getn(info)] ] = value AB.fadeParent:SetAlpha(1-value) end
+ },
+ colorGroup = {
+ order = 12,
+ type = "group",
+ name = L["Colors"],
+ guiInline = true,
+ get = function(info)
+ local t = E.db.actionbar[ info[getn(info)] ]
+ local d = P.actionbar[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.actionbar[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+
+ tullaRange:LoadDefaults()
+ tullaRange.colors = TULLARANGE_COLORS
+ for button in pairs(tullaRange.buttonsToUpdate) do
+ button.tullaRangeColor = nil
+ tullaRange.UpdateButtonUsable(button)
+ end
+ end,
+ args = {
+ noRangeColor = {
+ order = 1,
+ type = "color",
+ name = L["Out of Range"],
+ desc = L["Color of the actionbutton when out of range."]
+ },
+ noPowerColor = {
+ order = 2,
+ type = "color",
+ name = L["Out of Power"],
+ desc = L["Color of the actionbutton when out of power (Mana, Rage, Focus, Holy Power)."]
+ },
+ usableColor = {
+ order = 3,
+ type = "color",
+ name = L["Usable"],
+ desc = L["Color of the actionbutton when usable."]
+ },
+ notUsableColor = {
+ order = 4,
+ type = "color",
+ name = L["Not Usable"],
+ desc = L["Color of the actionbutton when not usable."]
+ }
+ }
+ },
+ fontGroup = {
+ order = 13,
+ type = "group",
+ guiInline = true,
+ name = L["Fonts"],
+ args = {
+ font = {
+ order = 4,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ fontSize = {
+ order = 5,
+ type = "range",
+ name = FONT_SIZE,
+ min = 4, max = 212, step = 1
+ },
+ fontOutline = {
+ order = 6,
+ type = "select",
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ values = {
+ ["NONE"] = NONE,
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ fontColor = {
+ order = 7,
+ type = "color",
+ name = COLOR,
+ get = function(info)
+ local t = E.db.actionbar[ info[getn(info)] ]
+ local d = P.actionbar[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.actionbar[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+ AB:UpdateButtonSettings()
+ end
+ }
+ }
+ }
+ }
+ }
+ group["microbar"] = {
+ order = 7,
+ type = "group",
+ name = L["Micro Bar"],
+ get = function(info) return E.db.actionbar.microbar[ info[getn(info)] ] end,
+ set = function(info, value) E.db.actionbar.microbar[ info[getn(info)] ] = value AB:UpdateMicroPositionDimensions() end,
+ disabled = function() return not E.private.actionbar.enable end,
+ args = {
+ info = {
+ order = 1,
+ type = "header",
+ name = L["Micro Bar"]
+ },
+ enabled = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"]
+ },
+ restorePosition = {
+ order = 3,
+ type = "execute",
+ name = L["Restore Bar"],
+ desc = L["Restore the actionbars default settings"],
+ func = function() E:CopyTable(E.db.actionbar["microbar"], P.actionbar["microbar"]) E:ResetMovers(L["Micro Bar"]) AB:UpdateMicroPositionDimensions() end,
+ disabled = function() return not E.db.actionbar.microbar.enabled end
+ },
+ spacer = {
+ order = 4,
+ type = "description",
+ name = " "
+ },
+ buttonsPerRow = {
+ order = 5,
+ type = "range",
+ name = L["Buttons Per Row"],
+ desc = L["The amount of buttons to display per row."],
+ min = 1, max = 8, step = 1,
+ disabled = function() return not E.db.actionbar.microbar.enabled end
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ min = -1, max = 10, step = 1,
+ disabled = function() return not E.db.actionbar.microbar.enabled end
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ min = -1, max = 10, step = 1,
+ disabled = function() return not E.db.actionbar.microbar.enabled end
+ },
+ alpha = {
+ order = 8,
+ type = "range",
+ isPercent = true,
+ name = L["Alpha"],
+ desc = L["Change the alpha level of the frame."],
+ min = 0, max = 1, step = 0.1,
+ disabled = function() return not E.db.actionbar.microbar.enabled end
+ },
+ mouseover = {
+ order = 9,
+ type = "toggle",
+ name = L["Mouse Over"],
+ desc = L["The frame is not shown unless you mouse over the frame."],
+ disabled = function() return not E.db.actionbar.microbar.enabled end
+ }
+ }
+ }
+end
+
+local function BuildBarConfig(i)
+ local name = L["Bar "]..i
+ group["bar"..i] = {
+ order = 1 + i,
+ name = name,
+ type = "group",
+ disabled = function() return not E.private.actionbar.enable end,
+ get = function(info) return E.db.actionbar["bar"..i][ info[getn(info)] ] end,
+ set = function(info, value)
+ E.db.actionbar["bar"..i][ info[getn(info)] ] = value
+ AB:PositionAndSizeBar("bar"..i)
+ end,
+ args = {
+ info = {
+ order = 1,
+ type = "header",
+ name = name
+ },
+ enabled = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ set = function(info, value)
+ E.db.actionbar["bar"..i][ info[getn(info)] ] = value
+ AB:PositionAndSizeBar("bar"..i)
+ end
+ },
+ restorePosition = {
+ order = 3,
+ type = "execute",
+ name = L["Restore Bar"],
+ desc = L["Restore the actionbars default settings"],
+ func = function()
+ E:CopyTable(E.db.actionbar["bar"..i], P.actionbar["bar"..i])
+ E:ResetMovers(L["Bar "..i]) AB:PositionAndSizeBar("bar"..i)
+ end,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ spacer = {
+ order = 4,
+ type = "description",
+ name = " "
+ },
+ backdrop = {
+ order = 5,
+ type = "toggle",
+ name = L["Backdrop"],
+ desc = L["Toggles the display of the actionbars backdrop."],
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ showGrid = {
+ order = 6,
+ type = "toggle",
+ name = L["Show Empty Buttons"],
+ set = function(info, value)
+ E.db.actionbar["bar"..i][ info[getn(info)] ] = value
+ AB:UpdateButtonSettingsForBar("bar"..i)
+ end,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ mouseover = {
+ order = 7,
+ type = "toggle",
+ name = L["Mouse Over"],
+ desc = L["The frame is not shown unless you mouse over the frame."],
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ inheritGlobalFade = {
+ order = 8,
+ type = "toggle",
+ name = L["Inherit Global Fade"],
+ desc = L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."],
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ point = {
+ order = 9,
+ type = "select",
+ name = L["Anchor Point"],
+ desc = L["The first button anchors itself to this point on the bar."],
+ values = points,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ buttons = {
+ order = 10,
+ type = "range",
+ name = L["Buttons"],
+ desc = L["The amount of buttons to display."],
+ min = 1, max = NUM_ACTIONBAR_BUTTONS, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ buttonsPerRow = {
+ order = 11,
+ type = "range",
+ name = L["Buttons Per Row"],
+ desc = L["The amount of buttons to display per row."],
+ min = 1, max = NUM_ACTIONBAR_BUTTONS, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ buttonsize = {
+ order = 12,
+ type = "range",
+ name = L["Button Size"],
+ desc = L["The size of the action buttons."],
+ min = 15, max = 60, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ buttonspacing = {
+ order = 13,
+ type = "range",
+ name = L["Button Spacing"],
+ desc = L["The spacing between buttons."],
+ min = -1, max = 10, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ backdropSpacing = {
+ order = 14,
+ type = "range",
+ name = L["Backdrop Spacing"],
+ desc = L["The spacing between the backdrop and the buttons."],
+ min = 0, max = 10, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ heightMult = {
+ order = 15,
+ type = "range",
+ name = L["Height Multiplier"],
+ desc = L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."],
+ min = 1, max = 5, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ widthMult = {
+ order = 16,
+ type = "range",
+ name = L["Width Multiplier"],
+ desc = L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."],
+ min = 1, max = 5, step = 1,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ },
+ alpha = {
+ order = 17,
+ type = "range",
+ name = L["Alpha"],
+ isPercent = true,
+ min = 0, max = 1, step = 0.01,
+ disabled = function() return not E.db.actionbar["bar"..i].enabled end
+ }
+ }
+ }
+end
+
+E.Options.args.actionbar = {
+ type = "group",
+ name = L["ActionBars"],
+ childGroups = "tab",
+ get = function(info) return E.db.actionbar[ info[getn(info)] ] end,
+ set = function(info, value) E.db.actionbar[ info[getn(info)] ] = value AB:UpdateButtonSettings() end,
+ args = {
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.private.actionbar[ info[getn(info)] ] end,
+ set = function(info, value) E.private.actionbar[ info[getn(info)] ] = value E:StaticPopup_Show("PRIVATE_RL") end
+ },
+ intro = {
+ order = 2,
+ type = "description",
+ name = L["ACTIONBARS_DESC"]
+ },
+ }
+}
+group = E.Options.args.actionbar.args
+BuildABConfig()
+for i = 1, 5 do
+ BuildBarConfig(i)
+end
\ No newline at end of file
diff --git a/ElvUI_Config/Auras.lua b/ElvUI_Config/Auras.lua
new file mode 100644
index 0000000..610cf43
--- /dev/null
+++ b/ElvUI_Config/Auras.lua
@@ -0,0 +1,230 @@
+local E, L, V, P, G, _ = unpack(ElvUI);
+local A = E:GetModule("Auras");
+
+local function GetAuraOptions(headerName)
+ local auraOptions = {
+ header = {
+ order = 0,
+ type = "header",
+ name = headerName
+ },
+ size = {
+ order = 1,
+ type = "range",
+ name = L["Size"],
+ desc = L["Set the size of the individual auras."],
+ min = 16, max = 60, step = 2
+ },
+ growthDirection = {
+ order = 2,
+ type = "select",
+ name = L["Growth Direction"],
+ desc = L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."],
+ values = {
+ DOWN_RIGHT = format(L["%s and then %s"], L["Down"], L["Right"]),
+ DOWN_LEFT = format(L["%s and then %s"], L["Down"], L["Left"]),
+ UP_RIGHT = format(L["%s and then %s"], L["Up"], L["Right"]),
+ UP_LEFT = format(L["%s and then %s"], L["Up"], L["Left"]),
+ RIGHT_DOWN = format(L["%s and then %s"], L["Right"], L["Down"]),
+ RIGHT_UP = format(L["%s and then %s"], L["Right"], L["Up"]),
+ LEFT_DOWN = format(L["%s and then %s"], L["Left"], L["Down"]),
+ LEFT_UP = format(L["%s and then %s"], L["Left"], L["Up"])
+ }
+ },
+ wrapAfter = {
+ order = 3,
+ type = "range",
+ name = L["Wrap After"],
+ desc = L["Begin a new row or column after this many auras."],
+ min = 1, max = 32, step = 1
+ },
+ maxWraps = {
+ order = 4,
+ type = "range",
+ name = L["Max Wraps"],
+ desc = L["Limit the number of rows or columns."],
+ min = 1, max = 32, step = 1
+ },
+ horizontalSpacing = {
+ order = 5,
+ type = "range",
+ name = L["Horizontal Spacing"],
+ min = 0, max = 50, step = 1
+ },
+ verticalSpacing = {
+ order = 6,
+ type = "range",
+ name = L["Vertical Spacing"],
+ min = 0, max = 50, step = 1
+ },
+ sortMethod = {
+ order = 7,
+ type = "select",
+ name = L["Sort Method"],
+ desc = L["Defines how the group is sorted."],
+ values = {
+ ["INDEX"] = L["Index"],
+ ["TIME"] = L["Time"],
+ ["NAME"] = L["Name"]
+ }
+ },
+ sortDir = {
+ order = 8,
+ type = "select",
+ name = L["Sort Direction"],
+ desc = L["Defines the sort order of the selected sort method."],
+ values = {
+ ["+"] = L["Ascending"],
+ ["-"] = L["Descending"]
+ }
+ },
+ seperateOwn = {
+ order = 9,
+ type = "select",
+ name = L["Seperate"],
+ desc = L["Indicate whether buffs you cast yourself should be separated before or after."],
+ values = {
+ [-1] = L["Other's First"],
+ [0] = L["No Sorting"],
+ [1] = L["Your Auras First"]
+ }
+ }
+ };
+ return auraOptions;
+end
+
+E.Options.args.auras = {
+ type = "group",
+ name = L["Buffs and Debuffs"],
+ childGroups = "tab",
+ get = function(info) return E.db.auras[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.auras[ info[getn(info)] ] = value; A:UpdateHeader(ElvUIPlayerBuffs); A:UpdateHeader(ElvUIPlayerDebuffs); end,
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["AURAS_DESC"]
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.private.auras[ info[getn(info)] ]; end,
+ set = function(info, value)
+ E.private.auras[ info[getn(info)] ] = value;
+ E:StaticPopup_Show("PRIVATE_RL");
+ end,
+ },
+ disableBlizzard = {
+ order = 3,
+ type = "toggle",
+ name = L["Disabled Blizzard"],
+ get = function(info) return E.private.auras[ info[getn(info)] ] end,
+ set = function(info, value)
+ E.private.auras[ info[getn(info)] ] = value;
+ E:StaticPopup_Show("PRIVATE_RL");
+ end
+ },
+ general = {
+ order = 4,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["General"]
+ },
+ fadeThreshold = {
+ order = 1,
+ type = "range",
+ name = L["Fade Threshold"],
+ desc = L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."],
+ min = -1, max = 30, step = 1
+ },
+ font = {
+ order = 2,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ fontSize = {
+ order = 3,
+ name = L["Font Size"],
+ type = "range",
+ min = 6, max = 33, step = 1
+ },
+ fontOutline = {
+ order = 4,
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ type = "select",
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ timeXOffset = {
+ order = 5,
+ type = "range",
+ name = L["Time xOffset"],
+ min = -60, max = 60, step = 1
+ },
+ timeYOffset = {
+ order = 6,
+ type = "range",
+ name = L["Time yOffset"],
+ min = -60, max = 60, step = 1
+ },
+ countXOffset = {
+ order = 7,
+ type = "range",
+ name = L["Count xOffset"],
+ min = -60, max = 60, step = 1
+ },
+ countYOffset = {
+ order = 8,
+ name = L["Count yOffset"],
+ type = "range",
+ min = -60, max = 60, step = 1
+ },
+ lbf = {
+ order = 9,
+ type = "group",
+ guiInline = true,
+ name = L["LBF Support"],
+ get = function(info) return E.private.auras.lbf[info[getn(info)]]; end,
+ set = function(info, value) E.private.auras.lbf[info[getn(info)]] = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ disabled = function() return not E.private.auras.enable; end,
+ args = {
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ desc = L["Allow LBF to handle the skinning of this element."]
+ }
+ }
+ }
+ }
+ },
+ buffs = {
+ order = 5,
+ type = "group",
+ name = L["Buffs"],
+ get = function(info) return E.db.auras.buffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.auras.buffs[ info[getn(info)] ] = value; A:UpdateHeader(ElvUIPlayerBuffs); end,
+ args = GetAuraOptions(L["Buffs"])
+ },
+ debuffs = {
+ order = 6,
+ type = "group",
+ name = L["Debuffs"],
+ get = function(info) return E.db.auras.debuffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.auras.debuffs[ info[getn(info)] ] = value; A:UpdateHeader(ElvUIPlayerDebuffs); end,
+ args = GetAuraOptions(L["Debuffs"])
+ }
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Bags.lua b/ElvUI_Config/Bags.lua
new file mode 100644
index 0000000..803c498
--- /dev/null
+++ b/ElvUI_Config/Bags.lua
@@ -0,0 +1,416 @@
+local E, L, V, P, G = unpack(ElvUI);
+local B = E:GetModule("Bags");
+
+E.Options.args.bags = {
+ type = "group",
+ name = L["Bags"],
+ childGroups = "tab",
+ get = function(info) return E.db.bags[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.bags[ info[getn(info)] ] = value; end,
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["BAGS_DESC"]
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ desc = L["Enable/Disable the all-in-one bag."],
+ get = function(info) return E.private.bags.enable; end,
+ set = function(info, value) E.private.bags.enable = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ general = {
+ order = 3,
+ type = "group",
+ name = L["General"],
+ disabled = function() return not E.bags; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["General"]
+ },
+ moneyFormat = {
+ order = 1,
+ type = "select",
+ name = L["Money Format"],
+ desc = L["The display format of the money text that is shown at the top of the main bag."],
+ values = {
+ ["SMART"] = L["Smart"],
+ ["FULL"] = L["Full"],
+ ["SHORT"] = L["Short"],
+ ["SHORTINT"] = L["Short (Whole Numbers)"],
+ ["CONDENSED"] = L["Condensed"],
+ ["BLIZZARD"] = L["Blizzard Style"]
+ },
+ set = function(info, value) E.db.bags[ info[getn(info)] ] = value; B:UpdateGoldText(); end
+ },
+ clearSearchOnClose = {
+ order = 2,
+ type = "toggle",
+ name = L["Clear Search On Close"],
+ set = function(info, value) E.db.bags[info[getn(info)]] = value; end
+ },
+ disableBagSort = {
+ order = 3,
+ type = "toggle",
+ name = L["Disable Bag Sort"],
+ set = function(info, value) E.db.bags[info[getn(info)]] = value; B:ToggleSortButtonState(false); end
+ },
+ disableBankSort = {
+ order = 4,
+ type = "toggle",
+ name = L["Disable Bank Sort"],
+ set = function(info, value) E.db.bags[info[getn(info)]] = value; B:ToggleSortButtonState(true); end
+ },
+ countGroup = {
+ order = 5,
+ type = "group",
+ name = L["Item Count Font"],
+ guiInline = true,
+ args = {
+ countFont = {
+ order = 1,
+ type = "select",
+ dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ set = function(info, value) E.db.bags.countFont = value; B:UpdateCountDisplay(); end
+ },
+ countFontSize = {
+ order = 2,
+ type = "range",
+ name = L["Font Size"],
+ min = 4, max = 22, step = 1,
+ set = function(info, value) E.db.bags.countFontSize = value; B:UpdateCountDisplay(); end
+ },
+ countFontOutline = {
+ order = 3,
+ type = "select",
+ name = L["Font Outline"],
+ set = function(info, value) E.db.bags.countFontOutline = value; B:UpdateCountDisplay(); end,
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ countFontColor = {
+ order = 4,
+ type = "color",
+ name = L["Color"],
+ get = function(info)
+ local t = E.db.bags[ info[getn(info)] ];
+ local d = P.bags[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.bags[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ B:UpdateCountDisplay();
+ end
+ }
+ }
+ },
+ itemLevelGroup = {
+ order = 6,
+ type = "group",
+ name = L["Item Level"],
+ guiInline = true,
+ args = {
+ itemLevel = {
+ order = 1,
+ type = "toggle",
+ name = L["Display Item Level"],
+ desc = L["Displays item level on equippable items."],
+ set = function(info, value) E.db.bags.itemLevel = value; B:UpdateItemLevelDisplay(); end
+ },
+ itemLevelThreshold = {
+ order = 2,
+ name = L["Item Level Threshold"],
+ desc = L["The minimum item level required for it to be shown."],
+ type = "range",
+ min = 1, max = 1000, step = 1,
+ disabled = function() return not E.db.bags.itemLevel; end,
+ set = function(info, value) E.db.bags.itemLevelThreshold = value; B:UpdateItemLevelDisplay(); end
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = " "
+ },
+ itemLevelFont = {
+ order = 4,
+ type = "select",
+ dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ disabled = function() return not E.db.bags.itemLevel; end,
+ set = function(info, value) E.db.bags.itemLevelFont = value; B:UpdateItemLevelDisplay(); end
+ },
+ itemLevelFontSize = {
+ order = 5,
+ type = "range",
+ name = L["Font Size"],
+ min = 6, max = 33, step = 1,
+ disabled = function() return not E.db.bags.itemLevel; end,
+ set = function(info, value) E.db.bags.itemLevelFontSize = value; B:UpdateItemLevelDisplay(); end
+ },
+ itemLevelFontOutline = {
+ order = 6,
+ type = "select",
+ name = L["Font Outline"],
+ disabled = function() return not E.db.bags.itemLevel end,
+ set = function(info, value) E.db.bags.itemLevelFontOutline = value; B:UpdateItemLevelDisplay() end,
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ }
+ }
+ }
+ }
+ },
+ sizeGroup = {
+ order = 4,
+ type = "group",
+ name = L["Size"],
+ disabled = function() return not E.bags; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Size and Positions"]
+ },
+ bagSize = {
+ order = 1,
+ type = "range",
+ name = L["Button Size (Bag)"],
+ desc = L["The size of the individual buttons on the bag frame."],
+ min = 15, max = 45, step = 1,
+ set = function(info, value) E.db.bags[ info[getn(info)] ] = value; B:Layout(); end
+ },
+ bankSize = {
+ order = 2,
+ type = "range",
+ name = L["Button Size (Bank)"],
+ desc = L["The size of the individual buttons on the bank frame."],
+ min = 15, max = 45, step = 1,
+ set = function(info, value) E.db.bags[ info[getn(info)] ] = value; B:Layout(true); end
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = " "
+ },
+ bagWidth = {
+ order = 4,
+ type = "range",
+ name = L["Panel Width (Bags)"],
+ desc = L["Adjust the width of the bag frame."],
+ min = 150, max = 1400, step = 1,
+ set = function(info, value) E.db.bags[ info[getn(info)] ] = value; B:Layout(); end
+ },
+ bankWidth = {
+ order = 5,
+ type = "range",
+ name = L["Panel Width (Bank)"],
+ desc = L["Adjust the width of the bank frame."],
+ min = 150, max = 1400, step = 1,
+ set = function(info, value) E.db.bags[ info[getn(info)] ] = value; B:Layout(true); end
+ }
+ }
+ },
+ bagBar = {
+ order = 5,
+ type = "group",
+ name = L["Bag-Bar"],
+ get = function(info) return E.db.bags.bagBar[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.bags.bagBar[ info[getn(info)] ] = value; B:SizeAndPositionBagBar(); end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Bag-Bar"]
+ },
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ desc = L["Enable/Disable the Bag-Bar."],
+ get = function(info) return E.private.bags.bagBar end,
+ set = function(info, value) E.private.bags.bagBar = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ showBackdrop = {
+ order = 2,
+ type = "toggle",
+ name = L["Backdrop"]
+ },
+ mouseover = {
+ order = 3,
+ name = L["Mouse Over"],
+ desc = L["The frame is not shown unless you mouse over the frame."],
+ type = "toggle"
+ },
+ size = {
+ order = 4,
+ type = "range",
+ name = L["Button Size"],
+ desc = L["Set the size of your bag buttons."],
+ min = 24, max = 60, step = 1
+ },
+ spacing = {
+ order = 5,
+ type = "range",
+ name = L["Button Spacing"],
+ desc = L["The spacing between buttons."],
+ min = 1, max = 10, step = 1
+ },
+ backdropSpacing = {
+ order = 6,
+ type = "range",
+ name = L["Backdrop Spacing"],
+ desc = L["The spacing between the backdrop and the buttons."],
+ min = 0, max = 10, step = 1
+ },
+ sortDirection = {
+ order = 7,
+ type = "select",
+ name = L["Sort Direction"],
+ desc = L["The direction that the bag frames will grow from the anchor."],
+ values = {
+ ["ASCENDING"] = L["Ascending"],
+ ["DESCENDING"] = L["Descending"]
+ }
+ },
+ growthDirection = {
+ order = 7,
+ type = "select",
+ name = L["Bar Direction"],
+ desc = L["The direction that the bag frames be (Horizontal or Vertical)."],
+ values = {
+ ["VERTICAL"] = L["Vertical"],
+ ["HORIZONTAL"] = L["Horizontal"]
+ }
+ }
+ }
+ },
+ bagSortingGroup = {
+ order = 6,
+ type = "group",
+ name = L["Bag Sorting"],
+ disabled = function() return not E.bags end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Bag Sorting"],
+ },
+ sortInverted = {
+ order = 1,
+ type = "toggle",
+ name = L["Sort Inverted"],
+ desc = L["Direction the bag sorting will use to allocate the items."]
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = " "
+ },
+ description = {
+ order = 3,
+ type = "description",
+ name = L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."]
+ },
+ addEntryGroup = {
+ order = 4,
+ type = "group",
+ name = L["Add Item or Search Syntax"],
+ guiInline = true,
+ args = {
+ addEntryProfile = {
+ order = 1,
+ type = "input",
+ name = L["Profile"],
+ desc = L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."],
+ get = function(info) return ""; end,
+ set = function(info, value)
+ if(value == "" or string.gsub(value, "%s+", "") == "") then return; end
+
+ local itemID = string.match(value, "item:(%d+)");
+ E.db.bags.ignoredItems[(itemID or value)] = value;
+ end
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = " ",
+ width = "normal"
+ },
+ addEntryGlobal = {
+ order = 3,
+ type = "input",
+ name = L["Global"],
+ desc = L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."],
+ get = function(info) return ""; end,
+ set = function(info, value)
+ if(value == "" or string.gsub(value, "%s+", "") == "") then return; end
+
+ local itemID = string.match(value, "item:(%d+)");
+ E.global.bags.ignoredItems[(itemID or value)] = value;
+
+ if(E.db.bags.ignoredItems[(itemID or value)]) then
+ E.db.bags.ignoredItems[(itemID or value)] = nil;
+ end
+ end
+ }
+ }
+ },
+ ignoredEntriesProfile = {
+ order = 5,
+ type = "multiselect",
+ name = L["Ignored Items and Search Syntax (Profile)"],
+ values = function() return E.db.bags.ignoredItems; end,
+ get = function(info, value) return E.db.bags.ignoredItems[value]; end,
+ set = function(info, value)
+ E.db.bags.ignoredItems[value] = nil;
+ GameTooltip:Hide();
+ end
+ },
+ --[[ignoredEntriesGlobal = {
+ order = 6,
+ type = "multiselect",
+ name = L["Ignored Items and Search Syntax (Global)"],
+ values = function() return E.global.bags.ignoredItems; end,
+ get = function(info, value) return E.global.bags.ignoredItems[value]; end,
+ set = function(info, value)
+ E.global.bags.ignoredItems[value] = nil;
+ GameTooltip:Hide();
+ end
+ }--]]
+ }
+ },
+ search_syntax = {
+ order = 7,
+ type = "group",
+ name = L["Search Syntax"],
+ disabled = function() return not E.bags; end,
+ args = {
+ text = {
+ order = 1,
+ type = "input",
+ multiline = 30,
+ width = "full",
+ name = L["Search Syntax"],
+ get = function(info) return L["SEARCH_SYNTAX_DESC"]; end,
+ set = function(info, value) value = L["SEARCH_SYNTAX_DESC"]; end
+ }
+ }
+ }
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Chat.lua b/ElvUI_Config/Chat.lua
new file mode 100644
index 0000000..5527253
--- /dev/null
+++ b/ElvUI_Config/Chat.lua
@@ -0,0 +1,497 @@
+local E, L, V, P, G = unpack(ElvUI);
+local CH = E:GetModule("Chat");
+
+E.Options.args.chat = {
+ type = "group",
+ name = L["Chat"],
+ childGroups = "tab",
+ get = function(info) return E.db.chat[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.chat[ info[getn(info)] ] = value; end,
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["CHAT_DESC"]
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.private.chat.enable; end,
+ set = function(info, value) E.private.chat.enable = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ general = {
+ order = 3,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["General"]
+ },
+ url = {
+ order = 1,
+ type = "toggle",
+ name = L["URL Links"],
+ desc = L["Attempt to create URL links inside the chat."]
+ },
+ shortChannels = {
+ order = 2,
+ type = "toggle",
+ name = L["Short Channels"],
+ desc = L["Shorten the channel names in chat."]
+ },
+ hyperlinkHover = {
+ order = 3,
+ type = "toggle",
+ name = L["Hyperlink Hover"],
+ desc = L["Display the hyperlink tooltip while hovering over a hyperlink."],
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ if(value == true) then
+ CH:EnableHyperlink();
+ else
+ CH:DisableHyperlink();
+ end
+ end
+ },
+ sticky = {
+ order = 4,
+ type = "toggle",
+ name = L["Sticky Chat"],
+ desc = L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."],
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ end
+ },
+ fade = {
+ order = 5,
+ type = "toggle",
+ name = L["Fade Chat"],
+ desc = L["Fade the chat text when there is no activity."],
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ CH:UpdateFading();
+ end
+ },
+ fadeUndockedTabs = {
+ order = 6,
+ type = "toggle",
+ name = L["Fade Undocked Tabs"],
+ desc = L["Fades the text on chat tabs that are not docked at the left or right chat panel."],
+ set = function(self, value)
+ E.db.chat.fadeUndockedTabs = value;
+ CH:UpdateChatTabs();
+ end
+ },
+ fadeTabsNoBackdrop = {
+ order = 7,
+ type = "toggle",
+ name = L["Fade Tabs No Backdrop"],
+ desc = L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."],
+ set = function(self, value)
+ E.db.chat.fadeTabsNoBackdrop = value;
+ CH:UpdateChatTabs();
+ end
+ },
+ chatHistory = {
+ order = 8,
+ type = "toggle",
+ name = L["Chat History"],
+ desc = L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."]
+ },
+ useAltKey = {
+ order = 9,
+ type = "toggle",
+ name = L["Use Alt Key"],
+ desc = L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."],
+ set = function(self, value)
+ E.db.chat.useAltKey = value;
+ CH:UpdateSettings();
+ end
+ },
+ spacer = {
+ order = 10,
+ type = "description",
+ name = " ",
+ },
+ throttleInterval = {
+ order = 11,
+ type = "range",
+ name = L["Spam Interval"],
+ desc = L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."],
+ min = 0, max = 120, step = 1,
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ if(value == 0) then
+ CH:DisableChatThrottle();
+ end
+ end
+ },
+ scrollDownInterval = {
+ order = 12,
+ type = "range",
+ name = L["Scroll Interval"],
+ desc = L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."],
+ min = 0, max = 120, step = 5,
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ end
+ },
+ numAllowedCombatRepeat = {
+ order = 13,
+ type = "range",
+ name = L["Allowed Combat Repeat"],
+ desc = L["Number of repeat characters while in combat before the chat editbox is automatically closed."],
+ min = 2, max = 10, step = 1
+ },
+ numScrollMessages = {
+ order = 14,
+ type = "range",
+ name = L["Scroll Messages"],
+ desc = L["Number of messages you scroll for each step."],
+ min = 1, max = 10, step = 1,
+ },
+ spacer2 = {
+ order = 16,
+ type = "description",
+ name = " ",
+ },
+ timeStampFormat = {
+ order = 15,
+ type = "select",
+ name = L["Chat Timestamps"],
+ desc = "OPTION_TOOLTIP_TIMESTAMPS",
+ values = {
+ ["NONE"] = NONE,
+ ["%I:%M "] = "03:27",
+ ["%I:%M:%S "] = "03:27:32",
+ ["%I:%M %p "] = "03:27 PM",
+ ["%I:%M:%S %p "] = "03:27:32 PM",
+ ["%H:%M "] = "15:27",
+ ["%H:%M:%S "] = "15:27:32"
+ }
+ },
+ useCustomTimeColor = {
+ order = 16,
+ type = "toggle",
+ name = L["Custom Timestamp Color"],
+ disabled = function() return not E.db.chat.timeStampFormat == "NONE"; end
+ },
+ customTimeColor = {
+ order = 17,
+ type = "color",
+ hasAlpha = false,
+ name = L["Timestamp Color"],
+ disabled = function() return (not E.db.chat.timeStampFormat == "NONE" or not E.db.chat.useCustomTimeColor); end,
+ get = function(info)
+ local t = E.db.chat.customTimeColor;
+ local d = P.chat.customTimeColor;
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.chat.customTimeColor;
+ t.r, t.g, t.b = r, g, b;
+ end
+ }
+ }
+ },
+ alerts = {
+ order = 4,
+ type = "group",
+ name = L["Alerts"],
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Alerts"]
+ },
+ whisperSound = {
+ order = 1,
+ type = "select", dialogControl = "LSM30_Sound",
+ name = L["Whisper Alert"],
+ values = AceGUIWidgetLSMlists.sound,
+ },
+ keywordSound = {
+ order = 2,
+ type = "select", dialogControl = "LSM30_Sound",
+ name = L["Keyword Alert"],
+ values = AceGUIWidgetLSMlists.sound,
+ },
+ noAlertInCombat = {
+ order = 3,
+ type = "toggle",
+ name = L["No Alert In Combat"]
+ },
+ keywords = {
+ order = 4,
+ name = L["Keywords"],
+ desc = L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"],
+ type = "input",
+ width = "full",
+ set = function(info, value) E.db.chat[ info[getn(info)] ] = value; CH:UpdateChatKeywords(); end
+ }
+ }
+ },
+ panels = {
+ order = 5,
+ type = "group",
+ name = L["Panels"],
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Panels"]
+ },
+ lockPositions = {
+ order = 1,
+ type = "toggle",
+ name = L["Lock Positions"],
+ desc = L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."],
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ if(value == true) then
+ CH:PositionChat(true);
+ end
+ end
+ },
+ panelTabTransparency = {
+ order = 2,
+ type = "toggle",
+ name = L["Tab Panel Transparency"],
+ set = function(info, value) E.db.chat.panelTabTransparency = value; E:GetModule("Layout"):SetChatTabStyle(); end
+ },
+ panelTabBackdrop = {
+ order = 3,
+ type = "toggle",
+ name = L["Tab Panel"],
+ desc = L["Toggle the chat tab panel backdrop."],
+ set = function(info, value) E.db.chat.panelTabBackdrop = value; E:GetModule("Layout"):ToggleChatPanels(); end
+ },
+ editBoxPosition = {
+ order = 4,
+ type = "select",
+ name = L["Chat EditBox Position"],
+ desc = L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."],
+ values = {
+ ["BELOW_CHAT"] = L["Below Chat"],
+ ["ABOVE_CHAT"] = L["Above Chat"]
+ },
+ set = function(info, value) E.db.chat[ info[getn(info)] ] = value; CH:UpdateAnchors(); end
+ },
+ panelBackdrop = {
+ order = 5,
+ type = "select",
+ name = L["Panel Backdrop"],
+ desc = L["Toggle showing of the left and right chat panels."],
+ set = function(info, value) E.db.chat.panelBackdrop = value; E:GetModule("Layout"):ToggleChatPanels(); E:GetModule("Chat"):PositionChat(true); E:GetModule("Chat"):UpdateAnchors(); end,
+ values = {
+ ["HIDEBOTH"] = L["Hide Both"],
+ ["SHOWBOTH"] = L["Show Both"],
+ ["LEFT"] = L["Left Only"],
+ ["RIGHT"] = L["Right Only"]
+ }
+ },
+ separateSizes = {
+ order = 6,
+ type = "toggle",
+ name = L["Separate Panel Sizes"],
+ desc = L["Enable the use of separate size options for the right chat panel."],
+ set = function(info, value)
+ E.db.chat.separateSizes = value;
+ E:GetModule("Chat"):PositionChat(true);
+ E:GetModule("Bags"):Layout();
+ end
+ },
+ spacer1 = {
+ order = 7,
+ type = "description",
+ name = ""
+ },
+ panelHeight = {
+ order = 8,
+ type = "range",
+ name = L["Panel Height"],
+ desc = L["PANEL_DESC"],
+ min = 50, max = 600, step = 1,
+ set = function(info, value) E.db.chat.panelHeight = value; E:GetModule("Chat"):PositionChat(true); end
+ },
+ panelWidth = {
+ order = 9,
+ type = "range",
+ name = L["Panel Width"],
+ desc = L["PANEL_DESC"],
+ min = 50, max = 1000, step = 1,
+ set = function(info, value)
+ E.db.chat.panelWidth = value;
+ E:GetModule("Chat"):PositionChat(true);
+ local bags = E:GetModule("Bags");
+ if(not E.db.chat.separateSizes) then
+ bags:Layout();
+ end
+ bags:Layout(true);
+ end
+ },
+ spacer2 = {
+ order = 10,
+ type = "description",
+ name = ""
+ },
+ panelHeightRight = {
+ order = 11,
+ type = "range",
+ name = L["Right Panel Height"],
+ desc = L["Adjust the height of your right chat panel."],
+ min = 50, max = 600, step = 1,
+ disabled = function() return not E.db.chat.separateSizes; end,
+ hidden = function() return not E.db.chat.separateSizes; end,
+ set = function(info, value) E.db.chat.panelHeightRight = value; E:GetModule("Chat"):PositionChat(true); end
+ },
+ panelWidthRight = {
+ order = 12,
+ type = "range",
+ name = L["Right Panel Width"],
+ desc = L["Adjust the width of your right chat panel."],
+ min = 50, max = 1000, step = 1,
+ disabled = function() return not E.db.chat.separateSizes end,
+ hidden = function() return not E.db.chat.separateSizes end,
+ set = function(info, value)
+ E.db.chat.panelWidthRight = value;
+ E:GetModule("Chat"):PositionChat(true);
+ E:GetModule("Bags"):Layout();
+ end
+ },
+ panelBackdropNameLeft = {
+ order = 13,
+ type = "input",
+ width = "full",
+ name = L["Panel Texture (Left)"],
+ desc = L["Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.\n\nPlease Note:\n-The image size recommended is 256x128\n-You must do a complete game restart after adding a file to the folder.\n-The file type must be tga format.\n\nExample: Interface\\AddOns\\ElvUI\\media\\textures\\copy\n\nOr for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here."],
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ E:UpdateMedia();
+ end
+ },
+ panelBackdropNameRight = {
+ order = 14,
+ type = "input",
+ width = "full",
+ name = L["Panel Texture (Right)"],
+ desc = L["Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.\n\nPlease Note:\n-The image size recommended is 256x128\n-You must do a complete game restart after adding a file to the folder.\n-The file type must be tga format.\n\nExample: Interface\\AddOns\\ElvUI\\media\\textures\\copy\n\nOr for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here."],
+ set = function(info, value)
+ E.db.chat[ info[getn(info)] ] = value;
+ E:UpdateMedia();
+ end
+ }
+ }
+ },
+ fontGroup = {
+ order = 6,
+ type = "group",
+ name = L["Fonts"],
+ set = function(info, value) E.db.chat[ info[getn(info)] ] = value; CH:SetupChat(); end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Fonts"]
+ },
+ font = {
+ order = 1,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ fontOutline = {
+ order = 2,
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ type = "select",
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCHROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ tabFont = {
+ type = "select", dialogControl = "LSM30_Font",
+ order = 4,
+ name = L["Tab Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ tabFontSize = {
+ order = 5,
+ type = "range",
+ name = L["Tab Font Size"],
+ min = 6, max = 22, step = 1
+ },
+ tabFontOutline = {
+ order = 6,
+ name = L["Tab Font Outline"],
+ desc = L["Set the font outline."],
+ type = "select",
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCHROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ }
+ }
+ },
+ classColorMentionGroup = {
+ order = 7,
+ type = "group",
+ name = L["Class Color Mentions"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Class Color Mentions"]
+ },
+ classColorMentionsChat = {
+ order = 2,
+ type = "toggle",
+ name = L["Chat"],
+ desc = L["Use class color for the names of players when they are mentioned."],
+ get = function(info) return E.db.chat.classColorMentionsChat end,
+ set = function(info, value) E.db.chat.classColorMentionsChat = value end,
+ disabled = function() return not E.private.chat.enable end
+ },
+ classColorMentionsSpeech = {
+ order = 3,
+ type = "toggle",
+ name = L["Chat Bubbles"],
+ desc = L["Use class color for the names of players when they are mentioned."],
+ get = function(info) return E.private.general.classColorMentionsSpeech end,
+ set = function(info, value) E.private.general.classColorMentionsSpeech = value; E:StaticPopup_Show("PRIVATE_RL") end,
+ disabled = function() return (E.private.general.chatBubbles == "disabled" or not E.private.chat.enable) end
+ },
+ classColorMentionExcludeName = {
+ order = 4,
+ name = L["Exclude Name"],
+ desc = L["Excluded names will not be class colored."],
+ type = 'input',
+ get = function(info) return "" end,
+ set = function(info, value)
+ if value == "" or string.gsub(value, "%s+", "") == "" then return; end
+ E.global.chat.classColorMentionExcludedNames[strlower(value)] = value
+ end
+ },
+ classColorMentionExcludedNames = {
+ order = 5,
+ type = "multiselect",
+ name = L["Excluded Names"],
+ values = function() return E.global.chat.classColorMentionExcludedNames end,
+ get = function(info, value) return E.global.chat.classColorMentionExcludedNames[value] end,
+ set = function(info, value)
+ E.global.chat.classColorMentionExcludedNames[value] = nil
+ GameTooltip:Hide()
+ end
+ }
+ }
+ }
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Core.lua b/ElvUI_Config/Core.lua
new file mode 100644
index 0000000..5610249
--- /dev/null
+++ b/ElvUI_Config/Core.lua
@@ -0,0 +1,465 @@
+local E, L, V, P, G = unpack(ElvUI);
+local D = E:GetModule("Distributor");
+local AceGUI = LibStub("AceGUI-3.0");
+
+local pairs = pairs;
+local tsort, tinsert = table.sort, table.insert;
+local format = string.format;
+
+local UnitExists = UnitExists;
+local UnitIsFriend = UnitIsFriend;
+local UnitIsPlayer = UnitIsPlayer;
+local UnitIsUnit = UnitIsUnit;
+local UnitName = UnitName;
+
+local DEFAULT_WIDTH = 890;
+local DEFAULT_HEIGHT = 651;
+local AC = LibStub("AceConfig-3.0");
+local ACD = LibStub("AceConfigDialog-3.0");
+local ACR = LibStub("AceConfigRegistry-3.0");
+
+AC.RegisterOptionsTable(E, "ElvUI", E.Options);
+ACD:SetDefaultSize("ElvUI", DEFAULT_WIDTH, DEFAULT_HEIGHT);
+
+function E:RefreshGUI()
+ self:RefreshCustomTextsConfigs();
+ ACR:NotifyChange("ElvUI");
+end
+
+E.Options.args = {
+ ElvUI_Header = {
+ order = 1,
+ type = "header",
+ name = L["Version"] .. format(": |cff99ff33%s|r", E.version),
+ width = "full"
+ },
+ LoginMessage = {
+ order = 2,
+ type = "toggle",
+ name = L["Login Message"],
+ get = function(info) return E.db.general.loginmessage; end,
+ set = function(info, value) E.db.general.loginmessage = value; end
+ },
+ ToggleTutorial = {
+ order = 3,
+ type = "execute",
+ name = L["Toggle Tutorials"],
+ func = function() E:Tutorials(true); E:ToggleConfig(); end
+ },
+ Install = {
+ order = 4,
+ type = "execute",
+ name = L["Install"],
+ desc = L["Run the installation process."],
+ func = function() E:Install(); E:ToggleConfig(); end
+ },
+ ToggleAnchors = {
+ order = 5,
+ type = "execute",
+ name = L["Toggle Anchors"],
+ desc = L["Unlock various elements of the UI to be repositioned."],
+ func = function() E:ToggleConfigMode(); end
+ },
+ ResetAllMovers = {
+ order = 6,
+ type = "execute",
+ name = L["Reset Anchors"],
+ desc = L["Reset all frames to their original positions."],
+ func = function() E:ResetUI(); end
+ }
+};
+
+local DONATOR_STRING = "";
+local DEVELOPER_STRING = "";
+local TESTER_STRING = "";
+local LINE_BREAK = "\n";
+local DONATORS = {
+ "Dandruff",
+ "Tobur/Tarilya",
+ "Netu",
+ "Alluren",
+ "Thorgnir",
+ "Emalal",
+ "Bendmeova",
+ "Curl",
+ "Zarac",
+ "Emmo",
+ "Oz",
+ "Hawké",
+ "Aynya",
+ "Tahira",
+ "Karsten Lumbye Thomsen",
+ "Thomas B. aka Pitschiqüü",
+ "Sea Garnet",
+ "Paul Storry",
+ "Azagar",
+ "Archury",
+ "Donhorn",
+ "Woodson Harmon",
+ "Phoenyx",
+ "Feat",
+ "Konungr",
+ "Leyrin",
+ "Dragonsys",
+ "Tkalec",
+ "Paavi",
+ "Giorgio",
+ "Bearscantank",
+ "Eidolic",
+ "Cosmo",
+ "Adorno",
+ "Domoaligato",
+ "Smorg",
+ "Pyrokee",
+ "Portable",
+ "Ithilyn"
+};
+
+local DEVELOPERS = {
+ "Tukz",
+ "Haste",
+ "Nightcracker",
+ "Omega1970",
+ "Hydrazine"
+};
+
+local TESTERS = {
+ "Tukui Community",
+ "|cffF76ADBSarah|r - For Sarahing",
+ "Affinity",
+ "Modarch",
+ "Bladesdruid",
+ "Tirain",
+ "Phima",
+ "Veiled",
+ "Blazeflack",
+ "Repooc",
+ "Darth Predator",
+ "Alex",
+ "Nidra",
+ "Kurhyus",
+ "BuG",
+ "Yachanay",
+ "Catok"
+}
+
+tsort(DONATORS, function(a, b) return a < b end);
+for _, donatorName in pairs(DONATORS) do
+ tinsert(E.CreditsList, donatorName);
+ DONATOR_STRING = DONATOR_STRING .. LINE_BREAK .. donatorName;
+end
+
+tsort(DEVELOPERS, function(a,b) return a < b end);
+for _, devName in pairs(DEVELOPERS) do
+ tinsert(E.CreditsList, devName);
+ DEVELOPER_STRING = DEVELOPER_STRING .. LINE_BREAK .. devName;
+end
+
+tsort(TESTERS, function(a, b) return a < b end)
+for _, testerName in pairs(TESTERS) do
+ tinsert(E.CreditsList, testerName);
+ TESTER_STRING = TESTER_STRING .. LINE_BREAK .. testerName;
+end
+
+E.Options.args.credits = {
+ type = "group",
+ name = L["Credits"],
+ order = -1,
+ args = {
+ text = {
+ order = 1,
+ type = "description",
+ name = L["ELVUI_CREDITS"] .. "\n\n" .. L["Coding:"] .. DEVELOPER_STRING .. "\n\n" .. L["Testing:"] .. TESTER_STRING .. "\n\n" .. L["Donations:"] .. DONATOR_STRING
+ }
+ }
+}
+
+local profileTypeItems = {
+ ["profile"] = L["Profile"],
+ ["private"] = L["Private (Character Settings)"],
+ ["global"] = L["Global (Account Settings)"],
+ ["filtersNP"] = L["Filters (NamePlates)"],
+ ["filtersUF"] = L["Filters (UnitFrames)"],
+ ["filtersAll"] = L["Filters (All)"]
+}
+
+local profileTypeListOrder = {
+ "profile",
+ "private",
+ "global",
+ "filtersNP",
+ "filtersUF",
+ "filtersAll"
+}
+
+local exportTypeItems = {
+ ["text"] = L["Text"],
+ ["luaTable"] = L["Table"],
+ ["luaPlugin"] = L["Plugin"]
+}
+
+local exportTypeListOrder = {
+ "text",
+ "luaTable",
+ "luaPlugin"
+}
+
+local exportString = ""
+local function ExportImport_Open(mode)
+ local frame = AceGUI:Create("Frame")
+ frame:SetTitle("")
+ frame:EnableResize(false)
+ frame:SetWidth(800)
+ frame:SetHeight(600)
+ frame.frame:SetFrameStrata("FULLSCREEN_DIALOG")
+ frame:SetLayout("flow")
+
+ local box = AceGUI:Create("MultiLineEditBox")
+ box:SetNumLines(30)
+ box:DisableButton(true)
+ box:SetWidth(800)
+ box:SetLabel("")
+ frame:AddChild(box)
+ box.editBox.OnTextChangedOrig = box.editBox:GetScript("OnTextChanged")
+ box.editBox.OnCursorChangedOrig = box.editBox:GetScript("OnCursorChanged")
+ box.editBox:SetScript("OnCursorChanged", nil)
+
+ local label1 = AceGUI:Create("Label")
+ local font = GameFontHighlightSmall:GetFont()
+ label1:SetFont(font, 14)
+ label1:SetText(" ")
+ label1:SetWidth(800)
+ frame:AddChild(label1)
+
+ local label2 = AceGUI:Create("Label")
+ local font = GameFontHighlightSmall:GetFont()
+ label2:SetFont(font, 14)
+ label2:SetText(" \n ")
+ label2:SetWidth(800)
+ frame:AddChild(label2)
+
+ if mode == "export" then
+ frame:SetTitle(L["Export Profile"])
+
+ local profileTypeDropdown = AceGUI:Create("Dropdown")
+ profileTypeDropdown:SetMultiselect(false)
+ profileTypeDropdown:SetLabel(L["Choose What To Export"])
+ profileTypeDropdown:SetList(profileTypeItems, profileTypeListOrder)
+ profileTypeDropdown:SetValue("profile")
+ frame:AddChild(profileTypeDropdown)
+
+ local exportFormatDropdown = AceGUI:Create("Dropdown")
+ exportFormatDropdown:SetMultiselect(false)
+ exportFormatDropdown:SetLabel(L["Choose Export Format"])
+ exportFormatDropdown:SetList(exportTypeItems, exportTypeListOrder)
+ exportFormatDropdown:SetValue("text")
+ exportFormatDropdown:SetWidth(150)
+ frame:AddChild(exportFormatDropdown)
+
+ local exportButton = AceGUI:Create("Button")
+ exportButton:SetText(L["Export Now"])
+ exportButton:SetAutoWidth(true)
+ local function OnClick(self)
+ label1:SetText(" ")
+ label2:SetText(" ")
+
+ local profileType, exportFormat = profileTypeDropdown:GetValue(), exportFormatDropdown:GetValue()
+ local profileKey, profileExport = D:ExportProfile(profileType, exportFormat)
+ if not profileKey or not profileExport then
+ label1:SetText(L["Error exporting profile!"])
+ else
+ label1:SetText(format("%s: %s%s|r", L["Exported"], E.media.hexvaluecolor, profileTypeItems[profileType]))
+ if(profileType == "profile") then
+ label2:SetText(format("%s: %s%s|r", L["Profile Name"], E.media.hexvaluecolor, profileKey))
+ end
+ end
+ box:SetText(profileExport)
+ box.editBox:HighlightText()
+ box:SetFocus()
+ exportString = profileExport
+ end
+ exportButton:SetCallback("OnClick", OnClick)
+ frame:AddChild(exportButton)
+
+ box.editBox:SetScript("OnChar", function() box:SetText(exportString) box.editBox:HighlightText() end)
+ box.editBox:SetScript("OnTextChanged", function()
+ if this then
+ box:SetText(exportString)
+ box.editBox:HighlightText()
+ end
+ box.scrollFrame:UpdateScrollChildRect()
+ end)
+ elseif mode == "import" then
+ frame:SetTitle(L["Import Profile"])
+ local importButton = AceGUI:Create("Button")
+ importButton:SetDisabled(true)
+ importButton:SetText(L["Import Now"])
+ importButton:SetAutoWidth(true)
+ importButton:SetCallback("OnClick", function()
+ label1:SetText(" ")
+ label2:SetText(" ")
+
+ local text
+ local success = D:ImportProfile(box:GetText())
+ if success then
+ text = L["Profile imported successfully!"]
+ else
+ text = L["Error decoding data. Import string may be corrupted!"]
+ end
+ label1:SetText(text)
+ end)
+ frame:AddChild(importButton)
+
+ local decodeButton = AceGUI:Create("Button")
+ decodeButton:SetDisabled(true)
+ decodeButton:SetText(L["Decode Text"])
+ decodeButton:SetAutoWidth(true)
+ decodeButton:SetCallback("OnClick", function()
+ label1:SetText(" ")
+ label2:SetText(" ")
+ local decodedText
+ local profileType, profileKey, profileData = D:Decode(box:GetText())
+ if profileData then
+ decodedText = E:TableToLuaString(profileData)
+ end
+ local importText = D:CreateProfileExport(decodedText, profileType, profileKey)
+ box:SetText(importText)
+ end)
+ frame:AddChild(decodeButton)
+
+ local oldText = ""
+ local function OnTextChanged()
+ local text = box:GetText()
+ if text == "" then
+ label1:SetText(" ")
+ label2:SetText(" ")
+ importButton:SetDisabled(true)
+ decodeButton:SetDisabled(true)
+ elseif oldText ~= text then
+ local stringType = D:GetImportStringType(text)
+ if stringType == "Base64" then
+ decodeButton:SetDisabled(false)
+ else
+ decodeButton:SetDisabled(true)
+ end
+
+ local profileType, profileKey = D:Decode(text)
+ if not profileType or (profileType and profileType == "profile" and not profileKey) then
+ label1:SetText(L["Error decoding data. Import string may be corrupted!"])
+ label2:SetText(" ")
+ importButton:SetDisabled(true)
+ decodeButton:SetDisabled(true)
+ else
+ label1:SetText(format("%s: %s%s|r", L["Importing"], E.media.hexvaluecolor, profileTypeItems[profileType] or ""))
+ if profileType == "profile" then
+ label2:SetText(format("%s: %s%s|r", L["Profile Name"], E.media.hexvaluecolor, profileKey))
+ end
+ importButton:SetDisabled(false)
+ end
+
+ box.scrollFrame:UpdateScrollChildRect()
+ box.scrollFrame:SetVerticalScroll(box.scrollFrame:GetVerticalScrollRange())
+
+ oldText = text
+ end
+ end
+
+ box.editBox:SetFocus()
+ box.editBox:SetScript("OnChar", nil)
+ box.editBox:SetScript("OnTextChanged", OnTextChanged)
+ end
+
+ frame:SetCallback("OnClose", function(widget)
+ box.editBox:SetScript("OnChar", nil)
+ box.editBox:SetScript("OnTextChanged", box.editBox.OnTextChangedOrig)
+ box.editBox:SetScript("OnCursorChanged", box.editBox.OnCursorChangedOrig)
+ box.editBox.OnTextChangedOrig = nil
+ box.editBox.OnCursorChangedOrig = nil
+
+ exportString = ""
+
+ AceGUI:Release(widget)
+ ACD:Open("ElvUI")
+ end)
+
+ label1:SetText(" ")
+ label2:SetText(" ")
+
+ ACD:Close("ElvUI")
+
+ GameTooltip:Hide()
+end
+
+E.Options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(E.data)
+AC.RegisterOptionsTable(E, "ElvProfiles", E.Options.args.profiles)
+E.Options.args.profiles.order = -10
+
+if not E.Options.args.profiles.plugins then
+ E.Options.args.profiles.plugins = {}
+end
+
+E.Options.args.profiles.plugins["ElvUI"] = {
+ spacer = {
+ order = 89,
+ type = "description",
+ name = "\n\n"
+ },
+ desc = {
+ order = 90,
+ type = "description",
+ name = L["This feature will allow you to transfer settings to other characters."]
+ },
+ distributeProfile = {
+ order = 91,
+ name = L["Share Current Profile"],
+ desc = L["Sends your current profile to your target."],
+ type = "execute",
+ func = function()
+ if not UnitExists("target") or not UnitIsPlayer("target") or not UnitIsFriend("player", "target") or UnitIsUnit("player", "target") then
+ E:Print(L["You must be targeting a player."])
+ return
+ end
+ local name, server = UnitName("target")
+ if name and not server or server == "" then
+ D:Distribute(name)
+ elseif server then
+ D:Distribute(name, true)
+ end
+ end
+ },
+ distributeGlobal = {
+ order = 92,
+ type = "execute",
+ name = L["Share Filters"],
+ desc = L["Sends your filter settings to your target."],
+ func = function()
+ if not UnitExists("target") or not UnitIsPlayer("target") or not UnitIsFriend("player", "target") or UnitIsUnit("player", "target") then
+ E:Print(L["You must be targeting a player."])
+ return
+ end
+ local name, server = UnitName("target")
+ if name and not server or server == "" then
+ D:Distribute(name, false, true)
+ elseif server then
+ D:Distribute(name, true, true)
+ end
+ end,
+ },
+ spacer2 = {
+ order = 93,
+ type = "description",
+ name = ""
+ },
+ exportProfile = {
+ order = 94,
+ type = "execute",
+ name = L["Export Profile"],
+ func = function() ExportImport_Open("export") end
+ },
+ importProfile = {
+ order = 95,
+ type = "execute",
+ name = L["Import Profile"],
+ func = function() ExportImport_Open("import") end
+ }
+}
\ No newline at end of file
diff --git a/ElvUI_Config/DataBars.lua b/ElvUI_Config/DataBars.lua
new file mode 100644
index 0000000..bc70139
--- /dev/null
+++ b/ElvUI_Config/DataBars.lua
@@ -0,0 +1,199 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local mod = E:GetModule("DataBars");
+
+local getn = table.getn
+
+E.Options.args.databars = {
+ type = "group",
+ name = L["DataBars"],
+ childGroups = "tab",
+ get = function(info) return E.db.databars[ info[getn(info)] ] end,
+ set = function(info, value) E.db.databars[ info[getn(info)] ] = value; end,
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["Setup on-screen display of information bars."]
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = ""
+ },
+ experience = {
+ order = 3,
+ get = function(info) return mod.db.experience[ info[getn(info)] ] end,
+ set = function(info, value) mod.db.experience[ info[getn(info)] ] = value; mod:UpdateExperienceDimensions() end,
+ type = "group",
+ name = XPBAR_LABEL,
+ args = {
+ enable = {
+ order = 0,
+ type = "toggle",
+ name = L["Enable"],
+ set = function(info, value) mod.db.experience[ info[getn(info)] ] = value; mod:EnableDisable_ExperienceBar() end
+ },
+ mouseover = {
+ order = 1,
+ type = "toggle",
+ name = L["Mouseover"]
+ },
+ hideAtMaxLevel = {
+ order = 2,
+ type = "toggle",
+ name = L["Hide At Max Level"],
+ set = function(info, value) mod.db.experience[ info[getn(info)] ] = value; mod:UpdateExperience() end
+ },
+ orientation = {
+ order = 3,
+ type = "select",
+ name = L["Statusbar Fill Orientation"],
+ desc = L["Direction the bar moves on gains/losses"],
+ values = {
+ ["HORIZONTAL"] = L["Horizontal"],
+ ["VERTICAL"] = L["Vertical"]
+ }
+ },
+ width = {
+ order = 4,
+ type = "range",
+ name = L["Width"],
+ min = 5, max = ceil(GetScreenWidth() or 800), step = 1
+ },
+ height = {
+ order = 5,
+ type = "range",
+ name = L["Height"],
+ min = 5, max = ceil(GetScreenHeight() or 800), step = 1
+ },
+ font = {
+ order = 6,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ textSize = {
+ order = 7,
+ name = FONT_SIZE,
+ type = "range",
+ min = 6, max = 33, step = 1
+ },
+ fontOutline = {
+ order = 8,
+ type = "select",
+ name = L["Font Outline"],
+ values = {
+ ["NONE"] = NONE,
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ textFormat = {
+ order = 9,
+ type = "select",
+ name = L["Text Format"],
+ width = "double",
+ values = {
+ NONE = NONE,
+ PERCENT = L["Percent"],
+ CUR = L["Current"],
+ REM = L["Remaining"],
+ CURMAX = L["Current - Max"],
+ CURPERC = L["Current - Percent"],
+ CURREM = L["Current - Remaining"],
+ CURPERCREM = L["Current - Percent (Remaining)"]
+ },
+ set = function(info, value) mod.db.experience[ info[getn(info)] ] = value; mod:UpdateExperience() end
+ }
+ }
+ },
+ reputation = {
+ order = 4,
+ get = function(info) return mod.db.reputation[ info[getn(info)] ] end,
+ set = function(info, value) mod.db.reputation[ info[getn(info)] ] = value; mod:UpdateReputationDimensions() end,
+ type = "group",
+ name = REPUTATION,
+ args = {
+ enable = {
+ order = 0,
+ type = "toggle",
+ name = L["Enable"],
+ set = function(info, value) mod.db.reputation[ info[getn(info)] ] = value; mod:EnableDisable_ReputationBar() end
+ },
+ mouseover = {
+ order = 1,
+ type = "toggle",
+ name = L["Mouseover"]
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = " "
+ },
+ orientation = {
+ order = 3,
+ type = "select",
+ name = L["Statusbar Fill Orientation"],
+ desc = L["Direction the bar moves on gains/losses"],
+ values = {
+ ["HORIZONTAL"] = L["Horizontal"],
+ ["VERTICAL"] = L["Vertical"]
+ }
+ },
+ width = {
+ order = 4,
+ type = "range",
+ name = L["Width"],
+ min = 5, max = ceil(GetScreenWidth() or 800), step = 1
+ },
+ height = {
+ order = 5,
+ type = "range",
+ name = L["Height"],
+ min = 5, max = ceil(GetScreenHeight() or 800), step = 1
+ },
+ font = {
+ order = 6,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ textSize = {
+ order = 7,
+ name = FONT_SIZE,
+ type = "range",
+ min = 6, max = 33, step = 1
+ },
+ fontOutline = {
+ order = 8,
+ type = "select",
+ name = L["Font Outline"],
+ values = {
+ ["NONE"] = NONE,
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ textFormat = {
+ order = 9,
+ type = "select",
+ name = L["Text Format"],
+ width = "double",
+ values = {
+ NONE = NONE,
+ CUR = L["Current"],
+ REM = L["Remaining"],
+ PERCENT = L["Percent"],
+ CURMAX = L["Current - Max"],
+ CURPERC = L["Current - Percent"],
+ CURREM = L["Current - Remaining"],
+ CURPERCREM = L["Current - Percent (Remaining)"],
+ },
+ set = function(info, value) mod.db.reputation[ info[getn(info)] ] = value; mod:UpdateReputation() end
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ElvUI_Config/DataTexts.lua b/ElvUI_Config/DataTexts.lua
new file mode 100644
index 0000000..1f02076
--- /dev/null
+++ b/ElvUI_Config/DataTexts.lua
@@ -0,0 +1,333 @@
+local E, L, V, P, G = unpack(ElvUI);
+local DT = E:GetModule("DataTexts");
+
+local find, upper = string.find, string.upper
+
+local datatexts = {};
+
+function DT:PanelLayoutOptions()
+ for name, data in pairs(DT.RegisteredDataTexts) do
+ datatexts[name] = data.localizedName or L[name]
+ end
+ datatexts[""] = NONE;
+
+ local order;
+ local table = E.Options.args.datatexts.args.panels.args;
+ for pointLoc, tab in pairs(P.datatexts.panels) do
+ if(not _G[pointLoc]) then table[pointLoc] = nil; return; end
+ if(type(tab) == "table") then
+ if find(pointLoc, "Chat") then
+ order = 15;
+ else
+ order = 20;
+ end
+ table[pointLoc] = {
+ order = order,
+ type = "group",
+ name = L[pointLoc] or pointLoc,
+ args = {}
+ };
+ for option, value in pairs(tab) do
+ table[pointLoc].args[option] = {
+ type = "select",
+ name = L[option] or upper(option),
+ values = datatexts,
+ get = function(info) return E.db.datatexts.panels[pointLoc][ info[getn(info)] ]; end,
+ set = function(info, value) E.db.datatexts.panels[pointLoc][ info[getn(info)] ] = value; DT:LoadDataTexts(); end
+ };
+ end
+ elseif(type(tab) == "string") then
+ table.smallPanels.args[pointLoc] = {
+ type = "select",
+ name = L[pointLoc] or pointLoc,
+ values = datatexts,
+ get = function(info) return E.db.datatexts.panels[pointLoc]; end,
+ set = function(info, value) E.db.datatexts.panels[pointLoc] = value; DT:LoadDataTexts(); end
+ };
+ end
+ end
+end
+
+E.Options.args.datatexts = {
+ type = "group",
+ name = L["DataTexts"],
+ childGroups = "tab",
+ get = function(info) return E.db.datatexts[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.datatexts[ info[getn(info)] ] = value; DT:LoadDataTexts(); end,
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["DATATEXT_DESC"]
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = ""
+ },
+ general = {
+ order = 3,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"]
+ },
+ generalGroup = {
+ order = 2,
+ type = "group",
+ guiInline = true,
+ name = L["General"],
+ args = {
+ battleground = {
+ order = 1,
+ type = "toggle",
+ name = L["Battleground Texts"],
+ desc = L["When inside a battleground display personal scoreboard information on the main datatext bars."]
+ },
+ panelTransparency = {
+ order = 2,
+ name = L["Panel Transparency"],
+ type = "toggle",
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Layout"):SetDataPanelStyle();
+ end
+ },
+ panelBackdrop = {
+ order = 3,
+ name = L["Backdrop"],
+ type = "toggle",
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value
+ E:GetModule("Layout"):SetDataPanelStyle()
+ end,
+ },
+ noCombatClick = {
+ order = 4,
+ type = "toggle",
+ name = L["Block Combat Click"],
+ desc = L["Blocks all click events while in combat."]
+ },
+ noCombatHover = {
+ order = 5,
+ type = "toggle",
+ name = L["Block Combat Hover"],
+ desc = L["Blocks datatext tooltip from showing in combat."]
+ },
+ goldFormat = {
+ order = 6,
+ type = "select",
+ name = L["Gold Format"],
+ desc = L["The display format of the money text that is shown in the gold datatext and its tooltip."],
+ values = {
+ ["SMART"] = L["Smart"],
+ ["FULL"] = L["Full"],
+ ["SHORT"] = L["Short"],
+ ["SHORTINT"] = L["Short (Whole Numbers)"],
+ ["CONDENSED"] = L["Condensed"],
+ ["BLIZZARD"] = L["Blizzard Style"]
+ }
+ }
+ }
+ },
+ fontGroup = {
+ order = 3,
+ type = "group",
+ guiInline = true,
+ name = L["Fonts"],
+ args = {
+ font = {
+ order = 1,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ fontSize = {
+ order = 2,
+ type = "range",
+ name = L["Font Size"],
+ min = 4, max = 22, step = 1
+ },
+ fontOutline = {
+ order = 3,
+ type = "select",
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ },
+ wordWrap = {
+ order = 4,
+ type = "toggle",
+ name = L["Word Wrap"]
+ }
+ }
+ }
+ }
+ },
+ panels = {
+ type = "group",
+ name = L["Panels"],
+ order = 4,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Panels"]
+ },
+ leftChatPanel = {
+ order = 2,
+ type = "toggle",
+ name = L["Datatext Panel (Left)"],
+ desc = L["Display data panels below the chat, used for datatexts."],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ if(E.db.LeftChatPanelFaded) then
+ E.db.LeftChatPanelFaded = true;
+ HideLeftChat();
+ end
+ E:GetModule("Chat"):UpdateAnchors();
+ E:GetModule("Layout"):ToggleChatPanels();
+ end
+ },
+ rightChatPanel = {
+ order = 3,
+ type = "toggle",
+ name = L["Datatext Panel (Right)"],
+ desc = L["Display data panels below the chat, used for datatexts."],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ if(E.db.RightChatPanelFaded) then
+ E.db.RightChatPanelFaded = true;
+ HideRightChat();
+ end
+ E:GetModule("Chat"):UpdateAnchors();
+ E:GetModule("Layout"):ToggleChatPanels();
+ end
+ },
+ minimapPanels = {
+ order = 4,
+ type = "toggle",
+ name = L["Minimap Panels"],
+ desc = L["Display minimap panels below the minimap, used for datatexts."],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end
+ },
+ minimapTop = {
+ order = 5,
+ name = L["TopMiniPanel"],
+ type = "toggle",
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end
+ },
+ minimapTopLeft = {
+ order = 6,
+ type = "toggle",
+ name = L["TopLeftMiniPanel"],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end,
+ },
+ minimapTopRight = {
+ order = 7,
+ type = "toggle",
+ name = L["TopRightMiniPanel"],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end
+ },
+ minimapBottom = {
+ order = 8,
+ type = "toggle",
+ name = L["BottomMiniPanel"],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end
+ },
+ minimapBottomLeft = {
+ order = 9,
+ type = "toggle",
+ name = L["BottomLeftMiniPanel"],
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end
+ },
+ minimapBottomRight = {
+ order = 10,
+ name = L["BottomRightMiniPanel"],
+ type = "toggle",
+ set = function(info, value)
+ E.db.datatexts[ info[getn(info)] ] = value;
+ E:GetModule("Minimap"):UpdateSettings();
+ end
+ },
+ spacer = {
+ order = 11,
+ type = "description",
+ name = "\n"
+ },
+ smallPanels = {
+ order = 12,
+ type = "group",
+ name = L["Small Panels"],
+ args = {}
+ }
+ }
+ },
+ time = {
+ order = 5,
+ type = "group",
+ name = L["Time"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Time"],
+ },
+ timeFormat = {
+ order = 2,
+ type = "select",
+ name = L["Time Format"],
+ values = {
+ [""] = NONE,
+ ["%I:%M"] = "03:27",
+ ["%I:%M:%S"] = "03:27:32",
+ ["%I:%M %p"] = "03:27 PM",
+ ["%I:%M:%S %p"] = "03:27:32 PM",
+ ["%H:%M"] = "15:27",
+ ["%H:%M:%S"] ="15:27:32"
+ }
+ },
+ dateFormat = {
+ order = 3,
+ type = "select",
+ name = L["Date Format"],
+ values = {
+ [""] = NONE,
+ ["%d/%m/%y "] = "27/03/16",
+ ["%m/%d/%y "] = "03/27/16",
+ ["%y/%m/%d "] = "16/03/27",
+ ["%d.%m.%y "] = "27.03.16"
+ }
+ }
+ }
+ }
+ }
+};
+
+DT:PanelLayoutOptions();
\ No newline at end of file
diff --git a/ElvUI_Config/ElvUI_Config.toc b/ElvUI_Config/ElvUI_Config.toc
new file mode 100644
index 0000000..3768671
--- /dev/null
+++ b/ElvUI_Config/ElvUI_Config.toc
@@ -0,0 +1,24 @@
+## Interface: 11200
+## Author: Elv, Bunny
+## Version: 1.01
+## Title: |cffA11313E|r|cffC4C4C4lvUI|r |cffA11313C|r|cffC4C4C4onfig|r
+## Notes: Options for ElvUI.
+## RequiredDeps: ElvUI
+## LoadOnDemand: true
+
+Libraries\Load_Libraries.xml
+Locales\Load_Locales.xml
+Core.lua
+General.lua
+ActionBars.lua
+Auras.lua
+Bags.lua
+Chat.lua
+DataTexts.lua
+Filters.lua
+NamePlates.lua
+Skins.lua
+Tooltip.lua
+Unitframes.lua
+DataBars.lua
+Maps.lua
\ No newline at end of file
diff --git a/ElvUI_Config/General.lua b/ElvUI_Config/General.lua
new file mode 100644
index 0000000..4459811
--- /dev/null
+++ b/ElvUI_Config/General.lua
@@ -0,0 +1,722 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local CC = E:GetModule("ClassCache");
+
+E.Options.args.general = {
+ type = "group",
+ name = L["General"],
+ order = 1,
+ childGroups = "tab",
+ get = function(info) return E.db.general[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general[ info[getn(info)] ] = value; end,
+ args = {
+ versionCheck = {
+ order = 1,
+ type = "toggle",
+ name = L["Version Check"],
+ get = function(info) return E.global.general.versionCheck; end,
+ set = function(info, value) E.global.general.versionCheck = value; end
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full",
+ },
+ intro = {
+ order = 3,
+ type = "description",
+ name = L["ELVUI_DESC"],
+ },
+ general = {
+ order = 4,
+ type = "group",
+ name = L["General"],
+ args = {
+ generalHeader = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ pixelPerfect = {
+ order = 2,
+ type = "toggle",
+ name = L["Thin Border Theme"],
+ desc = L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."],
+ get = function(info) return E.private.general.pixelPerfect; end,
+ set = function(info, value) E.private.general.pixelPerfect = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ interruptAnnounce = {
+ order = 3,
+ type = "select",
+ name = L["Announce Interrupts"],
+ desc = L["Announce when you interrupt a spell to the specified chat channel."],
+ values = {
+ ["NONE"] = NONE,
+ ["SAY"] = SAY,
+ ["PARTY"] = L["Party Only"],
+ ["RAID"] = L["Party / Raid"],
+ ["RAID_ONLY"] = L["Raid Only"],
+ ["EMOTE"] = CHAT_MSG_EMOTE
+ }
+ },
+ autoRepair = {
+ order = 4,
+ type = "select",
+ name = L["Auto Repair"],
+ desc = L["Automatically repair using the following method when visiting a merchant."],
+ values = {
+ ["NONE"] = NONE,
+ ["PLAYER"] = PLAYER
+ }
+ },
+ autoAcceptInvite = {
+ order = 5,
+ type = "toggle",
+ name = L["Accept Invites"],
+ desc = L["Automatically accept invites from guild/friends."]
+ },
+ vendorGrays = {
+ order = 6,
+ type = "toggle",
+ name = L["Vendor Grays"],
+ desc = L["Automatically vendor gray items when visiting a vendor."]
+ },
+ autoRoll = {
+ order = 7,
+ type = "toggle",
+ name = L["Auto Greed/DE"],
+ desc = L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."],
+ disabled = function() return not E.private.general.lootRoll; end
+ },
+ loot = {
+ order = 8,
+ type = "toggle",
+ name = L["Loot"],
+ desc = L["Enable/Disable the loot frame."],
+ get = function(info) return E.private.general.loot; end,
+ set = function(info, value) E.private.general.loot = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ lootRoll = {
+ order = 9,
+ type = "toggle",
+ name = L["Loot Roll"],
+ desc = L["Enable/Disable the loot roll frame."],
+ get = function(info) return E.private.general.lootRoll; end,
+ set = function(info, value) E.private.general.lootRoll = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ lootUnderMouse = {
+ order = 10,
+ type = "toggle",
+ name = L["Loot Under Mouse"],
+ desc = L["Enable/Disable loot frame under the mouse cursor."],
+ get = function(info) return E.private.general.lootUnderMouse; end,
+ set = function(info, value) E.private.general.lootUnderMouse = value; end,
+ disabled = function() return not E.private.general.loot; end
+ },
+ eyefinity = {
+ order = 11,
+ name = L["Multi-Monitor Support"],
+ desc = L["Attempt to support eyefinity/nvidia surround."],
+ type = "toggle",
+ get = function(info) return E.global.general.eyefinity; end,
+ set = function(info, value) E.global.general[ info[getn(info)] ] = value; E:StaticPopup_Show("GLOBAL_RL"); end
+ },
+ hideErrorFrame = {
+ order = 12,
+ type = "toggle",
+ name = L["Hide Error Text"],
+ desc = L["Hides the red error text at the top of the screen while in combat."]
+ },
+ taintLog = {
+ order = 13,
+ type = "toggle",
+ name = L["Log Taints"],
+ desc = L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."]
+ },
+ bottomPanel = {
+ order = 14,
+ type = "toggle",
+ name = L["Bottom Panel"],
+ desc = L["Display a panel across the bottom of the screen. This is for cosmetic only."],
+ get = function(info) return E.db.general.bottomPanel; end,
+ set = function(info, value) E.db.general.bottomPanel = value; E:GetModule("Layout"):BottomPanelVisibility(); end
+ },
+ topPanel = {
+ order = 15,
+ type = "toggle",
+ name = L["Top Panel"],
+ desc = L["Display a panel across the top of the screen. This is for cosmetic only."],
+ get = function(info) return E.db.general.topPanel; end,
+ set = function(info, value) E.db.general.topPanel = value; E:GetModule("Layout"):TopPanelVisibility(); end
+ },
+ afk = {
+ order = 16,
+ type = "toggle",
+ name = L["AFK Mode"],
+ desc = L["When you go AFK display the AFK screen."],
+ get = function(info) return E.db.general.afk; end,
+ set = function(info, value) E.db.general.afk = value; E:GetModule("AFK"):Toggle(); end
+ },
+ enhancedPvpMessages = {
+ order = 17,
+ type = "toggle",
+ name = L["Enhanced PVP Messages"],
+ desc = L["Display battleground messages in the middle of the screen."],
+ },
+ raidUtility = {
+ order = 18,
+ type = "toggle",
+ name = RAID_CONTROL,
+ desc = L["Enables the ElvUI Raid Control panel."],
+ get = function(info) return E.private.general.raidUtility end,
+ set = function(info, value) E.private.general.raidUtility = value; E:StaticPopup_Show("PRIVATE_RL") end
+ },
+ autoScale = {
+ order = 19,
+ name = L["Auto Scale"],
+ desc = L["Automatically scale the User Interface based on your screen resolution"],
+ type = "toggle",
+ get = function(info) return E.global.general.autoScale; end,
+ set = function(info, value) E.global.general[ info[getn(info)] ] = value; E:StaticPopup_Show("GLOBAL_RL") end
+ },
+ minUiScale = {
+ order = 20,
+ type = "range",
+ name = L["Lowest Allowed UI Scale"],
+ min = 0.32, max = 0.64, step = 0.01,
+ get = function(info) return E.global.general.minUiScale; end,
+ set = function(info, value) E.global.general.minUiScale = value; E:StaticPopup_Show("GLOBAL_RL"); end
+ },
+ numberPrefixStyle = {
+ order = 21,
+ type = "select",
+ name = L["Number Prefix"],
+ get = function(info) return E.db.general.numberPrefixStyle; end,
+ set = function(info, value) E.db.general.numberPrefixStyle = value; E:StaticPopup_Show("CONFIG_RL"); end,
+ values = {
+ ["METRIC"] = "Metric (k, M, G)",
+ ["ENGLISH"] = "English (K, M, B)",
+ ["CHINESE"] = "Chinese (W, Y)",
+ ["KOREAN"] = "Korean (천, 만, 억)",
+ ["GERMAN"] = "German (Tsd, Mio, Mrd)"
+ }
+ },
+ decimalLength = {
+ order = 22,
+ type = "range",
+ name = L["Decimal Length"],
+ desc = L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."],
+ min = 0, max = 4, step = 1,
+ get = function(info) return E.db.general.decimalLength end,
+ set = function(info, value) E.db.general.decimalLength = value; E:StaticPopup_Show("GLOBAL_RL") end
+ },
+ classCacheHeader = {
+ order = 51,
+ type = "header",
+ name = L["Class Cache"]
+ },
+ classCacheEnable = {
+ order = 52,
+ type = "toggle",
+ name = L["Enable"],
+ desc = L["Enable class caching to colorize names in chat and nameplates."],
+ get = function(info) return E.private.general.classCache end,
+ set = function(info, value)
+ E.private.general.classCache = value
+ CC:ToggleModule()
+ end
+ },
+ classCacheStoreInDB = {
+ order = 53,
+ type = "toggle",
+ name = L["Store cache in DB"],
+ desc = L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."],
+ get = function(info) return E.db.general.classCacheStoreInDB end,
+ set = function(info, value)
+ E.db.general.classCacheStoreInDB = value
+ CC:SwitchCacheType()
+ end,
+ disabled = function() return not E.private.general.classCache end
+ },
+ classCacheRequestInfo = {
+ order = 54,
+ type = "toggle",
+ name = L["Request info for class cache"],
+ desc = L["Use LibWho to cache class info"],
+ get = function(info) return E.db.general.classCacheRequestInfo end,
+ set = function(info, value)
+ E.db.general.classCacheRequestInfo = value
+ end,
+ disabled = function() return not E.private.general.classCache end
+ },
+ wipeClassCacheGlobal = {
+ order = 55,
+ type = "execute",
+ name = L["Wipe DB Cache"],
+ func = function()
+ CC:WipeCache(true)
+ GameTooltip:Hide()
+ end,
+ disabled = function() return not CC:GetCacheSize(true) end
+ },
+ wipeClassCacheLocal = {
+ order = 56,
+ type = "execute",
+ name = L["Wipe Session Cache"],
+ func = function()
+ CC:WipeCache()
+ GameTooltip:Hide()
+ end,
+ disabled = function() return not CC:GetCacheSize() end
+ }
+ }
+ },
+ media = {
+ order = 6,
+ type = "group",
+ name = L["Media"],
+ get = function(info) return E.db.general[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general[ info[getn(info)] ] = value end,
+ args = {
+ fontHeader = {
+ order = 1,
+ type = "header",
+ name = L["Fonts"]
+ },
+ fontSize = {
+ order = 2,
+ type = "range",
+ name = L["Font Size"],
+ desc = L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"],
+ min = 4, max = 33, step = 1,
+ set = function(info, value) E.db.general[ info[getn(info)] ] = value; E:UpdateMedia(); E:UpdateFontTemplates(); end
+ },
+ font = {
+ order = 3,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Default Font"],
+ desc = L["The font that the core of the UI will use."],
+ values = AceGUIWidgetLSMlists.font,
+ set = function(info, value) E.db.general[ info[getn(info)] ] = value; E:UpdateMedia(); E:UpdateFontTemplates(); end,
+ },
+ applyFontToAll = {
+ order = 4,
+ type = "execute",
+ name = L["Apply Font To All"],
+ desc = L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."],
+ func = function() E:StaticPopup_Show("APPLY_FONT_WARNING"); end
+ },
+ dmgfont = {
+ order = 5,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["CombatText Font"],
+ desc = L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"],
+ values = AceGUIWidgetLSMlists.font,
+ get = function(info) return E.private.general[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.general[ info[getn(info)] ] = value; E:UpdateMedia(); E:UpdateFontTemplates(); E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ namefont = {
+ order = 6,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Name Font"],
+ desc = L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"],
+ values = AceGUIWidgetLSMlists.font,
+ get = function(info) return E.private.general[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.general[ info[getn(info)] ] = value; E:UpdateMedia(); E:UpdateFontTemplates(); E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ replaceBlizzFonts = {
+ order = 7,
+ type = "toggle",
+ name = L["Replace Blizzard Fonts"],
+ desc = L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."],
+ get = function(info) return E.private.general[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.general[ info[getn(info)] ] = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ texturesHeaderSpacing = {
+ order = 8,
+ type = "description",
+ name = " "
+ },
+ texturesHeader = {
+ order = 9,
+ type = "header",
+ name = L["Textures"]
+ },
+ normTex = {
+ order = 10,
+ type = "select", dialogControl = "LSM30_Statusbar",
+ name = L["Primary Texture"],
+ desc = L["The texture that will be used mainly for statusbars."],
+ values = AceGUIWidgetLSMlists.statusbar,
+ get = function(info) return E.private.general[ info[getn(info)] ]; end,
+ set = function(info, value)
+ local previousValue = E.private.general[ info[getn(info)] ];
+ E.private.general[ info[getn(info)] ] = value;
+
+ if(E.db.unitframe.statusbar == previousValue) then
+ E.db.unitframe.statusbar = value;
+ E:UpdateAll(true);
+ else
+ E:UpdateMedia();
+ E:UpdateStatusBars();
+ end
+ end
+ },
+ glossTex = {
+ order = 11,
+ type = "select", dialogControl = "LSM30_Statusbar",
+ name = L["Secondary Texture"],
+ desc = L["This texture will get used on objects like chat windows and dropdown menus."],
+ values = AceGUIWidgetLSMlists.statusbar,
+ get = function(info) return E.private.general[ info[getn(info)] ]; end,
+ set = function(info, value)
+ E.private.general[ info[getn(info)] ] = value;
+ E:UpdateMedia();
+ E:UpdateFrameTemplates();
+ end
+ },
+ applyTextureToAll = {
+ order = 12,
+ type = "execute",
+ name = L["Apply Texture To All"],
+ desc = L["Applies the primary texture to all statusbars."],
+ func = function()
+ local texture = E.private.general.normTex;
+ E.db.unitframe.statusbar = texture;
+ E:UpdateAll(true);
+ end
+ },
+ colorsHeaderSpacing = {
+ order = 13,
+ type = "description",
+ name = " "
+ },
+ colorsHeader = {
+ order = 14,
+ type = "header",
+ name = L["Colors"]
+ },
+ bordercolor = {
+ type = "color",
+ order = 15,
+ name = L["Border Color"],
+ desc = L["Main border color of the UI."],
+ hasAlpha = false,
+ get = function(info)
+ local t = E.db.general[ info[getn(info)] ];
+ local d = P.general[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.general[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ E:UpdateMedia();
+ E:UpdateBorderColors();
+ end,
+ },
+ backdropcolor = {
+ type = "color",
+ order = 32,
+ name = L["Backdrop Color"],
+ desc = L["Main backdrop color of the UI."],
+ hasAlpha = false,
+ get = function(info)
+ local t = E.db.general[ info[getn(info)] ];
+ local d = P.general[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.general[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ E:UpdateMedia();
+ E:UpdateBackdropColors();
+ end
+ },
+ backdropfadecolor = {
+ type = "color",
+ order = 33,
+ name = L["Backdrop Faded Color"],
+ desc = L["Backdrop color of transparent frames"],
+ hasAlpha = true,
+ get = function(info)
+ local t = E.db.general[ info[getn(info)] ];
+ local d = P.general[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b, d.a;
+ end,
+ set = function(info, r, g, b, a)
+ E.db.general[ info[getn(info)] ] = {};
+ local t = E.db.general[ info[getn(info)] ];
+ t.r, t.g, t.b, t.a = r, g, b, a;
+ E:UpdateMedia();
+ E:UpdateBackdropColors();
+ end
+ },
+ valuecolor = {
+ type = "color",
+ order = 34,
+ name = L["Value Color"],
+ desc = L["Color some texts use."],
+ hasAlpha = false,
+ get = function(info)
+ local t = E.db.general[ info[getn(info)] ];
+ local d = P.general[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b, a)
+ E.db.general[ info[getn(info)] ] = {};
+ local t = E.db.general[ info[getn(info)] ];
+ t.r, t.g, t.b, t.a = r, g, b, a;
+ E:UpdateMedia();
+ end
+ }
+ }
+ },
+ --[[totems = {
+ order = 7,
+ type = "group",
+ name = TUTORIAL_TITLE47,
+ get = function(info) return E.db.general.totems[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.totems[ info[getn(info)] ] = value; E:GetModule("Totems"):PositionAndSize(); end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = TUTORIAL_TITLE47
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ set = function(info, value) E.db.general.totems[ info[getn(info)] ] = value; E:GetModule("Totems"):ToggleEnable(); end
+ },
+ size = {
+ order = 3,
+ type = "range",
+ name = L["Button Size"],
+ min = 24, max = 60, step = 1
+ },
+ spacing = {
+ order = 4,
+ type = "range",
+ name = L["Button Spacing"],
+ min = 1, max = 10, step = 1
+ },
+ sortDirection = {
+ order = 5,
+ type = "select",
+ name = L["Sort Direction"],
+ values = {
+ ["ASCENDING"] = L["Ascending"],
+ ["DESCENDING"] = L["Descending"]
+ }
+ },
+ growthDirection = {
+ order = 6,
+ type = "select",
+ name = L["Bar Direction"],
+ values = {
+ ["VERTICAL"] = L["Vertical"],
+ ["HORIZONTAL"] = L["Horizontal"]
+ }
+ }
+ }
+ },--]]
+ cooldown = {
+ type = "group",
+ order = 8,
+ name = L["Cooldown Text"],
+ get = function(info)
+ local t = E.db.cooldown[ info[getn(info)] ];
+ local d = P.cooldown[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.cooldown[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ E:UpdateCooldownSettings();
+ end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Cooldown Text"]
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ desc = L["Display cooldown text on anything with the cooldown spiral."],
+ get = function(info) return E.private.cooldown[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.cooldown[ info[getn(info)] ] = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ threshold = {
+ type = "range",
+ order = 3,
+ name = L["Low Threshold"],
+ desc = L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"],
+ min = -1, max = 20, step = 1,
+ get = function(info) return E.db.cooldown[ info[getn(info)] ]; end,
+ set = function(info, value)
+ E.db.cooldown[ info[getn(info)] ] = value;
+ E:UpdateCooldownSettings();
+ end
+ },
+ expiringColor = {
+ order = 4,
+ type = "color",
+ name = L["Expiring"],
+ desc = L["Color when the text is about to expire"]
+ },
+ secondsColor = {
+ order = 5,
+ type = "color",
+ name = L["Seconds"],
+ desc = L["Color when the text is in the seconds format."]
+ },
+ minutesColor = {
+ order = 6,
+ type = "color",
+ name = L["Minutes"],
+ desc = L["Color when the text is in the minutes format."]
+ },
+ hoursColor = {
+ order = 7,
+ type = "color",
+ name = L["Hours"],
+ desc = L["Color when the text is in the hours format."]
+ },
+ daysColor = {
+ order = 8,
+ type = "color",
+ name = L["Days"],
+ desc = L["Color when the text is in the days format."]
+ }
+ }
+ },
+ chatBubbles = {
+ order = 9,
+ type = "group",
+ name = L["Chat Bubbles"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Chat Bubbles"]
+ },
+ style = {
+ order = 2,
+ type = "select",
+ name = L["Chat Bubbles Style"],
+ desc = L["Skin the blizzard chat bubbles."],
+ get = function(info) return E.private.general.chatBubbles; end,
+ set = function(info, value) E.private.general.chatBubbles = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ values = {
+ ["backdrop"] = L["Skin Backdrop"],
+ ["nobackdrop"] = L["Remove Backdrop"],
+ ["backdrop_noborder"] = L["Skin Backdrop (No Borders)"],
+ ["disabled"] = L["Disabled"]
+ }
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = " ",
+ },
+ font = {
+ order = 4,
+ type = "select",
+ name = L["Font"],
+ dialogControl = "LSM30_Font",
+ values = AceGUIWidgetLSMlists.font,
+ get = function(info) return E.private.general.chatBubbleFont; end,
+ set = function(info, value) E.private.general.chatBubbleFont = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ disabled = function() return E.private.general.chatBubbles == "disabled"; end
+ },
+ fontSize = {
+ order = 5,
+ type = "range",
+ name = L["Font Size"],
+ get = function(info) return E.private.general.chatBubbleFontSize; end,
+ set = function(info, value) E.private.general.chatBubbleFontSize = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ min = 4, max = 33, step = 1,
+ disabled = function() return E.private.general.chatBubbles == "disabled"; end
+ },
+ fontOutline = {
+ order = 6,
+ type = "select",
+ name = L["Font Outline"],
+ get = function(info) return E.private.general.chatBubbleFontOutline end,
+ set = function(info, value) E.private.general.chatBubbleFontOutline = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ disabled = function() return E.private.general.chatBubbles == "disabled" end,
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE",
+ }
+ }
+ }
+ },
+ watchFrame = {
+ order = 10,
+ type = "group",
+ name = L["Watch Frame"],
+ get = function(info) return E.db.general[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general[ info[getn(info)] ] = value; end,
+ args = {
+ watchFrameHeader = {
+ order = 1,
+ type = "header",
+ name = L["Watch Frame"],
+ },
+ watchFrameHeight = {
+ order = 2,
+ type = "range",
+ name = L["Watch Frame Height"],
+ desc = L["Height of the watch tracker. Increase size to be able to see more objectives."],
+ min = 400, max = E.screenheight, step = 1,
+ set = function(info, value) E.db.general[ info[getn(info)] ] = value; E:GetModule("Blizzard"):SetWatchFrameHeight(); end
+ }
+ }
+ },
+ --[[threatGroup = {
+ order = 11,
+ type = "group",
+ name = L["Threat"],
+ args = {
+ threatHeader = {
+ order = 40,
+ type = "header",
+ name = L["Threat"]
+ },
+ threatEnable = {
+ order = 41,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.db.general.threat.enable; end,
+ set = function(info, value) E.db.general.threat.enable = value; E:GetModule("Threat"):ToggleEnable()end
+ },
+ threatPosition = {
+ order = 42,
+ type = "select",
+ name = L["Position"],
+ desc = L["Adjust the position of the threat bar to either the left or right datatext panels."],
+ values = {
+ ["LEFTCHAT"] = L["Left Chat"],
+ ["RIGHTCHAT"] = L["Right Chat"]
+ },
+ get = function(info) return E.db.general.threat.position; end,
+ set = function(info, value) E.db.general.threat.position = value; E:GetModule("Threat"):UpdatePosition(); end
+ },
+ threatTextSize = {
+ order = 43,
+ name = L["Font Size"],
+ type = "range",
+ min = 6, max = 22, step = 1,
+ get = function(info) return E.db.general.threat.textSize; end,
+ set = function(info, value) E.db.general.threat.textSize = value; E:GetModule("Threat"):UpdatePosition(); end
+ }
+ }
+ }--]]
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfig-3.0.lua b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfig-3.0.lua
new file mode 100644
index 0000000..e319f6f
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfig-3.0.lua
@@ -0,0 +1,70 @@
+--- AceConfig-3.0 wrapper library.
+-- Provides an API to register an options table with the config registry,
+-- as well as associate it with a slash command.
+-- @class file
+-- @name AceConfig-3.0
+-- @release $Id: AceConfig-3.0.lua 969 2010-10-07 02:11:48Z shefki $
+
+--[[
+AceConfig-3.0
+
+Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
+
+]]
+
+local MAJOR, MINOR = "AceConfig-3.0", 2
+local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceConfig then return end
+
+AceConfig.embeds = AceConfig.embeds or {}
+
+local cfgreg = LibStub("AceConfigRegistry-3.0")
+local cfgcmd = LibStub("AceConfigCmd-3.0")
+--TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true)
+--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true)
+
+-- Lua APIs
+local pcall, error, type, pairs = pcall, error, type, pairs
+
+-- -------------------------------------------------------------------
+-- :RegisterOptionsTable(appName, options, slashcmd, persist)
+--
+-- - appName - (string) application name
+-- - options - table or function ref, see AceConfigRegistry
+-- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
+
+--- Register a option table with the AceConfig registry.
+-- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
+-- @paramsig appName, options [, slashcmd]
+-- @param appName The application name for the config table.
+-- @param options The option table (or a function to generate one on demand). http://www.wowace.com/addons/ace3/pages/ace-config-3-0-options-tables/
+-- @param slashcmd A slash command to register for the option table, or a table of slash commands.
+-- @usage
+-- local AceConfig = LibStub("AceConfig-3.0")
+-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
+function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
+ if self == AceConfig then
+ error([[Usage: RegisterOptionsTable(appName, options[, slashcmd]): 'self' - use your own 'self']], 2)
+ end
+ local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
+ if not ok then error(msg, 2) end
+
+ if slashcmd then
+ if type(slashcmd) == "table" then
+ for _,cmd in pairs(slashcmd) do
+ cfgcmd.CreateChatCommand(self, cmd, appName)
+ end
+ else
+ cfgcmd.CreateChatCommand(self, slashcmd, appName)
+ end
+ end
+end
+
+function AceConfig:Embed(target)
+ target["RegisterOptionsTable"] = self["RegisterOptionsTable"]
+end
+
+for addon in pairs(AceConfig.embeds) do
+ AceConfig:Embed(addon)
+end
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfig-3.0.xml b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfig-3.0.xml
new file mode 100644
index 0000000..6d7e3d5
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfig-3.0.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua
new file mode 100644
index 0000000..02b87dc
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua
@@ -0,0 +1,863 @@
+--- AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames.
+-- @class file
+-- @name AceConfigCmd-3.0
+-- @release $Id: AceConfigCmd-3.0.lua 1045 2011-12-09 17:58:40Z nevcairiel $
+
+--[[
+AceConfigCmd-3.0
+
+Handles commandline optionstable access
+
+REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
+
+]]
+
+-- TODO: plugin args
+
+
+local MAJOR, MINOR = "AceConfigCmd-3.0", 13
+local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceConfigCmd then return end
+
+local AceCore = LibStub("AceCore-3.0")
+local Dispatchers = AceCore.Dispatchers
+local strtrim = AceCore.strtrim
+--local strsplit = AceCore.strsplit
+local new, del = AceCore.new, AceCore.del
+local wipe = AceCore.wipe
+
+AceConfigCmd.commands = AceConfigCmd.commands or {}
+AceConfigCmd.embeds = AceConfigCmd.embeds or {}
+local commands = AceConfigCmd.commands
+
+local cfgreg = LibStub("AceConfigRegistry-3.0")
+local AceConsole -- LoD
+local AceConsoleName = "AceConsole-3.0"
+
+-- Lua APIs
+local strbyte, strsub = string.byte, string.sub
+local strlen, strupper, strlower = string.len, string.upper, string.lower
+local strfind, strgfind, strgsub = string.find, string.gfind, string.gsub
+
+local format = string.format
+local tsort, tinsert, tgetn, tremove = table.sort, table.insert, table.getn, table.remove
+
+-- WoW APIs
+local _G = AceCore._G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, SELECTED_CHAT_FRAME, DEFAULT_CHAT_FRAME
+
+
+local L = setmetatable({}, { -- TODO: replace with proper locale
+ __index = function(self,k) return k end
+})
+
+
+
+local function print(msg)
+ (SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg)
+end
+
+-- constants used by getparam() calls below
+
+local handlertypes = {["table"]=true}
+local handlermsg = "expected a table"
+
+local functypes = {["function"]=true, ["string"]=true}
+local funcmsg = "expected function or member name"
+
+local pickfirstset = AceCore.pickfirstset
+
+-- err() - produce real error() regarding malformed options tables etc
+
+local function err(info,inputpos,msg )
+ local cmdstr=" "..strsub(info.input, 1, inputpos-1)
+ error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2)
+end
+
+
+-- usererr() - produce chatframe message regarding bad slash syntax etc
+
+local function usererr(info,inputpos,msg )
+ local cmdstr=strsub(info.input, 1, inputpos-1);
+ print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table"))
+end
+
+
+-- callmethod() - call a given named method (e.g. "get", "set") with given arguments
+
+
+
+local function callmethod(info, inputpos, tab, methodtype, argc, a1, a2, a3, a4)
+ local method = info[methodtype]
+ if not method then
+ err(info, inputpos, "'"..methodtype.."': not set")
+ end
+
+ argc = argc or 0
+ info.arg = tab.arg
+ info.option = tab
+ info.type = tab.type
+
+ if type(method)=="function" then
+ return Dispatchers[argc+1](method, info, a1, a2, a3, a4)
+ elseif type(method)=="string" then
+ if type(info.handler[method])~="function" then
+ err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
+ end
+ return Dispatchers[argc+2](info.handler[method], info.handler, info, a1, a2, a3, a4)
+ else
+ assert(false) -- type should have already been checked on read
+ end
+end
+
+-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
+
+-- Ace3v: the variable arguments are currently unused, so we removed it
+local function callfunction(info, tab, methodtype)
+ local method = tab[methodtype]
+
+ info.arg = tab.arg
+ info.option = tab
+ info.type = tab.type
+
+ if type(method)=="function" then
+ return method(info)
+ else
+ assert(false) -- type should have already been checked on read
+ end
+end
+
+-- do_final() - do the final step (set/execute) along with validation and confirmation
+-- Ace3v: experimental
+-- @param argc number of variable arguments
+local function do_final(info, inputpos, tab, methodtype, argc, a1, a2, a3, a4) -- currently maximum 4 arguments
+ if info.validate then
+ local res = callmethod(info,inputpos,tab,"validate",argc,a1,a2,a3,a4)
+ if type(res)=="string" then
+ usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
+ return
+ end
+ end
+ -- console ignores .confirm
+
+ callmethod(info,inputpos,tab,methodtype,argc,a1,a2,a3,a4)
+end
+
+
+-- getparam() - used by handle() to retreive and store "handler", "get", "set", etc
+
+local function getparam(info, inputpos, tab, depth, paramname, types, errormsg)
+ local old,oldat = info[paramname], info[paramname.."_at"]
+ local val=tab[paramname]
+ if val~=nil then
+ if val==false then
+ val=nil
+ elseif not types[type(val)] then
+ err(info, inputpos, "'" .. paramname.. "' - "..errormsg)
+ end
+ info[paramname] = val
+ info[paramname.."_at"] = depth
+ end
+ return old,oldat
+end
+
+
+-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
+local function iterateargs(tab)
+ if not tab.plugins then
+ return pairs(tab.args)
+ end
+
+ local argtabkey,argtab=next(tab.plugins)
+ local v
+
+ return function(_, k)
+ while argtab do
+ k,v = next(argtab, k)
+ if k then return k,v end
+ if argtab==tab.args then
+ argtab=nil
+ else
+ argtabkey,argtab = next(tab.plugins, argtabkey)
+ if not argtabkey then
+ argtab=tab.args
+ end
+ end
+ end
+ end
+end
+
+local function getValueFromTab(info, inputpos, tab, key)
+ local v = tab[key]
+ if type(v) == "function" or type(v) == "string" then
+ info[key] = v
+ v = callmethod(info, inputpos, tab, key)
+ info[key] = nil
+ end
+ return v
+end
+
+local function checkhidden(info, inputpos, tab)
+ if tab.cmdHidden~=nil then
+ return tab.cmdHidden
+ end
+ return getValueFromTab(info, inputpos, tab, "hidden")
+end
+
+local function showhelp(info, inputpos, tab, depth, noHead)
+ if not noHead then
+ print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
+ end
+
+ local sortTbl = new() -- [1..n]=name
+ local refTbl = new() -- [name]=tableref
+
+ for k,v in iterateargs(tab) do
+ if not refTbl[k] then -- a plugin overriding something in .args
+ tinsert(sortTbl, k)
+ refTbl[k] = v
+ end
+ end
+
+ tsort(sortTbl, function(one, two)
+ local o1 = refTbl[one].order or 100
+ local o2 = refTbl[two].order or 100
+ if type(o1) == "function" or type(o1) == "string" then
+ info.order = o1
+ tinsert(info, one)
+ o1 = callmethod(info, inputpos, refTbl[one], "order")
+ tremove(info)
+ info.order = nil
+ end
+ if type(o2) == "function" or type(o1) == "string" then
+ info.order = o2
+ tinsert(info, two)
+ o2 = callmethod(info, inputpos, refTbl[two], "order")
+ tremove(info)
+ info.order = nil
+ end
+ if o1<0 and o2<0 then return o1 4) and not _G["KEY_" .. text] then
+ return false
+ end
+ local s = text
+ if shift then
+ s = "SHIFT-" .. s
+ end
+ if ctrl then
+ s = "CTRL-" .. s
+ end
+ if alt then
+ s = "ALT-" .. s
+ end
+ return s
+end
+
+-- handle() - selfrecursing function that processes input->optiontable
+-- - depth - starts at 0
+-- - retfalse - return false rather than produce error if a match is not found (used by inlined groups)
+
+local function handle(info, inputpos, tab, depth, retfalse)
+
+ if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end
+
+ -------------------------------------------------------------------
+ -- Grab hold of handler,set,get,func,etc if set (and remember old ones)
+ -- Note that we do NOT validate if method names are correct at this stage,
+ -- the handler may change before they're actually used!
+
+ local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg)
+ local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg)
+ local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg)
+ local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg)
+ local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg)
+ --local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg)
+
+ -------------------------------------------------------------------
+ -- Act according to .type of this table
+
+ if tab.type=="group" then
+ ------------ group --------------------------------------------
+
+ if type(tab.args)~="table" then err(info, inputpos) end
+ if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end
+
+ -- grab next arg from input
+ local _,nextpos,arg = strfind(info.input, " *([^ ]+) *", inputpos)
+ if not arg then
+ showhelp(info, inputpos, tab, depth)
+ return
+ end
+ nextpos=nextpos+1
+
+ -- loop .args and try to find a key with a matching name
+ for k,v in iterateargs(tab) do
+ if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
+
+ -- is this child an inline group? if so, traverse into it
+ if v.type=="group" and pickfirstset(3, v.cmdInline, v.inline, false) then
+ tinsert(info,k)
+ if handle(info, inputpos, v, depth+1, true)==false then
+ tremove(info)
+ -- wasn't found in there, but that's ok, we just keep looking down here
+ else
+ return -- done, name was found in inline group
+ end
+ -- matching name and not a inline group
+ elseif strlower(arg)==strlower(strgsub(k, " ", "_")) then
+ tinsert(info,k)
+ return handle(info,nextpos,v,depth+1)
+ end
+ end
+
+ -- no match
+ if retfalse then
+ -- restore old infotable members and return false to indicate failure
+ info.handler,info.handler_at = oldhandler,oldhandler_at
+ info.set,info.set_at = oldset,oldset_at
+ info.get,info.get_at = oldget,oldget_at
+ info.func,info.func_at = oldfunc,oldfunc_at
+ info.validate,info.validate_at = oldvalidate,oldvalidate_at
+ --info.confirm,info.confirm_at = oldconfirm,oldconfirm_at
+ return false
+ end
+
+ -- couldn't find the command, display error
+ usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"])
+ return
+ end
+
+ local str = strsub(info.input,inputpos);
+
+ if tab.type=="execute" then
+ ------------ execute --------------------------------------------
+ do_final(info, inputpos, tab, "func")
+
+
+
+ elseif tab.type=="input" then
+ ------------ input --------------------------------------------
+
+ if str=="" and tab.nullable == false then
+ usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
+ return
+ end
+
+ local res = true
+ if tab.pattern then
+ if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
+ if not strfind(str, tab.pattern) then
+ usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
+ return
+ end
+ end
+
+ do_final(info, inputpos, tab, "set", 1, str)
+
+
+
+ elseif tab.type=="toggle" then
+ ------------ toggle --------------------------------------------
+ local b
+ local str = strtrim(strlower(str))
+ if str=="" then
+ b = callmethod(info, inputpos, tab, "get")
+
+ if tab.tristate then
+ --cycle in true, nil, false order
+ if b then
+ b = nil
+ elseif b == nil then
+ b = false
+ else
+ b = true
+ end
+ else
+ b = not b
+ end
+
+ elseif str==L["on"] then
+ b = true
+ elseif str==L["off"] then
+ b = false
+ elseif tab.tristate and str==L["default"] then
+ b = nil
+ else
+ if tab.tristate then
+ usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str))
+ else
+ usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str))
+ end
+ return
+ end
+
+ do_final(info, inputpos, tab, "set", 1, b)
+
+
+ elseif tab.type=="range" then
+ ------------ range --------------------------------------------
+ local str = strtrim(strlower(str))
+ if str == "" then
+ -- TODO: Show current value
+ return
+ end
+
+ local val = tonumber(str)
+ if not val then
+ usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
+ return
+ end
+
+ local step = getValueFromTab(info, inputpos, tab, "step")
+ local min = getValueFromTab(info, inputpos, tab, "min")
+
+ if type(step)=="number" then
+ val = min + math.floor((val-min)/step) * step
+ end
+
+ if type(min)=="number" and valmax then
+ usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(max)) )
+ return
+ end
+
+ do_final(info, inputpos, tab, "set", 1, val)
+
+
+ elseif tab.type=="select" then
+ ------------ select ------------------------------------
+ local str = strtrim(strlower(str))
+
+ local values = getValueFromTab(info, inputpos, tab, "values")
+
+ if str == "" then
+ -- Ace3v: it is possbile to not have a current value
+ -- we do this only for select but not for multiselect
+ local b = tab.get
+ if type(b) == "function" or type(b) == "string" then
+ b = callmethod(info, inputpos, tab, "get")
+ else
+ b = nil
+ end
+
+ local fmt = "|cffffff78- [%s]|r %s"
+ local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
+ print(L["Options for |cffffff78"..info[tgetn(info)].."|r:"])
+ for k, v in pairs(values) do
+ if b == k then
+ print(format(fmt_sel, k, v))
+ else
+ print(format(fmt, k, v))
+ end
+ end
+ if tab.valuesTableDestroyable then del(values) end
+ return
+ end
+
+ local ok
+ for k,v in pairs(values) do
+ if strlower(k)==str then
+ str = k -- overwrite with key (in case of case mismatches)
+ ok = true
+ break
+ end
+ end
+ if tab.valuesTableDestroyable then del(values) end
+ if not ok then
+ usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
+ return
+ end
+
+ do_final(info, inputpos, tab, "set", 1, str)
+
+ elseif tab.type=="multiselect" then
+ ------------ multiselect -------------------------------------------
+ local str = strtrim(strlower(str))
+
+ local values = getValueFromTab(info, inputpos, tab, "values")
+
+ if str == "" then
+ local fmt = "|cffffff78- [%s]|r %s"
+ local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
+ print(L["Options for |cffffff78"..info[tgetn(info)].."|r (multiple possible):"])
+ for k, v in pairs(values) do
+ if callmethod(info, inputpos, tab, "get", 1, k) then
+ print(format(fmt_sel, k, v))
+ else
+ print(format(fmt, k, v))
+ end
+ end
+ if tab.valuesTableDestroyable then del(values) end
+ return
+ end
+
+ --build a table of the selections, checking that they exist
+ --parse for =on =off =default in the process
+ --table will be key = true for options that should toggle, key = [on|off|default] for options to be set
+ local sels = new()
+ for v in strgfind(str, "[^ ]+") do
+ --parse option=on etc
+ local _, _, opt, val = strfind(v, '(.+)=(.+)')
+ --get option if toggling
+ if not opt then
+ opt = v
+ end
+
+ --check that the opt is valid
+ local ok
+ for k,v in pairs(values) do
+ if strlower(k)==opt then
+ opt = k -- overwrite with key (in case of case mismatches)
+ ok = true
+ break
+ end
+ end
+ if tab.valuesTableDestroyable then del(values) end
+
+ if not ok then
+ usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
+ return
+ end
+
+ --check that if val was supplied it is valid
+ if val then
+ if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then
+ --val is valid insert it
+ sels[opt] = val
+ else
+ if tab.tristate then
+ usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val))
+ else
+ usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
+ end
+ del(sels)
+ return
+ end
+ else
+ -- no val supplied, toggle
+ sels[opt] = true
+ end
+ end
+
+ for opt, val in pairs(sels) do
+ local newval
+
+ if (val == true) then
+ --toggle the option
+ local b = callmethod(info, inputpos, tab, "get", 1, opt)
+
+ if tab.tristate then
+ --cycle in true, nil, false order
+ if b then
+ b = nil
+ elseif b == nil then
+ b = false
+ else
+ b = true
+ end
+ else
+ b = not b
+ end
+ newval = b
+ else
+ --set the option as specified
+ if val==L["on"] then
+ newval = true
+ elseif val==L["off"] then
+ newval = false
+ elseif val==L["default"] then
+ newval = nil
+ end
+ end
+
+ do_final(info, inputpos, tab, "set", 2, opt, newval)
+ end
+ del(sels)
+
+
+ elseif tab.type=="color" then
+ ------------ color --------------------------------------------
+ local str = strtrim(strlower(str))
+ if str == "" then
+ --TODO: Show current value
+ return
+ end
+
+ local _, r, g, b, a
+
+ local hasAlpha = getValueFromTab(info, inputpos, tab, 'hasAlpha')
+
+ if hasAlpha then
+ if strlen(str) == 8 and strfind(str, "^%x*$") then
+ --parse a hex string
+ r,g,b,a = tonumber(strsub(str, 1, 2), 16) / 255, tonumber(strsub(str, 3, 4), 16) / 255, tonumber(strsub(str, 5, 6), 16) / 255, tonumber(strsub(str, 7, 8), 16) / 255
+ else
+ --parse seperate values
+ _,_,r,g,b,a = strfind(str, "^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$")
+ r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a)
+ end
+ if not (r and g and b and a) then
+ usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str))
+ return
+ end
+
+ if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then
+ --values are valid
+ elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then
+ --values are valid 0..255, convert to 0..1
+ r = r / 255
+ g = g / 255
+ b = b / 255
+ a = a / 255
+ else
+ --values are invalid
+ usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str))
+ end
+ else
+ a = 1.0
+ if strlen(str) == 6 and strfind(str, "^%x*$") then
+ --parse a hex string
+ r,g,b = tonumber(strsub(str, 1, 2), 16) / 255, tonumber(strsub(str, 3, 4), 16) / 255, tonumber(strsub(str, 5, 6), 16) / 255
+ else
+ --parse seperate values
+ _,_,r,g,b = strfind(str, "^([%d%.]+) ([%d%.]+) ([%d%.]+)$")
+ r,g,b = tonumber(r), tonumber(g), tonumber(b)
+ end
+ if not (r and g and b) then
+ usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str))
+ return
+ end
+ if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then
+ --values are valid
+ elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
+ --values are valid 0..255, convert to 0..1
+ r = r / 255
+ g = g / 255
+ b = b / 255
+ else
+ --values are invalid
+ usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str))
+ end
+ end
+
+ do_final(info, inputpos, tab, "set", 4, r,g,b,a)
+
+ elseif tab.type=="keybinding" then
+ ------------ keybinding --------------------------------------------
+ local str = strtrim(strlower(str))
+ if str == "" then
+ --TODO: Show current value
+ return
+ end
+ local value = keybindingValidateFunc(strupper(str))
+ if value == false then
+ usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str))
+ return
+ end
+
+ do_final(info, inputpos, tab, "set", 1, value)
+
+ elseif tab.type=="description" then
+ ------------ description --------------------
+ -- ignore description, GUI config only
+ else
+ err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'")
+ end
+end
+
+--- Handle the chat command.
+-- This is usually called from a chat command handler to parse the command input as operations on an aceoptions table.\\
+-- AceConfigCmd uses this function internally when a slash command is registered with `:CreateChatCommand`
+-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param input The commandline input (as given by the WoW handler, i.e. without the command itself)
+-- @usage
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
+-- -- Use AceConsole-3.0 to register a Chat Command
+-- MyAddon:RegisterChatCommand("mychat", "ChatCommand")
+--
+-- -- Show the GUI if no input is supplied, otherwise handle the chat input.
+-- function MyAddon:ChatCommand(input)
+-- -- Assuming "MyOptions" is the appName of a valid options table
+-- if not input or input:trim() == "" then
+-- LibStub("AceConfigDialog-3.0"):Open("MyOptions")
+-- else
+-- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
+-- end
+-- end
+-- Ace3v: experimental, user should copy info table if he wanna reuse it outside
+-- then handler
+local info_ = {}
+function AceConfigCmd:HandleCommand(slashcmd, appName, input)
+
+ local optgetter = cfgreg:GetOptionsTable(appName)
+ if not optgetter then
+ error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2)
+ end
+ local options = assert( optgetter("cmd", MAJOR) )
+
+ -- Ace3v: prevent user from using AceConfigCmd as self
+ if self == AceConfigCmd then
+ error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'self' - use your own 'self']], 2)
+ end
+
+ --local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
+ -- [0] = slashcmd,
+ -- appName = appName,
+ -- options = options,
+ -- input = input,
+ -- self = self,
+ -- handler = self,
+ -- uiType = "cmd",
+ -- uiName = MAJOR,
+ --}
+
+ wipe(info_)
+ info_[0] = slashcmd
+ info_.appName = appName
+ info_.options = options
+ info_.input = input
+ info_.self = self
+ info_.handler = self
+ info_.uiType = "cmd"
+ info_.uiName = MAJOR
+
+ handle(info_, 1, options, 0) -- (info, inputpos, table, depth)
+end
+
+--- Utility function to create a slash command handler.
+-- Also registers tab completion with AceTab
+-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+function AceConfigCmd:CreateChatCommand(slashcmd, appName, func)
+ if not AceConsole then
+ AceConsole = LibStub(AceConsoleName)
+ end
+
+ -- Ace3v: prevent user from using AceConfigCmd as self
+ if self == AceConfigCmd then
+ error([[Usage: CreateChatCommand("slashcmd", "appName"[, "func"]): 'self' - use your own 'self']], 2)
+ end
+
+ local t = type(func)
+
+ -- Ace3v: make it possible to call another function
+ local handler
+ if t == "string" then
+ handler = function(input) self[func](self, input, slashcmd, appName) end
+ elseif t ~= "function" then
+ handler = function(input)
+ AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable
+ end
+ else
+ handler = func
+ end
+
+ if AceConsole.RegisterChatCommand(self, slashcmd, handler, true) then
+ -- succesfully registered so lets get the command -> app table in
+ commands[slashcmd] = appName
+ end
+end
+
+--- Utility function that returns the options table that belongs to a slashcommand.
+-- Designed to be used for the AceTab interface.
+-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
+-- @return The options table associated with the slash command (or nil if the slash command was not registered)
+function AceConfigCmd:GetChatCommandOptions(slashcmd)
+ return commands[slashcmd]
+end
+
+function AceConfigCmd:Embed(target)
+ target["HandleCommand"] = self["HandleCommand"]
+ target["CreateChatCommand"] = self["CreateChatCommand"]
+end
+
+for addon in pairs(AceConfigCmd.embeds) do
+ AceConfigCmd:Embed(addon)
+end
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml
new file mode 100644
index 0000000..188d354
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua
new file mode 100644
index 0000000..56f3f98
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua
@@ -0,0 +1,1958 @@
+--- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables.
+-- @class file
+-- @name AceConfigDialog-3.0
+-- @release $Id: AceConfigDialog-3.0.lua 1139 2016-07-03 07:43:51Z nevcairiel $
+
+local LibStub = LibStub
+local MAJOR, MINOR = "AceConfigDialog-3.0", 61
+local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceConfigDialog then return end
+
+local AceCore = LibStub("AceCore-3.0")
+local wipe = AceCore.wipe
+local safecall = AceCore.safecall
+local Dispatchers = AceCore.Dispatchers
+local countargs = AceCore.countargs
+
+AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {}
+AceConfigDialog.Status = AceConfigDialog.Status or {}
+AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame")
+
+AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {}
+AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {}
+AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {}
+
+local gui = LibStub("AceGUI-3.0")
+local reg = LibStub("AceConfigRegistry-3.0")
+
+-- Lua APIs
+local tconcat, tinsert, tsort, tremove, tgetn, tsetn = table.concat, table.insert, table.sort, table.remove, table.getn, table.setn
+local format, strfind, strupper = string.format, string.find, string.upper
+local assert, loadstring, error = assert, loadstring, error
+local pairs, next, type, unpack, ipairs = pairs, next, type, unpack, ipairs
+local rawset, tostring, tonumber = rawset, tostring, tonumber
+local math_min, math_max, math_floor = math.min, math.max, math.floor
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: NORMAL_FONT_COLOR, GameTooltip, StaticPopupDialogs, ACCEPT, CANCEL, StaticPopup_Show
+-- GLOBALS: PlaySound, GameFontHighlight, GameFontHighlightSmall, GameFontHighlightLarge
+-- GLOBALS: CloseSpecialWindows, InterfaceOptions_AddCategory, geterrorhandler
+
+local emptyTbl = {}
+
+local width_multiplier = 170
+
+--[[
+Group Types
+ Tree - All Descendant Groups will all become nodes on the tree, direct child options will appear above the tree
+ - Descendant Groups with inline=true and thier children will not become nodes
+
+ Tab - Direct Child Groups will become tabs, direct child options will appear above the tab control
+ - Grandchild groups will default to inline unless specified otherwise
+
+ Select- Same as Tab but with entries in a dropdown rather than tabs
+
+
+ Inline Groups
+ - Will not become nodes of a select group, they will be effectivly part of thier parent group seperated by a border
+ - If declared on a direct child of a root node of a select group, they will appear above the group container control
+ - When a group is displayed inline, all descendants will also be inline members of the group
+
+]]
+
+-- Recycling functions
+local new, del, copy
+--newcount, delcount,createdcount,cached = 0,0,0
+do
+ local pool = setmetatable({},{__mode="k"})
+ function new()
+ --newcount = newcount + 1
+ local t = next(pool)
+ if t then
+ pool[t] = nil
+ return t
+ else
+ --createdcount = createdcount + 1
+ return {}
+ end
+ end
+ function copy(t)
+ local c = new()
+ for k, v in pairs(t) do
+ c[k] = v
+ end
+ tsetn(c, tgetn(t))
+ return c
+ end
+ function del(t)
+ --delcount = delcount + 1
+ wipe(t)
+ pool[t] = true
+ end
+-- function cached()
+-- local n = 0
+-- for k in pairs(pool) do
+-- n = n + 1
+-- end
+-- return n
+-- end
+end
+
+-- picks the first non-nil value and returns it
+local pickfirstset = AceCore.pickfirstset
+
+--gets an option from a given group, checking plugins
+local function GetSubOption(group, key)
+ if group.plugins then
+ for plugin, t in pairs(group.plugins) do
+ if t[key] then
+ return t[key]
+ end
+ end
+ end
+
+ return group.args[key]
+end
+
+--Option member type definitions, used to decide how to access it
+
+--Is the member Inherited from parent options
+local isInherited = {
+ set = true,
+ get = true,
+ func = true,
+ confirm = true,
+ validate = true,
+ disabled = true,
+ hidden = true
+}
+
+--Does a string type mean a literal value, instead of the default of a method of the handler
+local stringIsLiteral = {
+ name = true,
+ desc = true,
+ icon = true,
+ usage = true,
+ width = true,
+ image = true,
+ fontSize = true,
+}
+
+--Is Never a function or method
+local allIsLiteral = {
+ type = true,
+ descStyle = true,
+ imageWidth = true,
+ imageHeight = true,
+}
+
+--gets the value for a member that could be a function
+--function refs are called with an info arg
+--every other type is returned
+local function GetOptionsMemberValue(membername, option, options, path, appName, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ --get definition for the member
+ local inherits = isInherited[membername]
+
+ --get the member of the option, traversing the tree if it can be inherited
+ local member
+
+ if inherits then
+ local group = options
+ if group[membername] ~= nil then
+ member = group[membername]
+ end
+ for i = 1, tgetn(path) do
+ group = GetSubOption(group, path[i])
+ if group[membername] ~= nil then
+ member = group[membername]
+ end
+ end
+ elseif option then
+ member = option[membername]
+ end
+
+ --check if we need to call a functon, or if we have a literal value
+ if ( not allIsLiteral[membername] ) and ( type(member) == "function" or ((not stringIsLiteral[membername]) and type(member) == "string") ) then
+ --We have a function to call
+ local info = new()
+ --traverse the options table, picking up the handler and filling the info with the path
+ local handler
+ local group = options
+ handler = group.handler or handler
+
+ local l = tgetn(path)
+ for i = 1, l do
+ group = GetSubOption(group, path[i])
+ info[i] = path[i]
+ handler = group.handler or handler
+ end
+ tsetn(info, l)
+
+ info.options = options
+ info.appName = appName
+ info[0] = appName
+ info.arg = option.arg
+ info.handler = handler
+ info.option = option
+ info.type = option.type
+ info.uiType = "dialog"
+ info.uiName = MAJOR
+
+ argc = argc or 0
+ local a, b, c ,d
+ --using 4 returns for the get of a color type, increase if a type needs more
+ if type(member) == "function" then
+ --Call the function
+ a,b,c,d = Dispatchers[argc+1](member,info,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ else
+ --Call the method
+ if handler and handler[member] then
+ a,b,c,d = Dispatchers[argc+2](handler[member],handler,info,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ else
+ error(format("Method %s doesn't exist in handler for type %s", member, membername))
+ end
+ end
+ del(info)
+ return a,b,c,d
+ else
+ --The value isnt a function to call, return it
+ return member
+ end
+end
+
+--[[calls an options function that could be inherited, method name or function ref
+local function CallOptionsFunction(funcname ,option, options, path, appName, ...)
+ local info = new()
+
+ local func
+ local group = options
+ local handler
+
+ --build the info table containing the path
+ -- pick up functions while traversing the tree
+ if group[funcname] ~= nil then
+ func = group[funcname]
+ end
+ handler = group.handler or handler
+
+ for i, v in ipairs(path) do
+ group = GetSubOption(group, v)
+ info[i] = v
+ if group[funcname] ~= nil then
+ func = group[funcname]
+ end
+ handler = group.handler or handler
+ end
+
+ info.options = options
+ info[0] = appName
+ info.arg = option.arg
+
+ local a, b, c ,d
+ if type(func) == "string" then
+ if handler and handler[func] then
+ a,b,c,d = handler[func](handler, info, ...)
+ else
+ error(string.format("Method %s doesn't exist in handler for type func", func))
+ end
+ elseif type(func) == "function" then
+ a,b,c,d = func(info, ...)
+ end
+ del(info)
+ return a,b,c,d
+end
+--]]
+
+--tables to hold orders and names for options being sorted, will be created with new()
+--prevents needing to call functions repeatedly while sorting
+local tempOrders
+local tempNames
+
+local function compareOptions(a,b)
+ if not a then
+ return true
+ end
+ if not b then
+ return false
+ end
+ local OrderA, OrderB = tempOrders[a] or 100, tempOrders[b] or 100
+ if OrderA == OrderB then
+ local NameA = (type(tempNames[a]) == "string") and tempNames[a] or ""
+ local NameB = (type(tempNames[b]) == "string") and tempNames[b] or ""
+ return strupper(NameA) < strupper(NameB)
+ end
+ if OrderA < 0 then
+ if OrderB > 0 then
+ return false
+ end
+ else
+ if OrderB < 0 then
+ return true
+ end
+ end
+ return OrderA < OrderB
+end
+
+
+
+--builds 2 tables out of an options group
+-- keySort, sorted keys
+-- opts, combined options from .plugins and args
+local function BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
+ tempOrders = new()
+ tempNames = new()
+
+ if group.plugins then
+ for plugin, t in pairs(group.plugins) do
+ for k, v in pairs(t) do
+ if not opts[k] then
+ tinsert(keySort, k)
+ opts[k] = v
+
+ tinsert(path,k)
+ tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
+ tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
+ tremove(path)
+ end
+ end
+ end
+ end
+
+ for k, v in pairs(group.args) do
+ if not opts[k] then
+ tinsert(keySort, k)
+ opts[k] = v
+
+ tinsert(path,k)
+ tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
+ tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
+ tremove(path)
+ end
+ end
+
+ tsort(keySort, compareOptions)
+
+ del(tempOrders)
+ del(tempNames)
+end
+
+local function DelTree(tree)
+ if tree.children then
+ local childs = tree.children
+ for i = 1, tgetn(childs) do
+ DelTree(childs[i])
+ del(childs[i])
+ end
+ del(childs)
+ end
+end
+
+local function CleanUserData(widget, event)
+
+ local user = widget:GetUserDataTable()
+
+ if user.path then
+ del(user.path)
+ end
+
+ if widget.type == "TreeGroup" then
+ local tree = user.tree
+ widget:SetTree(nil)
+ if tree then
+ for i = 1, tgetn(tree) do
+ DelTree(tree[i])
+ del(tree[i])
+ end
+ del(tree)
+ end
+ end
+
+ if widget.type == "TabGroup-ElvUI" then
+ widget:SetTabs(nil)
+ if user.tablist then
+ del(user.tablist)
+ end
+ end
+
+ if widget.type == "DropdownGroup" then
+ widget:SetGroupList(nil)
+ if user.grouplist then
+ del(user.grouplist)
+ end
+ if user.orderlist then
+ del(user.orderlist)
+ end
+ end
+end
+
+-- - Gets a status table for the given appname and options path.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param path The path to the options (a table with all group keys)
+-- @return
+function AceConfigDialog:GetStatusTable(appName, path)
+ local status = self.Status
+
+ if not status[appName] then
+ status[appName] = {}
+ status[appName].status = {}
+ status[appName].children = {}
+ end
+
+ status = status[appName]
+
+ if path then
+ for i = 1, tgetn(path) do
+ local v = path[i]
+ if not status.children[v] then
+ status.children[v] = {}
+ status.children[v].status = {}
+ status.children[v].children = {}
+ end
+ status = status.children[v]
+ end
+ end
+
+ return status.status
+end
+
+--- Selects the specified path in the options window.
+-- The path specified has to match the keys of the groups in the table.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param ... The path to the key that should be selected
+do
+local args = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
+function AceConfigDialog:SelectGroup(appName, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ local path = new()
+
+ local app = reg:GetOptionsTable(appName)
+ if not app then
+ error(format("%s isn't registed with AceConfigRegistry, unable to open config", appName), 2)
+ end
+ local options = app("dialog", MAJOR)
+ local group = options
+ local status = self:GetStatusTable(appName, path)
+ if not status.groups then
+ status.groups = {}
+ end
+ status = status.groups
+ local treevalue
+ local treestatus
+
+ args[1] = a1
+ args[2] = a2
+ args[3] = a3
+ args[4] = a4
+ args[5] = a5
+ args[6] = a6
+ args[7] = a7
+ args[8] = a8
+ args[9] = a9
+ args[10] = a10
+ for n = 1, 10 do
+ local key = args[n]
+ args[n] = nil
+
+ if not key then break end
+
+ if group.childGroups == "tab" or group.childGroups == "select" then
+ --if this is a tab or select group, select the group
+ status.selected = key
+ --children of this group are no longer extra levels of a tree
+ treevalue = nil
+ else
+ --tree group by default
+ if treevalue then
+ --this is an extra level of a tree group, build a uniquevalue for it
+ treevalue = treevalue.."\001"..key
+ else
+ --this is the top level of a tree group, the uniquevalue is the same as the key
+ treevalue = key
+ if not status.groups then
+ status.groups = {}
+ end
+ --save this trees status table for any extra levels or groups
+ treestatus = status
+ end
+ --make sure that the tree entry is open, and select it.
+ --the selected group will be overwritten if a child is the final target but still needs to be open
+ treestatus.selected = treevalue
+ treestatus.groups[treevalue] = true
+
+ end
+
+ --move to the next group in the path
+ group = GetSubOption(group, key)
+ if not group then
+ break
+ end
+ tinsert(path, key)
+ status = self:GetStatusTable(appName, path)
+ if not status.groups then
+ status.groups = {}
+ end
+ status = status.groups
+ end
+
+ del(path)
+ reg:NotifyChange(appName)
+end
+end -- AceConfigDialog:SelectGroup
+
+local function OptionOnMouseOver(widget, event)
+ --show a tooltip/set the status bar to the desc text
+ local user = widget:GetUserDataTable()
+ local opt = user.option
+ local options = user.options
+ local path = user.path
+ local appName = user.appName
+
+ GameTooltip:SetOwner(widget.frame, "ANCHOR_TOPRIGHT")
+ local name = GetOptionsMemberValue("name", opt, options, path, appName)
+ local desc = GetOptionsMemberValue("desc", opt, options, path, appName)
+ local usage = GetOptionsMemberValue("usage", opt, options, path, appName)
+ local descStyle = opt.descStyle
+
+ if descStyle and descStyle ~= "tooltip" then return end
+
+ GameTooltip:SetText(name, 1, .82, 0, true)
+
+ if opt.type == "multiselect" then
+ GameTooltip:AddLine(user.text, 0.5, 0.5, 0.8, true)
+ end
+ if type(desc) == "string" then
+ GameTooltip:AddLine(desc, 1, 1, 1, true)
+ end
+ if type(usage) == "string" then
+ GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true)
+ end
+
+ GameTooltip:Show()
+end
+
+local function OptionOnMouseLeave(widget, event)
+ GameTooltip:Hide()
+end
+
+local function GetFuncName(option)
+ local type = option.type
+ if type == "execute" then
+ return "func"
+ else
+ return "set"
+ end
+end
+local function confirmPopup(appName, rootframe, basepath, info, message, func, argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then
+ StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {}
+ end
+ local t = StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"]
+ for k in pairs(t) do
+ t[k] = nil
+ end
+ t.text = message
+ t.button1 = ACCEPT
+ t.button2 = CANCEL
+ t.preferredIndex = STATICPOPUP_NUMDIALOGS
+ local dialog, oldstrata
+ t.OnAccept = function()
+ safecall(func, tgetn(t), unpack(t))
+ if dialog and oldstrata then
+ dialog:SetFrameStrata(oldstrata)
+ end
+ AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
+ del(info)
+ end
+ t.OnCancel = function()
+ if dialog and oldstrata then
+ dialog:SetFrameStrata(oldstrata)
+ end
+ AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
+ del(info)
+ end
+ t[1] = a1
+ t[2] = a2
+ t[3] = a3
+ t[4] = a4
+ t[5] = a5
+ t[6] = a6
+ t[7] = a7
+ t[8] = a8
+ t[9] = a9
+ t[10] = a10
+ for i=1,argc do
+ t[i] = t[i] or false
+ end
+ for i=argc+1,10 do
+ t[i] = nil
+ end
+ tsetn(t,argc)
+ t.timeout = 0
+ t.whileDead = 1
+ t.hideOnEscape = 1
+
+ dialog = StaticPopup_Show("ACECONFIGDIALOG30_CONFIRM_DIALOG")
+ if dialog then
+ oldstrata = dialog:GetFrameStrata()
+ dialog:SetFrameStrata("TOOLTIP")
+ end
+end
+
+local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ --This function will call the set / execute handler for the widget
+ --widget:GetUserDataTable() contains the needed info
+ local user = widget:GetUserDataTable()
+ local option = user.option
+ local options = user.options
+ local path = user.path
+ local info = new()
+
+ local func
+ local group = options
+ local funcname = GetFuncName(option)
+ local handler
+ local confirm
+ local validate
+ --build the info table containing the path
+ -- pick up functions while traversing the tree
+ if group[funcname] ~= nil then
+ func = group[funcname]
+ end
+ handler = group.handler or handler
+ confirm = group.confirm
+ validate = group.validate
+
+ local l = tgetn(path)
+ for i = 1, l do
+ local v = path[i]
+ group = GetSubOption(group, v)
+ info[i] = v
+ if group[funcname] ~= nil then
+ func = group[funcname]
+ end
+ handler = group.handler or handler
+ if group.confirm ~= nil then
+ confirm = group.confirm
+ end
+ if group.validate ~= nil then
+ validate = group.validate
+ end
+ end
+ tsetn(info, l)
+
+ info.options = options
+ info.appName = user.appName
+ info.arg = option.arg
+ info.handler = handler
+ info.option = option
+ info.type = option.type
+ info.uiType = "dialog"
+ info.uiName = MAJOR
+
+ local name
+
+ if type(option.name) == "function" then
+ name = option.name(info)
+ elseif type(option.name) == "string" then
+ name = option.name
+ else
+ name = ""
+ end
+ local usage = option.usage
+ local pattern = option.pattern
+
+ local validated = true
+
+ if option.type == "input" then
+ if type(pattern)=="string" then
+ if not strfind(a1, pattern) then
+ validated = false
+ end
+ end
+ end
+
+ local success
+ if validated and option.type ~= "execute" then
+ if type(validate) == "string" then
+ if handler and handler[validate] then
+ success, validated = safecall(handler[validate], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if not success then validated = false end
+ else
+ error(format("Method %s doesn't exist in handler for type execute", validate))
+ end
+ elseif type(validate) == "function" then
+ success, validated = safecall(validate, argc+1, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if not success then validated = false end
+ end
+ end
+
+ local rootframe = user.rootframe
+ if type(validated) == "string" then
+ --validate function returned a message to display
+ if rootframe.SetStatusText then
+ rootframe:SetStatusText(validated)
+ else
+ -- TODO: do something else.
+ end
+ PlaySound("igPlayerInviteDecline")
+ del(info)
+ return true
+ elseif not validated then
+ --validate returned false
+ if rootframe.SetStatusText then
+ if usage then
+ rootframe:SetStatusText(name..": "..usage)
+ else
+ if pattern then
+ rootframe:SetStatusText(name..": Expected "..pattern)
+ else
+ rootframe:SetStatusText(name..": Invalid Value")
+ end
+ end
+ else
+ -- TODO: do something else
+ end
+ PlaySound("igPlayerInviteDecline")
+ del(info)
+ return true
+ else
+
+ local confirmText = option.confirmText
+ --call confirm func/method
+ if type(confirm) == "string" then
+ if handler and handler[confirm] then
+ success, confirm = safecall(handler[confirm], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if success and type(confirm) == "string" then
+ confirmText = confirm
+ confirm = true
+ elseif not success then
+ confirm = false
+ end
+ else
+ error(format("Method %s doesn't exist in handler for type confirm", confirm))
+ end
+ elseif type(confirm) == "function" then
+ success, confirm = safecall(confirm, argc+1, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if success and type(confirm) == "string" then
+ confirmText = confirm
+ confirm = true
+ elseif not success then
+ confirm = false
+ end
+ end
+
+ --confirm if needed
+ if type(confirm) == "boolean" then
+ if confirm then
+ if not confirmText then
+ local name, desc = option.name, option.desc
+ if type(name) == "function" then
+ name = name(info)
+ end
+ if type(desc) == "function" then
+ desc = desc(info)
+ end
+ confirmText = name
+ if desc then
+ confirmText = confirmText.." - "..desc
+ end
+ end
+
+ local iscustom = user.rootframe:GetUserData("iscustom")
+ local rootframe
+
+ if iscustom then
+ rootframe = user.rootframe
+ end
+ local basepath = user.rootframe:GetUserData("basepath")
+ if type(func) == "string" then
+ if handler and handler[func] then
+ confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ else
+ error(format("Method %s doesn't exist in handler for type func", func))
+ end
+ elseif type(func) == "function" then
+ confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, argc+1, info,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+ --func will be called and info deleted when the confirm dialog is responded to
+ return
+ end
+ end
+
+ --call the function
+ if type(func) == "string" then
+ if handler and handler[func] then
+ safecall(handler[func], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ else
+ error(format("Method %s doesn't exist in handler for type func", func))
+ end
+ elseif type(func) == "function" then
+ safecall(func, argc+1, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+
+ local iscustom = user.rootframe:GetUserData("iscustom")
+ local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
+ --full refresh of the frame, some controls dont cause this on all events
+ if option.type == "color" then
+ if event == "OnValueConfirmed" then
+
+ if iscustom then
+ AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
+ else
+ AceConfigDialog:Open(user.appName, unpack(basepath))
+ end
+ end
+ elseif option.type == "range" then
+ if event == "OnMouseUp" then
+ if iscustom then
+ AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
+ else
+ AceConfigDialog:Open(user.appName, unpack(basepath))
+ end
+ end
+ --multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed'
+ elseif option.type == "multiselect" then
+ user.valuechanged = true
+ else
+ if iscustom then
+ AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
+ else
+ AceConfigDialog:Open(user.appName, unpack(basepath))
+ end
+ end
+
+ end
+ del(info)
+end
+
+local function ActivateSlider(widget, event, _, value)
+ local option = widget:GetUserData("option")
+ local min, max, step = option.min or (not option.softMin and 0 or nil), option.max or (not option.softMax and 100 or nil), option.step
+ if min then
+ if step then
+ value = math_floor((value - min) / step + 0.5) * step + min
+ end
+ value = math_max(value, min)
+ end
+ if max then
+ value = math_min(value, max)
+ end
+ ActivateControl(widget,event,1,value)
+end
+
+--called from a checkbox that is part of an internally created multiselect group
+--this type is safe to refresh on activation of one control
+local function ActivateMultiControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ ActivateControl(widget, event, argc+1, widget:GetUserData("value"), a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ local user = widget:GetUserDataTable()
+ local iscustom = user.rootframe:GetUserData("iscustom")
+ local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
+ if iscustom then
+ AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
+ else
+ AceConfigDialog:Open(user.appName, unpack(basepath))
+ end
+end
+
+local function MultiControlOnClosed(widget, event)
+ local user = widget:GetUserDataTable()
+ if user.valuechanged then
+ local iscustom = user.rootframe:GetUserData("iscustom")
+ local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
+ if iscustom then
+ AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
+ else
+ AceConfigDialog:Open(user.appName, unpack(basepath))
+ end
+ end
+end
+
+local function FrameOnClose(widget, event)
+ local appName = widget:GetUserData("appName")
+ AceConfigDialog.OpenFrames[appName] = nil
+ gui:Release(widget)
+end
+
+local function CheckOptionHidden(option, options, path, appName)
+ --check for a specific boolean option
+ local hidden = pickfirstset(2,option.dialogHidden,option.guiHidden)
+ if hidden ~= nil then
+ return hidden
+ end
+
+ return GetOptionsMemberValue("hidden", option, options, path, appName)
+end
+
+local function CheckOptionDisabled(option, options, path, appName)
+ --check for a specific boolean option
+ local disabled = pickfirstset(2,option.dialogDisabled,option.guiDisabled)
+ if disabled ~= nil then
+ return disabled
+ end
+
+ return GetOptionsMemberValue("disabled", option, options, path, appName)
+end
+--[[
+local function BuildTabs(group, options, path, appName)
+ local tabs = new()
+ local text = new()
+ local keySort = new()
+ local opts = new()
+
+ BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
+
+ for i = 1, #keySort do
+ local k = keySort[i]
+ local v = opts[k]
+ if v.type == "group" then
+ path[#path+1] = k
+ local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false)
+ local hidden = CheckOptionHidden(v, options, path, appName)
+ if not inline and not hidden then
+ tinsert(tabs, k)
+ text[k] = GetOptionsMemberValue("name", v, options, path, appName)
+ end
+ path[#path] = nil
+ end
+ end
+
+ del(keySort)
+ del(opts)
+
+ return tabs, text
+end
+]]
+local function BuildSelect(group, options, path, appName)
+ local groups = new()
+ local order = new()
+ local keySort = new()
+ local opts = new()
+
+ BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
+
+ for i = 1, tgetn(keySort) do
+ local k = keySort[i]
+ local v = opts[k]
+ if v.type == "group" then
+ tinsert(path,k)
+ local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false)
+ local hidden = CheckOptionHidden(v, options, path, appName)
+ if not inline and not hidden then
+ groups[k] = GetOptionsMemberValue("name", v, options, path, appName)
+ tinsert(order, k)
+ end
+ tremove(path)
+ end
+ end
+
+ del(opts)
+ del(keySort)
+
+ return groups, order
+end
+
+local function BuildSubGroups(group, tree, options, path, appName)
+ local keySort = new()
+ local opts = new()
+
+ BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
+
+ for i = 1, tgetn(keySort) do
+ local k = keySort[i]
+ local v = opts[k]
+ if v.type == "group" then
+ tinsert(path,k)
+ local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false)
+ local hidden = CheckOptionHidden(v, options, path, appName)
+ if not inline and not hidden then
+ local entry = new()
+ entry.value = k
+ entry.text = GetOptionsMemberValue("name", v, options, path, appName)
+ entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
+ entry.iconCoords = GetOptionsMemberValue("iconCoords", v, options, path, appName)
+ entry.disabled = CheckOptionDisabled(v, options, path, appName)
+ if not tree.children then tree.children = new() end
+ tinsert(tree.children,entry)
+ if (v.childGroups or "tree") == "tree" then
+ BuildSubGroups(v,entry, options, path, appName)
+ end
+ end
+ tremove(path)
+ end
+ end
+
+ del(keySort)
+ del(opts)
+end
+
+local function BuildGroups(group, options, path, appName, recurse)
+ local tree = new()
+ local keySort = new()
+ local opts = new()
+
+ BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
+
+ for i = 1, tgetn(keySort) do
+ local k = keySort[i]
+ local v = opts[k]
+ if v.type == "group" then
+ tinsert(path,k)
+ local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false)
+ local hidden = CheckOptionHidden(v, options, path, appName)
+ if not inline and not hidden then
+ local entry = new()
+ entry.value = k
+ entry.text = GetOptionsMemberValue("name", v, options, path, appName)
+ entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
+ entry.disabled = CheckOptionDisabled(v, options, path, appName)
+ tinsert(tree,entry)
+ if recurse and (v.childGroups or "tree") == "tree" then
+ BuildSubGroups(v,entry, options, path, appName)
+ end
+ end
+ tremove(path)
+ end
+ end
+ del(keySort)
+ del(opts)
+ return tree
+end
+
+local function InjectInfo(control, options, option, path, rootframe, appName)
+ local user = control:GetUserDataTable()
+ local l = tgetn(path)
+ for i = 1, l do
+ user[i] = path[i]
+ end
+ tsetn(user,l)
+
+ user.rootframe = rootframe
+ user.option = option
+ user.options = options
+ user.path = copy(path)
+ user.appName = appName
+ control:SetCallback("OnRelease", CleanUserData)
+ control:SetCallback("OnLeave", OptionOnMouseLeave)
+ control:SetCallback("OnEnter", OptionOnMouseOver)
+end
+
+
+--[[
+ options - root of the options table being fed
+ container - widget that controls will be placed in
+ rootframe - Frame object the options are in
+ path - table with the keys to get to the group being fed
+--]]
+
+local function FeedOptions(appName, options,container,rootframe,path,group,inline)
+ local keySort = new()
+ local opts = new()
+
+ BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
+
+ for i = 1, tgetn(keySort) do
+ local k = keySort[i]
+ local v = opts[k]
+ tinsert(path, k)
+ local hidden = CheckOptionHidden(v, options, path, appName)
+ local name = GetOptionsMemberValue("name", v, options, path, appName)
+ if not hidden then
+ if v.type == "group" then
+ if inline or pickfirstset(4, v.dialogInline,v.guiInline,v.inline, false) then
+ --Inline group
+ local GroupContainer
+ if name and name ~= "" then
+ GroupContainer = gui:Create("InlineGroup")
+ GroupContainer:SetTitle(name or "")
+ else
+ GroupContainer = gui:Create("SimpleGroup")
+ end
+
+ GroupContainer.width = "fill"
+ GroupContainer:SetLayout("flow")
+ container:AddChild(GroupContainer)
+ FeedOptions(appName,options,GroupContainer,rootframe,path,v,true)
+ end
+ else
+ --Control to feed
+ local control
+
+ local name = GetOptionsMemberValue("name", v, options, path, appName)
+
+ if v.type == "execute" then
+
+ local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
+ local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
+
+ if type(image) == "string" or type(image) == "number" then
+ control = gui:Create("Icon")
+ if not width then
+ width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
+ end
+ if not height then
+ height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
+ end
+ if type(imageCoords) == "table" then
+ control:SetImage(image, unpack(imageCoords))
+ else
+ control:SetImage(image)
+ end
+ if type(width) ~= "number" then
+ width = 32
+ end
+ if type(height) ~= "number" then
+ height = 32
+ end
+ control:SetImageSize(width, height)
+ control:SetLabel(name)
+ else
+ control = gui:Create("Button")
+ control:SetText(name)
+ end
+ control:SetCallback("OnClick",ActivateControl)
+
+ elseif v.type == "input" then
+ local controlType = v.dialogControl or v.control or (v.multiline and "MultiLineEditBox") or "EditBox"
+ control = gui:Create(controlType)
+ if not control then
+ geterrorhandler()(format("Invalid Custom Control Type - %s", tostring(controlType)))
+ control = gui:Create(v.multiline and "MultiLineEditBox" or "EditBox")
+ end
+
+ if v.multiline and control.SetNumLines then
+ control:SetNumLines(tonumber(v.multiline) or 4)
+ end
+ control:SetLabel(name)
+ control:SetCallback("OnEnterPressed",ActivateControl)
+ local text = GetOptionsMemberValue("get",v, options, path, appName)
+ if type(text) ~= "string" then
+ text = ""
+ end
+ control:SetText(text)
+
+ elseif v.type == "toggle" then
+ control = gui:Create("CheckBox")
+ control:SetLabel(name)
+ control:SetTriState(v.tristate)
+ local value = GetOptionsMemberValue("get",v, options, path, appName)
+ control:SetValue(value)
+ control:SetCallback("OnValueChanged",ActivateControl)
+
+ if v.descStyle == "inline" then
+ local desc = GetOptionsMemberValue("desc", v, options, path, appName)
+ control:SetDescription(desc)
+ end
+
+ local image = GetOptionsMemberValue("image", v, options, path, appName)
+ local imageCoords = GetOptionsMemberValue("imageCoords", v, options, path, appName)
+
+ if type(image) == "string" or type(image) == "number" then
+ if type(imageCoords) == "table" then
+ control:SetImage(image, unpack(imageCoords))
+ else
+ control:SetImage(image)
+ end
+ end
+ elseif v.type == "range" then
+ control = gui:Create("Slider")
+ control:SetLabel(name)
+ control:SetSliderValues(v.softMin or v.min or 0, v.softMax or v.max or 100, v.bigStep or v.step or 0)
+ control:SetIsPercent(v.isPercent)
+ local value = GetOptionsMemberValue("get",v, options, path, appName)
+ if type(value) ~= "number" then
+ value = 0
+ end
+ control:SetValue(value)
+ control:SetCallback("OnValueChanged",ActivateSlider)
+ control:SetCallback("OnMouseUp",ActivateSlider)
+
+ elseif v.type == "select" then
+ local values = GetOptionsMemberValue("values", v, options, path, appName)
+ if v.style == "radio" then
+ local disabled = CheckOptionDisabled(v, options, path, appName)
+ local width = GetOptionsMemberValue("width",v,options,path,appName)
+ control = gui:Create("InlineGroup")
+ control:SetLayout("Flow")
+ control:SetTitle(name)
+ control.width = "fill"
+
+ control:PauseLayout()
+ local optionValue = GetOptionsMemberValue("get",v, options, path, appName)
+ local t = {}
+ for value, text in pairs(values) do
+ tinsert(t,value)
+ end
+ tsort(t)
+ for k, value in ipairs(t) do
+ local text = values[value]
+ local radio = gui:Create("CheckBox")
+ radio:SetLabel(text)
+ radio:SetUserData("value", value)
+ radio:SetUserData("text", text)
+ radio:SetDisabled(disabled)
+ radio:SetType("radio")
+ radio:SetValue(optionValue == value)
+ radio:SetCallback("OnValueChanged", ActivateMultiControl)
+ InjectInfo(radio, options, v, path, rootframe, appName)
+ control:AddChild(radio)
+ if width == "double" then
+ radio:SetWidth(width_multiplier * 2)
+ elseif width == "half" then
+ radio:SetWidth(width_multiplier / 2)
+ elseif width == "full" then
+ radio.width = "fill"
+ else
+ radio:SetWidth(width_multiplier)
+ end
+ end
+ control:ResumeLayout()
+ control:DoLayout()
+ else
+ local controlType = v.dialogControl or v.control or "Dropdown"
+ control = gui:Create(controlType)
+ if not control then
+ geterrorhandler()(format("Invalid Custom Control Type - %s", tostring(controlType)))
+ control = gui:Create("Dropdown")
+
+ end
+ local itemType = v.itemControl
+ if itemType and not gui:GetWidgetVersion(itemType) then
+ geterrorhandler()(format("Invalid Custom Item Type - %s", tostring(itemType)))
+ itemType = nil
+ end
+ control:SetLabel(name)
+ control:SetList(values, nil, itemType)
+ local value = GetOptionsMemberValue("get",v, options, path, appName)
+ if not values[value] then
+ value = nil
+ end
+ control:SetValue(value)
+ control:SetCallback("OnValueChanged", ActivateControl)
+ end
+
+ elseif v.type == "multiselect" then
+ local values = GetOptionsMemberValue("values", v, options, path, appName)
+
+ local disabled = CheckOptionDisabled(v, options, path, appName)
+
+ local controlType = v.dialogControl or v.control
+
+ local valuesort = new()
+ if values then
+ for value, text in pairs(values) do
+ tinsert(valuesort, value)
+ end
+ end
+ tsort(valuesort)
+
+ if controlType then
+ control = gui:Create(controlType)
+ if not control then
+ geterrorhandler()(format("Invalid Custom Control Type - %s", tostring(controlType)))
+ end
+ end
+ if control then
+ control:SetMultiselect(true)
+ control:SetLabel(name)
+ control:SetList(values)
+ control:SetDisabled(disabled)
+ control:SetCallback("OnValueChanged",ActivateControl)
+ control:SetCallback("OnClosed", MultiControlOnClosed)
+ local width = GetOptionsMemberValue("width",v,options,path,appName)
+ if width == "double" then
+ control:SetWidth(width_multiplier * 2)
+ elseif width == "half" then
+ control:SetWidth(width_multiplier / 2)
+ elseif width == "full" then
+ control.width = "fill"
+ else
+ control:SetWidth(width_multiplier)
+ end
+ --check:SetTriState(v.tristate)
+ for i = 1, tgetn(valuesort) do
+ local key = valuesort[i]
+ local value = GetOptionsMemberValue("get", v, options, path, appName, 1, key)
+ control:SetItemValue(key,value)
+ end
+ else
+ control = gui:Create("InlineGroup")
+ control:SetLayout("Flow")
+ control:SetTitle(name)
+ control.width = "fill"
+
+ control:PauseLayout()
+ local width = GetOptionsMemberValue("width",v,options,path,appName)
+ for i = 1, tgetn(valuesort) do
+ local value = valuesort[i]
+ local text = values[value]
+ local check = gui:Create("CheckBox")
+ check:SetLabel(text)
+ check:SetUserData("value", value)
+ check:SetUserData("text", text)
+ check:SetDisabled(disabled)
+ check:SetTriState(v.tristate)
+ check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, 1, value))
+ check:SetCallback("OnValueChanged",ActivateMultiControl)
+ InjectInfo(check, options, v, path, rootframe, appName)
+ control:AddChild(check)
+ if width == "double" then
+ check:SetWidth(width_multiplier * 2)
+ elseif width == "half" then
+ check:SetWidth(width_multiplier / 2)
+ elseif width == "full" then
+ check.width = "fill"
+ else
+ check:SetWidth(width_multiplier)
+ end
+ end
+ control:ResumeLayout()
+ control:DoLayout()
+
+
+ end
+
+ del(valuesort)
+
+ elseif v.type == "color" then
+ control = gui:Create("ColorPicker")
+ control:SetLabel(name)
+ control:SetHasAlpha(GetOptionsMemberValue("hasAlpha",v, options, path, appName))
+ control:SetColor(GetOptionsMemberValue("get",v, options, path, appName))
+ control:SetCallback("OnValueChanged",ActivateControl)
+ control:SetCallback("OnValueConfirmed",ActivateControl)
+
+ elseif v.type == "keybinding" then
+ control = gui:Create("Keybinding")
+ control:SetLabel(name)
+ control:SetKey(GetOptionsMemberValue("get",v, options, path, appName))
+ control:SetCallback("OnKeyChanged",ActivateControl)
+
+ elseif v.type == "header" then
+ control = gui:Create("Heading")
+ control:SetText(name)
+ control.width = "fill"
+
+ elseif v.type == "description" then
+ control = gui:Create("Label")
+ control:SetText(name)
+
+ local fontSize = GetOptionsMemberValue("fontSize",v, options, path, appName)
+ if fontSize == "medium" then
+ control:SetFontObject(GameFontHighlight)
+ elseif fontSize == "large" then
+ control:SetFontObject(GameFontHighlightLarge)
+ else -- small or invalid
+ control:SetFontObject(GameFontHighlightSmall)
+ end
+
+ local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
+ local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
+
+ if type(image) == "string" or type(image) == "number" then
+ if not width then
+ width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
+ end
+ if not height then
+ height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
+ end
+ if type(imageCoords) == "table" then
+ control:SetImage(image, unpack(imageCoords))
+ else
+ control:SetImage(image)
+ end
+ if type(width) ~= "number" then
+ width = 32
+ end
+ if type(height) ~= "number" then
+ height = 32
+ end
+ control:SetImageSize(width, height)
+ end
+ local width = GetOptionsMemberValue("width",v,options,path,appName)
+ control.width = not width and "fill"
+ end
+
+ --Common Init
+ if control then
+ if control.width ~= "fill" then
+ local width = GetOptionsMemberValue("width",v,options,path,appName)
+ if width == "double" then
+ control:SetWidth(width_multiplier * 2)
+ elseif width == "half" then
+ control:SetWidth(width_multiplier / 2)
+ elseif width == "full" then
+ control.width = "fill"
+ else
+ control:SetWidth(width_multiplier)
+ end
+ end
+ if control.SetDisabled then
+ local disabled = CheckOptionDisabled(v, options, path, appName)
+ control:SetDisabled(disabled)
+ end
+
+ InjectInfo(control, options, v, path, rootframe, appName)
+ container:AddChild(control)
+ end
+
+ end
+ end
+ tremove(path)
+ end
+ container:ResumeLayout()
+ container:DoLayout()
+ del(keySort)
+ del(opts)
+end
+
+-- Ace3v: recursive
+local function BuildPath(path, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if a1 then
+ tinsert(path,a1)
+ BuildPath(path,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+end
+
+local function TreeOnButtonEnter(widget, event, _, uniquevalue, button)
+ local user = widget:GetUserDataTable()
+ if not user then return end
+ local options = user.options
+ local option = user.option
+ local path = user.path
+ local appName = user.appName
+
+ local feedpath = new()
+ for i = 1, tgetn(path) do
+ feedpath[i] = path[i]
+ end
+
+ BuildPath(feedpath, strsplit("\001", uniquevalue))
+ local group = options
+ for i = 1, tgetn(feedpath) do
+ if not group then return end
+ group = GetSubOption(group, feedpath[i])
+ end
+
+ local name = GetOptionsMemberValue("name", group, options, feedpath, appName)
+ local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName)
+
+ GameTooltip:SetOwner(button, "ANCHOR_NONE")
+ if widget.type == "TabGroup-ElvUI" then
+ GameTooltip:SetPoint("BOTTOM",button,"TOP")
+ else
+ GameTooltip:SetPoint("LEFT",button,"RIGHT")
+ end
+
+ if name then
+ GameTooltip:SetText(name, 1, .82, 0, true)
+ end
+
+ if type(desc) == "string" then
+ GameTooltip:AddLine(desc, 1, 1, 1, true)
+ end
+
+ GameTooltip:Show()
+end
+
+local function TreeOnButtonLeave(widget, event, _, value, button)
+ GameTooltip:Hide()
+end
+
+
+local function GroupExists(appName, options, path, uniquevalue)
+
+ if not uniquevalue then return false end
+ local feedpath = new()
+ local temppath = new()
+ local l = tgetn(path)
+ for i = 1, l do
+ feedpath[i] = path[i]
+ end
+ tsetn(feedpath,l)
+
+ BuildPath(feedpath, strsplit("\001", uniquevalue))
+
+ local group = options
+ for i = 1, tgetn(feedpath) do
+ local v = feedpath[i]
+ temppath[i] = v
+ group = GetSubOption(group, v)
+
+ if not group or group.type ~= "group" or CheckOptionHidden(group, options, temppath, appName) then
+ del(feedpath)
+ del(temppath)
+ return false
+ end
+ end
+ del(feedpath)
+ del(temppath)
+ return true
+end
+
+local function GroupSelected(widget, event, _, uniquevalue)
+ if not uniquevalue then widget:ReleaseChildren() return end
+
+ local user = widget:GetUserDataTable()
+
+ local options = user.options
+ local option = user.option
+ local path = user.path
+ local rootframe = user.rootframe
+
+ local feedpath = new()
+ local l = tgetn(path)
+ for i = 1, l do
+ feedpath[i] = path[i]
+ end
+ tsetn(feedpath,l)
+
+ BuildPath(feedpath, strsplit("\001", uniquevalue))
+ local group = options
+ for i = 1, tgetn(feedpath) do
+ group = GetSubOption(group, feedpath[i])
+ end
+ widget:ReleaseChildren()
+
+ AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath)
+
+ del(feedpath)
+end
+
+
+
+--[[
+-- INTERNAL --
+This function will feed one group, and any inline child groups into the given container
+Select Groups will only have the selection control (tree, tabs, dropdown) fed in
+and have a group selected, this event will trigger the feeding of child groups
+
+Rules:
+ If the group is Inline, FeedOptions
+ If the group has no child groups, FeedOptions
+
+ If the group is a tab or select group, FeedOptions then add the Group Control
+ If the group is a tree group FeedOptions then
+ its parent isnt a tree group: then add the tree control containing this and all child tree groups
+ if its parent is a tree group, its already a node on a tree
+--]]
+
+function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot)
+
+ local group = options
+ --follow the path to get to the curent group
+ local inline
+ local grouptype, parenttype = options.childGroups, "none"
+
+ for i = 1, tgetn(path) do
+ local v = path[i]
+ group = GetSubOption(group, v)
+ inline = inline or pickfirstset(4,group.dialogInline,group.guiInline,group.inline, false)
+ parenttype = grouptype
+ grouptype = group.childGroups
+ end
+
+ if not parenttype then
+ parenttype = "tree"
+ end
+
+ --check if the group has child groups
+ local hasChildGroups
+ for k, v in pairs(group.args) do
+ if v.type == "group" and not pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
+ hasChildGroups = true
+ end
+ end
+ if group.plugins then
+ for plugin, t in pairs(group.plugins) do
+ for k, v in pairs(t) do
+ if v.type == "group" and not pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
+ hasChildGroups = true
+ end
+ end
+ end
+ end
+
+ container:SetLayout("flow")
+ local scroll
+
+ --Add a scrollframe if we are not going to add a group control, this is the inverse of the conditions for that later on
+ if (not (hasChildGroups and not inline)) or (grouptype ~= "tab" and grouptype ~= "select" and (parenttype == "tree" and not isRoot)) then
+ if container.type ~= "InlineGroup" and container.type ~= "SimpleGroup" then
+ scroll = gui:Create("ScrollFrame")
+ scroll:SetLayout("flow")
+ scroll.width = "fill"
+ scroll.height = "fill"
+ container:SetLayout("fill")
+ container:AddChild(scroll)
+ container = scroll
+ end
+ end
+
+ FeedOptions(appName,options,container,rootframe,path,group,nil)
+
+ if scroll then
+ container:PerformLayout()
+ local status = self:GetStatusTable(appName, path)
+ if not status.scroll then
+ status.scroll = {}
+ end
+ scroll:SetStatusTable(status.scroll)
+ end
+
+ if hasChildGroups and not inline then
+ local name = GetOptionsMemberValue("name", group, options, path, appName)
+ if grouptype == "tab" then
+
+ local tab = gui:Create("TabGroup-ElvUI")
+ InjectInfo(tab, options, group, path, rootframe, appName)
+ tab:SetCallback("OnGroupSelected", GroupSelected)
+ tab:SetCallback("OnTabEnter", TreeOnButtonEnter)
+ tab:SetCallback("OnTabLeave", TreeOnButtonLeave)
+
+ local status = AceConfigDialog:GetStatusTable(appName, path)
+ if not status.groups then
+ status.groups = {}
+ end
+ tab:SetStatusTable(status.groups)
+ tab.width = "fill"
+ tab.height = "fill"
+
+ local tabs = BuildGroups(group, options, path, appName)
+ tab:SetTabs(tabs)
+ tab:SetUserData("tablist", tabs)
+
+ for i = 1, tgetn(tabs) do
+ local entry = tabs[i]
+ if not entry.disabled then
+ tab:SelectTab((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
+ break
+ end
+ end
+
+ container:AddChild(tab)
+
+ elseif grouptype == "select" then
+
+ local select = gui:Create("DropdownGroup")
+ select:SetTitle(name)
+ InjectInfo(select, options, group, path, rootframe, appName)
+ select:SetCallback("OnGroupSelected", GroupSelected)
+ local status = AceConfigDialog:GetStatusTable(appName, path)
+ if not status.groups then
+ status.groups = {}
+ end
+ select:SetStatusTable(status.groups)
+ local grouplist, orderlist = BuildSelect(group, options, path, appName)
+ select:SetGroupList(grouplist, orderlist)
+ select:SetUserData("grouplist", grouplist)
+ select:SetUserData("orderlist", orderlist)
+
+ local firstgroup = orderlist[1]
+ if firstgroup then
+ select:SetGroup((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup)
+ end
+
+ select.width = "fill"
+ select.height = "fill"
+
+ container:AddChild(select)
+
+ --assume tree group by default
+ --if parenttype is tree then this group is already a node on that tree
+ elseif (parenttype ~= "tree") or isRoot then
+ local tree = gui:Create("TreeGroup")
+ InjectInfo(tree, options, group, path, rootframe, appName)
+ tree:EnableButtonTooltips(false)
+
+ tree.width = "fill"
+ tree.height = "fill"
+
+ tree:SetCallback("OnGroupSelected", GroupSelected)
+ tree:SetCallback("OnButtonEnter", TreeOnButtonEnter)
+ tree:SetCallback("OnButtonLeave", TreeOnButtonLeave)
+
+ local status = AceConfigDialog:GetStatusTable(appName, path)
+ if not status.groups then
+ status.groups = {}
+ end
+ local treedefinition = BuildGroups(group, options, path, appName, true)
+ tree:SetStatusTable(status.groups)
+
+ tree:SetTree(treedefinition)
+ tree:SetUserData("tree",treedefinition)
+
+ for i = 1, tgetn(treedefinition) do
+ local entry = treedefinition[i]
+ if not entry.disabled then
+ tree:SelectByValue((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
+ break
+ end
+ end
+
+ container:AddChild(tree)
+ end
+ end
+end
+
+local old_CloseSpecialWindows
+
+
+local function RefreshOnUpdate()
+ for appName in pairs(this.closing) do
+ if AceConfigDialog.OpenFrames[appName] then
+ AceConfigDialog.OpenFrames[appName]:Hide()
+ end
+ if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then
+ for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do
+ if not widget:IsVisible() then
+ widget:ReleaseChildren()
+ end
+ end
+ end
+ this.closing[appName] = nil
+ end
+
+ if this.closeAll then
+ for k, v in pairs(AceConfigDialog.OpenFrames) do
+ if not this.closeAllOverride[k] then
+ v:Hide()
+ end
+ end
+ this.closeAll = nil
+ wipe(this.closeAllOverride)
+ end
+
+ for appName in pairs(this.apps) do
+ if AceConfigDialog.OpenFrames[appName] then
+ local user = AceConfigDialog.OpenFrames[appName]:GetUserDataTable()
+ AceConfigDialog:Open(appName, unpack(user.basepath or emptyTbl))
+ end
+ if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then
+ for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do
+ local user = widget:GetUserDataTable()
+ if widget:IsVisible() then
+ AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(user.basepath or emptyTbl))
+ end
+ end
+ end
+ this.apps[appName] = nil
+ end
+ this:SetScript("OnUpdate", nil)
+end
+
+-- Upgrade the OnUpdate script as well, if needed.
+if AceConfigDialog.frame:GetScript("OnUpdate") then
+ AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
+end
+
+--- Close all open options windows
+function AceConfigDialog:CloseAll()
+ AceConfigDialog.frame.closeAll = true
+ AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
+ if next(self.OpenFrames) then
+ return true
+ end
+end
+
+--- Close a specific options window.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+function AceConfigDialog:Close(appName)
+ if self.OpenFrames[appName] then
+ AceConfigDialog.frame.closing[appName] = true
+ AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
+ return true
+ end
+end
+
+-- Internal -- Called by AceConfigRegistry
+function AceConfigDialog:ConfigTableChanged(event, appName)
+ AceConfigDialog.frame.apps[appName] = true
+ AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
+end
+
+reg.RegisterCallback(AceConfigDialog, "ConfigTableChange", "ConfigTableChanged")
+
+--- Sets the default size of the options window for a specific application.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param width The default width
+-- @param height The default height
+function AceConfigDialog:SetDefaultSize(appName, width, height)
+ local status = AceConfigDialog:GetStatusTable(appName)
+ if type(width) == "number" and type(height) == "number" then
+ status.width = width
+ status.height = height
+ end
+end
+
+--- Open an option window at the specified path (if any).
+-- This function can optionally feed the group into a pre-created container
+-- instead of creating a new container frame.
+-- @paramsig appName [, container][, ...]
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param container An optional container frame to feed the options into
+-- @param ... The path to open after creating the options window (see `:SelectGroup` for details)
+function AceConfigDialog:Open(appName, container, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ if not old_CloseSpecialWindows then
+ old_CloseSpecialWindows = CloseSpecialWindows
+ CloseSpecialWindows = function()
+ local found = old_CloseSpecialWindows()
+ return self:CloseAll() or found
+ end
+ end
+ local app = reg:GetOptionsTable(appName)
+ if not app then
+ error(format("%s isn't registed with AceConfigRegistry, unable to open config", appName), 2)
+ end
+ local options = app("dialog", MAJOR)
+
+ local f
+
+ local path = new()
+ local name = GetOptionsMemberValue("name", options, options, path, appName)
+
+ --If an optional path is specified add it to the path table before feeding the options
+ --as container is optional as well it may contain the first element of the path
+ if type(container) == "string" then
+ tinsert(path, container)
+ container = nil
+ end
+ BuildPath(path, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+
+ local option = options
+ if type(container) == "table" and container.type == "BlizOptionsGroup" and tgetn(path) > 0 then
+ for i = 1, tgetn(path) do
+ option = options.args[path[i]]
+ end
+ name = format("%s - %s", name, GetOptionsMemberValue("name", option, options, path, appName))
+ end
+
+ --if a container is given feed into that
+ if container then
+ f = container
+ f:ReleaseChildren()
+ f:SetUserData("appName", appName)
+ f:SetUserData("iscustom", true)
+ if tgetn(path) > 0 then
+ f:SetUserData("basepath", copy(path))
+ end
+ local status = AceConfigDialog:GetStatusTable(appName)
+ if not status.width then
+ status.width = 700
+ end
+ if not status.height then
+ status.height = 500
+ end
+ if f.SetStatusTable then
+ f:SetStatusTable(status)
+ end
+ if f.SetTitle then
+ f:SetTitle(name or "")
+ end
+ else
+ if not self.OpenFrames[appName] then
+ f = gui:Create("Frame")
+ self.OpenFrames[appName] = f
+ else
+ f = self.OpenFrames[appName]
+ end
+ f:ReleaseChildren()
+ f:SetCallback("OnClose", FrameOnClose)
+ f:SetUserData("appName", appName)
+ if tgetn(path) > 0 then
+ f:SetUserData("basepath", copy(path))
+ end
+ f:SetTitle(name or "")
+ local status = AceConfigDialog:GetStatusTable(appName)
+ f:SetStatusTable(status)
+ end
+
+ self:FeedGroup(appName,options,f,f,path,true)
+ if f.Show then
+ f:Show()
+ end
+ del(path)
+
+ if AceConfigDialog.frame.closeAll then
+ -- close all is set, but thats not good, since we're just opening here, so force it
+ AceConfigDialog.frame.closeAllOverride[appName] = true
+ end
+end
+
+-- convert pre-39 BlizOptions structure to the new format
+if oldminor and oldminor < 39 and AceConfigDialog.BlizOptions then
+ local old = AceConfigDialog.BlizOptions
+ local new = {}
+ for key, widget in pairs(old) do
+ local appName = widget:GetUserData("appName")
+ if not new[appName] then new[appName] = {} end
+ new[appName][key] = widget
+ end
+ AceConfigDialog.BlizOptions = new
+else
+ AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {}
+end
+
+local function FeedToBlizPanel(widget, event)
+ local path = widget:GetUserData("path")
+ AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(path or emptyTbl))
+end
+
+local function ClearBlizPanel(widget, event)
+ local appName = widget:GetUserData("appName")
+ AceConfigDialog.frame.closing[appName] = true
+ AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
+end
+
+--- Add an option table into the Blizzard Interface Options panel.
+-- You can optionally supply a descriptive name to use and a parent frame to use,
+-- as well as a path in the options table.\\
+-- If no name is specified, the appName will be used instead.
+--
+-- If you specify a proper `parent` (by name), the interface options will generate a
+-- tree layout. Note that only one level of children is supported, so the parent always
+-- has to be a head-level note.
+--
+-- This function returns a reference to the container frame registered with the Interface
+-- Options. You can use this reference to open the options with the API function
+-- `InterfaceOptionsFrame_OpenToCategory`.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param name A descriptive name to display in the options tree (defaults to appName)
+-- @param parent The parent to use in the interface options tree.
+-- @param ... The path in the options table to feed into the interface options panel.
+-- @return The reference to the frame registered into the Interface Options.
+function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...)
+ local BlizOptions = AceConfigDialog.BlizOptions
+
+ local key = appName
+ local l = tgetn(arg)
+ for n = 1, l do
+ key = key .. "\001" .. arg[n]
+ end
+
+ if not BlizOptions[appName] then
+ BlizOptions[appName] = {}
+ end
+
+ if not BlizOptions[appName][key] then
+ local group = gui:Create("BlizOptionsGroup")
+ BlizOptions[appName][key] = group
+ group:SetName(name or appName, parent)
+
+ group:SetTitle(name or appName)
+ group:SetUserData("appName", appName)
+ if l > 0 then
+ local path = {}
+ for n = 1, l do
+ tinsert(path, args[n])
+ end
+ group:SetUserData("path", path)
+ end
+ group:SetCallback("OnShow", FeedToBlizPanel)
+ group:SetCallback("OnHide", ClearBlizPanel)
+ InterfaceOptions_AddCategory(group.frame)
+ return group.frame
+ else
+ error(format("%s has already been added to the Blizzard Options Window with the given path", appName), 2)
+ end
+end
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml
new file mode 100644
index 0000000..86ce057
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua
new file mode 100644
index 0000000..5e45cd0
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua
@@ -0,0 +1,352 @@
+--- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
+-- Options tables can be registered as raw tables, OR as function refs that return a table.\\
+-- Such functions receive three arguments: "uiType", "uiName", "appName". \\
+-- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
+-- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\
+-- * The **appName** field is the options table name as given at registration time \\
+--
+-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
+-- @class file
+-- @name AceConfigRegistry-3.0
+-- @release $Id: AceConfigRegistry-3.0.lua 1139 2016-07-03 07:43:51Z nevcairiel $
+local MAJOR, MINOR = "AceConfigRegistry-3.0", 16
+local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceConfigRegistry then return end
+
+AceConfigRegistry.tables = AceConfigRegistry.tables or {}
+
+local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
+
+if not AceConfigRegistry.callbacks then
+ AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
+end
+
+-- Lua APIs
+local tinsert, tconcat, tgetn = table.insert, table.concat, table.getn
+local strfind = string.find
+local type, tostring, pairs = type, tostring, pairs
+local error, assert = error, assert
+
+-----------------------------------------------------------------------
+-- Validating options table consistency:
+
+
+AceConfigRegistry.validated = {
+ -- list of options table names ran through :ValidateOptionsTable automatically.
+ -- CLEARED ON PURPOSE, since newer versions may have newer validators
+ cmd = {},
+ dropdown = {},
+ dialog = {},
+}
+
+local function err(msg, errlvl, ...)
+ local l = tgetn(arg)
+ local i,j = 1,l
+ while i < j do
+ arg[i], arg[j] = arg[j], arg[i]
+ i = i+1
+ j = j-1
+ end
+ error(MAJOR..":ValidateOptionsTable(): "..tconcat(arg,".")..msg, errlvl+2)
+end
+
+local isstring={["string"]=true, _="string"}
+local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
+local istable={["table"]=true, _="table"}
+local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
+local optstring={["nil"]=true,["string"]=true, _="string"}
+local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
+local optstringnumberfunc={["nil"]=true,["string"]=true,["number"]=true,["function"]=true, _="string, number or funcref"}
+local optnumber={["nil"]=true,["number"]=true, _="number"}
+local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
+local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
+local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
+local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
+local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
+local opttable={["nil"]=true,["table"]=true, _="table"}
+local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
+local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
+
+local basekeys={
+ type=isstring,
+ name=isstringfunc,
+ desc=optstringfunc,
+ descStyle=optstring,
+ order=optmethodnumber,
+ validate=optmethodfalse,
+ confirm=optmethodbool,
+ confirmText=optstring,
+ disabled=optmethodbool,
+ hidden=optmethodbool,
+ guiHidden=optmethodbool,
+ dialogHidden=optmethodbool,
+ dropdownHidden=optmethodbool,
+ cmdHidden=optmethodbool,
+ icon=optstringnumberfunc,
+ iconCoords=optmethodtable,
+ handler=opttable,
+ get=optmethodfalse,
+ set=optmethodfalse,
+ func=optmethodfalse,
+ arg={["*"]=true},
+ width=optstring,
+}
+
+local typedkeys={
+ header={},
+ description={
+ image=optstringnumberfunc,
+ imageCoords=optmethodtable,
+ imageHeight=optnumber,
+ imageWidth=optnumber,
+ fontSize=optstringfunc,
+ },
+ group={
+ args=istable,
+ plugins=opttable,
+ inline=optbool,
+ cmdInline=optbool,
+ guiInline=optbool,
+ dropdownInline=optbool,
+ dialogInline=optbool,
+ childGroups=optstring,
+ },
+ execute={
+ image=optstringnumberfunc,
+ imageCoords=optmethodtable,
+ imageHeight=optnumber,
+ imageWidth=optnumber,
+ },
+ input={
+ pattern=optstring,
+ usage=optstring,
+ control=optstring,
+ dialogControl=optstring,
+ dropdownControl=optstring,
+ multiline=optboolnumber,
+ nullable=optbool,
+ },
+ toggle={
+ tristate=optbool,
+ image=optstringnumberfunc,
+ imageCoords=optmethodtable,
+ },
+ tristate={
+ },
+ range={
+ min=optnumber,
+ softMin=optnumber,
+ max=optnumber,
+ softMax=optnumber,
+ step=optnumber,
+ bigStep=optnumber,
+ isPercent=optbool,
+ },
+ select={
+ values=ismethodtable,
+ valuesTableDestroyable=optbool, -- Ace3v: if the values table is generated by AceCore.new
+ style={
+ ["nil"]=true,
+ ["string"]={dropdown=true,radio=true},
+ _="string: 'dropdown' or 'radio'"
+ },
+ control=optstring,
+ dialogControl=optstring,
+ dropdownControl=optstring,
+ itemControl=optstring,
+ },
+ multiselect={
+ values=ismethodtable,
+ valuesTableDestroyable=optbool, -- Ace3v: if the values table is generated by AceCore.new
+ style=optstring,
+ tristate=optbool,
+ control=optstring,
+ dialogControl=optstring,
+ dropdownControl=optstring,
+ },
+ color={
+ hasAlpha=optmethodbool,
+ },
+ keybinding={
+ -- TODO
+ },
+}
+
+local function validateKey(k,errlvl,arg)
+ errlvl=(errlvl or 0)+1
+ if type(k)~="string" then
+ err("["..tostring(k).."] - key is not a string", errlvl, arg)
+ end
+ if strfind(k, "[%c\127]") then
+ err("["..tostring(k).."] - key name contained control characters", errlvl, arg)
+ end
+end
+
+local function validateVal(v, oktypes, errlvl, arg)
+ errlvl=(errlvl or 0)+1
+ local isok=oktypes[type(v)] or oktypes["*"]
+
+ if not isok then
+ err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl, arg)
+ end
+ if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
+ if not isok[v] then
+ err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl, arg)
+ end
+ end
+end
+
+local function validate(options,errlvl,arg)
+ errlvl=(errlvl or 0)+1
+ -- basic consistency
+ if type(options)~="table" then
+ err(": expected a table, got a "..type(options), errlvl, arg)
+ end
+ if type(options.type)~="string" then
+ err(".type: expected a string, got a "..type(options.type), errlvl, arg)
+ end
+
+ -- get type and 'typedkeys' member
+ local tk = typedkeys[options.type]
+ if not tk then
+ err(".type: unknown type '"..options.type.."'", errlvl, arg)
+ end
+
+ -- make sure that all options[] are known parameters
+ for k,v in pairs(options) do
+ if not (tk[k] or basekeys[k]) then
+ err(": unknown parameter", errlvl,tostring(k), arg)
+ end
+ end
+
+ -- verify that required params are there, and that everything is the right type
+ for k,oktypes in pairs(basekeys) do
+ validateVal(options[k], oktypes, errlvl, k, arg)
+ end
+ for k,oktypes in pairs(tk) do
+ validateVal(options[k], oktypes, errlvl, k, arg)
+ end
+
+ -- extra logic for groups
+ if options.type=="group" then
+ for k,v in pairs(options.args) do
+ validateKey(k,errlvl,"args", arg)
+ validate(v, errlvl,k,"args", arg)
+ end
+ if options.plugins then
+ for plugname,plugin in pairs(options.plugins) do
+ if type(plugin)~="table" then
+ err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname), "plugins", arg)
+ end
+ for k,v in pairs(plugin) do
+ validateKey(k,errlvl,tostring(plugname),"plugins",arg)
+ validate(v, errlvl,k,tostring(plugname),"plugins",arg)
+ end
+ end
+ end
+ end
+end
+
+
+--- Validates basic structure and integrity of an options table \\
+-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
+-- @param options The table to be validated
+-- @param name The name of the table to be validated (shown in any error message)
+-- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
+function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
+ errlvl=(errlvl or 0)+1
+ name = name or "Optionstable"
+ if not options.name then
+ options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
+ end
+ validate(options,errlvl,name)
+end
+
+--- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
+-- You should call this function if your options table changed from any outside event, like a game event
+-- or a timer.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+function AceConfigRegistry:NotifyChange(appName)
+ if not AceConfigRegistry.tables[appName] then return end
+ AceConfigRegistry.callbacks:Fire("ConfigTableChange", 1, appName)
+end
+
+-- -------------------------------------------------------------------
+-- Registering and retreiving options tables:
+
+
+-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
+
+local function validateGetterArgs(uiType, uiName, errlvl)
+ errlvl=(errlvl or 0)+2
+ if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
+ error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
+ end
+ if not strfind(uiName, "[A-Za-z]+-[0-9]") then -- Expecting e.g. "MyLib-1.2"
+ error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
+ end
+end
+
+--- Register an options table with the config registry.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param options The options table, OR a function reference that generates it on demand. \\
+-- See the top of the page for info on arguments passed to such functions.
+-- @param skipValidation Skip options table validation (primarily useful for extremely huge options, with a noticeable slowdown)
+function AceConfigRegistry:RegisterOptionsTable(appName, options, skipValidation)
+ if type(options)=="table" then
+ if options.type~="group" then -- quick sanity checker
+ error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
+ end
+ AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
+ errlvl=(errlvl or 0)+1
+ validateGetterArgs(uiType, uiName, errlvl)
+ if not AceConfigRegistry.validated[uiType][appName] and not skipValidation then
+ AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
+ AceConfigRegistry.validated[uiType][appName] = true
+ end
+ return options
+ end
+ elseif type(options)=="function" then
+ AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
+ errlvl=(errlvl or 0)+1
+ validateGetterArgs(uiType, uiName, errlvl)
+ local tab = assert(options(uiType, uiName, appName))
+ if not AceConfigRegistry.validated[uiType][appName] and not skipValidation then
+ AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
+ AceConfigRegistry.validated[uiType][appName] = true
+ end
+ return tab
+ end
+ else
+ error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
+ end
+end
+
+--- Returns an iterator of ["appName"]=funcref pairs
+function AceConfigRegistry:IterateOptionsTables()
+ return pairs(AceConfigRegistry.tables)
+end
+
+
+
+
+--- Query the registry for a specific options table.
+-- If only appName is given, a function is returned which you
+-- can call with (uiType,uiName) to get the table.\\
+-- If uiType&uiName are given, the table is returned.
+-- @param appName The application name as given to `:RegisterOptionsTable()`
+-- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
+-- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
+function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
+ local f = AceConfigRegistry.tables[appName]
+ if not f then
+ return nil
+ end
+
+ if uiType then
+ return f(uiType,uiName,1) -- get the table for us
+ else
+ return f -- return the function
+ end
+end
diff --git a/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml
new file mode 100644
index 0000000..101bfda
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceDBOptions-3.0/AceDBOptions-3.0.lua b/ElvUI_Config/Libraries/AceDBOptions-3.0/AceDBOptions-3.0.lua
new file mode 100644
index 0000000..9857b6a
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceDBOptions-3.0/AceDBOptions-3.0.lua
@@ -0,0 +1,471 @@
+--- AceDBOptions-3.0 provides a universal AceConfig options screen for managing AceDB-3.0 profiles.
+-- @class file
+-- @name AceDBOptions-3.0
+-- @release $Id: AceDBOptions-3.0.lua 1140 2016-07-03 07:53:29Z nevcairiel $
+local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 15
+local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR)
+
+if not AceDBOptions then return end -- No upgrade needed
+
+local AceCore = LibStub("AceCore-3.0")
+local new, del = AceCore.new, AceCore.del
+
+-- Lua APIs
+local pairs, next = pairs, next
+
+-- WoW APIs
+local UnitClass = UnitClass
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: NORMAL_FONT_COLOR_CODE, FONT_COLOR_CODE_CLOSE
+
+AceDBOptions.optionTables = AceDBOptions.optionTables or {}
+AceDBOptions.handlers = AceDBOptions.handlers or {}
+
+--[[
+ Localization of AceDBOptions-3.0
+]]
+
+local L = {
+ choose = "Existing Profiles",
+ choose_desc = "You can either create a new profile by entering a name in the editbox, or choose one of the already existing profiles.",
+ choose_sub = "Select one of your currently available profiles.",
+ copy = "Copy From",
+ copy_desc = "Copy the settings from one existing profile into the currently active profile.",
+ current = "Current Profile:",
+ default = "Default",
+ delete = "Delete a Profile",
+ delete_confirm = "Are you sure you want to delete the selected profile?",
+ delete_desc = "Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.",
+ delete_sub = "Deletes a profile from the database.",
+ intro = "You can change the active database profile, so you can have different settings for every character.",
+ new = "New",
+ new_sub = "Create a new empty profile.",
+ profiles = "Profiles",
+ profiles_sub = "Manage Profiles",
+ reset = "Reset Profile",
+ reset_desc = "Reset the current profile back to its default values, in case your configuration is broken, or you simply want to start over.",
+ reset_sub = "Reset the current profile to the default",
+}
+
+local LOCALE = GetLocale()
+if LOCALE == "deDE" then
+ L["choose"] = "Vorhandene Profile"
+ L["choose_desc"] = "Du kannst ein neues Profil erstellen, indem du einen neuen Namen in der Eingabebox 'Neu' eingibst, oder wähle eines der vorhandenen Profile aus."
+ L["choose_sub"] = "Wählt ein bereits vorhandenes Profil aus."
+ L["copy"] = "Kopieren von..."
+ L["copy_desc"] = "Kopiere die Einstellungen von einem vorhandenen Profil in das aktive Profil."
+ L["current"] = "Aktuelles Profil:"
+ L["default"] = "Standard"
+ L["delete"] = "Profil löschen"
+ L["delete_confirm"] = "Willst du das ausgewählte Profil wirklich löschen?"
+ L["delete_desc"] = "Lösche vorhandene oder unbenutzte Profile aus der Datenbank, um Platz zu sparen und die SavedVariables-Datei 'sauber' zu halten."
+ L["delete_sub"] = "Löscht ein Profil aus der Datenbank."
+ L["intro"] = "Hier kannst du das aktive Datenbankprofil ändern, damit du verschiedene Einstellungen für jeden Charakter erstellen kannst, wodurch eine sehr flexible Konfiguration möglich wird."
+ L["new"] = "Neu"
+ L["new_sub"] = "Ein neues Profil erstellen."
+ L["profiles"] = "Profile"
+ L["profiles_sub"] = "Profile verwalten"
+ L["reset"] = "Profil zurücksetzen"
+ L["reset_desc"] = "Setzt das momentane Profil auf Standardwerte zurück, für den Fall, dass mit der Konfiguration etwas schief lief oder weil du einfach neu starten willst."
+ L["reset_sub"] = "Das aktuelle Profil auf Standard zurücksetzen."
+elseif LOCALE == "frFR" then
+ L["choose"] = "Profils existants"
+ L["choose_desc"] = "Vous pouvez créer un nouveau profil en entrant un nouveau nom dans la boîte de saisie, ou en choississant un des profils déjà existants."
+ L["choose_sub"] = "Permet de choisir un des profils déjà disponibles."
+ L["copy"] = "Copier à partir de"
+ L["copy_desc"] = "Copie les paramètres d'un profil déjà existant dans le profil actuellement actif."
+ L["current"] = "Profil actuel :"
+ L["default"] = "Défaut"
+ L["delete"] = "Supprimer un profil"
+ L["delete_confirm"] = "Etes-vous sûr de vouloir supprimer le profil sélectionné ?"
+ L["delete_desc"] = "Supprime les profils existants inutilisés de la base de données afin de gagner de la place et de nettoyer le fichier SavedVariables."
+ L["delete_sub"] = "Supprime un profil de la base de données."
+ L["intro"] = "Vous pouvez changer le profil actuel afin d'avoir des paramètres différents pour chaque personnage, permettant ainsi d'avoir une configuration très flexible."
+ L["new"] = "Nouveau"
+ L["new_sub"] = "Créée un nouveau profil vierge."
+ L["profiles"] = "Profils"
+ L["profiles_sub"] = "Gestion des profils"
+ L["reset"] = "Réinitialiser le profil"
+ L["reset_desc"] = "Réinitialise le profil actuel au cas où votre configuration est corrompue ou si vous voulez tout simplement faire table rase."
+ L["reset_sub"] = "Réinitialise le profil actuel avec les paramètres par défaut."
+elseif LOCALE == "koKR" then
+ L["choose"] = "저장 중인 프로필"
+ L["choose_desc"] = "입력창에 새로운 이름을 입력하거나 저장 중인 프로필 중 하나를 선택하여 새로운 프로필을 만들 수 있습니다."
+ L["choose_sub"] = "현재 이용할 수 있는 프로필 중 하나를 선택합니다."
+ L["copy"] = "복사해오기"
+ L["copy_desc"] = "현재 사용 중인 프로필에 선택한 프로필의 설정을 복사합니다."
+ L["current"] = "현재 프로필:"
+ L["default"] = "기본값"
+ L["delete"] = "프로필 삭제"
+ L["delete_confirm"] = "정말로 선택한 프로필을 삭제할까요?"
+ L["delete_desc"] = "저장 공간 절약과 SavedVariables 파일의 정리를 위해 데이터베이스에서 사용하지 않는 프로필을 삭제하세요."
+ L["delete_sub"] = "데이터베이스의 프로필을 삭제합니다."
+ L["intro"] = "활성 데이터베이스 프로필을 변경할 수 있고, 각 캐릭터 별로 다른 설정을 할 수 있습니다."
+ L["new"] = "새로운 프로필"
+ L["new_sub"] = "새로운 프로필을 만듭니다."
+ L["profiles"] = "프로필"
+ L["profiles_sub"] = "프로필 관리"
+ L["reset"] = "프로필 초기화"
+ L["reset_desc"] = "설정이 깨졌거나 처음부터 다시 설정을 원하는 경우, 현재 프로필을 기본값으로 초기화하세요."
+ L["reset_sub"] = "현재 프로필을 기본값으로 초기화합니다"
+elseif LOCALE == "esES" or LOCALE == "esMX" then
+ L["choose"] = "Perfiles existentes"
+ L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes."
+ L["choose_sub"] = "Selecciona uno de los perfiles disponibles."
+ L["copy"] = "Copiar de"
+ L["copy_desc"] = "Copia los ajustes de un perfil existente al perfil actual."
+ L["current"] = "Perfil actual:"
+ L["default"] = "Por defecto"
+ L["delete"] = "Borrar un Perfil"
+ L["delete_confirm"] = "¿Estas seguro que quieres borrar el perfil seleccionado?"
+ L["delete_desc"] = "Borra los perfiles existentes y sin uso de la base de datos para ganar espacio y limpiar el archivo SavedVariables."
+ L["delete_sub"] = "Borra un perfil de la base de datos."
+ L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones."
+ L["new"] = "Nuevo"
+ L["new_sub"] = "Crear un nuevo perfil vacio."
+ L["profiles"] = "Perfiles"
+ L["profiles_sub"] = "Manejar Perfiles"
+ L["reset"] = "Reiniciar Perfil"
+ L["reset_desc"] = "Reinicia el perfil actual a los valores por defectos, en caso de que se haya estropeado la configuración o quieras volver a empezar de nuevo."
+ L["reset_sub"] = "Reinicar el perfil actual al de por defecto"
+elseif LOCALE == "zhTW" then
+ L["choose"] = "現有的設定檔"
+ L["choose_desc"] = "您可以在文字方塊內輸入名字以建立新的設定檔,或是選擇一個現有的設定檔使用。"
+ L["choose_sub"] = "從當前可用的設定檔裡面選擇一個。"
+ L["copy"] = "複製自"
+ L["copy_desc"] = "從一個現有的設定檔,將設定複製到現在使用中的設定檔。"
+ L["current"] = "目前設定檔:"
+ L["default"] = "預設"
+ L["delete"] = "刪除一個設定檔"
+ L["delete_confirm"] = "確定要刪除所選擇的設定檔嗎?"
+ L["delete_desc"] = "從資料庫裡刪除不再使用的設定檔,以節省空間,並且清理 SavedVariables 檔案。"
+ L["delete_sub"] = "從資料庫裡刪除一個設定檔。"
+ L["intro"] = "您可以從資料庫中選擇一個設定檔來使用,如此就可以讓每個角色使用不同的設定。"
+ L["new"] = "新建"
+ L["new_sub"] = "新建一個空的設定檔。"
+ L["profiles"] = "設定檔"
+ L["profiles_sub"] = "管理設定檔"
+ L["reset"] = "重置設定檔"
+ L["reset_desc"] = "將現用的設定檔重置為預設值;用於設定檔損壞,或者單純想要重來的情況。"
+ L["reset_sub"] = "將目前的設定檔重置為預設值"
+elseif LOCALE == "zhCN" then
+ L["choose"] = "现有的配置文件"
+ L["choose_desc"] = "你可以通过在文本框内输入一个名字创立一个新的配置文件,也可以选择一个已经存在的配置文件。"
+ L["choose_sub"] = "从当前可用的配置文件里面选择一个。"
+ L["copy"] = "复制自"
+ L["copy_desc"] = "从当前某个已保存的配置文件复制到当前正使用的配置文件。"
+ L["current"] = "当前配置文件:"
+ L["default"] = "默认"
+ L["delete"] = "删除一个配置文件"
+ L["delete_confirm"] = "你确定要删除所选择的配置文件么?"
+ L["delete_desc"] = "从数据库里删除不再使用的配置文件,以节省空间,并且清理SavedVariables文件。"
+ L["delete_sub"] = "从数据库里删除一个配置文件。"
+ L["intro"] = "你可以选择一个活动的数据配置文件,这样你的每个角色就可以拥有不同的设置值,可以给你的插件配置带来极大的灵活性。"
+ L["new"] = "新建"
+ L["new_sub"] = "新建一个空的配置文件。"
+ L["profiles"] = "配置文件"
+ L["profiles_sub"] = "管理配置文件"
+ L["reset"] = "重置配置文件"
+ L["reset_desc"] = "将当前的配置文件恢复到它的默认值,用于你的配置文件损坏,或者你只是想重来的情况。"
+ L["reset_sub"] = "将当前的配置文件恢复为默认值"
+elseif LOCALE == "ruRU" then
+ L["choose"] = "Существующие профили"
+ L["choose_desc"] = "Вы можете создать новый профиль, введя название в поле ввода, или выбрать один из уже существующих профилей."
+ L["choose_sub"] = "Выбор одиного из уже доступных профилей"
+ L["copy"] = "Скопировать из"
+ L["copy_desc"] = "Скопировать настройки из выбранного профиля в активный."
+ L["current"] = "Текущий профиль:"
+ L["default"] = "По умолчанию"
+ L["delete"] = "Удалить профиль"
+ L["delete_confirm"] = "Вы уверены, что вы хотите удалить выбранный профиль?"
+ L["delete_desc"] = "Удалить существующий и неиспользуемый профиль из БД для сохранения места, и очистить SavedVariables файл."
+ L["delete_sub"] = "Удаление профиля из БД"
+ L["intro"] = "Изменяя активный профиль, вы можете задать различные настройки модификаций для каждого персонажа."
+ L["new"] = "Новый"
+ L["new_sub"] = "Создать новый чистый профиль"
+ L["profiles"] = "Профили"
+ L["profiles_sub"] = "Управление профилями"
+ L["reset"] = "Сброс профиля"
+ L["reset_desc"] = "Сбросить текущий профиль к стандартным настройкам, если ваша конфигурация испорчена или вы хотите настроить всё заново."
+ L["reset_sub"] = "Сброс текущего профиля на стандартный"
+elseif LOCALE == "itIT" then
+ L["choose"] = "Profili Esistenti"
+ L["choose_desc"] = "Puoi creare un nuovo profilo digitando il nome della casella di testo, oppure scegliendone uno tra i profili già esistenti."
+ L["choose_sub"] = "Seleziona uno dei profili attualmente disponibili."
+ L["copy"] = "Copia Da"
+ L["copy_desc"] = "Copia le impostazioni da un profilo esistente, nel profilo attivo in questo momento."
+ L["current"] = "Profilo Attivo:"
+ L["default"] = "Standard"
+ L["delete"] = "Cancella un Profilo"
+ L["delete_confirm"] = "Sei sicuro di voler cancellare il profilo selezionato?"
+ L["delete_desc"] = "Cancella i profili non utilizzati dal database per risparmiare spazio e mantenere puliti i file di configurazione SavedVariables."
+ L["delete_sub"] = "Cancella un profilo dal Database."
+ L["intro"] = "Puoi cambiare il profilo attivo, in modo da usare impostazioni diverse per ogni personaggio."
+ L["new"] = "Nuovo"
+ L["new_sub"] = "Crea un nuovo profilo vuoto."
+ L["profiles"] = "Profili"
+ L["profiles_sub"] = "Gestisci Profili"
+ L["reset"] = "Reimposta Profilo"
+ L["reset_desc"] = "Riporta il tuo profilo attivo alle sue impostazioni predefinite, nel caso in cui la tua configurazione si sia corrotta, o semplicemente tu voglia re-inizializzarla."
+ L["reset_sub"] = "Reimposta il profilo ai suoi valori predefiniti."
+elseif LOCALE == "ptBR" then
+ L["choose"] = "Perfis Existentes"
+ L["choose_desc"] = "Você pode tanto criar um perfil novo tanto digitando um nome na caixa de texto, quanto escolher um dos perfis já existentes."
+ L["choose_sub"] = "Selecione um de seus perfis atualmente disponíveis."
+ L["copy"] = "Copiar De"
+ L["copy_desc"] = "Copia as definições de um perfil existente no perfil atualmente ativo."
+ L["current"] = "Perfil Autal:"
+ L["default"] = "Padrão"
+ L["delete"] = "Remover um Perfil"
+ L["delete_confirm"] = "Tem certeza que deseja remover o perfil selecionado?"
+ L["delete_desc"] = "Remove perfis existentes e inutilizados do banco de dados para economizar espaço, e limpar o arquivo SavedVariables."
+ L["delete_sub"] = "Remove um perfil do banco de dados."
+ L["intro"] = "Você pode alterar o perfil do banco de dados ativo, para que possa ter definições diferentes para cada personagem."
+ L["new"] = "Novo"
+ L["new_sub"] = "Cria um novo perfil vazio."
+ L["profiles"] = "Perfis"
+ L["profiles_sub"] = "Gerenciar Perfis"
+ L["reset"] = "Resetar Perfil"
+ L["reset_desc"] = "Reseta o perfil atual para os valores padrões, no caso de sua configuração estar quebrada, ou simplesmente se deseja começar novamente."
+ L["reset_sub"] = "Resetar o perfil atual ao padrão"
+end
+
+local defaultProfiles
+
+-- Get a list of available profiles for the specified database.
+-- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below.
+-- @param db The db object to retrieve the profiles from
+-- @param common If true, getProfileList will add the default profiles to the return list, even if they have not been created yet
+-- @param nocurrent If true, then getProfileList will not display the current profile in the list
+-- @return Hashtable of all profiles with the internal name as keys and the display name as value.
+local function getProfileList(db, common, nocurrent)
+ local profiles = new()
+ local tmpprofiles = new()
+ -- copy existing profiles into the table
+ local currentProfile = db:GetCurrentProfile()
+ for i,v in pairs(db:GetProfiles(tmpprofiles)) do
+ if not (nocurrent and v == currentProfile) then
+ profiles[v] = v
+ end
+ end
+ del(tmpprofiles)
+
+ -- add our default profiles to choose from ( or rename existing profiles)
+ for k,v in pairs(defaultProfiles) do
+ if (common or profiles[k]) and not (nocurrent and k == currentProfile) then
+ profiles[k] = v
+ end
+ end
+
+ return profiles
+end
+
+--[[
+ OptionsHandlerPrototype
+ prototype class for handling the options in a sane way
+]]
+local OptionsHandlerPrototype = {}
+
+--[[ Reset the profile ]]
+function OptionsHandlerPrototype:Reset()
+ self.db:ResetProfile()
+end
+
+--[[ Set the profile to value ]]
+function OptionsHandlerPrototype:SetProfile(info, value)
+ self.db:SetProfile(value)
+end
+
+--[[ returns the currently active profile ]]
+function OptionsHandlerPrototype:GetCurrentProfile()
+ return self.db:GetCurrentProfile()
+end
+
+--[[
+ List all active profiles
+ you can control the output with the .arg variable
+ currently four modes are supported
+
+ (empty) - return all available profiles
+ "nocurrent" - returns all available profiles except the currently active profile
+ "common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default")
+ "both" - common except the active profile
+]]
+-- Ace3v: It is recommanded to destroy the returned table by AceCore.del
+-- if it is no longer needed
+function OptionsHandlerPrototype:ListProfiles(info)
+ local arg = info.arg
+ local profiles
+ if arg == "common" and not self.noDefaultProfiles then
+ profiles = getProfileList(self.db, true, nil)
+ elseif arg == "nocurrent" then
+ profiles = getProfileList(self.db, nil, true)
+ elseif arg == "both" then -- currently not used
+ profiles = getProfileList(self.db, (not self.noDefaultProfiles) and true, true)
+ else
+ profiles = getProfileList(self.db)
+ end
+
+ return profiles
+end
+
+function OptionsHandlerPrototype:HasNoProfiles(info)
+ local profiles = self:ListProfiles(info)
+ local r = (not next(profiles)) and true or false
+ del(profiles)
+ return r
+end
+
+--[[ Copy a profile ]]
+function OptionsHandlerPrototype:CopyProfile(info, value)
+ self.db:CopyProfile(value)
+end
+
+--[[ Delete a profile from the db ]]
+function OptionsHandlerPrototype:DeleteProfile(info, value)
+ self.db:DeleteProfile(value)
+end
+
+--[[ fill defaultProfiles with some generic values ]]
+local function generateDefaultProfiles(db)
+ defaultProfiles = {
+ ["Default"] = L["default"],
+ [db.keys.char] = db.keys.char,
+ [db.keys.realm] = db.keys.realm,
+ [db.keys.class] = UnitClass("player")
+ }
+end
+
+--[[ create and return a handler object for the db, or upgrade it if it already existed ]]
+local function getOptionsHandler(db, noDefaultProfiles)
+ if not defaultProfiles then
+ generateDefaultProfiles(db)
+ end
+
+ local handler = AceDBOptions.handlers[db] or { db = db, noDefaultProfiles = noDefaultProfiles }
+
+ for k,v in pairs(OptionsHandlerPrototype) do
+ handler[k] = v
+ end
+
+ AceDBOptions.handlers[db] = handler
+ return handler
+end
+
+--[[
+ the real options table
+]]
+local optionsTable = {
+ desc = {
+ order = 1,
+ type = "description",
+ name = L["intro"] .. "\n",
+ },
+ descreset = {
+ order = 9,
+ type = "description",
+ name = L["reset_desc"],
+ },
+ reset = {
+ order = 10,
+ type = "execute",
+ name = L["reset"],
+ desc = L["reset_sub"],
+ func = "Reset",
+ },
+ current = {
+ order = 11,
+ type = "description",
+ name = function(info) return L["current"] .. " " .. NORMAL_FONT_COLOR_CODE .. info.handler:GetCurrentProfile() .. FONT_COLOR_CODE_CLOSE end,
+ width = "default",
+ },
+ choosedesc = {
+ order = 20,
+ type = "description",
+ name = "\n" .. L["choose_desc"],
+ },
+ new = {
+ name = L["new"],
+ desc = L["new_sub"],
+ type = "input",
+ order = 30,
+ get = false,
+ set = "SetProfile",
+ nullable = false, -- Ace3v: we do not want a null or empty value
+ },
+ choose = {
+ name = L["choose"],
+ desc = L["choose_sub"],
+ type = "select",
+ order = 40,
+ get = "GetCurrentProfile",
+ set = "SetProfile",
+ values = "ListProfiles",
+ valuesTableDestroyable = true,
+ arg = "common",
+ },
+ copydesc = {
+ order = 50,
+ type = "description",
+ name = "\n" .. L["copy_desc"],
+ },
+ copyfrom = {
+ order = 60,
+ type = "select",
+ name = L["copy"],
+ desc = L["copy_desc"],
+ get = false,
+ set = "CopyProfile",
+ values = "ListProfiles",
+ valuesTableDestroyable = true,
+ disabled = "HasNoProfiles",
+ arg = "nocurrent",
+ },
+ deldesc = {
+ order = 70,
+ type = "description",
+ name = "\n" .. L["delete_desc"],
+ },
+ delete = {
+ order = 80,
+ type = "select",
+ name = L["delete"],
+ desc = L["delete_sub"],
+ get = false,
+ set = "DeleteProfile",
+ values = "ListProfiles",
+ valuesTableDestroyable = true,
+ disabled = "HasNoProfiles",
+ arg = "nocurrent",
+ confirm = true,
+ confirmText = L["delete_confirm"],
+ },
+}
+
+--- Get/Create a option table that you can use in your addon to control the profiles of AceDB-3.0.
+-- @param db The database object to create the options table for.
+-- @return The options table to be used in AceConfig-3.0
+-- @usage
+-- -- Assuming `options` is your top-level options table and `self.db` is your database:
+-- options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
+function AceDBOptions:GetOptionsTable(db, noDefaultProfiles)
+ local tbl = AceDBOptions.optionTables[db] or {
+ type = "group",
+ name = L["profiles"],
+ desc = L["profiles_sub"],
+ }
+
+ tbl.handler = getOptionsHandler(db, noDefaultProfiles)
+ tbl.args = optionsTable
+
+ AceDBOptions.optionTables[db] = tbl
+ return tbl
+end
+
+-- upgrade existing tables
+for db,tbl in pairs(AceDBOptions.optionTables) do
+ tbl.handler = getOptionsHandler(db)
+ tbl.args = optionsTable
+end
diff --git a/ElvUI_Config/Libraries/AceDBOptions-3.0/AceDBOptions-3.0.xml b/ElvUI_Config/Libraries/AceDBOptions-3.0/AceDBOptions-3.0.xml
new file mode 100644
index 0000000..2668fb0
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceDBOptions-3.0/AceDBOptions-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/BackgroundWidget.lua b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/BackgroundWidget.lua
new file mode 100644
index 0000000..dfdae49
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/BackgroundWidget.lua
@@ -0,0 +1,235 @@
+-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0
+-- Widget created by Yssaril
+
+local AceGUI = LibStub("AceGUI-3.0")
+local Media = LibStub("LibSharedMedia-3.0")
+
+local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
+
+do
+ local widgetType = "LSM30_Background"
+ local widgetVersion = 11
+
+ local contentFrameCache = {}
+ local function ReturnSelf(self)
+ self:ClearAllPoints()
+ self:Hide()
+ self.check:Hide()
+ table.insert(contentFrameCache, self)
+ end
+
+ local function ContentOnClick(this, button)
+ local self = this.obj
+ self:Fire("OnValueChanged", this.text:GetText())
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function ContentOnEnter(this, button)
+ local self = this.obj
+ local text = this.text:GetText()
+ local background = self.list[text] ~= text and self.list[text] or Media:Fetch('background',text)
+ self.dropdown.bgTex:SetTexture(background)
+ end
+
+ local function GetContentLine()
+ local frame
+ if next(contentFrameCache) then
+ frame = table.remove(contentFrameCache)
+ else
+ frame = CreateFrame("Button", nil, UIParent)
+ --frame:SetWidth(200)
+ frame:SetHeight(18)
+ frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
+ frame:SetScript("OnClick", ContentOnClick)
+ frame:SetScript("OnEnter", ContentOnEnter)
+
+ local check = frame:CreateTexture("OVERLAY")
+ check:SetWidth(16)
+ check:SetHeight(16)
+ check:SetPoint("LEFT",frame,"LEFT",1,-1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:Hide()
+ frame.check = check
+
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontWhite")
+ local font, size = text:GetFont()
+ text:SetFont(font,size,"OUTLINE")
+
+ text:SetPoint("TOPLEFT", check, "TOPRIGHT", 1, 0)
+ text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 0)
+ text:SetJustifyH("LEFT")
+ text:SetText("Test Test Test Test Test Test Test")
+ frame.text = text
+
+ frame.ReturnSelf = ReturnSelf
+ end
+ frame:Show()
+ return frame
+ end
+
+ local function OnAcquire(self)
+ self:SetHeight(44)
+ self:SetWidth(200)
+ end
+
+ local function OnRelease(self)
+ self:SetText("")
+ self:SetLabel("")
+ self:SetDisabled(false)
+
+ self.value = nil
+ self.list = nil
+ self.open = nil
+ self.hasClose = nil
+
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ local function SetValue(self, value) -- Set the value to an item in the List.
+ if self.list then
+ self:SetText(value or "")
+ end
+ self.value = value
+ end
+
+ local function GetValue(self)
+ return self.value
+ end
+
+ local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs)
+ self.list = list or Media:HashTable("background")
+ end
+
+
+ local function SetText(self, text) -- Set the text displayed in the box.
+ self.frame.text:SetText(text or "")
+ local background = self.list[text] ~= text and self.list[text] or Media:Fetch('background',text)
+
+ self.frame.displayButton:SetBackdrop({bgFile = background,
+ edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
+ edgeSize = 16,
+ insets = { left = 4, right = 4, top = 4, bottom = 4 }})
+ end
+
+ local function SetLabel(self, text) -- Set the text for the label.
+ self.frame.label:SetText(text or "")
+ end
+
+ local function AddItem(self, key, value) -- Add an item to the list.
+ self.list = self.list or {}
+ self.list[key] = value
+ end
+ local SetItemValue = AddItem -- Set the value of a item in the list. <>
+
+ local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <>
+ local function GetMultiselect() return false end-- Query the multi-select flag. <>
+ local function SetItemDisabled(self, key) end-- Disable one item in the list. <>
+
+ local function SetDisabled(self, disabled) -- Disable the widget.
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ self.frame.displayButton:SetBackdropColor(.2,.2,.2,1)
+ else
+ self.frame:Enable()
+ self.frame.displayButton:SetBackdropColor(1,1,1,1)
+ end
+ end
+
+ local function textSort(a,b)
+ return string.upper(a) < string.upper(b)
+ end
+
+ local sortedlist = {}
+ local function ToggleDrop(this)
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ AceGUI:ClearFocus()
+ else
+ AceGUI:SetFocus(self)
+ self.dropdown = AGSMW:GetDropDownFrame()
+ local width = self.frame:GetWidth()
+ self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT")
+ self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0)
+ for k, v in pairs(self.list) do
+ sortedlist[getn(sortedlist)+1] = k
+ end
+ table.sort(sortedlist, textSort)
+ for i, k in ipairs(sortedlist) do
+ local f = GetContentLine()
+ f.text:SetText(k)
+ --print(k)
+ if k == self.value then
+ f.check:Show()
+ end
+ f.obj = self
+ f.dropdown = self.dropdown
+ self.dropdown:AddFrame(f)
+ end
+ wipe(sortedlist)
+ end
+ end
+
+ local function ClearFocus(self)
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function OnHide(this)
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function Drop_OnEnter(this)
+ this.obj:Fire("OnEnter")
+ end
+
+ local function Drop_OnLeave(this)
+ this.obj:Fire("OnLeave")
+ end
+
+ local function Constructor()
+ local frame = AGSMW:GetBaseFrameWithWindow()
+ local self = {}
+
+ self.type = widgetType
+ self.frame = frame
+ frame.obj = self
+ frame.dropButton.obj = self
+ frame.dropButton:SetScript("OnEnter", Drop_OnEnter)
+ frame.dropButton:SetScript("OnLeave", Drop_OnLeave)
+ frame.dropButton:SetScript("OnClick",ToggleDrop)
+ frame:SetScript("OnHide", OnHide)
+
+ self.alignoffset = 31
+
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+ self.ClearFocus = ClearFocus
+ self.SetText = SetText
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.SetList = SetList
+ self.SetLabel = SetLabel
+ self.SetDisabled = SetDisabled
+ self.AddItem = AddItem
+ self.SetMultiselect = SetMultiselect
+ self.GetMultiselect = GetMultiselect
+ self.SetItemValue = SetItemValue
+ self.SetItemDisabled = SetItemDisabled
+ self.ToggleDrop = ToggleDrop
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/BorderWidget.lua b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/BorderWidget.lua
new file mode 100644
index 0000000..5d77863
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/BorderWidget.lua
@@ -0,0 +1,230 @@
+-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0
+-- Widget created by Yssaril
+
+local AceGUI = LibStub("AceGUI-3.0")
+local Media = LibStub("LibSharedMedia-3.0")
+
+local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
+
+do
+ local widgetType = "LSM30_Border"
+ local widgetVersion = 11
+
+ local contentFrameCache = {}
+ local function ReturnSelf(self)
+ self:ClearAllPoints()
+ self:Hide()
+ self.check:Hide()
+ table.insert(contentFrameCache, self)
+ end
+
+ local function ContentOnClick(this, button)
+ local self = this.obj
+ self:Fire("OnValueChanged", this.text:GetText())
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function ContentOnEnter(this, button)
+ local self = this.obj
+ local text = this.text:GetText()
+ local border = self.list[text] ~= text and self.list[text] or Media:Fetch('border',text)
+ this.dropdown:SetBackdrop({edgeFile = border,
+ bgFile="Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 4, right = 4, top = 4, bottom = 4 }})
+ end
+
+ local function GetContentLine()
+ local frame
+ if next(contentFrameCache) then
+ frame = table.remove(contentFrameCache)
+ else
+ frame = CreateFrame("Button", nil, UIParent)
+ --frame:SetWidth(200)
+ frame:SetHeight(18)
+ frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
+ frame:SetScript("OnClick", ContentOnClick)
+ frame:SetScript("OnEnter", ContentOnEnter)
+ local check = frame:CreateTexture("OVERLAY")
+ check:SetWidth(16)
+ check:SetHeight(16)
+ check:SetPoint("LEFT",frame,"LEFT",1,-1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:Hide()
+ frame.check = check
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontWhite")
+ text:SetPoint("TOPLEFT", check, "TOPRIGHT", 1, 0)
+ text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 0)
+ text:SetJustifyH("LEFT")
+ text:SetText("Test Test Test Test Test Test Test")
+ frame.text = text
+ frame.ReturnSelf = ReturnSelf
+ end
+ frame:Show()
+ return frame
+ end
+
+ local function OnAcquire(self)
+ self:SetHeight(44)
+ self:SetWidth(200)
+ end
+
+ local function OnRelease(self)
+ self:SetText("")
+ self:SetLabel("")
+ self:SetDisabled(false)
+
+ self.value = nil
+ self.list = nil
+ self.open = nil
+ self.hasClose = nil
+
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ local function SetValue(self, value) -- Set the value to an item in the List.
+ if self.list then
+ self:SetText(value or "")
+ end
+ self.value = value
+ end
+
+ local function GetValue(self)
+ return self.value
+ end
+
+ local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs)
+ self.list = list or Media:HashTable("border")
+ end
+
+
+ local function SetText(self, text) -- Set the text displayed in the box.
+ self.frame.text:SetText(text or "")
+ local border = self.list[text] ~= text and self.list[text] or Media:Fetch('border',text)
+
+ self.frame.displayButton:SetBackdrop({edgeFile = border,
+ bgFile="Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 4, right = 4, top = 4, bottom = 4 }})
+ end
+
+ local function SetLabel(self, text) -- Set the text for the label.
+ self.frame.label:SetText(text or "")
+ end
+
+ local function AddItem(self, key, value) -- Add an item to the list.
+ self.list = self.list or {}
+ self.list[key] = value
+ end
+ local SetItemValue = AddItem -- Set the value of a item in the list. <>
+
+ local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <>
+ local function GetMultiselect() return false end-- Query the multi-select flag. <>
+ local function SetItemDisabled(self, key) end-- Disable one item in the list. <>
+
+ local function SetDisabled(self, disabled) -- Disable the widget.
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ else
+ self.frame:Enable()
+ end
+ end
+
+ local function textSort(a,b)
+ return string.upper(a) < string.upper(b)
+ end
+
+ local sortedlist = {}
+ local function ToggleDrop(this)
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ AceGUI:ClearFocus()
+ else
+ AceGUI:SetFocus(self)
+ self.dropdown = AGSMW:GetDropDownFrame()
+ local width = self.frame:GetWidth()
+ self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT")
+ self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0)
+ for k, v in pairs(self.list) do
+ sortedlist[getn(sortedlist)+1] = k
+ end
+ table.sort(sortedlist, textSort)
+ for i, k in ipairs(sortedlist) do
+ local f = GetContentLine()
+ f.text:SetText(k)
+ --print(k)
+ if k == self.value then
+ f.check:Show()
+ end
+ f.obj = self
+ f.dropdown = self.dropdown
+ self.dropdown:AddFrame(f)
+ end
+ wipe(sortedlist)
+ end
+ end
+
+ local function ClearFocus(self)
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function OnHide(this)
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function Drop_OnEnter(this)
+ this.obj:Fire("OnEnter")
+ end
+
+ local function Drop_OnLeave(this)
+ this.obj:Fire("OnLeave")
+ end
+
+ local function Constructor()
+ local frame = AGSMW:GetBaseFrameWithWindow()
+ local self = {}
+
+ self.type = widgetType
+ self.frame = frame
+ frame.obj = self
+ frame.dropButton.obj = self
+ frame.dropButton:SetScript("OnEnter", Drop_OnEnter)
+ frame.dropButton:SetScript("OnLeave", Drop_OnLeave)
+ frame.dropButton:SetScript("OnClick",ToggleDrop)
+ frame:SetScript("OnHide", OnHide)
+
+ self.alignoffset = 31
+
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+ self.ClearFocus = ClearFocus
+ self.SetText = SetText
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.SetList = SetList
+ self.SetLabel = SetLabel
+ self.SetDisabled = SetDisabled
+ self.AddItem = AddItem
+ self.SetMultiselect = SetMultiselect
+ self.GetMultiselect = GetMultiselect
+ self.SetItemValue = SetItemValue
+ self.SetItemDisabled = SetItemDisabled
+ self.ToggleDrop = ToggleDrop
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/FontWidget.lua b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/FontWidget.lua
new file mode 100644
index 0000000..3a8229d
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/FontWidget.lua
@@ -0,0 +1,216 @@
+-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0
+-- Widget created by Yssaril
+
+local AceGUI = LibStub("AceGUI-3.0")
+local Media = LibStub("LibSharedMedia-3.0")
+
+local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
+
+do
+ local widgetType = "LSM30_Font"
+ local widgetVersion = 11
+
+ local contentFrameCache = {}
+ local function ReturnSelf(self)
+ self:ClearAllPoints()
+ self:Hide()
+ self.check:Hide()
+ table.insert(contentFrameCache, self)
+ end
+
+ local function ContentOnClick()
+ local self = this.obj
+ self:Fire("OnValueChanged", this.text:GetText())
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function GetContentLine()
+ local frame
+ if next(contentFrameCache) then
+ frame = table.remove(contentFrameCache)
+ else
+ frame = CreateFrame("Button", nil, UIParent)
+ --frame:SetWidth(200)
+ frame:SetHeight(18)
+ frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
+ frame:SetScript("OnClick", ContentOnClick)
+ local check = frame:CreateTexture("OVERLAY")
+ check:SetWidth(16)
+ check:SetHeight(16)
+ check:SetPoint("LEFT",frame,"LEFT",1,-1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:Hide()
+ frame.check = check
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontWhite")
+ text:SetPoint("TOPLEFT", check, "TOPRIGHT", 1, 0)
+ text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 0)
+ text:SetJustifyH("LEFT")
+ text:SetText("Test Test Test Test Test Test Test")
+ frame.text = text
+ frame.ReturnSelf = ReturnSelf
+ end
+ frame:Show()
+ return frame
+ end
+
+ local function OnAcquire(self)
+ self:SetHeight(44)
+ self:SetWidth(200)
+ end
+
+ local function OnRelease(self)
+ self:SetText("")
+ self:SetLabel("")
+ self:SetDisabled(false)
+
+ self.value = nil
+ self.list = nil
+ self.open = nil
+ self.hasClose = nil
+
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ local function SetValue(self, value) -- Set the value to an item in the List.
+ if self.list then
+ self:SetText(value or "")
+ end
+ self.value = value
+ end
+
+ local function GetValue(self)
+ return self.value
+ end
+
+ local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs)
+ self.list = list or Media:HashTable("font")
+ end
+
+ local function SetText(self, text) -- Set the text displayed in the box.
+ self.frame.text:SetText(text or "")
+ local font = self.list[text] ~= text and self.list[text] or Media:Fetch('font',text)
+ local _, size, outline= self.frame.text:GetFont()
+ self.frame.text:SetFont(font,size,outline)
+ end
+
+ local function SetLabel(self, text) -- Set the text for the label.
+ self.frame.label:SetText(text or "")
+ end
+
+ local function AddItem(self, key, value) -- Add an item to the list.
+ self.list = self.list or {}
+ self.list[key] = value
+ end
+ local SetItemValue = AddItem -- Set the value of a item in the list. <>
+
+ local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <>
+ local function GetMultiselect() return false end-- Query the multi-select flag. <>
+ local function SetItemDisabled(self, key) end-- Disable one item in the list. <>
+
+ local function SetDisabled(self, disabled) -- Disable the widget.
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ else
+ self.frame:Enable()
+ end
+ end
+
+ local function textSort(a,b)
+ return string.upper(a) < string.upper(b)
+ end
+
+ local sortedlist = {}
+ local function ToggleDrop()
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ AceGUI:ClearFocus()
+ else
+ AceGUI:SetFocus(self)
+ self.dropdown = AGSMW:GetDropDownFrame()
+ local width = self.frame:GetWidth()
+ self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT")
+ self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0)
+ for k, v in pairs(self.list) do
+ sortedlist[getn(sortedlist)+1] = k
+ end
+ table.sort(sortedlist, textSort)
+ for i, k in ipairs(sortedlist) do
+ local f = GetContentLine()
+ local _, size, outline= f.text:GetFont()
+ local font = self.list[k] ~= k and self.list[k] or Media:Fetch('font',k)
+ f.text:SetFont(font,size,outline)
+ f.text:SetText(k)
+ if k == self.value then
+ f.check:Show()
+ end
+ f.obj = self
+ self.dropdown:AddFrame(f)
+ end
+ wipe(sortedlist)
+ end
+ end
+
+ local function ClearFocus(self)
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function OnHide()
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function Drop_OnEnter()
+ this.obj:Fire("OnEnter")
+ end
+
+ local function Drop_OnLeave()
+ this.obj:Fire("OnLeave")
+ end
+
+ local function Constructor()
+ local frame = AGSMW:GetBaseFrame()
+ local self = {}
+
+ self.type = widgetType
+ self.frame = frame
+ frame.obj = self
+ frame.dropButton.obj = self
+ frame.dropButton:SetScript("OnEnter", Drop_OnEnter)
+ frame.dropButton:SetScript("OnLeave", Drop_OnLeave)
+ frame.dropButton:SetScript("OnClick",ToggleDrop)
+ frame:SetScript("OnHide", OnHide)
+
+ self.alignoffset = 31
+
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+ self.ClearFocus = ClearFocus
+ self.SetText = SetText
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.SetList = SetList
+ self.SetLabel = SetLabel
+ self.SetDisabled = SetDisabled
+ self.AddItem = AddItem
+ self.SetMultiselect = SetMultiselect
+ self.GetMultiselect = GetMultiselect
+ self.SetItemValue = SetItemValue
+ self.SetItemDisabled = SetItemDisabled
+ self.ToggleDrop = ToggleDrop
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/SoundWidget.lua b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/SoundWidget.lua
new file mode 100644
index 0000000..962a2e4
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/SoundWidget.lua
@@ -0,0 +1,264 @@
+-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0
+-- Widget created by Yssaril
+
+local AceGUI = LibStub("AceGUI-3.0")
+local Media = LibStub("LibSharedMedia-3.0")
+
+local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
+
+do
+ local widgetType = "LSM30_Sound"
+ local widgetVersion = 11
+
+ local contentFrameCache = {}
+ local function ReturnSelf(self)
+ self:ClearAllPoints()
+ self:Hide()
+ self.check:Hide()
+ table.insert(contentFrameCache, self)
+ end
+
+ local function ContentOnClick()
+ local self = this.obj
+ self:Fire("OnValueChanged", this.text:GetText())
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function ContentSpeakerOnClick()
+ local self = this.frame.obj
+ local sound = this.frame.text:GetText()
+ PlaySoundFile(self.list[sound] ~= sound and self.list[sound] or Media:Fetch('sound',sound), "Master")
+ end
+
+ local function GetContentLine()
+ local frame
+ if next(contentFrameCache) then
+ frame = table.remove(contentFrameCache)
+ else
+ frame = CreateFrame("Button", nil, UIParent)
+ --frame:SetWidth(200)
+ frame:SetHeight(18)
+ frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
+ frame:SetScript("OnClick", ContentOnClick)
+ local check = frame:CreateTexture("OVERLAY")
+ check:SetWidth(16)
+ check:SetHeight(16)
+ check:SetPoint("LEFT",frame,"LEFT",1,-1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:Hide()
+ frame.check = check
+
+ local soundbutton = CreateFrame("Button", nil, frame)
+ soundbutton:SetWidth(16)
+ soundbutton:SetHeight(16)
+ soundbutton:SetPoint("RIGHT",frame,"RIGHT",-1,0)
+ soundbutton.frame = frame
+ soundbutton:SetScript("OnClick", ContentSpeakerOnClick)
+ frame.soundbutton = soundbutton
+
+ local speaker = soundbutton:CreateTexture(nil, "BACKGROUND")
+ speaker:SetTexture("Interface\\Common\\VoiceChat-Speaker")
+ speaker:SetAllPoints(soundbutton)
+ frame.speaker = speaker
+ local speakeron = soundbutton:CreateTexture(nil, "HIGHLIGHT")
+ speakeron:SetTexture("Interface\\Common\\VoiceChat-On")
+ speakeron:SetAllPoints(soundbutton)
+ frame.speakeron = speakeron
+
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontWhite")
+ text:SetPoint("TOPLEFT", check, "TOPRIGHT", 1, 0)
+ text:SetPoint("BOTTOMRIGHT", soundbutton, "BOTTOMLEFT", -2, 0)
+ text:SetJustifyH("LEFT")
+ text:SetText("Test Test Test Test Test Test Test")
+ frame.text = text
+ frame.ReturnSelf = ReturnSelf
+ end
+ frame:Show()
+ return frame
+ end
+
+ local function OnAcquire(self)
+ self:SetHeight(44)
+ self:SetWidth(200)
+ end
+
+ local function OnRelease(self)
+ self:SetText("")
+ self:SetLabel("")
+ self:SetDisabled(false)
+
+ self.value = nil
+ self.list = nil
+ self.open = nil
+ self.hasClose = nil
+
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ local function SetValue(self, value) -- Set the value to an item in the List.
+ if self.list then
+ self:SetText(value or "")
+ end
+ self.value = value
+ end
+
+ local function GetValue(self)
+ return self.value
+ end
+
+ local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs)
+ self.list = list or Media:HashTable("sound")
+ end
+
+ local function SetText(self, text) -- Set the text displayed in the box.
+ self.frame.text:SetText(text or "")
+ end
+
+ local function SetLabel(self, text) -- Set the text for the label.
+ self.frame.label:SetText(text or "")
+ end
+
+ local function AddItem(self, key, value) -- Add an item to the list.
+ self.list = self.list or {}
+ self.list[key] = value
+ end
+ local SetItemValue = AddItem -- Set the value of a item in the list. <>
+
+ local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <>
+ local function GetMultiselect() return false end-- Query the multi-select flag. <>
+ local function SetItemDisabled(self, key) end-- Disable one item in the list. <>
+
+ local function SetDisabled(self, disabled) -- Disable the widget.
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ self.speaker:SetDesaturated(true)
+ self.speakeron:SetDesaturated(true)
+ else
+ self.frame:Enable()
+ self.speaker:SetDesaturated(false)
+ self.speakeron:SetDesaturated(false)
+ end
+ end
+
+ local function textSort(a,b)
+ return string.upper(a) < string.upper(b)
+ end
+
+ local sortedlist = {}
+ local function ToggleDrop()
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ AceGUI:ClearFocus()
+ else
+ AceGUI:SetFocus(self)
+ self.dropdown = AGSMW:GetDropDownFrame()
+ local width = self.frame:GetWidth()
+ self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT")
+ self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0)
+ for k, v in pairs(self.list) do
+ sortedlist[getn(sortedlist)+1] = k
+ end
+ table.sort(sortedlist, textSort)
+ for i, k in ipairs(sortedlist) do
+ local f = GetContentLine()
+ f.text:SetText(k)
+ if k == self.value then
+ f.check:Show()
+ end
+ f.obj = self
+ self.dropdown:AddFrame(f)
+ end
+ wipe(sortedlist)
+ end
+ end
+
+ local function ClearFocus(self)
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function OnHide()
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function Drop_OnEnter()
+ this.obj:Fire("OnEnter")
+ end
+
+ local function Drop_OnLeave()
+ this.obj:Fire("OnLeave")
+ end
+
+ local function WidgetPlaySound()
+ local self = this.obj
+ local sound = self.frame.text:GetText()
+ PlaySoundFile(self.list[sound] ~= sound and self.list[sound] or Media:Fetch('sound',sound), "Master")
+ end
+
+ local function Constructor()
+ local frame = AGSMW:GetBaseFrame()
+ local self = {}
+
+ self.type = widgetType
+ self.frame = frame
+ frame.obj = self
+ frame.dropButton.obj = self
+ frame.dropButton:SetScript("OnEnter", Drop_OnEnter)
+ frame.dropButton:SetScript("OnLeave", Drop_OnLeave)
+ frame.dropButton:SetScript("OnClick",ToggleDrop)
+ frame:SetScript("OnHide", OnHide)
+
+
+ local soundbutton = CreateFrame("Button", nil, frame)
+ soundbutton:SetWidth(16)
+ soundbutton:SetHeight(16)
+ soundbutton:SetPoint("LEFT",frame.DLeft,"LEFT",26,1)
+ soundbutton:SetScript("OnClick", WidgetPlaySound)
+ soundbutton.obj = self
+ self.soundbutton = soundbutton
+ frame.text:SetPoint("LEFT",soundbutton,"RIGHT",2,0)
+
+
+ local speaker = soundbutton:CreateTexture(nil, "BACKGROUND")
+ speaker:SetTexture("Interface\\Common\\VoiceChat-Speaker")
+ speaker:SetAllPoints(soundbutton)
+ self.speaker = speaker
+ local speakeron = soundbutton:CreateTexture(nil, "HIGHLIGHT")
+ speakeron:SetTexture("Interface\\Common\\VoiceChat-On")
+ speakeron:SetAllPoints(soundbutton)
+ self.speakeron = speakeron
+
+ self.alignoffset = 31
+
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+ self.ClearFocus = ClearFocus
+ self.SetText = SetText
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.SetList = SetList
+ self.SetLabel = SetLabel
+ self.SetDisabled = SetDisabled
+ self.AddItem = AddItem
+ self.SetMultiselect = SetMultiselect
+ self.GetMultiselect = GetMultiselect
+ self.SetItemValue = SetItemValue
+ self.SetItemDisabled = SetItemDisabled
+ self.ToggleDrop = ToggleDrop
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/StatusbarWidget.lua b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/StatusbarWidget.lua
new file mode 100644
index 0000000..884cc2b
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/StatusbarWidget.lua
@@ -0,0 +1,233 @@
+-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0
+-- Widget created by Yssaril
+
+local AceGUI = LibStub("AceGUI-3.0")
+local Media = LibStub("LibSharedMedia-3.0")
+
+local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
+
+do
+ local widgetType = "LSM30_Statusbar"
+ local widgetVersion = 11
+
+ local contentFrameCache = {}
+ local function ReturnSelf(self)
+ self:ClearAllPoints()
+ self:Hide()
+ self.check:Hide()
+ table.insert(contentFrameCache, self)
+ end
+
+ local function ContentOnClick()
+ local self = this.obj
+ self:Fire("OnValueChanged", this.text:GetText())
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function GetContentLine()
+ local frame
+ if next(contentFrameCache) then
+ frame = table.remove(contentFrameCache)
+ else
+ frame = CreateFrame("Button", nil, UIParent)
+ --frame:SetWidth(200)
+ frame:SetHeight(18)
+ frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
+ frame:SetScript("OnClick", ContentOnClick)
+ local check = frame:CreateTexture("OVERLAY")
+ check:SetWidth(16)
+ check:SetHeight(16)
+ check:SetPoint("LEFT",frame,"LEFT",1,-1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:Hide()
+ frame.check = check
+ local bar = frame:CreateTexture("ARTWORK")
+ bar:SetHeight(16)
+ bar:SetPoint("LEFT",check,"RIGHT",1,0)
+ bar:SetPoint("RIGHT",frame,"RIGHT",-1,0)
+ frame.bar = bar
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontWhite")
+
+ local font, size = text:GetFont()
+ text:SetFont(font,size,"OUTLINE")
+
+ text:SetPoint("TOPLEFT", check, "TOPRIGHT", 3, 0)
+ text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 0)
+ text:SetJustifyH("LEFT")
+ text:SetText("Test Test Test Test Test Test Test")
+ frame.text = text
+ frame.ReturnSelf = ReturnSelf
+ end
+ frame:Show()
+ return frame
+ end
+
+ local function OnAcquire(self)
+ self:SetHeight(44)
+ self:SetWidth(200)
+ end
+
+ local function OnRelease(self)
+ self:SetText("")
+ self:SetLabel("")
+ self:SetDisabled(false)
+
+ self.value = nil
+ self.list = nil
+ self.open = nil
+ self.hasClose = nil
+
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ local function SetValue(self, value) -- Set the value to an item in the List.
+ if self.list then
+ self:SetText(value or "")
+ end
+ self.value = value
+ end
+
+ local function GetValue(self)
+ return self.value
+ end
+
+ local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs)
+ self.list = list or Media:HashTable("statusbar")
+ end
+
+
+ local function SetText(self, text) -- Set the text displayed in the box.
+ self.frame.text:SetText(text or "")
+ local statusbar = self.list[text] ~= text and self.list[text] or Media:Fetch('statusbar',text)
+ self.bar:SetTexture(statusbar)
+ end
+
+ local function SetLabel(self, text) -- Set the text for the label.
+ self.frame.label:SetText(text or "")
+ end
+
+ local function AddItem(self, key, value) -- Add an item to the list.
+ self.list = self.list or {}
+ self.list[key] = value
+ end
+ local SetItemValue = AddItem -- Set the value of a item in the list. <>
+
+ local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <>
+ local function GetMultiselect() return false end-- Query the multi-select flag. <>
+ local function SetItemDisabled(self, key) end-- Disable one item in the list. <>
+
+ local function SetDisabled(self, disabled) -- Disable the widget.
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ else
+ self.frame:Enable()
+ end
+ end
+
+ local function textSort(a,b)
+ return string.upper(a) < string.upper(b)
+ end
+
+ local sortedlist = {}
+ local function ToggleDrop()
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ AceGUI:ClearFocus()
+ else
+ AceGUI:SetFocus(self)
+ self.dropdown = AGSMW:GetDropDownFrame()
+ local width = self.frame:GetWidth()
+ self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT")
+ self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0)
+ for k, v in pairs(self.list) do
+ sortedlist[getn(sortedlist)+1] = k
+ end
+ table.sort(sortedlist, textSort)
+ for i, k in ipairs(sortedlist) do
+ local f = GetContentLine()
+ f.text:SetText(k)
+ --print(k)
+ if k == self.value then
+ f.check:Show()
+ end
+
+ local statusbar = self.list[k] ~= k and self.list[k] or Media:Fetch('statusbar',k)
+ f.bar:SetTexture(statusbar)
+ f.obj = self
+ f.dropdown = self.dropdown
+ self.dropdown:AddFrame(f)
+ end
+ wipe(sortedlist)
+ end
+ end
+
+ local function ClearFocus(self)
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function OnHide()
+ local self = this.obj
+ if self.dropdown then
+ self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
+ end
+ end
+
+ local function Drop_OnEnter()
+ this.obj:Fire("OnEnter")
+ end
+
+ local function Drop_OnLeave()
+ this.obj:Fire("OnLeave")
+ end
+
+ local function Constructor()
+ local frame = AGSMW:GetBaseFrame()
+ local self = {}
+
+ self.type = widgetType
+ self.frame = frame
+ frame.obj = self
+ frame.dropButton.obj = self
+ frame.dropButton:SetScript("OnEnter", Drop_OnEnter)
+ frame.dropButton:SetScript("OnLeave", Drop_OnLeave)
+ frame.dropButton:SetScript("OnClick",ToggleDrop)
+ frame:SetScript("OnHide", OnHide)
+
+ local bar = frame:CreateTexture(nil, "OVERLAY")
+ bar:SetPoint("TOPLEFT", frame,"TOPLEFT",6,-25)
+ bar:SetPoint("BOTTOMRIGHT", frame,"BOTTOMRIGHT", -21, 5)
+ bar:SetAlpha(0.5)
+ self.bar = bar
+
+ self.alignoffset = 31
+
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+ self.ClearFocus = ClearFocus
+ self.SetText = SetText
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.SetList = SetList
+ self.SetLabel = SetLabel
+ self.SetDisabled = SetDisabled
+ self.AddItem = AddItem
+ self.SetMultiselect = SetMultiselect
+ self.GetMultiselect = GetMultiselect
+ self.SetItemValue = SetItemValue
+ self.SetItemDisabled = SetItemDisabled
+ self.ToggleDrop = ToggleDrop
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/prototypes.lua b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/prototypes.lua
new file mode 100644
index 0000000..b2e8965
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/prototypes.lua
@@ -0,0 +1,273 @@
+-- Widget created by Yssaril
+--[===[@debug@
+local DataVersion = 9001 -- dev version always overwrites everything else :)
+--@end-debug@]===]
+--@non-debug@
+local DataVersion = 56
+--@end-non-debug@
+local AGSMW = LibStub:NewLibrary("AceGUISharedMediaWidgets-1.0", DataVersion)
+
+if not AGSMW then
+ return -- already loaded and no upgrade necessary
+end
+
+local AceGUI = LibStub("AceGUI-3.0")
+local Media = LibStub("LibSharedMedia-3.0")
+
+AGSMW = AGSMW or {}
+
+AceGUIWidgetLSMlists = {
+ ['font'] = Media:HashTable("font"),
+ ['sound'] = Media:HashTable("sound"),
+ ['statusbar'] = Media:HashTable("statusbar"),
+ ['border'] = Media:HashTable("border"),
+ ['background'] = Media:HashTable("background"),
+}
+
+do
+ local function disable(frame)
+ frame.label:SetTextColor(.5,.5,.5)
+ frame.text:SetTextColor(.5,.5,.5)
+ frame.dropButton:Disable()
+ if frame.displayButtonFont then
+ frame.displayButtonFont:SetTextColor(.5,.5,.5)
+ frame.displayButton:Disable()
+ end
+ end
+
+ local function enable(frame)
+ frame.label:SetTextColor(1,.82,0)
+ frame.text:SetTextColor(1,1,1)
+ frame.dropButton:Enable()
+ if frame.displayButtonFont then
+ frame.displayButtonFont:SetTextColor(1,1,1)
+ frame.displayButton:Enable()
+ end
+ end
+
+ local displayButtonBackdrop = {
+ edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 4, right = 4, top = 4, bottom = 4 },
+ }
+
+ -- create or retrieve BaseFrame
+ function AGSMW:GetBaseFrame()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:SetHeight(44)
+ frame:SetWidth(200)
+
+ local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
+ label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
+ label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
+ label:SetJustifyH("LEFT")
+ label:SetHeight(18)
+ label:SetText("")
+ frame.label = label
+
+ local DLeft = frame:CreateTexture(nil, "ARTWORK")
+ DLeft:SetWidth(25)
+ DLeft:SetHeight(64)
+ DLeft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", -17, -21)
+ DLeft:SetTexture([[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]])
+ DLeft:SetTexCoord(0, 0.1953125, 0, 1)
+ frame.DLeft = DLeft
+
+ local DRight = frame:CreateTexture(nil, "ARTWORK")
+ DRight:SetWidth(25)
+ DRight:SetHeight(64)
+ DRight:SetPoint("TOP", DLeft, "TOP")
+ DRight:SetPoint("RIGHT", frame, "RIGHT", 17, 0)
+ DRight:SetTexture([[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]])
+ DRight:SetTexCoord(0.8046875, 1, 0, 1)
+ frame.DRight = DRight
+
+ local DMiddle = frame:CreateTexture(nil, "ARTWORK")
+ DMiddle:SetHeight(64)
+ DMiddle:SetPoint("TOP", DLeft, "TOP")
+ DMiddle:SetPoint("LEFT", DLeft, "RIGHT")
+ DMiddle:SetPoint("RIGHT", DRight, "LEFT")
+ DMiddle:SetTexture([[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]])
+ DMiddle:SetTexCoord(0.1953125, 0.8046875, 0, 1)
+ frame.DMiddle = DMiddle
+
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall")
+ text:SetPoint("RIGHT",DRight,"RIGHT",-43,1)
+ text:SetPoint("LEFT",DLeft,"LEFT",26,1)
+ text:SetJustifyH("RIGHT")
+ text:SetHeight(18)
+ text:SetText("")
+ frame.text = text
+
+ local dropButton = CreateFrame("Button", nil, frame)
+ dropButton:SetWidth(24)
+ dropButton:SetHeight(24)
+ dropButton:SetPoint("TOPRIGHT", DRight, "TOPRIGHT", -16, -18)
+ dropButton:SetNormalTexture([[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Up]])
+ dropButton:SetPushedTexture([[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Down]])
+ dropButton:SetDisabledTexture([[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Disabled]])
+ dropButton:SetHighlightTexture([[Interface\Buttons\UI-Common-MouseHilight]], "ADD")
+ frame.dropButton = dropButton
+
+ frame.Disable = disable
+ frame.Enable = enable
+ return frame
+ end
+
+ function AGSMW:GetBaseFrameWithWindow()
+ local frame = self:GetBaseFrame()
+
+ local displayButton = CreateFrame("Button", nil, frame)
+ displayButton:SetHeight(42)
+ displayButton:SetWidth(42)
+ displayButton:SetPoint("TOPLEFT", frame, "TOPLEFT", 1, -2)
+ displayButton:SetBackdrop(displayButtonBackdrop)
+ displayButton:SetBackdropBorderColor(.5, .5, .5)
+ frame.displayButton = displayButton
+
+ frame.label:SetPoint("TOPLEFT",displayButton,"TOPRIGHT",1,2)
+
+ frame.DLeft:SetPoint("BOTTOMLEFT", displayButton, "BOTTOMRIGHT", -17, -20)
+
+ return frame
+ end
+
+end
+
+do
+
+ local sliderBackdrop = {
+ ["bgFile"] = "Interface\\Buttons\\UI-SliderBar-Background",
+ ["edgeFile"] = "Interface\\Buttons\\UI-SliderBar-Border",
+ ["tile"] = true,
+ ["edgeSize"] = 8,
+ ["tileSize"] = 8,
+ ["insets"] = {
+ ["left"] = 3,
+ ["right"] = 3,
+ ["top"] = 3,
+ ["bottom"] = 3,
+ },
+ }
+ local frameBackdrop = {
+ bgFile="Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 32, edgeSize = 32,
+ insets = { left = 11, right = 12, top = 12, bottom = 9 },
+ }
+
+ local function OnMouseWheel(self, dir)
+ self.slider:SetValue(self.slider:GetValue()+(15*dir*-1))
+ end
+
+ local function AddFrame(self, frame)
+ frame:SetParent(self.contentframe)
+ frame:SetFrameStrata(self:GetFrameStrata())
+ frame:SetFrameLevel(self:GetFrameLevel() + 100)
+
+ if next(self.contentRepo) then
+ frame:SetPoint("TOPLEFT", self.contentRepo[getn(self.contentRepo)], "BOTTOMLEFT", 0, 0)
+ frame:SetPoint("RIGHT", self.contentframe, "RIGHT", 0, 0)
+ self.contentframe:SetHeight(self.contentframe:GetHeight() + frame:GetHeight())
+ self.contentRepo[getn(self.contentRepo)+1] = frame
+ else
+ self.contentframe:SetHeight(frame:GetHeight())
+ frame:SetPoint("TOPLEFT", self.contentframe, "TOPLEFT", 0, 0)
+ frame:SetPoint("RIGHT", self.contentframe, "RIGHT", 0, 0)
+ self.contentRepo[1] = frame
+ end
+
+ if self.contentframe:GetHeight() > UIParent:GetHeight()*2/5 - 20 then
+ self.scrollframe:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -28, 12)
+ self:SetHeight(UIParent:GetHeight()*2/5)
+ self.slider:Show()
+ self:SetScript("OnMouseWheel", OnMouseWheel)
+ self.scrollframe:UpdateScrollChildRect()
+ self.slider:SetMinMaxValues(0, self.contentframe:GetHeight()-self.scrollframe:GetHeight())
+ else
+ self.scrollframe:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -14, 12)
+ self:SetHeight(self.contentframe:GetHeight()+25)
+ self.slider:Hide()
+ self:SetScript("OnMouseWheel", nil)
+ self.scrollframe:UpdateScrollChildRect()
+ self.slider:SetMinMaxValues(0, 0)
+ end
+ self.contentframe:SetWidth(self.scrollframe:GetWidth())
+ end
+
+ local function ClearFrames(self)
+ for i, frame in ipairs(self.contentRepo) do
+ frame:ReturnSelf()
+ self.contentRepo[i] = nil
+ end
+ end
+
+ local function slider_OnValueChanged()
+ this.frame.scrollframe:SetVerticalScroll(arg1)
+ end
+
+ local DropDownCache = {}
+ function AGSMW:GetDropDownFrame()
+ local frame
+ if next(DropDownCache) then
+ frame = table.remove(DropDownCache)
+ else
+ frame = CreateFrame("Frame", nil, UIParent)
+ frame:SetClampedToScreen(true)
+ frame:SetWidth(188)
+ frame:SetBackdrop(frameBackdrop)
+ frame:SetFrameStrata("TOOLTIP")
+ frame:EnableMouseWheel(true)
+
+ local contentframe = CreateFrame("Frame", nil, frame)
+ contentframe:SetWidth(160)
+ contentframe:SetHeight(0)
+ frame.contentframe = contentframe
+
+ local scrollframe = CreateFrame("ScrollFrame", nil, frame)
+ scrollframe:SetWidth(160)
+ scrollframe:SetPoint("TOPLEFT", frame, "TOPLEFT", 14, -13)
+ scrollframe:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 12)
+ scrollframe:SetScrollChild(contentframe)
+ frame.scrollframe = scrollframe
+
+ contentframe:SetPoint("TOPLEFT", scrollframe)
+ contentframe:SetPoint("TOPRIGHT", scrollframe)
+
+ local bgTex = frame:CreateTexture(nil, "ARTWORK")
+ bgTex:SetAllPoints(scrollframe)
+ frame.bgTex = bgTex
+
+ frame.AddFrame = AddFrame
+ frame.ClearFrames = ClearFrames
+ frame.contentRepo = {} -- store all our frames in here so we can get rid of them later
+
+ local slider = CreateFrame("Slider", nil, scrollframe)
+ slider:SetOrientation("VERTICAL")
+ slider:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -14, -10)
+ slider:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 10)
+ slider:SetBackdrop(sliderBackdrop)
+ slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
+ slider:SetMinMaxValues(0, 1)
+ --slider:SetValueStep(1)
+ slider:SetWidth(12)
+ slider.frame = frame
+ slider:SetScript("OnValueChanged", slider_OnValueChanged)
+ frame.slider = slider
+ end
+ frame:SetHeight(UIParent:GetHeight()*2/5)
+ frame.slider:SetValue(0)
+ frame:Show()
+ return frame
+ end
+
+ function AGSMW:ReturnDropDownFrame(frame)
+ ClearFrames(frame)
+ frame:ClearAllPoints()
+ frame:Hide()
+ frame:SetBackdrop(frameBackdrop)
+ frame.bgTex:SetTexture(nil)
+ table.insert(DropDownCache, frame)
+ return nil
+ end
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/widget.xml b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/widget.xml
new file mode 100644
index 0000000..15cd102
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0-SharedMediaWidgets/widget.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/AceGUI-3.0.lua b/ElvUI_Config/Libraries/AceGUI-3.0/AceGUI-3.0.lua
new file mode 100644
index 0000000..3b8340f
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/AceGUI-3.0.lua
@@ -0,0 +1,789 @@
+--- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs.
+-- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself
+-- to create any custom GUI. There are more extensive examples in the test suite in the Ace3
+-- stand-alone distribution.
+--
+-- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly,
+-- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool
+-- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we"ll
+-- implement a proper API to modify it.
+-- @usage
+-- local AceGUI = LibStub("AceGUI-3.0")
+-- -- Create a container frame
+-- local f = AceGUI:Create("Frame")
+-- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end)
+-- f:SetTitle("AceGUI-3.0 Example")
+-- f:SetStatusText("Status Bar")
+-- f:SetLayout("Flow")
+-- -- Create a button
+-- local btn = AceGUI:Create("Button")
+-- btn:SetWidth(170)
+-- btn:SetText("Button !")
+-- btn:SetCallback("OnClick", function() print("Click!") end)
+-- -- Add the button to the container
+-- f:AddChild(btn)
+-- @class file
+-- @name AceGUI-3.0
+-- @release $Id: AceGUI-3.0.lua 1102 2013-10-25 14:15:23Z nevcairiel $
+local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 34
+local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
+
+if not AceGUI then return end -- No upgrade needed
+
+local AceCore = LibStub("AceCore-3.0")
+local hooksecurefunc = AceCore.hooksecurefunc
+local safecall = AceCore.safecall
+
+-- Lua APIs
+local tconcat, tremove, tinsert, tgetn, tsetn = table.concat, table.remove, table.insert, table.getn, table.setn
+local pairs, next, type = pairs, next, type
+local error, assert, loadstring = error, assert, loadstring
+local setmetatable, rawget, rawset = setmetatable, rawget, rawset
+local math_max = math.max
+local strupper, strfmt = string.upper, string.format
+
+-- WoW APIs
+local UIParent = UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler, LibStub
+
+--local con = LibStub("AceConsole-3.0",true)
+
+AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
+AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
+AceGUI.WidgetBase = AceGUI.WidgetBase or {}
+AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
+AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
+AceGUI.HookedFunctions = AceGUI.HookedFunctions or {}
+
+-- local upvalues
+local WidgetRegistry = AceGUI.WidgetRegistry
+local LayoutRegistry = AceGUI.LayoutRegistry
+local WidgetVersions = AceGUI.WidgetVersions
+local HookedFunctions = AceGUI.HookedFunctions
+
+-- Recycling functions
+local newWidget, delWidget
+do
+ AceGUI.objPools = AceGUI.objPools or {}
+ local objPools = AceGUI.objPools
+ --Returns a new instance, if none are available either returns a new table or calls the given contructor
+ function newWidget(type)
+ if not WidgetRegistry[type] then
+ error("Attempt to instantiate unknown widget type", 2)
+ end
+
+ if not objPools[type] then
+ objPools[type] = {}
+ end
+
+ local newObj = next(objPools[type])
+ if not newObj then
+ newObj = WidgetRegistry[type]()
+ newObj.AceGUIWidgetVersion = WidgetVersions[type]
+ else
+ objPools[type][newObj] = nil
+ -- if the widget is older then the latest, don't even try to reuse it
+ -- just forget about it, and grab a new one.
+ if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[type] then
+ return newWidget(type)
+ end
+ end
+ return newObj
+ end
+ -- Releases an instance to the Pool
+ function delWidget(obj,type)
+ if not objPools[type] then
+ objPools[type] = {}
+ end
+ if objPools[type][obj] then
+ error("Attempt to Release Widget that is already released", 2)
+ end
+ objPools[type][obj] = true
+ end
+end
+
+local function fixlevels(parent,...)
+ local i = 1
+ local child = arg[i]
+ while child do
+ child:SetFrameLevel(parent:GetFrameLevel() + (parent.backdrop and -1 or 2))
+ fixlevels(child, child:GetChildren())
+ i = i + 1
+ child = arg[i]
+ end
+end
+-------------------
+-- API Functions --
+-------------------
+
+-- Gets a widget Object
+
+--- Create a new Widget of the given type.
+-- This function will instantiate a new widget (or use one from the widget pool), and call the
+-- OnAcquire function on it, before returning.
+-- @param type The type of the widget.
+-- @return The newly created widget.
+function AceGUI:Create(type)
+ if WidgetRegistry[type] then
+ local widget = newWidget(type)
+
+ if widget.OnAcquire then
+ widget:OnAcquire()
+ else
+ error(strfmt("Widget type %s doesn't supply an OnAcquire Function", type))
+ end
+
+ -- Set the default Layout ("List")
+ safecall(widget.SetLayout, 2, widget, "List")
+ safecall(widget.ResumeLayout, 1, widget)
+ return widget
+ end
+end
+
+--- Releases a widget Object.
+-- This function calls OnRelease on the widget and places it back in the widget pool.
+-- Any data on the widget is being erased, and the widget will be hidden.\\
+-- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well.
+-- @param widget The widget to release
+function AceGUI:Release(widget)
+ safecall(widget.PauseLayout, 1, widget)
+ widget:Fire("OnRelease")
+ safecall(widget.ReleaseChildren, 1, widget)
+
+ if widget.OnRelease then
+ widget:OnRelease()
+-- else
+-- error(strfmt("Widget type %s doesn't supply an OnRelease Function", widget.type))
+ end
+ for k in pairs(widget.userdata) do
+ widget.userdata[k] = nil
+ end
+ for k in pairs(widget.events) do
+ widget.events[k] = nil
+ end
+ widget.width = nil
+ widget.relWidth = nil
+ widget.height = nil
+ widget.relHeight = nil
+ widget.noAutoHeight = nil
+ widget.frame:ClearAllPoints()
+ widget.frame:Hide()
+ widget.frame:SetParent(UIParent)
+ widget.frame.width = nil
+ widget.frame.height = nil
+ if widget.content then
+ widget.content.width = nil
+ widget.content.height = nil
+ end
+ delWidget(widget, widget.type)
+end
+
+-----------
+-- Focus --
+-----------
+
+
+--- Called when a widget has taken focus.
+-- e.g. Dropdowns opening, Editboxes gaining kb focus
+-- @param widget The widget that should be focused
+function AceGUI:SetFocus(widget)
+ if self.FocusedWidget and self.FocusedWidget ~= widget then
+ safecall(self.FocusedWidget.ClearFocus, 1, self.FocusedWidget)
+ end
+ self.FocusedWidget = widget
+end
+
+
+--- Called when something has happened that could cause widgets with focus to drop it
+-- e.g. titlebar of a frame being clicked
+function AceGUI:ClearFocus()
+ if self.FocusedWidget then
+ safecall(self.FocusedWidget.ClearFocus, 1, self.FocusedWidget)
+ self.FocusedWidget = nil
+ end
+end
+
+-------------
+-- Widgets --
+-------------
+--[[
+ Widgets must provide the following functions
+ OnAcquire() - Called when the object is acquired, should set everything to a default hidden state
+
+ And the following members
+ frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
+ type - the type of the object, same as the name given to :RegisterWidget()
+
+ Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
+ It will be cleared automatically when a widget is released
+ Placing values directly into a widget object should be avoided
+
+ If the Widget can act as a container for other Widgets the following
+ content - frame or derivitive that children will be anchored to
+
+ The Widget can supply the following Optional Members
+ :OnRelease() - Called when the object is Released, should remove any additional anchors and clear any data
+ :OnWidthSet(width) - Called when the width of the widget is changed
+ :OnHeightSet(height) - Called when the height of the widget is changed
+ Widgets should not use the OnSizeChanged events of thier frame or content members, use these methods instead
+ AceGUI already sets a handler to the event
+ :LayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the
+ area used for controls. These can be nil if the layout used the existing size to layout the controls.
+
+]]
+
+--------------------------
+-- Widget Base Template --
+--------------------------
+do
+ local WidgetBase = AceGUI.WidgetBase
+
+ WidgetBase.SetParent = function(self, parent)
+ local frame = self.frame
+ frame:SetParent(nil)
+ frame:SetParent(parent.content)
+ self.parent = parent
+ fixlevels(frame, frame:GetChildren())
+ end
+
+ WidgetBase.SetCallback = function(self, name, func)
+ if type(func) == "function" then
+ self.events[name] = func
+ end
+ end
+
+ WidgetBase.Fire = function(self, name, argc, ...)
+ argc = table.getn(arg)
+ local func = self.events[name]
+ if func then
+ local success, ret = safecall(func, argc+3, self, name, argc, unpack(arg))
+ if success then
+ return ret
+ end
+ end
+ end
+
+ WidgetBase.SetWidth = function(self, width)
+ self.frame:SetWidth(width)
+ self.frame.width = width
+ if self.OnWidthSet then
+ self:OnWidthSet(width)
+ end
+ end
+
+ WidgetBase.SetRelativeWidth = function(self, width)
+ if width <= 0 or width > 1 then
+ error(":SetRelativeWidth(width): Invalid relative width.", 2)
+ end
+ self.relWidth = width
+ self.width = "relative"
+ end
+
+ WidgetBase.SetHeight = function(self, height)
+ self.frame:SetHeight(height)
+ self.frame.height = height
+ if self.OnHeightSet then
+ self:OnHeightSet(height)
+ end
+ end
+
+ --[[ WidgetBase.SetRelativeHeight = function(self, height)
+ if height <= 0 or height > 1 then
+ error(":SetRelativeHeight(height): Invalid relative height.", 2)
+ end
+ self.relHeight = height
+ self.height = "relative"
+ end ]]
+
+ WidgetBase.IsVisible = function(self)
+ return self.frame:IsVisible()
+ end
+
+ WidgetBase.IsShown= function(self)
+ return self.frame:IsShown()
+ end
+
+ WidgetBase.Release = function(self)
+ AceGUI:Release(self)
+ end
+
+ WidgetBase.SetPoint = function(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ return self.frame:SetPoint(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+
+ WidgetBase.ClearAllPoints = function(self)
+ return self.frame:ClearAllPoints()
+ end
+
+ WidgetBase.GetNumPoints = function(self)
+ return self.frame:GetNumPoints()
+ end
+
+ WidgetBase.GetPoint = function(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ return self.frame:GetPoint(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end
+
+ WidgetBase.GetUserDataTable = function(self)
+ return self.userdata
+ end
+
+ WidgetBase.SetUserData = function(self, key, value)
+ self.userdata[key] = value
+ end
+
+ WidgetBase.GetUserData = function(self, key)
+ return self.userdata[key]
+ end
+
+ WidgetBase.IsFullHeight = function(self)
+ return self.height == "fill"
+ end
+
+ WidgetBase.SetFullHeight = function(self, isFull)
+ if isFull then
+ self.height = "fill"
+ else
+ self.height = nil
+ end
+ end
+
+ WidgetBase.IsFullWidth = function(self)
+ return self.width == "fill"
+ end
+
+ WidgetBase.SetFullWidth = function(self, isFull)
+ if isFull then
+ self.width = "fill"
+ else
+ self.width = nil
+ end
+ end
+
+-- local function LayoutOnUpdate(this)
+-- this:SetScript("OnUpdate",nil)
+-- this.obj:PerformLayout()
+-- end
+
+ local WidgetContainerBase = AceGUI.WidgetContainerBase
+
+ WidgetContainerBase.PauseLayout = function(self)
+ self.LayoutPaused = true
+ end
+
+ WidgetContainerBase.ResumeLayout = function(self)
+ self.LayoutPaused = nil
+ end
+
+ WidgetContainerBase.PerformLayout = function(self)
+ if self.LayoutPaused then
+ return
+ end
+ safecall(self.LayoutFunc, 2, self.content, self.children)
+ end
+
+ --call this function to layout, makes sure layed out objects get a frame to get sizes etc
+ WidgetContainerBase.DoLayout = function(self)
+ self:PerformLayout()
+-- if not self.parent then
+-- self.frame:SetScript("OnUpdate", LayoutOnUpdate)
+-- end
+ end
+
+ WidgetContainerBase.AddChild = function(self, child, beforeWidget)
+ if beforeWidget then
+ local siblingIndex = 1
+ for _, widget in pairs(self.children) do
+ if widget == beforeWidget then
+ break
+ end
+ siblingIndex = siblingIndex + 1
+ end
+ tinsert(self.children, siblingIndex, child)
+ else
+ tinsert(self.children, child)
+ end
+ child:SetParent(self)
+ child.frame:Show()
+ self:DoLayout()
+ end
+
+ do
+ local args = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
+ WidgetContainerBase.AddChildren = function(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ args[1] = a1
+ args[2] = a2
+ args[3] = a3
+ args[4] = a4
+ args[5] = a5
+ args[6] = a6
+ args[7] = a7
+ args[8] = a8
+ args[9] = a9
+ args[10] = a10
+ for i = 1,10 do
+ local child = args[i]
+ arg[i] = nil
+
+ if not child then break end
+ tinsert(self.children, child)
+ child:SetParent(self)
+ child.frame:Show()
+ end
+ self:DoLayout()
+ end
+ end -- WidgetContainerBase.AddChildren
+
+ WidgetContainerBase.ReleaseChildren = function(self)
+ local children = self.children
+ for i = 1,tgetn(children) do
+ AceGUI:Release(tremove(children))
+ end
+ end
+
+ --[[WidgetContainerBase.SetParent = function(self, parent)
+ --WidgetBase.SetParent(self, parent)
+
+ local lv = self.frame:GetFrameLevel()
+ self.content:SetFrameLevel(lv+1)
+ local children = self.children
+ for i = 1,tgetn(children) do
+ local child = children[i]
+ child:SetParent(self)
+ end
+ end]]
+
+ WidgetContainerBase.SetLayout = function(self, Layout)
+ self.LayoutFunc = AceGUI:GetLayout(Layout)
+ end
+
+ WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust)
+ if adjust then
+ self.noAutoHeight = nil
+ else
+ self.noAutoHeight = true
+ end
+ end
+
+ local function FrameResize()
+ local self = this.obj
+ if this:GetWidth() and this:GetHeight() then
+ if self.OnWidthSet then
+ self:OnWidthSet(this:GetWidth())
+ end
+ if self.OnHeightSet then
+ self:OnHeightSet(this:GetHeight())
+ end
+ end
+ end
+
+ local function ContentResize()
+ if this:GetWidth() and this:GetHeight() then
+ this.width = this:GetWidth()
+ this.height = this:GetHeight()
+ this.obj:DoLayout()
+ end
+ end
+
+ setmetatable(WidgetContainerBase, {__index=WidgetBase})
+
+ --One of these function should be called on each Widget Instance as part of its creation process
+
+ --- Register a widget-class as a container for newly created widgets.
+ -- @param widget The widget class
+ function AceGUI:RegisterAsContainer(widget)
+ widget.children = {}
+ widget.userdata = {}
+ widget.events = {}
+ widget.base = WidgetContainerBase
+ widget.content.obj = widget
+ widget.frame.obj = widget
+ widget.content:SetScript("OnSizeChanged", ContentResize)
+ widget.frame:SetScript("OnSizeChanged", FrameResize)
+ setmetatable(widget, {__index = WidgetContainerBase})
+ widget:SetLayout("List")
+ return widget
+ end
+
+ --- Register a widget-class as a widget.
+ -- @param widget The widget class
+ function AceGUI:RegisterAsWidget(widget)
+ widget.userdata = {}
+ widget.events = {}
+ widget.base = WidgetBase
+ widget.frame.obj = widget
+ widget.frame:SetScript("OnSizeChanged", FrameResize)
+ setmetatable(widget, {__index = WidgetBase})
+ return widget
+ end
+end
+
+
+
+
+------------------
+-- Widget API --
+------------------
+
+--- Registers a widget Constructor, this function returns a new instance of the Widget
+-- @param Name The name of the widget
+-- @param Constructor The widget constructor function
+-- @param Version The version of the widget
+function AceGUI:RegisterWidgetType(Name, Constructor, Version)
+ assert(type(Constructor) == "function")
+ assert(type(Version) == "number")
+
+ local oldVersion = WidgetVersions[Name]
+ if oldVersion and oldVersion >= Version then return end
+
+ WidgetVersions[Name] = Version
+ WidgetRegistry[Name] = Constructor
+end
+
+--- Registers a Layout Function
+-- @param Name The name of the layout
+-- @param LayoutFunc Reference to the layout function
+function AceGUI:RegisterLayout(Name, LayoutFunc)
+ assert(type(LayoutFunc) == "function")
+ if type(Name) == "string" then
+ Name = string.upper(Name)
+ end
+ LayoutRegistry[Name] = LayoutFunc
+end
+
+--- Get a Layout Function from the registry
+-- @param Name The name of the layout
+function AceGUI:GetLayout(Name)
+ if type(Name) == "string" then
+ Name = strupper(Name)
+ end
+ return LayoutRegistry[Name]
+end
+
+AceGUI.counts = AceGUI.counts or {}
+
+--- A type-based counter to count the number of widgets created.
+-- This is used by widgets that require a named frame, e.g. when a Blizzard
+-- Template requires it.
+-- @param type The widget type
+function AceGUI:GetNextWidgetNum(type)
+ if not self.counts[type] then
+ self.counts[type] = 0
+ end
+ self.counts[type] = self.counts[type] + 1
+ return self.counts[type]
+end
+
+--- Return the number of created widgets for this type.
+-- In contrast to GetNextWidgetNum, the number is not incremented.
+-- @param type The widget type
+function AceGUI:GetWidgetCount(type)
+ return self.counts[type] or 0
+end
+
+--- Return the version of the currently registered widget type.
+-- @param type The widget type
+function AceGUI:GetWidgetVersion(type)
+ return WidgetVersions[type]
+end
+
+-------------
+-- Layouts --
+-------------
+
+--[[
+ A Layout is a func that takes 2 parameters
+ content - the frame that widgets will be placed inside
+ children - a table containing the widgets to layout
+]]
+
+-- Very simple Layout, Children are stacked on top of each other down the left side
+AceGUI:RegisterLayout("List",
+ function(content, children)
+ local height = 0
+ local width = content.width or content:GetWidth() or 0
+ for i = 1, tgetn(children) do
+ local child = children[i]
+
+ local frame = child.frame
+ frame:ClearAllPoints()
+ frame:Show()
+ if i == 1 then
+ frame:SetPoint("TOPLEFT", content)
+ else
+ frame:SetPoint("TOPLEFT", children[i-1].frame, "BOTTOMLEFT")
+ end
+
+ if child.width == "fill" then
+ child:SetWidth(width)
+ frame:SetPoint("RIGHT", content)
+
+ if child.DoLayout then
+ child:DoLayout()
+ end
+ elseif child.width == "relative" then
+ child:SetWidth(width * child.relWidth)
+
+ if child.DoLayout then
+ child:DoLayout()
+ end
+ end
+
+ height = height + (frame.height or frame:GetHeight() or 0)
+ end
+ safecall(content.obj.LayoutFinished, 3, content.obj, nil, height)
+ end)
+
+-- A single control fills the whole content area
+AceGUI:RegisterLayout("Fill",
+ function(content, children)
+ if children[1] then
+ children[1]:SetWidth(content:GetWidth() or 0)
+ children[1]:SetHeight(content:GetHeight() or 0)
+ children[1].frame:SetAllPoints(content)
+ children[1].frame:Show()
+ safecall(content.obj.LayoutFinished, 3, content.obj, nil, children[1].frame:GetHeight())
+ end
+ end)
+
+-- Ace3v: currently only a1 used
+local layoutrecursionblock = nil
+local function safelayoutcall(object, func, a1)
+ layoutrecursionblock = true
+ object[func](object, a1)
+ layoutrecursionblock = nil
+end
+
+AceGUI:RegisterLayout("Flow",
+ function(content, children)
+ if layoutrecursionblock then return end
+ --used height so far
+ local height = 0
+ --width used in the current row
+ local usedwidth = 0
+ --height of the current row
+ local rowheight = 0
+ local rowoffset = 0
+ local lastrowoffset
+
+ local width = content.width or content:GetWidth() or 0
+
+ --control at the start of the row
+ local rowstart
+ local rowstartoffset
+ local lastrowstart
+ local isfullheight
+
+ local frameoffset
+ local lastframeoffset
+ local oversize
+ for i = 1, tgetn(children) do
+ local child = children[i]
+ oversize = nil
+ local frame = child.frame
+ local frameheight = frame.height or frame:GetHeight() or 0
+ local framewidth = frame.width or frame:GetWidth() or 0
+ lastframeoffset = frameoffset
+ -- HACK: Why did we set a frameoffset of (frameheight / 2) ?
+ -- That was moving all widgets half the widgets size down, is that intended?
+ -- Actually, it seems to be neccessary for many cases, we'll leave it in for now.
+ -- If widgets seem to anchor weirdly with this, provide a valid alignoffset for them.
+ -- TODO: Investigate moar!
+ frameoffset = child.alignoffset or (frameheight / 2)
+
+ if child.width == "relative" then
+ framewidth = width * child.relWidth
+ end
+
+ frame:Show()
+ frame:ClearAllPoints()
+ if i == 1 then
+ -- anchor the first control to the top left
+ frame:SetPoint("TOPLEFT", content)
+ rowheight = frameheight
+ rowoffset = frameoffset
+ rowstart = frame
+ rowstartoffset = frameoffset
+ usedwidth = framewidth
+ if usedwidth > width then
+ oversize = true
+ end
+ else
+ -- if there isn't available width for the control start a new row
+ -- if a control is "fill" it will be on a row of its own full width
+ if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then
+ if isfullheight then
+ -- a previous row has already filled the entire height, there's nothing we can usefully do anymore
+ -- (maybe error/warn about this?)
+ break
+ end
+ --anchor the previous row, we will now know its height and offset
+ rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
+ height = height + rowheight + 3
+ --save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it
+ rowstart = frame
+ rowstartoffset = frameoffset
+ rowheight = frameheight
+ rowoffset = frameoffset
+ usedwidth = framewidth
+ if usedwidth > width then
+ oversize = true
+ end
+ -- put the control on the current row, adding it to the width and checking if the height needs to be increased
+ else
+ --handles cases where the new height is higher than either control because of the offsets
+ --math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset)
+
+ --offset is always the larger of the two offsets
+ rowoffset = math_max(rowoffset, frameoffset)
+ rowheight = math_max(rowheight, rowoffset + (frameheight / 2))
+
+ frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT", 0, frameoffset - lastframeoffset)
+ usedwidth = framewidth + usedwidth
+ end
+ end
+
+ if child.width == "fill" then
+ safelayoutcall(child, "SetWidth", width)
+ frame:SetPoint("RIGHT", content)
+
+ usedwidth = 0
+ rowstart = frame
+ rowstartoffset = frameoffset
+
+ if child.DoLayout then
+ child:DoLayout()
+ end
+ rowheight = frame.height or frame:GetHeight() or 0
+ rowoffset = child.alignoffset or (rowheight / 2)
+ rowstartoffset = rowoffset
+ elseif child.width == "relative" then
+ safelayoutcall(child, "SetWidth", width * child.relWidth)
+
+ if child.DoLayout then
+ child:DoLayout()
+ end
+ elseif oversize then
+ if width > 1 then
+ frame:SetPoint("RIGHT", content)
+ end
+ end
+
+ if child.height == "fill" then
+ frame:SetPoint("BOTTOM", content)
+ isfullheight = true
+ end
+ end
+
+ --anchor the last row, if its full height needs a special case since its height has just been changed by the anchor
+ if isfullheight then
+ rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height)
+ elseif rowstart then
+ rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
+ end
+
+ height = height + rowheight + 3
+ safecall(content.obj.LayoutFinished, 3, content.obj, nil, height)
+ end)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/AceGUI-3.0.xml b/ElvUI_Config/Libraries/AceGUI-3.0/AceGUI-3.0.xml
new file mode 100644
index 0000000..0419ee2
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/AceGUI-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua
new file mode 100644
index 0000000..9a48f8b
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua
@@ -0,0 +1,138 @@
+--[[-----------------------------------------------------------------------------
+BlizOptionsGroup Container
+Simple container widget for the integration of AceGUI into the Blizzard Interface Options
+-------------------------------------------------------------------------------]]
+local Type, Version = "BlizOptionsGroup", 21
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local CreateFrame = CreateFrame
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+
+local function OnShow(frame)
+ frame.obj:Fire("OnShow")
+end
+
+local function OnHide(frame)
+ frame.obj:Fire("OnHide")
+end
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+
+local function okay(frame)
+ frame.obj:Fire("okay")
+end
+
+local function cancel(frame)
+ frame.obj:Fire("cancel")
+end
+
+local function default(frame)
+ frame.obj:Fire("default")
+end
+
+local function refresh(frame)
+ frame.obj:Fire("refresh")
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetName()
+ self:SetTitle()
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ local contentwidth = width - 63
+ if contentwidth < 0 then
+ contentwidth = 0
+ end
+ content:SetWidth(contentwidth)
+ content.width = contentwidth
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ local contentheight = height - 26
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end,
+
+ ["SetName"] = function(self, name, parent)
+ self.frame.name = name
+ self.frame.parent = parent
+ end,
+
+ ["SetTitle"] = function(self, title)
+ local content = self.content
+ content:ClearAllPoints()
+ if not title or title == "" then
+ content:SetPoint("TOPLEFT", 10, -10)
+ self.label:SetText("")
+ else
+ content:SetPoint("TOPLEFT", 10, -40)
+ self.label:SetText(title)
+ end
+ content:SetPoint("BOTTOMRIGHT", -10, 10)
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Frame")
+ frame:Hide()
+
+ -- support functions for the Blizzard Interface Options
+ frame.okay = okay
+ frame.cancel = cancel
+ frame.default = default
+ frame.refresh = refresh
+
+ frame:SetScript("OnHide", OnHide)
+ frame:SetScript("OnShow", OnShow)
+
+ local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
+ label:SetPoint("TOPLEFT", 10, -15)
+ label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
+ label:SetJustifyH("LEFT")
+ label:SetJustifyV("TOP")
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, frame)
+ content:SetPoint("TOPLEFT", 10, -10)
+ content:SetPoint("BOTTOMRIGHT", -10, 10)
+
+ local widget = {
+ label = label,
+ frame = frame,
+ content = content,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua
new file mode 100644
index 0000000..777dbef
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua
@@ -0,0 +1,157 @@
+--[[-----------------------------------------------------------------------------
+DropdownGroup Container
+Container controlled by a dropdown on the top.
+-------------------------------------------------------------------------------]]
+local Type, Version = "DropdownGroup", 21
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local assert, pairs, type = assert, pairs, type
+
+-- WoW APIs
+local CreateFrame = CreateFrame
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function SelectedGroup(self, event, _, value)
+ local group = self.parentgroup
+ local status = group.status or group.localstatus
+ status.selected = value
+ self.parentgroup:Fire("OnGroupSelected", 1, value)
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self.dropdown:SetText("")
+ self:SetDropdownWidth(200)
+ self:SetTitle("")
+ end,
+
+ ["OnRelease"] = function(self)
+ self.dropdown.list = nil
+ self.status = nil
+ for k in pairs(self.localstatus) do
+ self.localstatus[k] = nil
+ end
+ end,
+
+ ["SetTitle"] = function(self, title)
+ self.titletext:SetText(title)
+ self.dropdown.frame:ClearAllPoints()
+ if title and title ~= "" then
+ self.dropdown.frame:SetPoint("TOPRIGHT", -2, 0)
+ else
+ self.dropdown.frame:SetPoint("TOPLEFT", -1, 0)
+ end
+ end,
+
+ ["SetGroupList"] = function(self,list,order)
+ self.dropdown:SetList(list,order)
+ end,
+
+ ["SetStatusTable"] = function(self, status)
+ assert(type(status) == "table")
+ self.status = status
+ end,
+
+ ["SetGroup"] = function(self,group)
+ self.dropdown:SetValue(group)
+ local status = self.status or self.localstatus
+ status.selected = group
+ self:Fire("OnGroupSelected", 1, group)
+ end,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ local contentwidth = width - 26
+ if contentwidth < 0 then
+ contentwidth = 0
+ end
+ content:SetWidth(contentwidth)
+ content.width = contentwidth
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ local contentheight = height - 63
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end,
+
+ ["LayoutFinished"] = function(self, width, height)
+ self:SetHeight((height or 0) + 63)
+ end,
+
+ ["SetDropdownWidth"] = function(self, width)
+ self.dropdown:SetWidth(width)
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local PaneBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 3, right = 3, top = 5, bottom = 3 }
+}
+
+local function Constructor()
+ local frame = CreateFrame("Frame")
+ frame:SetHeight(100)
+ frame:SetWidth(100)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ titletext:SetPoint("TOPLEFT", 4, -5)
+ titletext:SetPoint("TOPRIGHT", -4, -5)
+ titletext:SetJustifyH("LEFT")
+ titletext:SetHeight(18)
+
+ local dropdown = AceGUI:Create("Dropdown")
+ dropdown.frame:SetParent(frame)
+ dropdown.frame:SetFrameLevel(dropdown.frame:GetFrameLevel() + 2)
+ dropdown:SetCallback("OnValueChanged", SelectedGroup)
+ dropdown.frame:SetPoint("TOPLEFT", -1, 0)
+ dropdown.frame:Show()
+ dropdown:SetLabel("")
+
+ local border = CreateFrame("Frame", nil, frame)
+ border:SetPoint("TOPLEFT", 0, -26)
+ border:SetPoint("BOTTOMRIGHT", 0, 3)
+ border:SetBackdrop(PaneBackdrop)
+ border:SetBackdropColor(0.1,0.1,0.1,0.5)
+ border:SetBackdropBorderColor(0.4,0.4,0.4)
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, border)
+ content:SetPoint("TOPLEFT", 10, -10)
+ content:SetPoint("BOTTOMRIGHT", -10, 10)
+
+ local widget = {
+ frame = frame,
+ localstatus = {},
+ titletext = titletext,
+ dropdown = dropdown,
+ border = border,
+ content = content,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ dropdown.parentgroup = widget
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua
new file mode 100644
index 0000000..15d9f97
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua
@@ -0,0 +1,303 @@
+--[[-----------------------------------------------------------------------------
+Frame Container
+-------------------------------------------------------------------------------]]
+local Type, Version = "Frame", 24
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+local AceCore = LibStub("AceCore-3.0")
+local wipe = AceCore.wipe
+
+-- Lua APIs
+local pairs, assert, type = pairs, assert, type
+
+-- WoW APIs
+local PlaySound = PlaySound
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: CLOSE
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Button_OnClick()
+ PlaySound("gsTitleOptionExit")
+ this.obj:Hide()
+end
+
+local function Frame_OnClose()
+ this.obj:Fire("OnClose")
+end
+
+local function Frame_OnMouseDown()
+ AceGUI:ClearFocus()
+end
+
+local function Title_OnMouseDown()
+ this:GetParent():StartMoving()
+ AceGUI:ClearFocus()
+end
+
+local function MoverSizer_OnMouseUp()
+ local frame = this:GetParent()
+ frame:StopMovingOrSizing()
+ local self = frame.obj
+ local status = self.status or self.localstatus
+ status.width = frame:GetWidth()
+ status.height = frame:GetHeight()
+ status.top = frame:GetTop()
+ status.left = frame:GetLeft()
+end
+
+local function SizerSE_OnMouseDown()
+ this:GetParent():StartSizing("BOTTOMRIGHT")
+ AceGUI:ClearFocus()
+end
+
+local function SizerS_OnMouseDown()
+ this:GetParent():StartSizing("BOTTOM")
+ AceGUI:ClearFocus()
+end
+
+local function SizerE_OnMouseDown()
+ this:GetParent():StartSizing("RIGHT")
+ AceGUI:ClearFocus()
+end
+
+local function StatusBar_OnEnter()
+ this.obj:Fire("OnEnterStatusBar")
+end
+
+local function StatusBar_OnLeave()
+ this.obj:Fire("OnLeaveStatusBar")
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self.frame:SetParent(UIParent)
+ self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
+ self:SetTitle()
+ self:SetStatusText()
+ self:ApplyStatus()
+ self:Show()
+ self:EnableResize(true)
+ end,
+
+ ["OnRelease"] = function(self)
+ self.status = nil
+ wipe(self.localstatus)
+ end,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ local contentwidth = width - 34
+ if contentwidth < 0 then
+ contentwidth = 0
+ end
+ content:SetWidth(contentwidth)
+ content.width = contentwidth
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ local contentheight = height - 67
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end,
+
+ ["SetTitle"] = function(self, title)
+ self.titletext:SetText(title)
+ self.titlebg:SetWidth((self.titletext:GetWidth() or 0) + 10)
+ end,
+
+ ["SetStatusText"] = function(self, text)
+ self.statustext:SetText(text)
+ end,
+
+ ["Hide"] = function(self)
+ self.frame:Hide()
+ end,
+
+ ["Show"] = function(self)
+ self.frame:Show()
+ end,
+
+ ["EnableResize"] = function(self, state)
+ local func = state and "Show" or "Hide"
+ self.sizer_se[func](self.sizer_se)
+ self.sizer_s[func](self.sizer_s)
+ self.sizer_e[func](self.sizer_e)
+ end,
+
+ -- called to set an external table to store status in
+ ["SetStatusTable"] = function(self, status)
+ assert(type(status) == "table")
+ self.status = status
+ self:ApplyStatus()
+ end,
+
+ ["ApplyStatus"] = function(self)
+ local status = self.status or self.localstatus
+ local frame = self.frame
+ self:SetWidth(status.width or 700)
+ self:SetHeight(status.height or 500)
+ frame:ClearAllPoints()
+ if status.top and status.left then
+ frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top)
+ frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0)
+ else
+ frame:SetPoint("CENTER", UIParent)
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local FrameBackdrop = {
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 32, edgeSize = 32,
+ insets = { left = 8, right = 8, top = 8, bottom = 8 }
+}
+
+local PaneBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 3, right = 3, top = 5, bottom = 3 }
+}
+
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:Hide()
+
+ frame:EnableMouse(true)
+ frame:SetMovable(true)
+ frame:SetResizable(true)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+ frame:SetBackdrop(FrameBackdrop)
+ frame:SetBackdropColor(0, 0, 0, 1)
+ frame:SetMinResize(400, 200)
+ frame:SetToplevel(true)
+ frame:SetScript("OnHide", Frame_OnClose)
+ frame:SetScript("OnMouseDown", Frame_OnMouseDown)
+
+ local closebutton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
+ closebutton:SetScript("OnClick", Button_OnClick)
+ closebutton:SetPoint("BOTTOMRIGHT", -27, 17)
+ closebutton:SetHeight(20)
+ closebutton:SetWidth(100)
+ closebutton:SetText(CLOSE)
+
+ local statusbg = CreateFrame("Button", nil, frame)
+ statusbg:SetPoint("BOTTOMLEFT", 15, 15)
+ statusbg:SetPoint("BOTTOMRIGHT", -132, 15)
+ statusbg:SetHeight(24)
+ statusbg:SetBackdrop(PaneBackdrop)
+ statusbg:SetBackdropColor(0.1,0.1,0.1)
+ statusbg:SetBackdropBorderColor(0.4,0.4,0.4)
+ statusbg:SetScript("OnEnter", StatusBar_OnEnter)
+ statusbg:SetScript("OnLeave", StatusBar_OnLeave)
+
+ local statustext = statusbg:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ statustext:SetPoint("TOPLEFT", 7, -2)
+ statustext:SetPoint("BOTTOMRIGHT", -7, 2)
+ statustext:SetHeight(20)
+ statustext:SetJustifyH("LEFT")
+ statustext:SetText("")
+
+ local titlebg = frame:CreateTexture(nil, "OVERLAY")
+ titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
+ titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
+ titlebg:SetPoint("TOP", 0, 12)
+ titlebg:SetWidth(100)
+ titlebg:SetHeight(40)
+
+ local title = CreateFrame("Frame", nil, frame)
+ title:EnableMouse(true)
+ title:SetScript("OnMouseDown", Title_OnMouseDown)
+ title:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
+ title:SetAllPoints(titlebg)
+
+ local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
+
+ local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
+ titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
+ titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
+ titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
+ titlebg_l:SetWidth(30)
+ titlebg_l:SetHeight(40)
+
+ local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
+ titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
+ titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
+ titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
+ titlebg_r:SetWidth(30)
+ titlebg_r:SetHeight(40)
+
+ -- bottom right sizer
+ local sizer_se = CreateFrame("Frame", nil, frame)
+ sizer_se:SetPoint("BOTTOMRIGHT", 0, 0)
+ sizer_se:SetWidth(25)
+ sizer_se:SetHeight(25)
+ sizer_se:EnableMouse()
+ sizer_se:SetScript("OnMouseDown",SizerSE_OnMouseDown)
+ sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
+
+ local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
+ line1:SetPoint("BOTTOMRIGHT", -10, 10)
+ line1:SetTexture("Interface\\Cursor\\Item")
+ line1:SetTexCoord(1, 0, 1, 0)
+
+ local sizer_s = CreateFrame("Frame", nil, frame)
+ sizer_s:SetPoint("BOTTOMRIGHT", -25, 0)
+ sizer_s:SetPoint("BOTTOMLEFT", 0, 0)
+ sizer_s:SetHeight(25)
+ sizer_s:EnableMouse(true)
+ sizer_s:SetScript("OnMouseDown", SizerS_OnMouseDown)
+ sizer_s:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
+
+ local sizer_e = CreateFrame("Frame", nil, frame)
+ sizer_e:SetPoint("BOTTOMRIGHT", 0, 25)
+ sizer_e:SetPoint("TOPRIGHT", 0, 0)
+ sizer_e:SetWidth(25)
+ sizer_e:EnableMouse(true)
+ sizer_e:SetScript("OnMouseDown", SizerE_OnMouseDown)
+ sizer_e:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, frame)
+ content:SetPoint("TOPLEFT", 17, -27)
+ --content:SetPoint("BOTTOMRIGHT", -17, 40)
+
+ local widget = {
+ localstatus = {},
+ titletext = titletext,
+ statustext = statustext,
+ titlebg = titlebg,
+ sizer_se = sizer_se,
+ sizer_s = sizer_s,
+ sizer_e = sizer_e,
+ content = content,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ closebutton.obj, statusbg.obj = widget, widget
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua
new file mode 100644
index 0000000..f3db7d6
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua
@@ -0,0 +1,103 @@
+--[[-----------------------------------------------------------------------------
+InlineGroup Container
+Simple container widget that creates a visible "box" with an optional title.
+-------------------------------------------------------------------------------]]
+local Type, Version = "InlineGroup", 21
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetWidth(300)
+ self:SetHeight(100)
+ self:SetTitle("")
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetTitle"] = function(self,title)
+ self.titletext:SetText(title)
+ end,
+
+
+ ["LayoutFinished"] = function(self, width, height)
+ if self.noAutoHeight then return end
+ self:SetHeight((height or 0) + 40)
+ end,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ local contentwidth = width - 20
+ if contentwidth < 0 then
+ contentwidth = 0
+ end
+ content:SetWidth(contentwidth)
+ content.width = contentwidth
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ local contentheight = height - 20
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local PaneBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 3, right = 3, top = 5, bottom = 3 }
+}
+
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ titletext:SetPoint("TOPLEFT", 14, 0)
+ titletext:SetPoint("TOPRIGHT", -14, 0)
+ titletext:SetJustifyH("LEFT")
+ titletext:SetHeight(18)
+
+ local border = CreateFrame("Frame", nil, frame)
+ border:SetPoint("TOPLEFT", 0, -17)
+ border:SetPoint("BOTTOMRIGHT", -1, 3)
+ border:SetBackdrop(PaneBackdrop)
+ border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
+ border:SetBackdropBorderColor(0.4, 0.4, 0.4)
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, border)
+ content:SetPoint("TOPLEFT", 10, -10)
+ content:SetPoint("BOTTOMRIGHT", -10, 10)
+
+ local widget = {
+ frame = frame,
+ content = content,
+ titletext = titletext,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua
new file mode 100644
index 0000000..e301695
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua
@@ -0,0 +1,212 @@
+--[[-----------------------------------------------------------------------------
+ScrollFrame Container
+Plain container that scrolls its content and doesn't grow in height.
+-------------------------------------------------------------------------------]]
+local Type, Version = "ScrollFrame", 24
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs, assert, type = pairs, assert, type
+local min, max, floor, abs = math.min, math.max, math.floor, math.abs
+local format = string.format
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+local function FixScrollOnUpdate()
+ this:SetScript("OnUpdate", nil)
+ this.obj:FixScroll()
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function ScrollFrame_OnMouseWheel()
+ this.obj:MoveScroll(arg1)
+end
+
+local function ScrollFrame_OnSizeChanged()
+ this:SetScript("OnUpdate", FixScrollOnUpdate)
+end
+
+local function ScrollBar_OnScrollValueChanged()
+ this.obj:SetScroll(arg1)
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetScroll(0)
+ self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
+ end,
+
+ ["OnRelease"] = function(self)
+ self.status = nil
+ for k in pairs(self.localstatus) do
+ self.localstatus[k] = nil
+ end
+ self.scrollframe:SetPoint("BOTTOMRIGHT",0,0)
+ self.scrollbar:Hide()
+ self.scrollBarShown = nil
+ self.content.height, self.content.width = nil, nil
+ end,
+
+ ["SetScroll"] = function(self, value)
+ local status = self.status or self.localstatus
+ local viewheight = self.scrollframe:GetHeight()
+ local height = self.content:GetHeight()
+ local offset
+
+ if viewheight > height then
+ offset = 0
+ else
+ offset = floor((height - viewheight) / 1000.0 * value)
+ end
+ self.content:ClearAllPoints()
+ self.content:SetPoint("TOPLEFT", 0, offset)
+ self.content:SetPoint("TOPRIGHT", 0, offset)
+ status.offset = offset
+ status.scrollvalue = value
+ end,
+
+ ["MoveScroll"] = function(self, value)
+ local status = self.status or self.localstatus
+ local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
+
+ if self.scrollBarShown then
+ local diff = height - viewheight
+ local delta = 1
+ if value < 0 then
+ delta = -1
+ end
+ self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
+ end
+ end,
+
+ ["FixScroll"] = function(self)
+
+ if self.updateLock then return end
+ self.updateLock = true
+ local status = self.status or self.localstatus
+ local scrollframe, content, scrollbar = self.scrollframe, self.content, self.scrollbar
+ local viewheight, height = self.scrollframe:GetHeight(), self.content:GetHeight()
+ local offset = status.offset or 0
+ local curvalue = scrollbar:GetValue()
+ -- Give us a margin of error of 2 pixels to stop some conditions that i would blame on floating point inaccuracys
+ -- No-one is going to miss 2 pixels at the bottom of the frame, anyhow!
+
+ if height < viewheight + 2 then
+ if self.scrollBarShown then
+ self.scrollBarShown = nil
+ scrollbar:Hide()
+ scrollbar:SetValue(0)
+ scrollframe:SetPoint("BOTTOMRIGHT",0,0)
+ self:DoLayout()
+ end
+ offset = 0
+ else
+ if not self.scrollBarShown then
+ self.scrollBarShown = true
+ scrollbar:Show()
+ scrollframe:SetPoint("BOTTOMRIGHT", -20, 0)
+ self:DoLayout()
+ end
+ local value = (offset / (height - viewheight) * 1000)
+ if value > 1000 then
+ value = 1000
+ offset = height - viewheight
+ end
+ scrollbar:SetValue(value)
+ self:SetScroll(value)
+ end
+ status.offset = offset
+ scrollframe:SetScrollChild(content)
+ content:ClearAllPoints()
+ content:SetPoint("TOPLEFT", 0, offset)
+ content:SetPoint("TOPRIGHT", 0, offset)
+ self.updateLock = nil
+ end,
+
+ ["LayoutFinished"] = function(self, width, height)
+ self.content:SetHeight(height or 0 + 20)
+ self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
+ end,
+
+ ["SetStatusTable"] = function(self, status)
+ assert(type(status) == "table")
+ self.status = status
+ if not status.scrollvalue then
+ status.scrollvalue = 0
+ end
+ end,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ content:SetWidth(width)
+ content.width = width
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ content.height = height
+ end
+}
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ local num = AceGUI:GetNextWidgetNum(Type)
+
+ local scrollframe = CreateFrame("ScrollFrame", nil, frame)
+ scrollframe:SetPoint("TOPLEFT",0,0)
+ scrollframe:SetPoint("BOTTOMRIGHT",0,0)
+ scrollframe:EnableMouseWheel(true)
+ scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel)
+-- scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged)
+
+ local scrollbar = CreateFrame("Slider", format("AceConfigDialogScrollFrame%dScrollBar", num), scrollframe, "UIPanelScrollBarTemplate")
+ scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
+ scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16)
+ scrollbar:SetMinMaxValues(0, 1000)
+ scrollbar:SetValueStep(1)
+ scrollbar:SetValue(0)
+ scrollbar:SetWidth(16)
+ scrollbar:Hide()
+ -- set the script as the last step, so it doesn't fire yet
+ scrollbar:SetScript("OnValueChanged", ScrollBar_OnScrollValueChanged)
+
+ local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
+ scrollbg:SetAllPoints(scrollbar)
+ scrollbg:SetTexture(0, 0, 0, 0.4)
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, scrollframe)
+ content:SetPoint("TOPLEFT",0,0)
+ content:SetPoint("TOPRIGHT",0,0)
+ content:SetHeight(400)
+ scrollframe:SetScrollChild(content)
+
+ local widget = {
+ localstatus = { scrollvalue = 0 },
+ scrollframe = scrollframe,
+ scrollbar = scrollbar,
+ content = content,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ scrollframe.obj, scrollbar.obj = widget, widget
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua
new file mode 100644
index 0000000..57512c3
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua
@@ -0,0 +1,69 @@
+--[[-----------------------------------------------------------------------------
+SimpleGroup Container
+Simple container widget that just groups widgets.
+-------------------------------------------------------------------------------]]
+local Type, Version = "SimpleGroup", 20
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetWidth(300)
+ self:SetHeight(100)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["LayoutFinished"] = function(self, width, height)
+ if self.noAutoHeight then return end
+ self:SetHeight(height or 0)
+ end,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ content:SetWidth(width)
+ content.width = width
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ content:SetHeight(height)
+ content.height = height
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, frame)
+ content:SetPoint("TOPLEFT")
+ content:SetPoint("BOTTOMRIGHT")
+
+ local widget = {
+ frame = frame,
+ content = content,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-TabGroup.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-TabGroup.lua
new file mode 100644
index 0000000..173fe8b
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-TabGroup.lua
@@ -0,0 +1,353 @@
+--[[-----------------------------------------------------------------------------
+TabGroup Container
+Container that uses tabs on top to switch between groups.
+-------------------------------------------------------------------------------]]
+local Type, Version = "TabGroup-ElvUI", 31
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs, ipairs, assert, type, wipe = pairs, ipairs, assert, type, wipe
+local getn = table.getn
+local format = string.format
+
+-- WoW APIs
+local PlaySound = PlaySound
+local CreateFrame, UIParent = CreateFrame, UIParent
+local _G = _G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: PanelTemplates_TabResize, PanelTemplates_SetDisabledTabState, PanelTemplates_SelectTab, PanelTemplates_DeselectTab
+
+-- local upvalue storage used by BuildTabs
+local widths = {}
+local rowwidths = {}
+local rowends = {}
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+local function UpdateTabLook(frame)
+ if frame.disabled then
+ PanelTemplates_SetDisabledTabState(frame)
+ elseif frame.selected then
+ PanelTemplates_SelectTab(frame)
+ else
+ PanelTemplates_DeselectTab(frame)
+ end
+end
+
+local function Tab_SetText(frame, text)
+ frame:_SetText(text)
+ local width = frame.obj.frame.width or frame.obj.frame:GetWidth() or 0
+ PanelTemplates_TabResize(0, frame, nil, width)
+end
+
+local function Tab_SetSelected(frame, selected)
+ frame.selected = selected
+ UpdateTabLook(frame)
+end
+
+local function Tab_SetDisabled(frame, disabled)
+ frame.disabled = disabled
+ UpdateTabLook(frame)
+end
+
+local function BuildTabsOnUpdate()
+ local self = this.obj
+ self:BuildTabs()
+ this:SetScript("OnUpdate", nil)
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Tab_OnClick()
+ if not (this.selected or this.disabled) then
+ PlaySound("igCharacterInfoTab")
+ this.obj:SelectTab(this.value)
+ end
+end
+
+local function Tab_OnEnter()
+ local self = this.obj
+ self:Fire("OnTabEnter", 2, self.tabs[this.id].value, this)
+end
+
+local function Tab_OnLeave()
+ local self = this.obj
+ self:Fire("OnTabLeave", 2, self.tabs[this.id].value, this)
+end
+
+local function Tab_OnShow()
+ _G[this:GetName().."HighlightTexture"]:SetWidth(this:GetTextWidth() + 30)
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetTitle()
+ end,
+
+ ["OnRelease"] = function(self)
+ self.status = nil
+ for k in pairs(self.localstatus) do
+ self.localstatus[k] = nil
+ end
+ self.tablist = nil
+ for _, tab in pairs(self.tabs) do
+ tab:Hide()
+ end
+ end,
+
+ ["CreateTab"] = function(self, id)
+ local tabname = format("AceGUITabGroup%dTab%d", self.num, id)
+ local tab = CreateFrame("Button", tabname, self.border, "TabButtonTemplate")
+ tab.obj = self
+ tab.id = id
+ tab:SetHeight(24)
+
+ tab.text = _G[tabname .. "Text"]
+ tab.text:ClearAllPoints()
+ tab.text:SetPoint("LEFT", 14, -3)
+ tab.text:SetPoint("RIGHT", -12, -3)
+
+ tab:SetScript("OnClick", Tab_OnClick)
+ tab:SetScript("OnEnter", Tab_OnEnter)
+ tab:SetScript("OnLeave", Tab_OnLeave)
+ tab:SetScript("OnShow", Tab_OnShow)
+
+ tab._SetText = tab.SetText
+ tab.SetText = Tab_SetText
+ tab.SetSelected = Tab_SetSelected
+ tab.SetDisabled = Tab_SetDisabled
+
+ return tab
+ end,
+
+ ["SetTitle"] = function(self, text)
+ self.titletext:SetText(text or "")
+ if text and text ~= "" then
+ self.alignoffset = 25
+ else
+ self.alignoffset = 18
+ end
+ self:BuildTabs()
+ end,
+
+ ["SetStatusTable"] = function(self, status)
+ assert(type(status) == "table")
+ self.status = status
+ end,
+
+ ["SelectTab"] = function(self, value)
+ local status = self.status or self.localstatus
+ local found
+ for i, v in ipairs(self.tabs) do
+ if v.value == value then
+ v:SetSelected(true)
+ found = true
+ else
+ v:SetSelected(false)
+ end
+ end
+ status.selected = value
+ if found then
+ self:Fire("OnGroupSelected",1,value)
+ end
+ end,
+
+ ["SetTabs"] = function(self, tabs)
+ self.tablist = tabs
+ self:BuildTabs()
+ end,
+
+
+ ["BuildTabs"] = function(self)
+ local hastitle = (self.titletext:GetText() and self.titletext:GetText() ~= "")
+ local status = self.status or self.localstatus
+ local tablist = self.tablist
+ local tabs = self.tabs
+
+ if not tablist then return end
+
+ local width = self.frame.width or self.frame:GetWidth() or 0
+
+ wipe(widths)
+ wipe(rowwidths)
+ wipe(rowends)
+
+ --Place Text into tabs and get thier initial width
+ for i, v in ipairs(tablist) do
+ local tab = tabs[i]
+ if not tab then
+ tab = self:CreateTab(i)
+ tabs[i] = tab
+ end
+
+ tab:Show()
+ tab:SetText(v.text)
+ tab:SetDisabled(v.disabled)
+ tab.value = v.value
+
+ widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text
+ end
+
+ local numtabs = getn(tablist)
+ for i = numtabs+1, numtabs, 1 do
+ tabs[i]:Hide()
+ end
+
+ --First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout
+ local numrows = 1
+ local usedwidth = 0
+
+ for i = 1, numtabs do
+ --If this is not the first tab of a row and there isn't room for it
+ if usedwidth ~= 0 and (width - usedwidth - widths[i]) < 0 then
+ rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
+ rowends[numrows] = i - 1
+ numrows = numrows + 1
+ usedwidth = 0
+ end
+ usedwidth = usedwidth + widths[i]
+ end
+ rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
+ rowends[numrows] = numtabs
+
+ --Fix for single tabs being left on the last row, move a tab from the row above if applicable
+ if numrows > 1 then
+ --if the last row has only one tab
+ if rowends[numrows-1] == numtabs-1 then
+ --if there are more than 2 tabs in the 2nd last row
+ if (numrows == 2 and rowends[numrows-1] > 2) or (rowends[numrows] - rowends[numrows-1] > 2) then
+ --move 1 tab from the second last row to the last, if there is enough space
+ if (rowwidths[numrows] + widths[numtabs-1]) <= width then
+ rowends[numrows-1] = rowends[numrows-1] - 1
+ rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1]
+ rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1]
+ end
+ end
+ end
+ end
+
+ --anchor the rows as defined and resize tabs to fill thier row
+ local starttab = 1
+ for row, endtab in ipairs(rowends) do
+ local first = true
+ for tabno = starttab, endtab do
+ local tab = tabs[tabno]
+ tab:ClearAllPoints()
+ if first then
+ tab:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 0, -(hastitle and 14 or 7)-(row-1)*20 )
+ first = false
+ else
+ tab:SetPoint("LEFT", tabs[tabno-1], "RIGHT", -10, 0)
+ end
+ end
+
+ -- equal padding for each tab to fill the available width,
+ -- if the used space is above 75% already
+ -- the 18 pixel is the typical width of a scrollbar, so we can have a tab group inside a scrolling frame,
+ -- and not have the tabs jump around funny when switching between tabs that need scrolling and those that don't
+ local padding = 0
+ if not (numrows == 1 and rowwidths[1] < width*0.75 - 18) then
+ padding = (width - rowwidths[row]) / (endtab - starttab+1)
+ end
+
+ for i = starttab, endtab do
+ PanelTemplates_TabResize(padding + 4, tabs[i], nil, width)
+ end
+ starttab = endtab + 1
+ end
+
+ self.borderoffset = (hastitle and 17 or 10)+((numrows)*20)
+ self.border:SetPoint("TOPLEFT", 1, -self.borderoffset)
+ end,
+
+ ["OnWidthSet"] = function(self, width)
+ local content = self.content
+ local contentwidth = width - 60
+ if contentwidth < 0 then
+ contentwidth = 0
+ end
+ content:SetWidth(contentwidth)
+ content.width = contentwidth
+ self:BuildTabs(self)
+ self.frame:SetScript("OnUpdate", BuildTabsOnUpdate)
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ local contentheight = height - (self.borderoffset + 23)
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end,
+
+ ["LayoutFinished"] = function(self, width, height)
+ if self.noAutoHeight then return end
+ self:SetHeight((height or 0) + (self.borderoffset + 23))
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local PaneBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 3, right = 3, top = 5, bottom = 3 }
+}
+
+local function Constructor()
+ local num = AceGUI:GetNextWidgetNum(Type)
+ local frame = CreateFrame("Frame",nil,UIParent)
+ frame:SetHeight(100)
+ frame:SetWidth(100)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
+ titletext:SetPoint("TOPLEFT", 14, 0)
+ titletext:SetPoint("TOPRIGHT", -14, 0)
+ titletext:SetJustifyH("LEFT")
+ titletext:SetHeight(18)
+ titletext:SetText("")
+
+ local border = CreateFrame("Frame", nil, frame)
+ border:SetPoint("TOPLEFT", 1, -27)
+ border:SetPoint("BOTTOMRIGHT", -1, 3)
+ border:SetBackdrop(PaneBackdrop)
+ border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
+ border:SetBackdropBorderColor(0.4, 0.4, 0.4)
+
+ local content = CreateFrame("Frame", nil, border)
+ content:SetPoint("TOPLEFT", 10, -7)
+ content:SetPoint("BOTTOMRIGHT", -10, 7)
+
+ local widget = {
+ num = num,
+ frame = frame,
+ localstatus = {},
+ alignoffset = 18,
+ titletext = titletext,
+ border = border,
+ borderoffset = 27,
+ tabs = {},
+ content = content,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua
new file mode 100644
index 0000000..6537fb1
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua
@@ -0,0 +1,739 @@
+--[[-----------------------------------------------------------------------------
+TreeGroup Container
+Container that uses a tree control to switch between groups.
+-------------------------------------------------------------------------------]]
+local Type, Version = "TreeGroup", 40
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type
+local math_min, math_max, floor = math.min, math.max, floor
+local select, tremove, unpack, tconcat = select, table.remove, unpack, table.concat
+local tgetn = table.getn
+local strfmt = string.format
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GameTooltip, FONT_COLOR_CODE_CLOSE
+
+-- Recycling functions
+local new, del
+do
+ local pool = setmetatable({},{__mode='k'})
+ function new()
+ local t = next(pool)
+ if t then
+ pool[t] = nil
+ return t
+ else
+ return {}
+ end
+ end
+ function del(t)
+ for k in pairs(t) do
+ t[k] = nil
+ end
+ pool[t] = true
+ end
+end
+
+local DEFAULT_TREE_WIDTH = 175
+local DEFAULT_TREE_SIZABLE = true
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+local function GetButtonUniqueValue(line)
+ local parent = line.parent
+ if parent and parent.value then
+ return GetButtonUniqueValue(parent).."\001"..line.value
+ else
+ return line.value
+ end
+end
+
+local function UpdateButton(button, treeline, selected, canExpand, isExpanded)
+ local self = button.obj
+ local toggle = button.toggle
+ local frame = self.frame
+ local text = treeline.text or ""
+ local icon = treeline.icon
+ local iconCoords = treeline.iconCoords
+ local level = treeline.level
+ local value = treeline.value
+ local uniquevalue = treeline.uniquevalue
+ local disabled = treeline.disabled
+
+ button.treeline = treeline
+ button.value = value
+ button.uniquevalue = uniquevalue
+ if selected then
+ button:LockHighlight()
+ button.selected = true
+ else
+ button:UnlockHighlight()
+ button.selected = false
+ end
+ local normalTexture = button:GetNormalTexture()
+ local line = button.line
+ button.level = level
+ if ( level == 1 ) then
+ button.text:SetFontObject("GameFontNormal")
+ button:SetHighlightFontObject("GameFontHighlight")
+ button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2)
+ else
+ button.text:SetFontObject("GameFontHighlightSmall")
+ button:SetHighlightFontObject("GameFontHighlightSmall")
+ button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2)
+ end
+
+ if disabled then
+ button:EnableMouse(false)
+ button.text:SetText("|cff808080"..text..FONT_COLOR_CODE_CLOSE)
+ else
+ button.text:SetText(text)
+ button:EnableMouse(true)
+ end
+
+ if icon then
+ button.icon:SetTexture(icon)
+ button.icon:SetPoint("LEFT", 8 * level, (level == 1) and 0 or 1)
+ else
+ button.icon:SetTexture(nil)
+ end
+
+ if iconCoords then
+ button.icon:SetTexCoord(unpack(iconCoords))
+ else
+ button.icon:SetTexCoord(0, 1, 0, 1)
+ end
+
+ if canExpand then
+ if not isExpanded then
+ toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP")
+ toggle:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-DOWN")
+ else
+ toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
+ toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
+ end
+ toggle:Show()
+ else
+ toggle:Hide()
+ end
+end
+
+local function ShouldDisplayLevel(tree)
+ local result = false
+ for k, v in ipairs(tree) do
+ if v.children == nil and v.visible ~= false then
+ result = true
+ elseif v.children then
+ result = result or ShouldDisplayLevel(v.children)
+ end
+ if result then return result end
+ end
+ return false
+end
+
+local function addLine(self, v, tree, level, parent)
+ local line = new()
+ line.value = v.value
+ line.text = v.text
+ line.icon = v.icon
+ line.iconCoords = v.iconCoords
+ line.disabled = v.disabled
+ line.tree = tree
+ line.level = level
+ line.parent = parent
+ line.visible = v.visible
+ line.uniquevalue = GetButtonUniqueValue(line)
+ if v.children then
+ line.hasChildren = true
+ else
+ line.hasChildren = nil
+ end
+ tinsert(self.lines, line)
+ return line
+end
+
+--fire an update after one frame to catch the treeframes height
+local function FirstFrameUpdate()
+ local self = this.obj
+ this:SetScript("OnUpdate", nil)
+ self:RefreshTree()
+end
+
+local function BuildUniqueValue(...)
+ local n = tgetn(arg)
+ if n == 1 then
+ return arg[1]
+ else
+ return (unpack(arg)).."\001"..BuildUniqueValue(select(2, unpack(arg)))
+ end
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Expand_OnClick()
+ local button = this.button
+ local self = button.obj
+ local status = (self.status or self.localstatus).groups
+ status[button.uniquevalue] = not status[button.uniquevalue]
+ self:RefreshTree()
+end
+
+local function Button_OnClick()
+ local self = this.obj
+ self:Fire("OnClick", 2, this.uniquevalue, this.selected)
+ if not this.selected then
+ self:SetSelected(this.uniquevalue)
+ this.selected = true
+ this:LockHighlight()
+ self:RefreshTree()
+ end
+ AceGUI:ClearFocus()
+end
+
+local function Button_OnDoubleClick()
+ local self = this.obj
+ local status = self.status or self.localstatus
+ local status = (self.status or self.localstatus).groups
+ status[this.uniquevalue] = not status[this.uniquevalue]
+ self:RefreshTree()
+end
+
+local function Button_OnEnter()
+ local self = this.obj
+ self:Fire("OnButtonEnter", 2, this.uniquevalue, this)
+
+ if self.enabletooltips then
+ GameTooltip:SetOwner(this, "ANCHOR_NONE")
+ GameTooltip:SetPoint("LEFT",this,"RIGHT")
+ GameTooltip:SetText(this.text:GetText() or "", 1, .82, 0, true)
+
+ GameTooltip:Show()
+ end
+end
+
+local function Button_OnLeave()
+ local self = this.obj
+ self:Fire("OnButtonLeave", 2, this.uniquevalue, this)
+
+ if self.enabletooltips then
+ GameTooltip:Hide()
+ end
+end
+
+local function OnScrollValueChanged()
+ if this.obj.noupdate then return end
+ local self = this.obj
+ local status = self.status or self.localstatus
+ status.scrollvalue = floor(arg1 + 0.5)
+ self:RefreshTree()
+ AceGUI:ClearFocus()
+end
+
+local function Tree_OnSizeChanged()
+ this.obj:RefreshTree()
+end
+
+local function Tree_OnMouseWheel()
+ local self = this.obj
+ if self.showscroll then
+ local scrollbar = self.scrollbar
+ local min, max = scrollbar:GetMinMaxValues()
+ local value = scrollbar:GetValue()
+ local newvalue = math_min(max,math_max(min,value - arg1))
+ if value ~= newvalue then
+ scrollbar:SetValue(newvalue)
+ end
+ end
+end
+
+local function Dragger_OnLeave()
+ this:SetBackdropColor(1, 1, 1, 0)
+end
+
+local function Dragger_OnEnter()
+ this:SetBackdropColor(1, 1, 1, 0.8)
+end
+
+local function Dragger_OnMouseDown()
+ local treeframe = this:GetParent()
+ treeframe:StartSizing("RIGHT")
+end
+
+local function Dragger_OnMouseUp()
+ local treeframe = this:GetParent()
+ local self = treeframe.obj
+ local this = treeframe:GetParent()
+ treeframe:StopMovingOrSizing()
+ --treeframe:SetScript("OnUpdate", nil)
+ treeframe:SetUserPlaced(false)
+ --Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize
+ treeframe:SetHeight(0)
+ treeframe:SetPoint("TOPLEFT", this, "TOPLEFT",0,0)
+ treeframe:SetPoint("BOTTOMLEFT", this, "BOTTOMLEFT",0,0)
+
+ local status = self.status or self.localstatus
+ status.treewidth = treeframe:GetWidth()
+
+ treeframe.obj:Fire("OnTreeResize", 1, treeframe:GetWidth())
+ -- recalculate the content width
+ treeframe.obj:OnWidthSet(status.fullwidth)
+ -- update the layout of the content
+ treeframe.obj:DoLayout()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE)
+ self:EnableButtonTooltips(true)
+ self.frame:SetScript("OnUpdate", FirstFrameUpdate)
+ end,
+
+ ["OnRelease"] = function(self)
+ self.status = nil
+ for k, v in pairs(self.localstatus) do
+ if k == "groups" then
+ for k2 in pairs(v) do
+ v[k2] = nil
+ end
+ else
+ self.localstatus[k] = nil
+ end
+ end
+ self.localstatus.scrollvalue = 0
+ self.localstatus.treewidth = DEFAULT_TREE_WIDTH
+ self.localstatus.treesizable = DEFAULT_TREE_SIZABLE
+ end,
+
+ ["EnableButtonTooltips"] = function(self, enable)
+ self.enabletooltips = enable
+ end,
+
+ ["CreateButton"] = function(self)
+ local num = AceGUI:GetNextWidgetNum("TreeGroupButton")
+
+ local button = CreateFrame("Button", strfmt("AceGUI30TreeButton%d", num), self.treeframe)
+ button.obj = self
+ button:SetWidth(175)
+ button:SetHeight(18)
+
+ local toggle = CreateFrame("Button", "$parentToggle", button)
+ toggle:SetWidth(14)
+ toggle:SetHeight(14)
+ toggle:SetPoint("TOPRIGHT", button, "TOPRIGHT", -6, -1)
+ toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
+ toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
+ toggle:SetHighlightTexture("Interface\Buttons\UI-PlusButton-Hilight", "ADD")
+ button.toggle = toggle
+
+ local text = button:CreateFontString()
+ button.text = text
+ text:SetFontObject(GameFontNormal)
+ button:SetHighlightFontObject(GameFontHighlight)
+ text:SetPoint("RIGHT", toggle, "LEFT", -2, 0);
+ text:SetJustifyH("LEFT")
+
+ local highlight = button:CreateTexture(nil, "HIGHLIGHT");
+ button.highlight = highlight
+ highlight:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight")
+ highlight:SetBlendMode("ADD")
+ highlight:SetVertexColor(.196, .388, .8);
+ highlight:ClearAllPoints()
+ highlight:SetPoint("TOPLEFT",0,1)
+ highlight:SetPoint("BOTTOMRIGHT",0,1)
+
+ local icon = button:CreateTexture(nil, "OVERLAY")
+ icon:SetWidth(14)
+ icon:SetHeight(14)
+ button.icon = icon
+
+ button:SetScript("OnClick",Button_OnClick)
+ button:SetScript("OnDoubleClick", Button_OnDoubleClick)
+ button:SetScript("OnEnter",Button_OnEnter)
+ button:SetScript("OnLeave",Button_OnLeave)
+
+ button.toggle.button = button
+ button.toggle:SetScript("OnClick",Expand_OnClick)
+
+ button.text:SetHeight(14) -- Prevents text wrapping
+
+ return button
+ end,
+
+ ["SetStatusTable"] = function(self, status)
+ assert(type(status) == "table")
+ self.status = status
+ if not status.groups then
+ status.groups = {}
+ end
+ if not status.scrollvalue then
+ status.scrollvalue = 0
+ end
+ if not status.treewidth then
+ status.treewidth = DEFAULT_TREE_WIDTH
+ end
+ if status.treesizable == nil then
+ status.treesizable = DEFAULT_TREE_SIZABLE
+ end
+ self:SetTreeWidth(status.treewidth,status.treesizable)
+ self:RefreshTree()
+ end,
+
+ --sets the tree to be displayed
+ ["SetTree"] = function(self, tree, filter)
+ self.filter = filter
+ if tree then
+ assert(type(tree) == "table")
+ end
+ self.tree = tree
+ self:RefreshTree()
+ end,
+
+ ["BuildLevel"] = function(self, tree, level, parent)
+ local groups = (self.status or self.localstatus).groups
+ local hasChildren = self.hasChildren
+
+ for i, v in ipairs(tree) do
+ if v.children then
+ if not self.filter or ShouldDisplayLevel(v.children) then
+ local line = addLine(self, v, tree, level, parent)
+ if groups[line.uniquevalue] then
+ self:BuildLevel(v.children, level+1, line)
+ end
+ end
+ elseif v.visible ~= false or not self.filter then
+ addLine(self, v, tree, level, parent)
+ end
+ end
+ end,
+
+ ["RefreshTree"] = function(self,scrollToSelection)
+ local t = GetTime()
+ local buttons = self.buttons
+ local lines = self.lines
+
+ for i, v in ipairs(buttons) do
+ v:Hide()
+ end
+ while lines[1] do
+ local t = tremove(lines)
+ for k in pairs(t) do
+ t[k] = nil
+ end
+ del(t)
+ end
+
+ if not self.tree then return end
+ --Build the list of visible entries from the tree and status tables
+ local status = self.status or self.localstatus
+ local groupstatus = status.groups
+ local tree = self.tree
+
+ local treeframe = self.treeframe
+
+ status.scrollToSelection = status.scrollToSelection or scrollToSelection -- needs to be cached in case the control hasn't been drawn yet (code bails out below)
+
+ self:BuildLevel(tree, 1)
+
+ local numlines = tgetn(lines)
+
+ local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
+ if maxlines <= 0 then return end
+
+ local first, last
+
+ scrollToSelection = status.scrollToSelection
+ status.scrollToSelection = nil
+
+ if numlines <= maxlines then
+ --the whole tree fits in the frame
+ status.scrollvalue = 0
+ self:ShowScroll(false)
+ first, last = 1, numlines
+ else
+ self:ShowScroll(true)
+ --scrolling will be needed
+ self.noupdate = true
+ self.scrollbar:SetMinMaxValues(0, numlines - maxlines)
+ --check if we are scrolled down too far
+ if numlines - status.scrollvalue < maxlines then
+ status.scrollvalue = numlines - maxlines
+ end
+ self.noupdate = nil
+ first, last = status.scrollvalue+1, status.scrollvalue + maxlines
+ --show selection?
+ if scrollToSelection and status.selected then
+ local show
+ for i,line in ipairs(lines) do -- find the line number
+ if line.uniquevalue==status.selected then
+ show=i
+ end
+ end
+ if not show then
+ -- selection was deleted or something?
+ elseif show>=first and show<=last then
+ -- all good
+ else
+ -- scrolling needed!
+ if show 100 and status.treewidth > maxtreewidth then
+ self:SetTreeWidth(maxtreewidth, status.treesizable)
+ end
+ treeframe:SetMaxResize(maxtreewidth, 1600)
+ end,
+
+ ["OnHeightSet"] = function(self, height)
+ local content = self.content
+ local contentheight = height - 20
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end,
+
+ ["SetTreeWidth"] = function(self, treewidth, resizable)
+ if not resizable then
+ if type(treewidth) == 'number' then
+ resizable = false
+ elseif type(treewidth) == 'boolean' then
+ resizable = treewidth
+ treewidth = DEFAULT_TREE_WIDTH
+ else
+ resizable = false
+ treewidth = DEFAULT_TREE_WIDTH
+ end
+ end
+ self.treeframe:SetWidth(treewidth)
+ self.dragger:EnableMouse(resizable)
+
+ local status = self.status or self.localstatus
+ status.treewidth = treewidth
+ status.treesizable = resizable
+
+ -- recalculate the content width
+ if status.fullwidth then
+ self:OnWidthSet(status.fullwidth)
+ end
+ end,
+
+ ["GetTreeWidth"] = function(self)
+ local status = self.status or self.localstatus
+ return status.treewidth or DEFAULT_TREE_WIDTH
+ end,
+
+ ["LayoutFinished"] = function(self, width, height)
+ if self.noAutoHeight then return end
+ self:SetHeight((height or 0) + 20)
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local PaneBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 3, right = 3, top = 5, bottom = 3 }
+}
+
+local DraggerBackdrop = {
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ edgeFile = nil,
+ tile = true, tileSize = 16, edgeSize = 0,
+ insets = { left = 3, right = 3, top = 7, bottom = 7 }
+}
+
+local function Constructor()
+ local num = AceGUI:GetNextWidgetNum(Type)
+ local frame = CreateFrame("Frame", nil, UIParent)
+
+ local treeframe = CreateFrame("Frame", nil, frame)
+ treeframe:SetPoint("TOPLEFT", 0, 0)
+ treeframe:SetPoint("BOTTOMLEFT", 0, 0)
+ treeframe:SetWidth(DEFAULT_TREE_WIDTH)
+ treeframe:EnableMouseWheel(true)
+ treeframe:SetBackdrop(PaneBackdrop)
+ treeframe:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
+ treeframe:SetBackdropBorderColor(0.4, 0.4, 0.4)
+ treeframe:SetResizable(true)
+ treeframe:SetMinResize(100, 1)
+ treeframe:SetMaxResize(400, 1600)
+ treeframe:SetScript("OnUpdate", FirstFrameUpdate)
+ treeframe:SetScript("OnSizeChanged", Tree_OnSizeChanged)
+ treeframe:SetScript("OnMouseWheel", Tree_OnMouseWheel)
+
+ local dragger = CreateFrame("Frame", nil, treeframe)
+ dragger:SetWidth(8)
+ dragger:SetPoint("TOP", treeframe, "TOPRIGHT")
+ dragger:SetPoint("BOTTOM", treeframe, "BOTTOMRIGHT")
+ dragger:SetBackdrop(DraggerBackdrop)
+ dragger:SetBackdropColor(1, 1, 1, 0)
+ dragger:SetScript("OnEnter", Dragger_OnEnter)
+ dragger:SetScript("OnLeave", Dragger_OnLeave)
+ dragger:SetScript("OnMouseDown", Dragger_OnMouseDown)
+ dragger:SetScript("OnMouseUp", Dragger_OnMouseUp)
+
+ local scrollbar = CreateFrame("Slider", strfmt("AceConfigDialogTreeGroup%dScrollBar", num), treeframe, "UIPanelScrollBarTemplate")
+ scrollbar:SetScript("OnValueChanged", nil)
+ scrollbar:SetPoint("TOPRIGHT", -10, -26)
+ scrollbar:SetPoint("BOTTOMRIGHT", -10, 26)
+ scrollbar:SetMinMaxValues(0,0)
+ scrollbar:SetValueStep(1)
+ scrollbar:SetValue(0)
+ scrollbar:SetWidth(16)
+ scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
+
+ local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
+ scrollbg:SetAllPoints(scrollbar)
+ scrollbg:SetTexture(0,0,0,0.4)
+
+ local border = CreateFrame("Frame",nil,frame)
+ border:SetPoint("TOPLEFT", treeframe, "TOPRIGHT")
+ border:SetPoint("BOTTOMRIGHT", 0, 0)
+ border:SetBackdrop(PaneBackdrop)
+ border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
+ border:SetBackdropBorderColor(0.4, 0.4, 0.4)
+
+ --Container Support
+ local content = CreateFrame("Frame", nil, border)
+ content:SetPoint("TOPLEFT", 10, -10)
+ content:SetPoint("BOTTOMRIGHT", -10, 10)
+
+ local widget = {
+ frame = frame,
+ lines = {},
+ levels = {},
+ buttons = {},
+ hasChildren = {},
+ localstatus = { groups = {}, scrollvalue = 0 },
+ filter = false,
+ treeframe = treeframe,
+ dragger = dragger,
+ scrollbar = scrollbar,
+ border = border,
+ content = content,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ treeframe.obj, dragger.obj, scrollbar.obj = widget, widget, widget
+
+ return AceGUI:RegisterAsContainer(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-Window.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-Window.lua
new file mode 100644
index 0000000..6074e18
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIContainer-Window.lua
@@ -0,0 +1,331 @@
+local AceGUI = LibStub("AceGUI-3.0")
+
+-- Lua APIs
+local pairs, assert, type = pairs, assert, type
+
+-- WoW APIs
+local PlaySound = PlaySound
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GameFontNormal
+
+----------------
+-- Main Frame --
+----------------
+--[[
+ Events :
+ OnClose
+
+]]
+do
+ local Type = "Window"
+ local Version = 4
+
+ local function frameOnClose()
+ this.obj:Fire("OnClose")
+ end
+
+ local function closeOnClick()
+ PlaySound("gsTitleOptionExit")
+ this.obj:Hide()
+ end
+
+ local function frameOnMouseDown()
+ AceGUI:ClearFocus()
+ end
+
+ local function titleOnMouseDown()
+ this:GetParent():StartMoving()
+ AceGUI:ClearFocus()
+ end
+
+ local function frameOnMouseUp()
+ local frame = this:GetParent()
+ frame:StopMovingOrSizing()
+ local self = frame.obj
+ local status = self.status or self.localstatus
+ status.width = frame:GetWidth()
+ status.height = frame:GetHeight()
+ status.top = frame:GetTop()
+ status.left = frame:GetLeft()
+ end
+
+ local function sizerseOnMouseDown()
+ this:GetParent():StartSizing("BOTTOMRIGHT")
+ AceGUI:ClearFocus()
+ end
+
+ local function sizersOnMouseDown()
+ this:GetParent():StartSizing("BOTTOM")
+ AceGUI:ClearFocus()
+ end
+
+ local function sizereOnMouseDown()
+ this:GetParent():StartSizing("RIGHT")
+ AceGUI:ClearFocus()
+ end
+
+ local function sizerOnMouseUp()
+ this:GetParent():StopMovingOrSizing()
+ end
+
+ local function SetTitle(self,title)
+ self.titletext:SetText(title)
+ end
+
+ local function SetStatusText(self,text)
+ -- self.statustext:SetText(text)
+ end
+
+ local function Hide(self)
+ self.frame:Hide()
+ end
+
+ local function Show(self)
+ self.frame:Show()
+ end
+
+ local function OnAcquire(self)
+ self.frame:SetParent(UIParent)
+ self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
+ self:ApplyStatus()
+ self:EnableResize(true)
+ self:Show()
+ end
+
+ local function OnRelease(self)
+ self.status = nil
+ for k in pairs(self.localstatus) do
+ self.localstatus[k] = nil
+ end
+ end
+
+ -- called to set an external table to store status in
+ local function SetStatusTable(self, status)
+ assert(type(status) == "table")
+ self.status = status
+ self:ApplyStatus()
+ end
+
+ local function ApplyStatus(self)
+ local status = self.status or self.localstatus
+ local frame = self.frame
+ self:SetWidth(status.width or 700)
+ self:SetHeight(status.height or 500)
+ if status.top and status.left then
+ frame:SetPoint("TOP",UIParent,"BOTTOM",0,status.top)
+ frame:SetPoint("LEFT",UIParent,"LEFT",status.left,0)
+ else
+ frame:SetPoint("CENTER",UIParent,"CENTER")
+ end
+ end
+
+ local function OnWidthSet(self, width)
+ local content = self.content
+ local contentwidth = width - 34
+ if contentwidth < 0 then
+ contentwidth = 0
+ end
+ content:SetWidth(contentwidth)
+ content.width = contentwidth
+ end
+
+
+ local function OnHeightSet(self, height)
+ local content = self.content
+ local contentheight = height - 57
+ if contentheight < 0 then
+ contentheight = 0
+ end
+ content:SetHeight(contentheight)
+ content.height = contentheight
+ end
+
+ local function EnableResize(self, state)
+ local func = state and "Show" or "Hide"
+ self.sizer_se[func](self.sizer_se)
+ self.sizer_s[func](self.sizer_s)
+ self.sizer_e[func](self.sizer_e)
+ end
+
+ local function Constructor()
+ local frame = CreateFrame("Frame",nil,UIParent)
+ local self = {}
+ self.type = "Window"
+
+ self.Hide = Hide
+ self.Show = Show
+ self.SetTitle = SetTitle
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+ self.SetStatusText = SetStatusText
+ self.SetStatusTable = SetStatusTable
+ self.ApplyStatus = ApplyStatus
+ self.OnWidthSet = OnWidthSet
+ self.OnHeightSet = OnHeightSet
+ self.EnableResize = EnableResize
+
+ self.localstatus = {}
+
+ self.frame = frame
+ frame.obj = self
+ frame:SetWidth(700)
+ frame:SetHeight(500)
+ frame:SetPoint("CENTER",UIParent,"CENTER",0,0)
+ frame:EnableMouse()
+ frame:SetMovable(true)
+ frame:SetResizable(true)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+ frame:SetScript("OnMouseDown", frameOnMouseDown)
+
+ frame:SetScript("OnHide",frameOnClose)
+ frame:SetMinResize(240,240)
+ frame:SetToplevel(true)
+
+ local titlebg = frame:CreateTexture(nil, "BACKGROUND")
+ titlebg:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Title-Background]])
+ titlebg:SetPoint("TOPLEFT", 9, -6)
+ titlebg:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -28, -24)
+
+ local dialogbg = frame:CreateTexture(nil, "BACKGROUND")
+ dialogbg:SetTexture([[Interface\Tooltips\UI-Tooltip-Background]])
+ dialogbg:SetPoint("TOPLEFT", 8, -24)
+ dialogbg:SetPoint("BOTTOMRIGHT", -6, 8)
+ dialogbg:SetVertexColor(0, 0, 0, .75)
+
+ local topleft = frame:CreateTexture(nil, "BORDER")
+ topleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ topleft:SetWidth(64)
+ topleft:SetHeight(64)
+ topleft:SetPoint("TOPLEFT")
+ topleft:SetTexCoord(0.501953125, 0.625, 0, 1)
+
+ local topright = frame:CreateTexture(nil, "BORDER")
+ topright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ topright:SetWidth(64)
+ topright:SetHeight(64)
+ topright:SetPoint("TOPRIGHT")
+ topright:SetTexCoord(0.625, 0.75, 0, 1)
+
+ local top = frame:CreateTexture(nil, "BORDER")
+ top:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ top:SetHeight(64)
+ top:SetPoint("TOPLEFT", topleft, "TOPRIGHT")
+ top:SetPoint("TOPRIGHT", topright, "TOPLEFT")
+ top:SetTexCoord(0.25, 0.369140625, 0, 1)
+
+ local bottomleft = frame:CreateTexture(nil, "BORDER")
+ bottomleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ bottomleft:SetWidth(64)
+ bottomleft:SetHeight(64)
+ bottomleft:SetPoint("BOTTOMLEFT")
+ bottomleft:SetTexCoord(0.751953125, 0.875, 0, 1)
+
+ local bottomright = frame:CreateTexture(nil, "BORDER")
+ bottomright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ bottomright:SetWidth(64)
+ bottomright:SetHeight(64)
+ bottomright:SetPoint("BOTTOMRIGHT")
+ bottomright:SetTexCoord(0.875, 1, 0, 1)
+
+ local bottom = frame:CreateTexture(nil, "BORDER")
+ bottom:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ bottom:SetHeight(64)
+ bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT")
+ bottom:SetPoint("BOTTOMRIGHT", bottomright, "BOTTOMLEFT")
+ bottom:SetTexCoord(0.376953125, 0.498046875, 0, 1)
+
+ local left = frame:CreateTexture(nil, "BORDER")
+ left:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ left:SetWidth(64)
+ left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT")
+ left:SetPoint("BOTTOMLEFT", bottomleft, "TOPLEFT")
+ left:SetTexCoord(0.001953125, 0.125, 0, 1)
+
+ local right = frame:CreateTexture(nil, "BORDER")
+ right:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
+ right:SetWidth(64)
+ right:SetPoint("TOPRIGHT", topright, "BOTTOMRIGHT")
+ right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT")
+ right:SetTexCoord(0.1171875, 0.2421875, 0, 1)
+
+ local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
+ close:SetPoint("TOPRIGHT", 2, 1)
+ close:SetScript("OnClick", closeOnClick)
+ self.closebutton = close
+ close.obj = self
+
+ local titletext = frame:CreateFontString(nil, "ARTWORK")
+ titletext:SetFontObject(GameFontNormal)
+ titletext:SetPoint("TOPLEFT", 12, -8)
+ titletext:SetPoint("TOPRIGHT", -32, -8)
+ self.titletext = titletext
+
+ local title = CreateFrame("Button", nil, frame)
+ title:SetPoint("TOPLEFT", titlebg)
+ title:SetPoint("BOTTOMRIGHT", titlebg)
+ title:EnableMouse()
+ title:SetScript("OnMouseDown",titleOnMouseDown)
+ title:SetScript("OnMouseUp", frameOnMouseUp)
+ self.title = title
+
+ local sizer_se = CreateFrame("Frame",nil,frame)
+ sizer_se:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
+ sizer_se:SetWidth(25)
+ sizer_se:SetHeight(25)
+ sizer_se:EnableMouse()
+ sizer_se:SetScript("OnMouseDown",sizerseOnMouseDown)
+ sizer_se:SetScript("OnMouseUp", sizerOnMouseUp)
+ self.sizer_se = sizer_se
+
+ local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
+ self.line1 = line1
+ line1:SetWidth(14)
+ line1:SetHeight(14)
+ line1:SetPoint("BOTTOMRIGHT", -8, 8)
+ line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
+ local x = 0.1 * 14/17
+ line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
+
+ local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
+ self.line2 = line2
+ line2:SetWidth(8)
+ line2:SetHeight(8)
+ line2:SetPoint("BOTTOMRIGHT", -8, 8)
+ line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
+ local x = 0.1 * 8/17
+ line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
+
+ local sizer_s = CreateFrame("Frame",nil,frame)
+ sizer_s:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-25,0)
+ sizer_s:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
+ sizer_s:SetHeight(25)
+ sizer_s:EnableMouse()
+ sizer_s:SetScript("OnMouseDown",sizersOnMouseDown)
+ sizer_s:SetScript("OnMouseUp", sizerOnMouseUp)
+ self.sizer_s = sizer_s
+
+ local sizer_e = CreateFrame("Frame",nil,frame)
+ sizer_e:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,25)
+ sizer_e:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
+ sizer_e:SetWidth(25)
+ sizer_e:EnableMouse()
+ sizer_e:SetScript("OnMouseDown",sizereOnMouseDown)
+ sizer_e:SetScript("OnMouseUp", sizerOnMouseUp)
+ self.sizer_e = sizer_e
+
+ --Container Support
+ local content = CreateFrame("Frame",nil,frame)
+ self.content = content
+ content.obj = self
+ content:SetPoint("TOPLEFT",frame,"TOPLEFT",12,-32)
+ content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-12,13)
+
+ AceGUI:RegisterAsContainer(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(Type,Constructor,Version)
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Button-ElvUI.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Button-ElvUI.lua
new file mode 100644
index 0000000..a38cc7d
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Button-ElvUI.lua
@@ -0,0 +1,180 @@
+--[[-----------------------------------------------------------------------------
+Button Widget (Modified to change text color on SetDisabled method)
+Graphical Button.
+-------------------------------------------------------------------------------]]
+local Type, Version = "Button-ElvUI", 2
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs, unpack = pairs, unpack
+
+-- WoW APIs
+local _G = _G
+local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
+local IsShiftKeyDown = IsShiftKeyDown
+-- GLOBALS: GameTooltip, ElvUI
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local dragdropButton
+local function lockTooltip()
+ GameTooltip:SetOwner(UIParent, "ANCHOR_CURSOR")
+ GameTooltip:SetText(" ")
+ GameTooltip:Show()
+end
+local function dragdrop_OnMouseDown(frame, ...)
+ if frame.obj.dragOnMouseDown then
+ dragdropButton.mouseDownFrame = frame
+ dragdropButton:SetText(frame.obj.value or "Unknown")
+ dragdropButton:SetWidth(frame:GetWidth())
+ dragdropButton:SetHeight(frame:SetHeight())
+ frame.obj.dragOnMouseDown(frame, unpack(arg))
+ end
+end
+local function dragdrop_OnMouseUp(frame, ...)
+ if frame.obj.dragOnMouseUp then
+ frame:SetAlpha(1)
+ GameTooltip:Hide()
+ dragdropButton:Hide()
+ if dragdropButton.enteredFrame and dragdropButton.enteredFrame ~= frame and dragdropButton.enteredFrame:IsMouseOver() then
+ frame.obj.dragOnMouseUp(frame, unpack(arg))
+ frame.obj.ActivateMultiControl(frame.obj, unpack(arg))
+ end
+ dragdropButton.enteredFrame = nil
+ dragdropButton.mouseDownFrame = nil
+ end
+end
+local function dragdrop_OnLeave(frame, ...)
+ if frame.obj.dragOnLeave then
+ if dragdropButton.mouseDownFrame then
+ lockTooltip()
+ end
+ if frame == dragdropButton.mouseDownFrame then
+ frame:SetAlpha(0)
+ dragdropButton:Show()
+ frame.obj.dragOnLeave(frame, unpack(arg))
+ end
+ end
+end
+local function dragdrop_OnEnter(frame, ...)
+ if frame.obj.dragOnEnter and dragdropButton:IsShown() then
+ dragdropButton.enteredFrame = frame
+ lockTooltip()
+ frame.obj.dragOnEnter(frame, unpack(arg))
+ end
+end
+local function dragdrop_OnClick(frame, ...)
+ local button = unpack(arg)
+ if frame.obj.dragOnClick and button == "RightButton" then
+ frame.obj.dragOnClick(frame, unpack(arg))
+ frame.obj.ActivateMultiControl(frame.obj, unpack(arg))
+ elseif frame.obj.stateSwitchOnClick and (button == "LeftButton") and IsShiftKeyDown() then
+ frame.obj.stateSwitchOnClick(frame, unpack(arg))
+ frame.obj.ActivateMultiControl(frame.obj, unpack(arg))
+ end
+end
+
+local function Button_OnClick(frame, ...)
+ AceGUI:ClearFocus()
+ PlaySound("igMainMenuOption")
+ frame.obj:Fire("OnClick", unpack(arg))
+end
+
+local function Control_OnEnter(frame)
+ frame.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave(frame)
+ frame.obj:Fire("OnLeave")
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ -- restore default values
+ self:SetHeight(24)
+ self:SetWidth(200)
+ self:SetDisabled(false)
+ self:SetAutoWidth(false)
+ self:SetText()
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetText"] = function(self, text)
+ self.text:SetText(text)
+ if self.autoWidth then
+ self:SetWidth(self.text:GetStringWidth() + 30)
+ end
+ end,
+
+ ["SetAutoWidth"] = function(self, autoWidth)
+ self.autoWidth = autoWidth
+ if self.autoWidth then
+ self:SetWidth(self.text:GetStringWidth() + 30)
+ end
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ self.text:SetTextColor(0.4, 0.4, 0.4)
+ else
+ self.frame:Enable()
+ self.text:SetTextColor(1, 0.82, 0)
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
+ local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate")
+ frame:Hide()
+ frame:EnableMouse(true)
+ frame:RegisterForClicks("AnyUp")
+ frame:SetScript("OnClick", Button_OnClick)
+ frame:SetScript("OnEnter", Control_OnEnter)
+ frame:SetScript("OnLeave", Control_OnLeave)
+
+ -- dragdrop
+ if not dragdropButton then
+ dragdropButton = CreateFrame("Button", "ElvUIAceGUI30DragDropButton", UIParent, "UIPanelButtonTemplate")
+ dragdropButton:SetFrameStrata("TOOLTIP")
+ dragdropButton:SetFrameLevel(5)
+ dragdropButton:SetPoint('BOTTOM', GameTooltip, "BOTTOM", 0, 10)
+ dragdropButton:Hide()
+ ElvUI[1]:GetModule('Skins'):HandleButton(dragdropButton)
+ end
+ frame:HookScript("OnClick", dragdrop_OnClick)
+ frame:HookScript("OnEnter", dragdrop_OnEnter)
+ frame:HookScript("OnLeave", dragdrop_OnLeave)
+ frame:HookScript("OnMouseUp", dragdrop_OnMouseUp)
+ frame:HookScript("OnMouseDown", dragdrop_OnMouseDown)
+
+ local text = frame:GetFontString()
+ text:ClearAllPoints()
+ text:SetPoint("TOPLEFT", 15, -1)
+ text:SetPoint("BOTTOMRIGHT", -15, 1)
+ text:SetJustifyV("MIDDLE")
+
+ local widget = {
+ text = text,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Button.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Button.lua
new file mode 100644
index 0000000..59be0e3
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Button.lua
@@ -0,0 +1,106 @@
+--[[-----------------------------------------------------------------------------
+Button Widget
+Graphical Button.
+-------------------------------------------------------------------------------]]
+local Type, Version = "Button", 23
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+local AceCore = LibStub("AceCore-3.0")
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local _G = AceCore._G
+local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+-- arg1 is the button for OnClick event
+local function Button_OnClick()
+ AceGUI:ClearFocus()
+ PlaySound("igMainMenuOption")
+ this.obj:Fire("OnClick", 1, arg1)
+end
+
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ -- restore default values
+ self:SetHeight(24)
+ self:SetWidth(200)
+ self:SetDisabled(false)
+ self:SetAutoWidth(false)
+ self:SetText()
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetText"] = function(self, text)
+ self.text:SetText(text)
+ if self.autoWidth then
+ self:SetWidth(self.text:GetStringWidth() + 30)
+ end
+ end,
+
+ ["SetAutoWidth"] = function(self, autoWidth)
+ self.autoWidth = autoWidth
+ if self.autoWidth then
+ self:SetWidth(self.text:GetStringWidth() + 30)
+ end
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ else
+ self.frame:Enable()
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
+ local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate2")
+ frame:Hide()
+
+ frame:EnableMouse(true)
+ frame:SetScript("OnClick", Button_OnClick)
+ frame:SetScript("OnEnter", Control_OnEnter)
+ frame:SetScript("OnLeave", Control_OnLeave)
+
+ local text = frame:GetFontString()
+ text:ClearAllPoints()
+ text:SetPoint("TOPLEFT", 15, -1)
+ text:SetPoint("BOTTOMRIGHT", -15, 1)
+ text:SetJustifyV("MIDDLE")
+
+ local widget = {
+ text = text,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua
new file mode 100644
index 0000000..f71a6e2
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua
@@ -0,0 +1,296 @@
+--[[-----------------------------------------------------------------------------
+Checkbox Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "CheckBox", 22
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local PlaySound = PlaySound
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: SetDesaturation, GameFontHighlight
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+local function AlignImage(self)
+ local img = self.image:GetTexture()
+ self.text:ClearAllPoints()
+ if not img then
+ self.text:SetPoint("LEFT", self.checkbg, "RIGHT")
+ self.text:SetPoint("RIGHT",0,0)
+ else
+ self.text:SetPoint("LEFT", self.image,"RIGHT", 1, 0)
+ self.text:SetPoint("RIGHT",0,0)
+ end
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function CheckBox_OnMouseDown()
+ local self = this.obj
+ if not self.disabled then
+ if self.image:GetTexture() then
+ self.text:SetPoint("LEFT", self.image,"RIGHT", 2, -1)
+ else
+ self.text:SetPoint("LEFT", self.checkbg, "RIGHT", 1, -1)
+ end
+ end
+ AceGUI:ClearFocus()
+end
+
+local function CheckBox_OnMouseUp()
+
+ local self = this.obj
+ if not self.disabled then
+ self:ToggleChecked()
+
+ if self.checked then
+ PlaySound("igMainMenuOptionCheckBoxOn")
+ else -- for both nil and false (tristate)
+ PlaySound("igMainMenuOptionCheckBoxOff")
+ end
+
+ self:Fire("OnValueChanged", 1, self.checked)
+ AlignImage(self)
+ end
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetType()
+ self:SetValue(false)
+ self:SetTriState(nil)
+ -- height is calculated from the width and required space for the description
+ self:SetWidth(200)
+ self:SetImage()
+ self:SetDisabled(nil)
+ self:SetDescription(nil)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["OnWidthSet"] = function(self, width)
+ if self.desc then
+ self.desc:SetWidth(width - 30)
+ if self.desc:GetText() and self.desc:GetText() ~= "" then
+ self:SetHeight(28 + self.desc:GetHeight())
+ end
+ end
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ self.text:SetTextColor(0.5, 0.5, 0.5)
+ SetDesaturation(self.check, true)
+ if self.desc then
+ self.desc:SetTextColor(0.5, 0.5, 0.5)
+ end
+ else
+ self.frame:Enable()
+ self.text:SetTextColor(1, 1, 1)
+ if self.tristate and self.checked == nil then
+ SetDesaturation(self.check, true)
+ else
+ SetDesaturation(self.check, false)
+ end
+ if self.desc then
+ self.desc:SetTextColor(1, 1, 1)
+ end
+ end
+ end,
+
+ ["SetValue"] = function(self,value)
+ local check = self.check
+ self.checked = value
+ if value then
+ SetDesaturation(self.check, false)
+ self.check:Show()
+ else
+ --Nil is the unknown tristate value
+ if self.tristate and value == nil then
+ SetDesaturation(self.check, true)
+ self.check:Show()
+ else
+ SetDesaturation(self.check, false)
+ self.check:Hide()
+ end
+ end
+ self:SetDisabled(self.disabled)
+ end,
+
+ ["GetValue"] = function(self)
+ return self.checked
+ end,
+
+ ["SetTriState"] = function(self, enabled)
+ self.tristate = enabled
+ self:SetValue(self:GetValue())
+ end,
+
+ ["SetType"] = function(self, type)
+ local checkbg = self.checkbg
+ local check = self.check
+ local highlight = self.highlight
+
+ local size
+ if type == "radio" then
+ size = 16
+ checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
+ checkbg:SetTexCoord(0, 0.25, 0, 1)
+ check:SetTexture("Interface\\Buttons\\UI-RadioButton")
+ check:SetTexCoord(0.25, 0.5, 0, 1)
+ check:SetBlendMode("ADD")
+ highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
+ highlight:SetTexCoord(0.5, 0.75, 0, 1)
+ else
+ size = 24
+ checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
+ checkbg:SetTexCoord(0, 1, 0, 1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:SetTexCoord(0, 1, 0, 1)
+ check:SetBlendMode("BLEND")
+ highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
+ highlight:SetTexCoord(0, 1, 0, 1)
+ end
+
+ checkbg:SetHeight(size)
+ checkbg:SetWidth(size)
+ end,
+
+ ["ToggleChecked"] = function(self)
+ local value = self:GetValue()
+ if self.tristate then
+ --cycle in true, nil, false order
+ if value then
+ self:SetValue(nil)
+ elseif value == nil then
+ self:SetValue(false)
+ else
+ self:SetValue(true)
+ end
+ else
+ self:SetValue(not self:GetValue())
+ end
+ end,
+
+ ["SetLabel"] = function(self, label)
+ self.text:SetText(label)
+ end,
+
+ ["SetDescription"] = function(self, desc)
+ if desc then
+ if not self.desc then
+ local desc = self.frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
+ desc:ClearAllPoints()
+ desc:SetPoint("TOPLEFT", self.checkbg, "TOPRIGHT", 5, -21)
+ desc:SetWidth(self.frame.width - 30)
+ desc:SetJustifyH("LEFT")
+ desc:SetJustifyV("TOP")
+ self.desc = desc
+ end
+ self.desc:Show()
+ --self.text:SetFontObject(GameFontNormal)
+ self.desc:SetText(desc)
+ self:SetHeight(28 + self.desc:GetHeight())
+ else
+ if self.desc then
+ self.desc:SetText("")
+ self.desc:Hide()
+ end
+ --self.text:SetFontObject(GameFontHighlight)
+ self:SetHeight(24)
+ end
+ end,
+
+ ["SetImage"] = function(self, path, a1,a2,a3,a4,a5,a6,a7,a8)
+ local image = self.image
+ image:SetTexture(path)
+
+ if image:GetTexture() then
+ if a4 or a8 then
+ image:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8)
+ else
+ image:SetTexCoord(0, 1, 0, 1)
+ end
+ end
+ AlignImage(self)
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Button", nil, UIParent)
+ frame:Hide()
+
+ frame:EnableMouse(true)
+ frame:SetScript("OnEnter", Control_OnEnter)
+ frame:SetScript("OnLeave", Control_OnLeave)
+ frame:SetScript("OnMouseDown", CheckBox_OnMouseDown)
+ frame:SetScript("OnMouseUp", CheckBox_OnMouseUp)
+
+ local checkbg = frame:CreateTexture(nil, "ARTWORK")
+ checkbg:SetWidth(24)
+ checkbg:SetHeight(24)
+ checkbg:SetPoint("TOPLEFT",0,0)
+ checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
+
+ local check = frame:CreateTexture(nil, "OVERLAY")
+ check:SetAllPoints(checkbg)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+
+ local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
+ text:SetJustifyH("LEFT")
+ text:SetHeight(18)
+ text:SetPoint("LEFT", checkbg, "RIGHT")
+ text:SetPoint("RIGHT",0,0)
+
+ local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
+ highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
+ highlight:SetBlendMode("ADD")
+ highlight:SetAllPoints(checkbg)
+
+ local image = frame:CreateTexture(nil, "OVERLAY")
+ image:SetHeight(16)
+ image:SetWidth(16)
+ image:SetPoint("LEFT", checkbg, "RIGHT", 1, 0)
+
+ local widget = {
+ checkbg = checkbg,
+ check = check,
+ text = text,
+ highlight = highlight,
+ image = image,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua
new file mode 100644
index 0000000..8feaca4
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua
@@ -0,0 +1,187 @@
+--[[-----------------------------------------------------------------------------
+ColorPicker Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "ColorPicker", 23
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: ShowUIPanel, HideUIPanel, ColorPickerFrame, OpacitySliderFrame
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+local function ColorCallback(self, r, g, b, a, isAlpha)
+ if not self.HasAlpha then
+ a = 1
+ end
+ self:SetColor(r, g, b, a)
+ if ColorPickerFrame:IsVisible() then
+ --colorpicker is still open
+ self:Fire("OnValueChanged", 4, r, g, b, a)
+ else
+ --colorpicker is closed, color callback is first, ignore it,
+ --alpha callback is the final call after it closes so confirm now
+ if isAlpha then
+ self:Fire("OnValueConfirmed", 4, r, g, b, a)
+ end
+ end
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function ColorSwatch_OnClick()
+ HideUIPanel(ColorPickerFrame)
+ local self = this.obj
+ if not self.disabled then
+ ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
+ ColorPickerFrame:SetClampedToScreen(true)
+
+ ColorPickerFrame.func = function()
+ local r, g, b = ColorPickerFrame:GetColorRGB()
+ local a = 1 - OpacitySliderFrame:GetValue()
+ ColorCallback(self, r, g, b, a)
+ end
+
+ ColorPickerFrame.hasOpacity = self.HasAlpha
+ ColorPickerFrame.opacityFunc = function()
+ local r, g, b = ColorPickerFrame:GetColorRGB()
+ local a = 1 - OpacitySliderFrame:GetValue()
+ ColorCallback(self, r, g, b, a, true)
+ end
+
+ local r, g, b, a = self.r, self.g, self.b, self.a
+ if self.HasAlpha then
+ ColorPickerFrame.opacity = 1 - (a or 0)
+ end
+ ColorPickerFrame:SetColorRGB(r, g, b)
+
+ ColorPickerFrame.cancelFunc = function()
+ ColorCallback(self, r, g, b, a, true)
+ end
+
+ ShowUIPanel(ColorPickerFrame)
+ end
+ AceGUI:ClearFocus()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetHeight(24)
+ self:SetWidth(200)
+ self:SetHasAlpha(false)
+ self:SetColor(0, 0, 0, 1)
+ self:SetDisabled(nil)
+ self:SetLabel(nil)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetLabel"] = function(self, text)
+ self.text:SetText(text)
+ end,
+
+ ["SetColor"] = function(self, r, g, b, a)
+ self.r = r
+ self.g = g
+ self.b = b
+ self.a = a or 1
+ self.colorSwatch:SetVertexColor(r, g, b, a)
+ end,
+
+ ["SetHasAlpha"] = function(self, HasAlpha)
+ self.HasAlpha = HasAlpha
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if self.disabled then
+ self.frame:Disable()
+ self.text:SetTextColor(0.5, 0.5, 0.5)
+ else
+ self.frame:Enable()
+ self.text:SetTextColor(1, 1, 1)
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Button", nil, UIParent)
+ frame:Hide()
+
+ frame:EnableMouse(true)
+ frame:SetScript("OnEnter", Control_OnEnter)
+ frame:SetScript("OnLeave", Control_OnLeave)
+ frame:SetScript("OnClick", ColorSwatch_OnClick)
+
+ local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
+ colorSwatch:SetWidth(19)
+ colorSwatch:SetHeight(19)
+ colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
+ colorSwatch:SetPoint("LEFT",0,0)
+
+ local texture = frame:CreateTexture(nil, "BACKGROUND")
+ texture:SetWidth(16)
+ texture:SetHeight(16)
+ texture:SetTexture(1, 1, 1)
+ texture:SetPoint("CENTER", colorSwatch)
+ texture:Show()
+
+ local checkers = frame:CreateTexture(nil, "BACKGROUND")
+ checkers:SetWidth(14)
+ checkers:SetHeight(14)
+ checkers:SetTexture("Tileset\\Generic\\Checkers")
+ checkers:SetTexCoord(.25, 0, 0.5, .25)
+ checkers:SetDesaturated(true)
+ checkers:SetVertexColor(1, 1, 1, 0.75)
+ checkers:SetPoint("CENTER", colorSwatch)
+ checkers:Show()
+
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
+ text:SetHeight(24)
+ text:SetJustifyH("LEFT")
+ text:SetTextColor(1, 1, 1)
+ text:SetPoint("LEFT", colorSwatch, "RIGHT", 2, 0)
+ text:SetPoint("RIGHT",0,0)
+
+ --local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
+ --highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+ --highlight:SetBlendMode("ADD")
+ --highlight:SetAllPoints(frame)
+
+ local widget = {
+ colorSwatch = colorSwatch,
+ text = text,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua
new file mode 100644
index 0000000..eb9842a
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua
@@ -0,0 +1,465 @@
+--[[ $Id: AceGUIWidget-DropDown-Items.lua 1137 2016-05-15 10:57:36Z nevcairiel $ ]]--
+
+local AceGUI = LibStub("AceGUI-3.0")
+
+local IsLegion = false
+
+-- Lua APIs
+local assert = assert
+local tgetn = table.getn
+
+-- WoW APIs
+local PlaySound = PlaySound
+local CreateFrame = CreateFrame
+
+local function fixlevels(parent,...)
+ local i = 1
+ local child = arg[i]
+ while child do
+ child:SetFrameLevel(parent:GetFrameLevel()+1)
+ fixlevels(child, child:GetChildren())
+ i = i + 1
+ child = arg[i]
+ end
+end
+
+-- ItemBase is the base "class" for all dropdown items.
+-- Each item has to use ItemBase.Create(widgetType) to
+-- create an initial 'self' value.
+-- ItemBase will add common functions and ui event handlers.
+-- Be sure to keep basic usage when you override functions.
+
+local ItemBase = {
+ -- NOTE: The ItemBase version is added to each item's version number
+ -- to ensure proper updates on ItemBase changes.
+ -- Use at least 1000er steps.
+ version = 1000,
+ counter = 0,
+}
+
+function ItemBase.Frame_OnEnter()
+ local self = this.obj
+
+ if self.useHighlight then
+ self.highlight:Show()
+ end
+ self:Fire("OnEnter")
+
+ if self.specialOnEnter then
+ self.specialOnEnter(self)
+ end
+end
+
+function ItemBase.Frame_OnLeave()
+ local self = this.obj
+
+ self.highlight:Hide()
+ self:Fire("OnLeave")
+
+ if self.specialOnLeave then
+ self.specialOnLeave(self)
+ end
+end
+
+-- exported, AceGUI callback
+function ItemBase.OnAcquire(self)
+ self.frame:SetToplevel(true)
+ self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
+end
+
+-- exported, AceGUI callback
+function ItemBase.OnRelease(self)
+ self:SetDisabled(false)
+ self.pullout = nil
+ self.frame:SetParent(nil)
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+end
+
+-- exported
+-- NOTE: this is called by a Dropdown-Pullout.
+-- Do not call this method directly
+function ItemBase.SetPullout(self, pullout)
+ self.pullout = pullout
+
+ self.frame:SetParent(nil)
+ local itemFrame = pullout.itemFrame
+ self.frame:SetParent(itemFrame)
+ self.parent = itemFrame
+ fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
+end
+
+-- exported
+function ItemBase.SetText(self, text)
+ self.text:SetText(text or "")
+end
+
+-- exported
+function ItemBase.GetText(self)
+ return self.text:GetText()
+end
+
+-- exported
+function ItemBase.SetPoint(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ self.frame:SetPoint(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+end
+
+-- exported
+function ItemBase.Show(self)
+ self.frame:Show()
+end
+
+-- exported
+function ItemBase.Hide(self)
+ self.frame:Hide()
+end
+
+-- exported
+function ItemBase.SetDisabled(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.useHighlight = false
+ self.text:SetTextColor(.5, .5, .5)
+ else
+ self.useHighlight = true
+ self.text:SetTextColor(1, 1, 1)
+ end
+end
+
+-- exported
+-- NOTE: this is called by a Dropdown-Pullout.
+-- Do not call this method directly
+function ItemBase.SetOnLeave(self, func)
+ self.specialOnLeave = func
+end
+
+-- exported
+-- NOTE: this is called by a Dropdown-Pullout.
+-- Do not call this method directly
+function ItemBase.SetOnEnter(self, func)
+ self.specialOnEnter = func
+end
+
+function ItemBase.Create(type)
+ -- NOTE: Most of the following code is copied from AceGUI-3.0/Dropdown widget
+ local count = AceGUI:GetNextWidgetNum(type)
+ local frame = CreateFrame("Button", "AceGUI30DropDownItem"..count)
+ local self = {}
+ self.frame = frame
+ frame.obj = self
+ self.type = type
+
+ self.useHighlight = true
+
+ frame:SetHeight(17)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ local text = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
+ text:SetTextColor(1,1,1)
+ text:SetJustifyH("LEFT")
+ text:SetPoint("TOPLEFT",frame,"TOPLEFT",18,0)
+ text:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-8,0)
+ self.text = text
+
+ local highlight = frame:CreateTexture(nil, "OVERLAY")
+ highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+ highlight:SetBlendMode("ADD")
+ highlight:SetHeight(14)
+ highlight:ClearAllPoints()
+ highlight:SetPoint("RIGHT",frame,"RIGHT",-3,0)
+ highlight:SetPoint("LEFT",frame,"LEFT",5,0)
+ highlight:Hide()
+ self.highlight = highlight
+
+ local check = frame:CreateTexture("OVERLAY")
+ check:SetWidth(16)
+ check:SetHeight(16)
+ check:SetPoint("LEFT",frame,"LEFT",3,-1)
+ check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
+ check:Hide()
+ self.check = check
+
+ local sub = frame:CreateTexture("OVERLAY")
+ sub:SetWidth(16)
+ sub:SetHeight(16)
+ sub:SetPoint("RIGHT",frame,"RIGHT",-3,-1)
+ sub:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
+ sub:Hide()
+ self.sub = sub
+
+ frame:SetScript("OnEnter", ItemBase.Frame_OnEnter)
+ frame:SetScript("OnLeave", ItemBase.Frame_OnLeave)
+
+ self.OnAcquire = ItemBase.OnAcquire
+ self.OnRelease = ItemBase.OnRelease
+
+ self.SetPullout = ItemBase.SetPullout
+ self.GetText = ItemBase.GetText
+ self.SetText = ItemBase.SetText
+ self.SetDisabled = ItemBase.SetDisabled
+
+ self.SetPoint = ItemBase.SetPoint
+ self.Show = ItemBase.Show
+ self.Hide = ItemBase.Hide
+
+ self.SetOnLeave = ItemBase.SetOnLeave
+ self.SetOnEnter = ItemBase.SetOnEnter
+
+ return self
+end
+
+-- Register a dummy LibStub library to retrieve the ItemBase, so other addons can use it.
+local IBLib = LibStub:NewLibrary("AceGUI-3.0-DropDown-ItemBase", ItemBase.version)
+if IBLib then
+ IBLib.GetItemBase = function() return ItemBase end
+end
+
+--[[
+ Template for items:
+
+-- Item:
+--
+do
+ local widgetType = "Dropdown-Item-"
+ local widgetVersion = 1
+
+ local function Constructor()
+ local self = ItemBase.Create(widgetType)
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
+end
+--]]
+
+-- Item: Header
+-- A single text entry.
+-- Special: Different text color and no highlight
+do
+ local widgetType = "Dropdown-Item-Header"
+ local widgetVersion = 1
+
+ local function OnEnter(this)
+ local self = this.obj
+ self:Fire("OnEnter")
+
+ if self.specialOnEnter then
+ self.specialOnEnter(self)
+ end
+ end
+
+ local function OnLeave()
+ local self = this.obj
+ self:Fire("OnLeave")
+
+ if self.specialOnLeave then
+ self.specialOnLeave(self)
+ end
+ end
+
+ -- exported, override
+ local function SetDisabled(self, disabled)
+ ItemBase.SetDisabled(self, disabled)
+ if not disabled then
+ self.text:SetTextColor(1, 1, 0)
+ end
+ end
+
+ local function Constructor()
+ local self = ItemBase.Create(widgetType)
+
+ self.SetDisabled = SetDisabled
+
+ self.frame:SetScript("OnEnter", OnEnter)
+ self.frame:SetScript("OnLeave", OnLeave)
+
+ self.text:SetTextColor(1, 1, 0)
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
+end
+
+-- Item: Execute
+-- A simple button
+do
+ local widgetType = "Dropdown-Item-Execute"
+ local widgetVersion = 1
+
+ local function Frame_OnClick(this, button)
+ local self = this.obj
+ if self.disabled then return end
+ self:Fire("OnClick")
+ if self.pullout then
+ self.pullout:Close()
+ end
+ end
+
+ local function Constructor()
+ local self = ItemBase.Create(widgetType)
+
+ self.frame:SetScript("OnClick", Frame_OnClick)
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
+end
+
+-- Item: Toggle
+-- Some sort of checkbox for dropdown menus.
+-- Does not close the pullout on click.
+do
+ local widgetType = "Dropdown-Item-Toggle"
+ local widgetVersion = 3
+
+ local function UpdateToggle(self)
+ if self.value then
+ self.check:Show()
+ else
+ self.check:Hide()
+ end
+ end
+
+ local function OnRelease(self)
+ ItemBase.OnRelease(self)
+ self:SetValue(nil)
+ end
+
+ local function Frame_OnClick()
+ local self = this.obj
+ if self.disabled then return end
+ self.value = not self.value
+ if self.value then
+ PlaySound("igMainMenuOptionCheckBoxOn")
+ else
+ PlaySound("igMainMenuOptionCheckBoxOff")
+ end
+ UpdateToggle(self)
+ self:Fire("OnValueChanged", 1, self.value)
+ end
+
+ -- exported
+ local function SetValue(self, value)
+ self.value = value
+ UpdateToggle(self)
+ end
+
+ -- exported
+ local function GetValue(self)
+ return self.value
+ end
+
+ local function Constructor()
+ local self = ItemBase.Create(widgetType)
+
+ self.frame:SetScript("OnClick", Frame_OnClick)
+
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.OnRelease = OnRelease
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
+end
+
+-- Item: Menu
+-- Shows a submenu on mouse over
+-- Does not close the pullout on click
+do
+ local widgetType = "Dropdown-Item-Menu"
+ local widgetVersion = 2
+
+ local function OnEnter()
+ local self = this.obj
+ self:Fire("OnEnter")
+
+ if self.specialOnEnter then
+ self.specialOnEnter(self)
+ end
+
+ self.highlight:Show()
+
+ if not self.disabled and self.submenu then
+ self.submenu:Open("TOPLEFT", self.frame, "TOPRIGHT", self.pullout:GetRightBorderWidth(), 0, self.frame:GetFrameLevel() + 100)
+ end
+ end
+
+ local function OnHide()
+ local self = this.obj
+ if self.submenu then
+ self.submenu:Close()
+ end
+ end
+
+ -- exported
+ local function SetMenu(self, menu)
+ assert(menu.type == "Dropdown-Pullout")
+ self.submenu = menu
+ end
+
+ -- exported
+ local function CloseMenu(self)
+ self.submenu:Close()
+ end
+
+ local function Constructor()
+ local self = ItemBase.Create(widgetType)
+
+ self.sub:Show()
+
+ self.frame:SetScript("OnEnter", OnEnter)
+ self.frame:SetScript("OnHide", OnHide)
+
+ self.SetMenu = SetMenu
+ self.CloseMenu = CloseMenu
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
+end
+
+-- Item: Separator
+-- A single line to separate items
+do
+ local widgetType = "Dropdown-Item-Separator"
+ local widgetVersion = 2
+
+ -- exported, override
+ local function SetDisabled(self, disabled)
+ ItemBase.SetDisabled(self, disabled)
+ self.useHighlight = false
+ end
+
+ local function Constructor()
+ local self = ItemBase.Create(widgetType)
+
+ self.SetDisabled = SetDisabled
+
+ local line = self.frame:CreateTexture(nil, "OVERLAY")
+ line:SetHeight(1)
+ line:SetTexture(.5, .5, .5)
+
+ line:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
+ line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0)
+
+ self.text:Hide()
+
+ self.useHighlight = false
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua
new file mode 100644
index 0000000..24ff244
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua
@@ -0,0 +1,745 @@
+--[[ $Id: AceGUIWidget-DropDown.lua 1116 2014-10-12 08:15:46Z nevcairiel $ ]]--
+local AceGUI = LibStub("AceGUI-3.0")
+
+local AceCore = LibStub("AceCore-3.0")
+
+-- Lua APIs
+local min, max, floor = math.min, math.max, math.floor
+local pairs, ipairs, type = pairs, ipairs, type
+local tsort, tinsert, tgetn, tsetn = table.sort, table.insert, table.getn, table.setn
+
+-- WoW APIs
+local PlaySound = PlaySound
+local UIParent, CreateFrame = UIParent, CreateFrame
+local _G = AceCore._G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: CLOSE
+
+local function fixlevels(parent,...)
+ local i = 1
+ local child = arg[i]
+ while child do
+ child:SetFrameLevel(parent:GetFrameLevel()+1)
+ fixlevels(child, child:GetChildren())
+ i = i + 1
+ child = arg[i]
+ end
+end
+
+local function fixstrata(strata, parent, ...)
+ local i = 1
+ local child = arg[i]
+ parent:SetFrameStrata(strata)
+ while child do
+ fixstrata(strata, child, child:GetChildren())
+ i = i + 1
+ child = arg[i]
+ end
+end
+
+do
+ local widgetType = "Dropdown-Pullout"
+ local widgetVersion = 3
+
+ --[[ Static data ]]--
+
+ local backdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ edgeSize = 32,
+ tileSize = 32,
+ tile = true,
+ insets = { left = 11, right = 12, top = 12, bottom = 11 },
+ }
+ local sliderBackdrop = {
+ bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
+ edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
+ tile = true, tileSize = 8, edgeSize = 8,
+ insets = { left = 3, right = 3, top = 3, bottom = 3 }
+ }
+
+ local defaultWidth = 200
+ local defaultMaxHeight = 600
+
+ --[[ UI Event Handlers ]]--
+
+ -- HACK: This should be no part of the pullout, but there
+ -- is no other 'clean' way to response to any item-OnEnter
+ -- Used to close Submenus when an other item is entered
+ local function OnEnter(item)
+ local self = item.pullout
+ for k, v in ipairs(self.items) do
+ if v.CloseMenu and v ~= item then
+ v:CloseMenu()
+ end
+ end
+ end
+
+ -- See the note in Constructor() for each scroll related function
+ local function OnMouseWheel()
+ this.obj:MoveScroll(arg1)
+ end
+
+ local function OnScrollValueChanged()
+ this.obj:SetScroll(arg1)
+ end
+
+ local function OnSizeChanged()
+ this.obj:FixScroll()
+ end
+
+ --[[ Exported methods ]]--
+
+ -- exported
+ local function SetScroll(self, value)
+ local status = self.scrollStatus
+ local frame, child = self.scrollFrame, self.itemFrame
+ local height, viewheight = frame:GetHeight(), child:GetHeight()
+
+ local offset
+ if height > viewheight then
+ offset = 0
+ else
+ offset = floor((viewheight - height) / 1000 * value)
+ end
+ child:ClearAllPoints()
+ child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
+ child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
+ status.offset = offset
+ status.scrollvalue = value
+ end
+
+ -- exported
+ local function MoveScroll(self, value)
+ local status = self.scrollStatus
+ local frame, child = self.scrollFrame, self.itemFrame
+ local height, viewheight = frame:GetHeight(), child:GetHeight()
+
+ if height > viewheight then
+ self.slider:Hide()
+ else
+ self.slider:Show()
+ local diff = height - viewheight
+ local delta = 1
+ if value < 0 then
+ delta = -1
+ end
+ self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
+ end
+ end
+
+ -- exported
+ local function FixScroll(self)
+ local status = self.scrollStatus
+ local frame, child = self.scrollFrame, self.itemFrame
+ local height, viewheight = frame:GetHeight(), child:GetHeight()
+ local offset = status.offset or 0
+
+ if viewheight < height then
+ self.slider:Hide()
+ child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
+ self.slider:SetValue(0)
+ else
+ self.slider:Show()
+ local value = (offset / (viewheight - height) * 1000)
+ if value > 1000 then value = 1000 end
+ self.slider:SetValue(value)
+ self:SetScroll(value)
+ if value < 1000 then
+ child:ClearAllPoints()
+ child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
+ child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
+ status.offset = offset
+ end
+ end
+ end
+
+ -- exported, AceGUI callback
+ local function OnAcquire(self)
+ self.frame:SetParent(UIParent)
+ --self.itemFrame:SetToplevel(true)
+ end
+
+ -- exported, AceGUI callback
+ local function OnRelease(self)
+ self:Clear()
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ -- exported
+ local function AddItem(self, item)
+ tinsert(self.items, item)
+
+ local h = tgetn(self.items) * 16
+ self.itemFrame:SetHeight(h)
+ self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement
+
+ item.frame:SetPoint("LEFT", self.itemFrame, "LEFT")
+ item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT")
+
+ item:SetPullout(self)
+ item:SetOnEnter(OnEnter)
+ end
+
+ -- exported
+ local function Open(self, point, relFrame, relPoint, x, y)
+ local items = self.items
+ local frame = self.frame
+ local itemFrame = self.itemFrame
+
+ frame:SetPoint(point, relFrame, relPoint, x, y)
+
+
+ local height = 8
+ for i, item in pairs(items) do
+ if i == 1 then
+ item:SetPoint("TOP", itemFrame, "TOP", 0, -2)
+ else
+ item:SetPoint("TOP", items[i-1].frame, "BOTTOM", 0, 1)
+ end
+
+ item:Show()
+
+ height = height + 16
+ end
+ itemFrame:SetHeight(height)
+ fixstrata("TOOLTIP", frame, frame:GetChildren())
+ frame:Show()
+ self:Fire("OnOpen")
+ end
+
+ -- exported
+ local function Close(self)
+ self.frame:Hide()
+ self:Fire("OnClose")
+ end
+
+ -- exported
+ local function Clear(self)
+ local items = self.items
+ for i, item in pairs(items) do
+ AceGUI:Release(item)
+ items[i] = nil
+ end
+ tsetn(items,0)
+ end
+
+ -- exported
+ local function IterateItems(self)
+ return ipairs(self.items)
+ end
+
+ -- exported
+ local function SetHideOnLeave(self, val)
+ self.hideOnLeave = val
+ end
+
+ -- exported
+ local function SetMaxHeight(self, height)
+ self.maxHeight = height or defaultMaxHeight
+ if self.frame:GetHeight() > height then
+ self.frame:SetHeight(height)
+ elseif (self.itemFrame:GetHeight() + 34) < height then
+ self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem
+ end
+ end
+
+ -- exported
+ local function GetRightBorderWidth(self)
+ return 6 + (self.slider:IsShown() and 12 or 0)
+ end
+
+ -- exported
+ local function GetLeftBorderWidth(self)
+ return 6
+ end
+
+ --[[ Constructor ]]--
+
+ local function Constructor()
+ local count = AceGUI:GetNextWidgetNum(widgetType)
+ local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent)
+ local self = {}
+ self.count = count
+ self.type = widgetType
+ self.frame = frame
+ frame.obj = self
+
+ self.OnAcquire = OnAcquire
+ self.OnRelease = OnRelease
+
+ self.AddItem = AddItem
+ self.Open = Open
+ self.Close = Close
+ self.Clear = Clear
+ self.IterateItems = IterateItems
+ self.SetHideOnLeave = SetHideOnLeave
+
+ self.SetScroll = SetScroll
+ self.MoveScroll = MoveScroll
+ self.FixScroll = FixScroll
+
+ self.SetMaxHeight = SetMaxHeight
+ self.GetRightBorderWidth = GetRightBorderWidth
+ self.GetLeftBorderWidth = GetLeftBorderWidth
+
+ self.items = {}
+
+ self.scrollStatus = {
+ scrollvalue = 0,
+ }
+
+ self.maxHeight = defaultMaxHeight
+
+ frame:SetBackdrop(backdrop)
+ frame:SetBackdropColor(0, 0, 0)
+ frame:SetFrameStrata("FULLSCREEN_DIALOG")
+ frame:SetClampedToScreen(true)
+ frame:SetWidth(defaultWidth)
+ frame:SetHeight(self.maxHeight)
+ --frame:SetToplevel(true)
+
+ -- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame
+ local scrollFrame = CreateFrame("ScrollFrame", nil, frame)
+ local itemFrame = CreateFrame("Frame", nil, scrollFrame)
+
+ self.scrollFrame = scrollFrame
+ self.itemFrame = itemFrame
+
+ scrollFrame.obj = self
+ itemFrame.obj = self
+
+ local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame)
+ slider:SetOrientation("VERTICAL")
+ slider:SetHitRectInsets(0, 0, -10, 0)
+ slider:SetBackdrop(sliderBackdrop)
+ slider:SetWidth(8)
+ slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
+ slider:SetFrameStrata("FULLSCREEN_DIALOG")
+ self.slider = slider
+ slider.obj = self
+
+ scrollFrame:SetScrollChild(itemFrame)
+ scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
+ scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
+ scrollFrame:EnableMouseWheel(true)
+ scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
+ scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
+ scrollFrame:SetToplevel(true)
+ scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
+ itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
+ itemFrame:SetHeight(400)
+ itemFrame:SetToplevel(true)
+ itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
+
+ slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
+ slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
+ slider:SetScript("OnValueChanged", OnScrollValueChanged)
+ slider:SetMinMaxValues(0, 1000)
+ slider:SetValueStep(1)
+ slider:SetValue(0)
+
+ scrollFrame:Show()
+ itemFrame:Show()
+ slider:Hide()
+
+ self:FixScroll()
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+end
+
+do
+ local widgetType = "Dropdown"
+ local widgetVersion = 30
+
+ --[[ Static data ]]--
+
+ --[[ UI event handler ]]--
+
+ local function Control_OnEnter()
+ this.obj.button:LockHighlight()
+ this.obj:Fire("OnEnter")
+ end
+
+ local function Control_OnLeave()
+ this.obj.button:UnlockHighlight()
+ this.obj:Fire("OnLeave")
+ end
+
+ local function Dropdown_OnHide()
+ local self = this.obj
+ if self.open then
+ self.pullout:Close()
+ end
+ end
+
+ local function Dropdown_TogglePullout()
+ local self = this.obj
+ PlaySound("igMainMenuOptionCheckBoxOn") -- missleading name, but the Blizzard code uses this sound
+ if self.open then
+ self.open = nil
+ self.pullout:Close()
+ AceGUI:ClearFocus()
+ else
+ self.open = true
+ self.pullout:SetWidth(self.pulloutWidth or self.frame:GetWidth())
+ self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0)
+ AceGUI:SetFocus(self)
+ end
+ end
+
+ local function OnPulloutOpen(this)
+ local self = this.userdata.obj
+ local value = self.value
+
+ if not self.multiselect then
+ for i, item in this:IterateItems() do
+ item:SetValue(item.userdata.value == value)
+ end
+ end
+
+ self.open = true
+ self:Fire("OnOpened")
+ end
+
+ local function OnPulloutClose(this)
+ local self = this.userdata.obj
+ self.open = nil
+ self:Fire("OnClosed")
+ end
+
+ local function ShowMultiText(self)
+ local text
+ for i, widget in self.pullout:IterateItems() do
+ if widget.type == "Dropdown-Item-Toggle" then
+ if widget:GetValue() then
+ if text then
+ text = text..", "..widget:GetText()
+ else
+ text = widget:GetText()
+ end
+ end
+ end
+ end
+ self:SetText(text)
+ end
+
+ local function OnItemValueChanged(this, event, _, checked)
+ local self = this.userdata.obj
+
+ if self.multiselect then
+ self:Fire("OnValueChanged", 2, this.userdata.value, checked)
+ ShowMultiText(self)
+ else
+ if checked then
+ self:SetValue(this.userdata.value)
+ self:Fire("OnValueChanged", 1, this.userdata.value)
+ this:SetValue(false)
+ else
+ self:SetValue(nil)
+ self:Fire("OnValueChanged", 1, nil)
+ this:SetValue(true)
+ end
+ if self.open then
+ self.pullout:Close()
+ end
+ end
+ end
+
+ --[[ Exported methods ]]--
+
+ -- exported, AceGUI callback
+ local function OnAcquire(self)
+ local pullout = AceGUI:Create("Dropdown-Pullout")
+ self.pullout = pullout
+ pullout.userdata.obj = self
+ pullout:SetCallback("OnClose", OnPulloutClose)
+ pullout:SetCallback("OnOpen", OnPulloutOpen)
+ self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
+ local frame = self.pullout.frame
+ fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
+
+ self:SetHeight(44)
+ self:SetWidth(200)
+ self:SetLabel()
+ self:SetPulloutWidth(nil)
+ end
+
+ -- exported, AceGUI callback
+ local function OnRelease(self)
+ if self.open then
+ self.pullout:Close()
+ end
+ AceGUI:Release(self.pullout)
+ self.pullout = nil
+
+ self:SetText("")
+ self:SetDisabled(false)
+ self:SetMultiselect(false)
+
+ self.value = nil
+ self.list = nil
+ self.open = nil
+ self.hasClose = nil
+
+ self.frame:ClearAllPoints()
+ self.frame:Hide()
+ end
+
+ -- exported
+ local function SetDisabled(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.text:SetTextColor(0.5,0.5,0.5)
+ self.button:Disable()
+ self.button_cover:Disable()
+ self.label:SetTextColor(0.5,0.5,0.5)
+ else
+ self.button:Enable()
+ self.button_cover:Enable()
+ self.label:SetTextColor(1,.82,0)
+ self.text:SetTextColor(1,1,1)
+ end
+ end
+
+ -- exported
+ local function ClearFocus(self)
+ if self.open then
+ self.pullout:Close()
+ end
+ end
+
+ -- exported
+ local function SetText(self, text)
+ self.text:SetText(text or "")
+ end
+
+ -- exported
+ local function SetLabel(self, text)
+ if text and text ~= "" then
+ self.label:SetText(text)
+ self.label:Show()
+ self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-14)
+ self:SetHeight(40)
+ self.alignoffset = 26
+ else
+ self.label:SetText("")
+ self.label:Hide()
+ self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0)
+ self:SetHeight(26)
+ self.alignoffset = 12
+ end
+ end
+
+ -- exported
+ local function SetValue(self, value)
+ if self.list then
+ self:SetText(self.list[value] or "")
+ end
+ self.value = value
+ end
+
+ -- exported
+ local function GetValue(self)
+ return self.value
+ end
+
+ -- exported
+ local function SetItemValue(self, item, value)
+ if not self.multiselect then return end
+ for i, widget in self.pullout:IterateItems() do
+ if widget.userdata.value == item then
+ if widget.SetValue then
+ widget:SetValue(value)
+ end
+ end
+ end
+ ShowMultiText(self)
+ end
+
+ -- exported
+ local function SetItemDisabled(self, item, disabled)
+ for i, widget in self.pullout:IterateItems() do
+ if widget.userdata.value == item then
+ widget:SetDisabled(disabled)
+ end
+ end
+ end
+
+ local function AddListItem(self, value, text, itemType)
+ if not itemType then itemType = "Dropdown-Item-Toggle" end
+ local exists = AceGUI:GetWidgetVersion(itemType)
+ if not exists then error(("The given item type, %q, does not exist within AceGUI-3.0"):format(tostring(itemType)), 2) end
+
+ local item = AceGUI:Create(itemType)
+ item:SetText(text)
+ item.userdata.obj = self
+ item.userdata.value = value
+ item:SetCallback("OnValueChanged", OnItemValueChanged)
+ self.pullout:AddItem(item)
+ end
+
+ local function AddCloseButton(self)
+ if not self.hasClose then
+ local close = AceGUI:Create("Dropdown-Item-Execute")
+ close:SetText(CLOSE)
+ self.pullout:AddItem(close)
+ self.hasClose = true
+ end
+ end
+
+ -- exported
+ local sortlist = {}
+ local function SetList(self, list, order, itemType)
+ self.list = list
+ self.pullout:Clear()
+ self.hasClose = nil
+ if not list then return end
+
+ if type(order) ~= "table" then
+ for v in pairs(list) do
+ tinsert(sortlist, v)
+ end
+ tsort(sortlist)
+
+ for i, key in ipairs(sortlist) do
+ AddListItem(self, key, list[key], itemType)
+ sortlist[i] = nil
+ end
+ tsetn(sortlist,0)
+ else
+ for i, key in ipairs(order) do
+ AddListItem(self, key, list[key], itemType)
+ end
+ end
+ if self.multiselect then
+ ShowMultiText(self)
+ AddCloseButton(self)
+ end
+ end
+
+ -- exported
+ local function AddItem(self, value, text, itemType)
+ if self.list then
+ self.list[value] = text
+ AddListItem(self, value, text, itemType)
+ end
+ end
+
+ -- exported
+ local function SetMultiselect(self, multi)
+ self.multiselect = multi
+ if multi then
+ ShowMultiText(self)
+ AddCloseButton(self)
+ end
+ end
+
+ -- exported
+ local function GetMultiselect(self)
+ return self.multiselect
+ end
+
+ local function SetPulloutWidth(self, width)
+ self.pulloutWidth = width
+ end
+
+ --[[ Constructor ]]--
+
+ local function Constructor()
+ local count = AceGUI:GetNextWidgetNum(widgetType)
+ local frame = CreateFrame("Frame", nil, UIParent)
+ local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate")
+
+ local self = {}
+ self.type = widgetType
+ self.frame = frame
+ self.dropdown = dropdown
+ self.count = count
+ frame.obj = self
+ dropdown.obj = self
+
+ self.OnRelease = OnRelease
+ self.OnAcquire = OnAcquire
+
+ self.ClearFocus = ClearFocus
+
+ self.SetText = SetText
+ self.SetValue = SetValue
+ self.GetValue = GetValue
+ self.SetList = SetList
+ self.SetLabel = SetLabel
+ self.SetDisabled = SetDisabled
+ self.AddItem = AddItem
+ self.SetMultiselect = SetMultiselect
+ self.GetMultiselect = GetMultiselect
+ self.SetItemValue = SetItemValue
+ self.SetItemDisabled = SetItemDisabled
+ self.SetPulloutWidth = SetPulloutWidth
+
+ self.alignoffset = 26
+
+ frame:SetScript("OnHide",Dropdown_OnHide)
+
+ dropdown:ClearAllPoints()
+ dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0)
+ dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0)
+ dropdown:SetScript("OnHide", nil)
+
+ local left = _G[dropdown:GetName() .. "Left"]
+ local middle = _G[dropdown:GetName() .. "Middle"]
+ local right = _G[dropdown:GetName() .. "Right"]
+
+ middle:ClearAllPoints()
+ right:ClearAllPoints()
+
+ middle:SetPoint("LEFT", left, "RIGHT", 0, 0)
+ middle:SetPoint("RIGHT", right, "LEFT", 0, 0)
+ right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17)
+
+ local button = _G[dropdown:GetName() .. "Button"]
+ self.button = button
+ button.obj = self
+ button:SetScript("OnEnter",Control_OnEnter)
+ button:SetScript("OnLeave",Control_OnLeave)
+ button:SetScript("OnClick",Dropdown_TogglePullout)
+
+ local button_cover = CreateFrame("BUTTON",nil,self.frame)
+ self.button_cover = button_cover
+ button_cover.obj = self
+ button_cover:SetPoint("TOPLEFT",self.frame,"BOTTOMLEFT",0,25)
+ button_cover:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT")
+ button_cover:SetScript("OnEnter",Control_OnEnter)
+ button_cover:SetScript("OnLeave",Control_OnLeave)
+ button_cover:SetScript("OnClick",Dropdown_TogglePullout)
+
+ local text = _G[dropdown:GetName() .. "Text"]
+ self.text = text
+ text.obj = self
+ text:ClearAllPoints()
+ text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2)
+ text:SetPoint("LEFT", left, "LEFT", 25, 2)
+
+ local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
+ label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
+ label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
+ label:SetJustifyH("LEFT")
+ label:SetHeight(18)
+ label:Hide()
+ self.label = label
+
+ AceGUI:RegisterAsWidget(self)
+ return self
+ end
+
+ AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
+end
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua
new file mode 100644
index 0000000..a08d937
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua
@@ -0,0 +1,367 @@
+--[[-----------------------------------------------------------------------------
+EditBox Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "EditBox", 26
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+local AceCore = LibStub("AceCore-3.0")
+local hooksecurefunc = AceCore.hooksecurefunc
+local _G = AceCore._G
+local GetCursorInfo = _G.GetCursorInfo
+
+-- Lua APIs
+local tostring, pairs = tostring, pairs
+
+-- WoW APIs
+local PlaySound = PlaySound
+local GetCursorInfo, ClearCursor, GetSpellInfo = GetCursorInfo, ClearCursor, GetSpellInfo
+local CreateFrame, UIParent = CreateFrame, UIParent
+local strlen = string.len
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: AceGUIEditBoxInsertLink, ChatFontNormal, OKAY
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+if not AceGUIEditBoxInsertLink then
+ -- upgradeable hook
+ hooksecurefunc("BankFrameItemButtonGeneric_OnClick",
+ function(button)
+ if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
+ return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(BANK_CONTAINER, this:GetID()))
+ end
+ end)
+ hooksecurefunc("ContainerFrameItemButton_OnClick",
+ function(button, ignoreModifiers)
+ if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
+ return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(this:GetParent():GetID(), this:GetID()))
+ end
+ end)
+
+ hooksecurefunc("KeyRingItemButton_OnClick",
+ function(button)
+ if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
+ return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(KEYRING_CONTAINER, this:GetID()))
+ end
+ end)
+ hooksecurefunc("LootFrameItem_OnClick",
+ function(button)
+ if button == "LeftButton" and IsShiftKeyDown() then
+ return _G.AceGUIEditBoxInsertLink(GetLootSlotLink(this.slot))
+ end
+ end)
+ hooksecurefunc("SetItemRef",
+ function(link, text, button)
+ if IsShiftKeyDown() then
+ if strsub(link,1,6) == "player" then
+ local name = strsub(link,8)
+ if name and (strlen(name) > 0) then
+ return _G.AceGUIEditBoxInsertLink(name)
+ end
+ else
+ return _G.AceGUIEditBoxInsertLink(text)
+ end
+ end
+ end)
+ hooksecurefunc("MerchantItemButton_OnClick",
+ function(button, ignoreModifiers)
+ if MerchantFrame.selectedTab == 1 and button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
+ return _G.AceGUIEditBoxInsertLink(GetMerchantItemLink(this:GetID()))
+ end
+ end)
+ hooksecurefunc("PaperDollItemSlotButton_OnClick",
+ function(button, ignoreModifiers)
+ if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
+ return _G.AceGUIEditBoxInsertLink(GetInventoryItemLink("player", this:GetID()))
+ end
+ end)
+ hooksecurefunc("QuestItem_OnClick",
+ function()
+ if IsShiftKeyDown() and this.rewardType ~= "spell" then
+ return _G.AceGUIEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
+ end
+ end)
+ hooksecurefunc("QuestRewardItem_OnClick",
+ function()
+ if IsShiftKeyDown() and this.rewardType ~= "spell" then
+ return _G.AceGUIEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
+ end
+ end)
+ hooksecurefunc("QuestLogTitleButton_OnClick",
+ function(button)
+ if IsShiftKeyDown() and (not this.isHeader) then
+ return _G.AceGUIEditBoxInsertLink(gsub(this:GetText(), " *(.*)", "%1"))
+ end
+ end)
+ hooksecurefunc("QuestLogRewardItem_OnClick",
+ function()
+ if IsShiftKeyDown() and this.rewardType ~= "spell" then
+ return _G.AceGUIEditBoxInsertLink(GetQuestLogItemLink(this.type, this:GetID()))
+ end
+ end)
+ hooksecurefunc("SpellButton_OnClick",
+ function(drag)
+ local id = SpellBook_GetSpellID(this:GetID())
+ if id <= MAX_SPELLS and (not drag) and IsShiftKeyDown() then
+ local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType)
+ if spellName and not IsSpellPassive(id, SpellBookFrame.bookType) then
+ if subSpellName and (strlen(subSpellName) > 0) then
+ _G.AceGUIEditBoxInsertLink(spellName.."("..subSpellName..")");
+ else
+ _G.AceGUIEditBoxInsertLink(spellName);
+ end
+ end
+ end
+ end)
+end
+
+function _G.AceGUIEditBoxInsertLink(text)
+ for i = 1, AceGUI:GetWidgetCount(Type) do
+ local editbox = _G["AceGUI-3.0EditBox"..i]
+ if editbox and editbox:IsVisible() and editbox.hasfocus then
+ editbox:Insert(text)
+ return true
+ end
+ end
+end
+
+local function ShowButton(self)
+ if not self.disablebutton then
+ self.button:Show()
+ self.editbox:SetTextInsets(0, 20, 3, 3)
+ end
+end
+
+local function HideButton(self)
+ self.button:Hide()
+ self.editbox:SetTextInsets(0, 0, 3, 3)
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function Frame_OnShowFocus()
+ this.obj.editbox:SetFocus()
+ this:SetScript("OnShow", nil)
+end
+
+local function EditBox_OnEscapePressed()
+ AceGUI:ClearFocus()
+end
+
+local function EditBox_OnEnterPressed()
+ local self = this.obj
+ local value = this:GetText()
+ local cancel = self:Fire("OnEnterPressed", 1, value)
+ if not cancel then
+ PlaySound("igMainMenuOptionCheckBoxOn")
+ HideButton(self)
+ end
+end
+
+local function EditBox_OnReceiveDrag()
+ if not GetCursorInfo then return end
+ local self = this.obj
+ local type, id, info = GetCursorInfo()
+ if type == "item" then
+ self:SetText(info)
+ self:Fire("OnEnterPressed", 1, info)
+ ClearCursor()
+ elseif type == "spell" then
+ local spell, rank = GetSpellName(id, info)
+ if rank ~= "" then spell = spell.."("..rank..")" end
+ self:SetText(spell)
+ self:Fire("OnEnterPressed", 1, spell)
+ ClearCursor()
+ elseif type == "macro" then
+ local name = GetMacroInfo(id)
+ self:SetText(name)
+ self:Fire("OnEnterPressed", 1, name)
+ ClearCursor()
+ end
+ HideButton(self)
+ AceGUI:ClearFocus()
+end
+
+
+local function EditBox_OnTextChanged()
+ local self = this.obj
+ local value = this:GetText()
+ if tostring(value) ~= tostring(self.lasttext) then
+ self:Fire("OnTextChanged", 1, value)
+ self.lasttext = value
+ ShowButton(self)
+ end
+end
+
+local function EditBox_OnFocusGained()
+ this.hasfocus = true
+ AceGUI:SetFocus(this.obj)
+end
+
+local function EditBox_OnFocusLost()
+ this.hasfocus = nil
+end
+
+local function Button_OnClick()
+ local editbox = this.obj.editbox
+ editbox:ClearFocus()
+ this = editbox -- Ace3v: this is kinda hack here
+ EditBox_OnEnterPressed()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ -- height is controlled by SetLabel
+ self:SetWidth(200)
+ self:SetDisabled(false)
+ self:SetLabel()
+ self:SetText()
+ self:DisableButton(false)
+ self:SetMaxLetters(0)
+ end,
+
+ ["OnRelease"] = function(self)
+ self:ClearFocus()
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.editbox:EnableMouse(false)
+ self.editbox:ClearFocus()
+ self.editbox:SetTextColor(0.5,0.5,0.5)
+ self.label:SetTextColor(0.5,0.5,0.5)
+ else
+ self.editbox:EnableMouse(true)
+ self.editbox:SetTextColor(1,1,1)
+ self.label:SetTextColor(1,.82,0)
+ end
+ end,
+
+ ["SetText"] = function(self, text)
+ self.lasttext = text or ""
+ self.editbox:SetText(text or "")
+ self.editbox:HighlightText(0)
+ HideButton(self)
+ end,
+
+ ["GetText"] = function(self, text)
+ return self.editbox:GetText()
+ end,
+
+ ["SetLabel"] = function(self, text)
+ if text and text ~= "" then
+ self.label:SetText(text)
+ self.label:Show()
+ self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
+ self:SetHeight(44)
+ self.alignoffset = 30
+ else
+ self.label:SetText("")
+ self.label:Hide()
+ self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
+ self:SetHeight(26)
+ self.alignoffset = 12
+ end
+ end,
+
+ ["DisableButton"] = function(self, disabled)
+ self.disablebutton = disabled
+ if disabled then
+ HideButton(self)
+ end
+ end,
+
+ ["SetMaxLetters"] = function (self, num)
+ self.editbox:SetMaxLetters(num or 0)
+ end,
+
+ ["ClearFocus"] = function(self)
+ self.editbox:ClearFocus()
+ self.frame:SetScript("OnShow", nil)
+ end,
+
+ ["SetFocus"] = function(self)
+ self.editbox:SetFocus()
+ if not self.frame:IsShown() then
+ self.frame:SetScript("OnShow", Frame_OnShowFocus)
+ end
+ end,
+
+ ["HighlightText"] = function(self, from, to)
+ self.editbox:HighlightText(from, to)
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local num = AceGUI:GetNextWidgetNum(Type)
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:Hide()
+
+ local editbox = CreateFrame("EditBox", "AceGUI-3.0EditBox"..num, frame, "InputBoxTemplate")
+ editbox:SetAutoFocus(false)
+ editbox:SetFontObject(ChatFontNormal)
+ editbox:SetScript("OnEnter", Control_OnEnter)
+ editbox:SetScript("OnLeave", Control_OnLeave)
+ editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
+ editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
+ editbox:SetScript("OnTextChanged", EditBox_OnTextChanged)
+ editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
+ editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
+ editbox:SetScript("OnEditFocusGained", EditBox_OnFocusGained)
+ editbox:SetScript("OnEditFocusLost", EditBox_OnFocusLost)
+ editbox:SetTextInsets(0, 0, 3, 3)
+ editbox:SetMaxLetters(256)
+ editbox:SetPoint("BOTTOMLEFT", 6, 0)
+ editbox:SetPoint("BOTTOMRIGHT", 0, 0)
+ editbox:SetHeight(19)
+
+ local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
+ label:SetPoint("TOPLEFT", 0, -2)
+ label:SetPoint("TOPRIGHT", 0, -2)
+ label:SetJustifyH("LEFT")
+ label:SetHeight(18)
+
+ local button = CreateFrame("Button", nil, editbox, "UIPanelButtonTemplate")
+ button:SetWidth(40)
+ button:SetHeight(20)
+ button:SetPoint("RIGHT", -2, 0)
+ button:SetText(OKAY)
+ button:SetScript("OnClick", Button_OnClick)
+ button:Hide()
+
+ local widget = {
+ alignoffset = 30,
+ editbox = editbox,
+ label = label,
+ button = button,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ editbox.obj, button.obj = widget, widget
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua
new file mode 100644
index 0000000..e4793a6
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua
@@ -0,0 +1,78 @@
+--[[-----------------------------------------------------------------------------
+Heading Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "Heading", 20
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetText()
+ self:SetFullWidth()
+ self:SetHeight(18)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetText"] = function(self, text)
+ self.label:SetText(text or "")
+ if text and text ~= "" then
+ self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0)
+ self.right:Show()
+ else
+ self.left:SetPoint("RIGHT", -3, 0)
+ self.right:Hide()
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:Hide()
+
+ local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
+ label:SetPoint("TOP",0,0)
+ label:SetPoint("BOTTOM",0,0)
+ label:SetJustifyH("CENTER")
+
+ local left = frame:CreateTexture(nil, "BACKGROUND")
+ left:SetHeight(8)
+ left:SetPoint("LEFT", 3, 0)
+ left:SetPoint("RIGHT", label, "LEFT", -5, 0)
+ left:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
+ left:SetTexCoord(0.81, 0.94, 0.5, 1)
+
+ local right = frame:CreateTexture(nil, "BACKGROUND")
+ right:SetHeight(8)
+ right:SetPoint("RIGHT", -3, 0)
+ right:SetPoint("LEFT", label, "RIGHT", 5, 0)
+ right:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
+ right:SetTexCoord(0.81, 0.94, 0.5, 1)
+
+ local widget = {
+ label = label,
+ left = left,
+ right = right,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua
new file mode 100644
index 0000000..c4d96fd
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua
@@ -0,0 +1,139 @@
+--[[-----------------------------------------------------------------------------
+Icon Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "Icon", 21
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs, print = pairs, print
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function Button_OnClick()
+ this.obj:Fire("OnClick", 1, arg1)
+ AceGUI:ClearFocus()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetHeight(110)
+ self:SetWidth(110)
+ self:SetLabel()
+ self:SetImage(nil)
+ self:SetImageSize(64, 64)
+ self:SetDisabled(false)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetLabel"] = function(self, text)
+ if text and text ~= "" then
+ self.label:Show()
+ self.label:SetText(text)
+ self:SetHeight(self.image:GetHeight() + 25)
+ else
+ self.label:Hide()
+ self:SetHeight(self.image:GetHeight() + 10)
+ end
+ end,
+
+ ["SetImage"] = function(self, path, a1,a2,a3,a4,a5,a6,a7,a8)
+ local image = self.image
+ image:SetTexture(path)
+
+ if image:GetTexture() then
+ if a4 or a8 then
+ image:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8)
+ else
+ image:SetTexCoord(0, 1, 0, 1)
+ end
+ end
+ end,
+
+ ["SetImageSize"] = function(self, width, height)
+ self.image:SetWidth(width)
+ self.image:SetHeight(height)
+ --self.frame:SetWidth(width + 30)
+ if self.label:IsShown() then
+ self:SetHeight(height + 25)
+ else
+ self:SetHeight(height + 10)
+ end
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.frame:Disable()
+ self.label:SetTextColor(0.5, 0.5, 0.5)
+ self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5)
+ else
+ self.frame:Enable()
+ self.label:SetTextColor(1, 1, 1)
+ self.image:SetVertexColor(1, 1, 1, 1)
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Button", nil, UIParent)
+ frame:Hide()
+
+ frame:EnableMouse(true)
+ frame:SetScript("OnEnter", Control_OnEnter)
+ frame:SetScript("OnLeave", Control_OnLeave)
+ frame:SetScript("OnClick", Button_OnClick)
+
+ local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlight")
+ label:SetPoint("BOTTOMLEFT")
+ label:SetPoint("BOTTOMRIGHT")
+ label:SetJustifyH("CENTER")
+ label:SetJustifyV("TOP")
+ label:SetHeight(18)
+
+ local image = frame:CreateTexture(nil, "BACKGROUND")
+ image:SetWidth(64)
+ image:SetHeight(64)
+ image:SetPoint("TOP", 0, -5)
+
+ local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
+ highlight:SetAllPoints(image)
+ highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
+ highlight:SetTexCoord(0, 1, 0.23, 0.77)
+ highlight:SetBlendMode("ADD")
+
+ local widget = {
+ label = label,
+ image = image,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ widget.SetText = function(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua
new file mode 100644
index 0000000..542d20d
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua
@@ -0,0 +1,100 @@
+--[[-----------------------------------------------------------------------------
+InteractiveLabel Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "InteractiveLabel", 20
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GameFontHighlightSmall
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function Label_OnClick()
+ this.obj:Fire("OnClick", 1, arg1)
+ AceGUI:ClearFocus()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:LabelOnAcquire()
+ self:SetHighlight()
+ self:SetHighlightTexCoord()
+ self:SetDisabled(false)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetHighlight"] = function(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ self.highlight:SetTexture(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ end,
+
+ ["SetHighlightTexCoord"] = function(self, a1,a2,a3,a4,a5,a6,a7,a8)
+ if a4 or a8 then
+ self.highlight:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+ else
+ self.highlight:SetTexCoord(0, 1, 0, 1)
+ end
+ end,
+
+ ["SetDisabled"] = function(self,disabled)
+ self.disabled = disabled
+ if disabled then
+ self.frame:EnableMouse(false)
+ self.label:SetTextColor(0.5, 0.5, 0.5)
+ else
+ self.frame:EnableMouse(true)
+ self.label:SetTextColor(1, 1, 1)
+ end
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ -- create a Label type that we will hijack
+ local label = AceGUI:Create("Label")
+
+ local frame = label.frame
+ frame:EnableMouse(true)
+ frame:SetScript("OnEnter", Control_OnEnter)
+ frame:SetScript("OnLeave", Control_OnLeave)
+ frame:SetScript("OnMouseDown", Label_OnClick)
+
+ local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
+ highlight:SetTexture(nil)
+ highlight:SetAllPoints()
+ highlight:SetBlendMode("ADD")
+
+ label.highlight = highlight
+ label.type = Type
+ label.LabelOnAcquire = label.OnAcquire
+ for method, func in pairs(methods) do
+ label[method] = func
+ end
+
+ return label
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
+
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua
new file mode 100644
index 0000000..3640432
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua
@@ -0,0 +1,259 @@
+--[[-----------------------------------------------------------------------------
+Keybinding Widget
+Set Keybindings in the Config UI.
+-------------------------------------------------------------------------------]]
+local Type, Version = "Keybinding", 25
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local pairs = pairs
+
+-- WoW APIs
+local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: NOT_BOUND
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function Keybinding_OnHide()
+ local self = this.obj
+ this:EnableKeyboard(false)
+ this:EnableMouseWheel(false)
+ self.msgframe:Hide()
+ this:UnlockHighlight()
+ self.waitingForKey = nil
+end
+
+local ignoreKeys = {
+ ["BUTTON1"] = true, ["BUTTON2"] = true,
+ ["UNKNOWN"] = true,
+ ["SHIFT"] = true, ["CTRL"] = true, ["ALT"] = true,
+}
+local function Keybinding_OnKeyDown()
+ local self = this.obj
+ if self.waitingForKey then
+ local keyPressed = arg1
+ if keyPressed == "ESCAPE" then
+ keyPressed = ""
+ else
+ if ignoreKeys[keyPressed] then return end
+ if IsShiftKeyDown() then
+ keyPressed = "SHIFT-"..keyPressed
+ end
+ if IsControlKeyDown() then
+ keyPressed = "CTRL-"..keyPressed
+ end
+ if IsAltKeyDown() then
+ keyPressed = "ALT-"..keyPressed
+ end
+ end
+
+ this:EnableKeyboard(false)
+ this:EnableMouseWheel(false)
+ self.msgframe:Hide()
+ this:UnlockHighlight()
+ self.waitingForKey = nil
+
+ if not self.disabled then
+ self:SetKey(keyPressed)
+ self:Fire("OnKeyChanged", 1, keyPressed)
+ end
+ end
+end
+
+local function Keybinding_OnMouseDown()
+ getglobal(this:GetName().."Left"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
+ getglobal(this:GetName().."Middle"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
+ getglobal(this:GetName().."Right"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
+end
+
+local function Keybinding_OnMouseUp()
+ getglobal(this:GetName().."Left"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
+ getglobal(this:GetName().."Middle"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
+ getglobal(this:GetName().."Right"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
+ local self = this.obj
+ if MouseIsOver(this) and not self.disabled then
+ if self.waitingForKey then
+ if arg1 ~= "LeftButton" and arg1 ~= "RightButton" then
+ Keybinding_OnKeyDown()
+ end
+ this:EnableKeyboard(false)
+ this:EnableMouseWheel(false)
+ self.msgframe:Hide()
+ this:UnlockHighlight()
+ self.waitingForKey = nil
+ else
+ this:EnableKeyboard(true)
+ this:EnableMouseWheel(true)
+ self.msgframe:Show()
+ this:LockHighlight()
+ self.waitingForKey = true
+ end
+ end
+ AceGUI:ClearFocus()
+end
+
+local function Keybinding_OnMouseWheel()
+ if arg1 >= 0 then
+ arg1 = "MOUSEWHEELUP"
+ else
+ arg1 = "MOUSEWHEELDOWN"
+ end
+ Keybinding_OnKeyDown()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetWidth(200)
+ self:SetLabel("")
+ self:SetKey("")
+ self.waitingForKey = nil
+ self.msgframe:Hide()
+ self:SetDisabled(false)
+ self.button:EnableKeyboard(false)
+ self.button:EnableMouseWheel(false)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.button:Disable()
+ self.label:SetTextColor(0.5,0.5,0.5)
+ else
+ self.button:Enable()
+ self.label:SetTextColor(1,1,1)
+ end
+ end,
+
+ ["SetKey"] = function(self, key)
+ if (key or "") == "" then
+ self.button:SetText(NOT_BOUND)
+ self.text:SetFontObject("GameFontNormal")
+ else
+ self.button:SetText(key)
+ self.text:SetFontObject("GameFontHighlight")
+ end
+ end,
+
+ ["GetKey"] = function(self)
+ local key = self.button:GetText()
+ if key == NOT_BOUND then
+ key = nil
+ end
+ return key
+ end,
+
+ ["SetLabel"] = function(self, label)
+ self.label:SetText(label or "")
+ if (label or "") == "" then
+ self.alignoffset = nil
+ self:SetHeight(24)
+ else
+ self.alignoffset = 30
+ self:SetHeight(44)
+ end
+ end,
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+
+local ControlBackdrop = {
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true, tileSize = 16, edgeSize = 16,
+ insets = { left = 3, right = 3, top = 3, bottom = 3 }
+}
+
+local function keybindingMsgFixWidth()
+ this:SetWidth(this.msg:GetWidth() + 10)
+ this:SetScript("OnUpdate", nil)
+end
+
+local function Constructor()
+ local name = "AceGUI30KeybindingButton" .. AceGUI:GetNextWidgetNum(Type)
+
+ local frame = CreateFrame("Frame", nil, UIParent)
+ local button = CreateFrame("Button", name, frame, "UIPanelButtonTemplate2")
+
+ button:EnableMouse(true)
+ button:EnableMouseWheel(false)
+ button:SetScript("OnEnter", Control_OnEnter)
+ button:SetScript("OnLeave", Control_OnLeave)
+
+ button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
+ button:RegisterForClicks("AnyDown","AnyUp")
+ -- Ace3v: RegisterForClicks means OnClick will not be triggered, so use OnKeyDown and OnKeyUp
+ button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
+ button:SetScript("OnMouseUp", Keybinding_OnMouseUp)
+ button:SetScript("OnMouseWheel", Keybinding_OnMouseWheel)
+ button:SetScript("OnHide", Keybinding_OnHide)
+ button:SetPoint("BOTTOMLEFT",0,0)
+ button:SetPoint("BOTTOMRIGHT",0,0)
+ button:SetHeight(24)
+ button:EnableKeyboard(false)
+
+ local text = button:GetFontString()
+ text:SetPoint("LEFT", 7, 0)
+ text:SetPoint("RIGHT", -7, 0)
+
+ local label = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
+ label:SetPoint("TOPLEFT",0,0)
+ label:SetPoint("TOPRIGHT",0,0)
+ label:SetJustifyH("CENTER")
+ label:SetHeight(18)
+
+ local msgframe = CreateFrame("Frame", nil, UIParent)
+ msgframe:SetHeight(30)
+ msgframe:SetBackdrop(ControlBackdrop)
+ msgframe:SetBackdropColor(0,0,0)
+ msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
+ msgframe:SetFrameLevel(1000)
+ msgframe:SetToplevel(true)
+
+ local msg = msgframe:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ msg:SetText("Press a key to bind, ESC to clear the binding or click the button again to cancel.")
+ msgframe.msg = msg
+ msg:SetPoint("TOPLEFT", 5, -5)
+ msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
+ msgframe:SetPoint("BOTTOM", button, "TOP")
+ msgframe:Hide()
+
+ local widget = {
+ button = button,
+ label = label,
+ msgframe = msgframe,
+ frame = frame,
+ alignoffset = 30,
+ type = Type,
+ text = text
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ button.obj = widget
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Label.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Label.lua
new file mode 100644
index 0000000..53dd0e0
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Label.lua
@@ -0,0 +1,165 @@
+--[[-----------------------------------------------------------------------------
+Label Widget
+Displays text and optionally an icon.
+-------------------------------------------------------------------------------]]
+local Type, Version = "Label", 23
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local max, pairs = math.max, pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GameFontHighlightSmall
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+
+local function UpdateImageAnchor(self)
+ if self.resizing then return end
+ local frame = self.frame
+ local width = frame.width or frame:GetWidth() or 0
+ local image = self.image
+ local label = self.label
+ local height
+
+ label:ClearAllPoints()
+ image:ClearAllPoints()
+
+ if self.imageshown then
+ local imagewidth = image:GetWidth()
+ if (width - imagewidth) < 200 or (label:GetText() or "") == "" then
+ -- image goes on top centered when less than 200 width for the text, or if there is no text
+ image:SetPoint("TOP",0,0)
+ label:SetPoint("TOP", image, "BOTTOM")
+ label:SetPoint("LEFT",0,0)
+ label:SetWidth(width)
+ height = image:GetHeight() + label:GetHeight()
+ else
+ -- image on the left
+ image:SetPoint("TOPLEFT",0,0)
+ if image:GetHeight() > label:GetHeight() then
+ label:SetPoint("LEFT", image, "RIGHT", 4, 0)
+ else
+ label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0)
+ end
+ label:SetWidth(width - imagewidth - 4)
+ height = max(image:GetHeight(), label:GetHeight())
+ end
+ else
+ -- no image shown
+ label:SetPoint("TOPLEFT",0,0)
+ label:SetWidth(width)
+ height = label:GetHeight()
+ end
+
+ self.resizing = true
+ frame:SetHeight(height)
+ frame.height = height
+ self.resizing = nil
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ -- set the flag to stop constant size updates
+ self.resizing = true
+ -- height is set dynamically by the text and image size
+ self:SetWidth(200)
+ self:SetText()
+ self:SetImage(nil)
+ self:SetImageSize(16, 16)
+ self:SetColor()
+ self:SetFontObject()
+
+ -- reset the flag
+ self.resizing = nil
+ -- run the update explicitly
+ UpdateImageAnchor(self)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["OnWidthSet"] = function(self, width)
+ UpdateImageAnchor(self)
+ end,
+
+ ["SetText"] = function(self, text)
+ self.label:SetText(text)
+ UpdateImageAnchor(self)
+ end,
+
+ ["SetColor"] = function(self, r, g, b)
+ if not (r and g and b) then
+ r, g, b = 1, 1, 1
+ end
+ self.label:SetVertexColor(r, g, b)
+ end,
+
+ ["SetImage"] = function(self, path, a1,a2,a3,a4,a5,a6,a7,a8)
+ local image = self.image
+ image:SetTexture(path)
+
+ if image:GetTexture() then
+ self.imageshown = true
+ if a4 or a8 then
+ image:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8)
+ else
+ image:SetTexCoord(0, 1, 0, 1)
+ end
+ else
+ self.imageshown = nil
+ end
+ UpdateImageAnchor(self)
+ end,
+
+ ["SetFont"] = function(self, font, height, flags)
+ self.label:SetFont(font, height, flags)
+ end,
+
+ ["SetFontObject"] = function(self, font)
+ self:SetFont((font or GameFontHighlightSmall):GetFont())
+ end,
+
+ ["SetImageSize"] = function(self, width, height)
+ self.image:SetWidth(width)
+ self.image:SetHeight(height)
+ UpdateImageAnchor(self)
+ end,
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:Hide()
+
+ local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
+ label:SetJustifyH("LEFT")
+ label:SetJustifyV("TOP")
+
+ local image = frame:CreateTexture(nil, "BACKGROUND")
+
+ -- create widget
+ local widget = {
+ label = label,
+ image = image,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua
new file mode 100644
index 0000000..9adee87
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua
@@ -0,0 +1,475 @@
+local Type, Version = "MultiLineEditBox", 28
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+local AceCore = LibStub("AceCore-3.0")
+local hooksecurefunc = AceCore.hooksecurefunc
+
+-- Lua APIs
+local strfmt = string.format
+local pairs = pairs
+
+-- WoW APIs
+local GetCursorInfo, GetSpellInfo, ClearCursor = GetCursorInfo, GetSpellInfo, ClearCursor
+local CreateFrame, UIParent = CreateFrame, UIParent
+local _G = AceCore._G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: ACCEPT, ChatFontNormal
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+if not AceGUIMultiLineEditBoxInsertLink then
+ -- upgradeable hook
+ hooksecurefunc("BankFrameItemButtonGeneric_OnClick",
+ function(button)
+ if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(BANK_CONTAINER, this:GetID()))
+ end
+ end)
+ hooksecurefunc("ContainerFrameItemButton_OnClick",
+ function(button, ignoreModifiers)
+ if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(this:GetParent():GetID(), this:GetID()))
+ end
+ end)
+
+ hooksecurefunc("KeyRingItemButton_OnClick",
+ function(button)
+ if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(KEYRING_CONTAINER, this:GetID()))
+ end
+ end)
+ hooksecurefunc("LootFrameItem_OnClick",
+ function(button)
+ if button == "LeftButton" and IsShiftKeyDown() then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetLootSlotLink(this.slot))
+ end
+ end)
+ hooksecurefunc("SetItemRef",
+ function(link, text, button)
+ if IsShiftKeyDown() then
+ if strsub(link,1,6) == "player" then
+ local name = strsub(link,8)
+ if name and (strlen(name) > 0) then
+ return _G.AceGUIMultiLineEditBoxInsertLink(name)
+ end
+ else
+ return _G.AceGUIMultiLineEditBoxInsertLink(text)
+ end
+ end
+ end)
+ hooksecurefunc("MerchantItemButton_OnClick",
+ function(button, ignoreModifiers)
+ if MerchantFrame.selectedTab == 1 and button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetMerchantItemLink(this:GetID()))
+ end
+ end)
+ hooksecurefunc("PaperDollItemSlotButton_OnClick",
+ function(button, ignoreModifiers)
+ if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetInventoryItemLink("player", this:GetID()))
+ end
+ end)
+ hooksecurefunc("QuestItem_OnClick",
+ function()
+ if IsShiftKeyDown() and this.rewardType ~= "spell" then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
+ end
+ end)
+ hooksecurefunc("QuestRewardItem_OnClick",
+ function()
+ if IsShiftKeyDown() and this.rewardType ~= "spell" then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
+ end
+ end)
+ hooksecurefunc("QuestLogTitleButton_OnClick",
+ function(button)
+ if IsShiftKeyDown() and (not this.isHeader) then
+ return _G.AceGUIMultiLineEditBoxInsertLink(gsub(this:GetText(), " *(.*)", "%1"))
+ end
+ end)
+ hooksecurefunc("QuestLogRewardItem_OnClick",
+ function()
+ if IsShiftKeyDown() and this.rewardType ~= "spell" then
+ return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestLogItemLink(this.type, this:GetID()))
+ end
+ end)
+ hooksecurefunc("SpellButton_OnClick",
+ function(drag)
+ local id = SpellBook_GetSpellID(this:GetID())
+ if id <= MAX_SPELLS and (not drag) and IsShiftKeyDown() then
+ local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType)
+ if spellName and not IsSpellPassive(id, SpellBookFrame.bookType) then
+ if subSpellName and (strlen(subSpellName) > 0) then
+ _G.AceGUIMultiLineEditBoxInsertLink(spellName.."("..subSpellName..")");
+ else
+ _G.AceGUIMultiLineEditBoxInsertLink(spellName);
+ end
+ end
+ end
+ end)
+end
+
+function _G.AceGUIMultiLineEditBoxInsertLink(text)
+ for i = 1, AceGUI:GetWidgetCount(Type) do
+ local editbox = _G[strfmt("MultiLineEditBox%uEdit",i)]
+ if editbox and editbox:IsVisible() and editbox.hasfocus then
+ editbox:Insert(text)
+ return true
+ end
+ end
+end
+
+local function Layout(self)
+ self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)
+
+ if self.labelHeight == 0 then
+ self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
+ else
+ self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
+ end
+
+ if self.disablebutton then
+ self.scrollBar:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 21)
+ self.scrollBG:SetPoint("BOTTOMLEFT", 0, 4)
+ else
+ self.scrollBar:SetPoint("BOTTOM", self.button, "TOP", 0, 18)
+ self.scrollBG:SetPoint("BOTTOMLEFT", self.button, "TOPLEFT")
+ end
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function OnClick() -- Button
+ local self = this.obj
+ self.editBox:ClearFocus()
+ if not self:Fire("OnEnterPressed", 1, self.editBox:GetText()) then
+ self.button:Disable()
+ end
+end
+
+local function OnCursorChanged() -- EditBox
+
+ local self, y = this.obj.scrollFrame, -arg2
+ local offset = self:GetVerticalScroll()
+ if y < offset then
+ self:SetVerticalScroll(y)
+ else
+ y = y + arg4 - self:GetHeight()
+ if y > offset then
+ self:SetVerticalScroll(y)
+ end
+ end
+end
+
+local function OnEditFocusLost() -- EditBox
+ this.hasfocus = nil
+ this:HighlightText(0, 0)
+ this.obj:Fire("OnEditFocusLost")
+end
+
+local function OnEnter() -- EditBox / ScrollFrame
+ local self = this.obj
+ if not self.entered then
+ self.entered = true
+ self:Fire("OnEnter")
+ end
+end
+
+local function OnLeave() -- EditBox / ScrollFrame
+ local self = this.obj
+ if self.entered then
+ self.entered = nil
+ self:Fire("OnLeave")
+ end
+end
+
+local function OnMouseUp() -- ScrollFrame
+ local self = this.obj.editBox
+ self:SetFocus()
+ local n = self:GetNumLetters()
+ self:HighlightText(n,n)
+end
+
+local function OnReceiveDrag() -- EditBox / ScrollFrame
+ if not GetCursorInfo then return end
+ local type, id, info = GetCursorInfo()
+ if type == "spell" then
+ local spell, rank = GetSpellName(id, info)
+ if rank ~= "" then spell = spell.."("..rank..")" end
+ info = spell
+ elseif type ~= "item" then
+ return
+ end
+ ClearCursor()
+ local self = this.obj
+ local editBox = self.editBox
+ if not this.hasfocus then
+ this.hasfocus = true
+ editBox:SetFocus()
+ local n = editBox:GetNumLetters()
+ editBox:HighlightText(n,n)
+ end
+ editBox:Insert(info)
+ self.button:Enable()
+end
+
+local function OnSizeChanged() -- ScrollFrame
+ this.obj.editBox:SetWidth(arg1)
+end
+
+local function OnTextChanged() -- EditBox
+ local self = this.obj
+ local value = this:GetText()
+ if tostring(value) ~= tostring(self.lasttext) then
+ self:Fire("OnTextChanged", 1, value)
+ self.lasttext = value
+ self.button:Enable()
+ end
+end
+
+local function OnTextSet() -- EditBox
+ this:HighlightText(0, 0)
+ this.obj.button:Disable()
+end
+
+local function OnVerticalScroll() -- ScrollFrame
+ local self = this.obj
+ local editBox = self.editBox
+ editBox:SetHitRectInsets(0, 0, arg1, editBox:GetHeight() - arg1 - this:GetHeight())
+
+ self.scrollFrame:SetScrollChild(self.editBox)
+ self.editBox:SetPoint("TOPLEFT",0,arg1)
+ self.editBox:SetPoint("TOPRIGHT",0,arg1)
+end
+
+local function OnShowFocus()
+ this.obj.editBox:SetFocus()
+ this:SetScript("OnShow", nil)
+end
+
+local function OnEditFocusGained()
+ this.hasfocus = true
+ AceGUI:SetFocus(this.obj)
+ this.obj:Fire("OnEditFocusGained")
+end
+
+local function OnEscapePressed() -- EditBox
+ AceGUI:ClearFocus()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self.editBox:SetText("")
+ self:SetDisabled(false)
+ self:SetWidth(200)
+ self:DisableButton(false)
+ self:SetNumLines()
+ self.entered = nil
+ self:SetMaxLetters(0)
+ end,
+
+ ["OnRelease"] = function(self)
+ self:ClearFocus()
+ end,
+
+ ["SetDisabled"] = function(self, disabled)
+ local editBox = self.editBox
+ if disabled then
+ editBox:ClearFocus()
+ editBox:EnableMouse(false)
+ editBox:SetTextColor(0.5, 0.5, 0.5)
+ self.label:SetTextColor(0.5, 0.5, 0.5)
+ self.scrollFrame:EnableMouse(false)
+ self.button:Disable()
+ else
+ editBox:EnableMouse(true)
+ editBox:SetTextColor(1, 1, 1)
+ self.label:SetTextColor(1, 0.82, 0)
+ self.scrollFrame:EnableMouse(true)
+ end
+ end,
+
+ ["SetLabel"] = function(self, text)
+ if text and text ~= "" then
+ self.label:SetText(text)
+ if self.labelHeight ~= 10 then
+ self.labelHeight = 10
+ self.label:Show()
+ end
+ elseif self.labelHeight ~= 0 then
+ self.labelHeight = 0
+ self.label:Hide()
+ end
+ Layout(self)
+ end,
+
+ ["SetNumLines"] = function(self, value)
+ if not value or value < 4 then
+ value = 4
+ end
+ self.numlines = value
+ Layout(self)
+ end,
+
+ ["SetText"] = function(self, text)
+ self.lasttext = text or ""
+ self.editBox:SetText(text or "")
+ self.editBox:HighlightText(0)
+ self.button:Disable()
+ end,
+
+ ["GetText"] = function(self)
+ return self.editBox:GetText()
+ end,
+
+ ["SetMaxLetters"] = function (self, num)
+ self.editBox:SetMaxLetters(num or 0)
+ end,
+
+ ["DisableButton"] = function(self, disabled)
+ self.disablebutton = disabled
+ if disabled then
+ self.button:Hide()
+ else
+ self.button:Show()
+ end
+ Layout(self)
+ end,
+
+ ["ClearFocus"] = function(self)
+ self.editBox:ClearFocus()
+ self.frame:SetScript("OnShow", nil)
+ end,
+
+ ["SetFocus"] = function(self)
+ self.editBox:SetFocus()
+ if not self.frame:IsShown() then
+ self.frame:SetScript("OnShow", OnShowFocus)
+ end
+ end,
+
+ ["HighlightText"] = function(self, from, to)
+ self.editBox:HighlightText(from, to)
+ end,
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local backdrop = {
+ bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
+ edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
+ insets = { left = 4, right = 3, top = 4, bottom = 3 }
+}
+
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:Hide()
+
+ local widgetNum = AceGUI:GetNextWidgetNum(Type)
+
+ local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
+ label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
+ label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
+ label:SetJustifyH("LEFT")
+ label:SetText(ACCEPT)
+ label:SetHeight(10)
+
+ local button = CreateFrame("Button", strfmt("%s%dButton", Type, widgetNum), frame, "UIPanelButtonTemplate")
+ button:SetPoint("BOTTOMLEFT", 0, 4)
+ button:SetHeight(22)
+ button:SetWidth(label:GetStringWidth() + 24)
+ button:SetText(ACCEPT)
+ button:SetScript("OnClick", OnClick)
+ button:Disable()
+
+ local text = button:GetFontString()
+ text:ClearAllPoints()
+ text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
+ text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
+ text:SetJustifyV("MIDDLE")
+
+ local scrollBG = CreateFrame("Frame", nil, frame)
+ scrollBG:SetBackdrop(backdrop)
+ scrollBG:SetBackdropColor(0, 0, 0)
+ scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
+
+ local scrollFrame = CreateFrame("ScrollFrame", strfmt("%s%dScrollFrame", Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
+
+ local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
+ scrollBar:ClearAllPoints()
+ scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
+ scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
+ scrollBar:SetPoint("RIGHT", frame, "RIGHT")
+
+ scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
+ scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
+
+ scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
+ scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
+ scrollFrame:SetScript("OnEnter", OnEnter)
+ scrollFrame:SetScript("OnLeave", OnLeave)
+ scrollFrame:SetScript("OnMouseUp", OnMouseUp)
+ scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
+ scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
+ local old = scrollFrame:GetScript("OnVerticalScroll");
+ if old then
+ scrollFrame:SetScript("OnVerticalScroll", function()
+ old()
+ OnVerticalScroll()
+ end)
+ else
+ scrollFrame:SetScript("OnVerticalScroll", OnVerticalScroll)
+ end
+
+ local editBox = CreateFrame("EditBox", strfmt("%s%dEdit", Type, widgetNum), scrollFrame)
+ editBox:SetFontObject(ChatFontNormal)
+ editBox:SetMultiLine(true)
+ editBox:EnableMouse(true)
+ editBox:SetAutoFocus(false)
+ --editBox:SetCountInvisibleLetters(false)
+ editBox:SetScript("OnCursorChanged", OnCursorChanged)
+ editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
+ editBox:SetScript("OnEnter", OnEnter)
+ editBox:SetScript("OnEscapePressed", OnEscapePressed)
+ editBox:SetScript("OnLeave", OnLeave)
+ editBox:SetScript("OnMouseDown", OnReceiveDrag)
+ editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
+ editBox:SetScript("OnTextChanged", OnTextChanged)
+ editBox:SetScript("OnTextSet", OnTextSet)
+ editBox:SetScript("OnEditFocusGained", OnEditFocusGained)
+
+ -- Ace3v: the orders are important here
+ scrollFrame:SetScrollChild(editBox)
+ editBox:SetPoint("TOPLEFT",0,0)
+ editBox:SetPoint("TOPRIGHT",0,0)
+
+ local widget = {
+ button = button,
+ editBox = editBox,
+ frame = frame,
+ label = label,
+ labelHeight = 10,
+ numlines = 4,
+ scrollBar = scrollBar,
+ scrollBG = scrollBG,
+ scrollFrame = scrollFrame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua
new file mode 100644
index 0000000..aa26131
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua
@@ -0,0 +1,285 @@
+--[[-----------------------------------------------------------------------------
+Slider Widget
+Graphical Slider, like, for Range values.
+-------------------------------------------------------------------------------]]
+local Type, Version = "Slider", 21
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local min, max, floor, format = math.min, math.max, math.floor, string.format
+local tonumber, pairs = tonumber, pairs
+
+-- WoW APIs
+local PlaySound = PlaySound
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GameFontHighlightSmall
+
+--[[-----------------------------------------------------------------------------
+Support functions
+-------------------------------------------------------------------------------]]
+local function UpdateText(self)
+ local value = self.value or 0
+ if self.ispercent then
+ self.editbox:SetText(format("%s%%", floor(value * 1000 + 0.5) / 10))
+ else
+ self.editbox:SetText(floor(value * 100 + 0.5) / 100)
+ end
+end
+
+local function UpdateLabels(self)
+ local min, max = (self.min or 0), (self.max or 100)
+ if self.ispercent then
+ self.lowtext:SetText(format("%s%%", (min * 100)))
+ self.hightext:SetText(format("%s%%", (max * 100)))
+ else
+ self.lowtext:SetText(min)
+ self.hightext:SetText(max)
+ end
+end
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter()
+ this.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave()
+ this.obj:Fire("OnLeave")
+end
+
+local function Frame_OnMouseDown()
+ this.obj.slider:EnableMouseWheel(true)
+ AceGUI:ClearFocus()
+end
+
+local function Slider_OnValueChanged()
+ local self = this.obj
+ if not this.setup then
+ local newvalue = this:GetValue()
+ if self.step and self.step > 0 then
+ local min_value = self.min or 0
+ newvalue = floor((newvalue - min_value) / self.step + 0.5) * self.step + min_value
+ end
+ if newvalue ~= self.value and not self.disabled then
+ self.value = newvalue
+ self:Fire("OnValueChanged", 1, newvalue)
+ end
+ if self.value then
+ UpdateText(self)
+ end
+ end
+end
+
+local function Slider_OnMouseUp()
+ local self = this.obj
+ self:Fire("OnMouseUp", 1, self.value)
+end
+
+local function Slider_OnMouseWheel()
+ local self = this.obj
+ if not self.disabled then
+ local value = self.value
+ if arg1 > 0 then
+ value = min(value + (self.step or 1), self.max)
+ else
+ value = max(value - (self.step or 1), self.min)
+ end
+ self.slider:SetValue(value)
+ end
+end
+
+local function EditBox_OnEscapePressed()
+ this:ClearFocus()
+end
+
+local function EditBox_OnEnterPressed()
+ local self = this.obj
+ local value = this:GetText()
+ if self.ispercent then
+ value = value:gsub('%%', '')
+ value = tonumber(value) / 100
+ else
+ value = tonumber(value)
+ end
+
+ if value then
+ PlaySound("igMainMenuOptionCheckBoxOn")
+ self.slider:SetValue(value)
+ self:Fire("OnMouseUp", 1, value)
+ end
+end
+
+local function EditBox_OnEnter()
+ this:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
+end
+
+local function EditBox_OnLeave()
+ this:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+ ["OnAcquire"] = function(self)
+ self:SetWidth(200)
+ self:SetHeight(44)
+ self:SetDisabled(false)
+ self:SetIsPercent(nil)
+ self:SetSliderValues(0,100,1)
+ self:SetValue(0)
+ self.slider:EnableMouseWheel(false)
+ end,
+
+ -- ["OnRelease"] = nil,
+
+ ["SetDisabled"] = function(self, disabled)
+ self.disabled = disabled
+ if disabled then
+ self.slider:EnableMouse(false)
+ self.label:SetTextColor(.5, .5, .5)
+ self.hightext:SetTextColor(.5, .5, .5)
+ self.lowtext:SetTextColor(.5, .5, .5)
+ --self.valuetext:SetTextColor(.5, .5, .5)
+ self.editbox:SetTextColor(.5, .5, .5)
+ self.editbox:EnableMouse(false)
+ self.editbox:ClearFocus()
+ else
+ self.slider:EnableMouse(true)
+ self.label:SetTextColor(1, .82, 0)
+ self.hightext:SetTextColor(1, 1, 1)
+ self.lowtext:SetTextColor(1, 1, 1)
+ --self.valuetext:SetTextColor(1, 1, 1)
+ self.editbox:SetTextColor(1, 1, 1)
+ self.editbox:EnableMouse(true)
+ end
+ end,
+
+ ["SetValue"] = function(self, value)
+ self.slider.setup = true
+ self.slider:SetValue(value)
+ self.value = value
+ UpdateText(self)
+ self.slider.setup = nil
+ end,
+
+ ["GetValue"] = function(self)
+ return self.value
+ end,
+
+ ["SetLabel"] = function(self, text)
+ self.label:SetText(text)
+ end,
+
+ ["SetSliderValues"] = function(self, min, max, step)
+ local frame = self.slider
+ frame.setup = true
+ self.min = min
+ self.max = max
+ self.step = step
+ frame:SetMinMaxValues(min or 0,max or 100)
+ UpdateLabels(self)
+ frame:SetValueStep(step or 1)
+ if self.value then
+ frame:SetValue(self.value)
+ end
+ frame.setup = nil
+ end,
+
+ ["SetIsPercent"] = function(self, value)
+ self.ispercent = value
+ UpdateLabels(self)
+ UpdateText(self)
+ end
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local SliderBackdrop = {
+ bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
+ edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
+ tile = true, tileSize = 8, edgeSize = 8,
+ insets = { left = 3, right = 3, top = 6, bottom = 6 }
+}
+
+local ManualBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ tile = true, edgeSize = 1, tileSize = 5,
+}
+
+local function Constructor()
+ local frame = CreateFrame("Frame", nil, UIParent)
+
+ frame:EnableMouse(true)
+ frame:SetScript("OnMouseDown", Frame_OnMouseDown)
+
+ local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ label:SetPoint("TOPLEFT",0,0)
+ label:SetPoint("TOPRIGHT",0,0)
+ label:SetJustifyH("CENTER",0,0)
+ label:SetHeight(15)
+
+ local slider = CreateFrame("Slider", nil, frame)
+ slider:SetOrientation("HORIZONTAL")
+ slider:SetHeight(15)
+ slider:SetHitRectInsets(0, 0, -10, 0)
+ slider:SetBackdrop(SliderBackdrop)
+ slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Horizontal")
+ slider:SetPoint("TOP", label, "BOTTOM")
+ slider:SetPoint("LEFT", 3, 0)
+ slider:SetPoint("RIGHT", -3, 0)
+ slider:SetValue(0)
+ slider:SetScript("OnValueChanged",Slider_OnValueChanged)
+ slider:SetScript("OnEnter", Control_OnEnter)
+ slider:SetScript("OnLeave", Control_OnLeave)
+ slider:SetScript("OnMouseUp", Slider_OnMouseUp)
+ slider:SetScript("OnMouseWheel", Slider_OnMouseWheel)
+
+ local lowtext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+ lowtext:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 2, 3)
+
+ local hightext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+ hightext:SetPoint("TOPRIGHT", slider, "BOTTOMRIGHT", -2, 3)
+
+ local editbox = CreateFrame("EditBox", nil, frame)
+ editbox:SetAutoFocus(false)
+ editbox:SetFontObject(GameFontHighlightSmall)
+ editbox:SetPoint("TOP", slider, "BOTTOM")
+ editbox:SetHeight(14)
+ editbox:SetWidth(70)
+ editbox:SetJustifyH("CENTER")
+ editbox:EnableMouse(true)
+ editbox:SetBackdrop(ManualBackdrop)
+ editbox:SetBackdropColor(0, 0, 0, 0.5)
+ editbox:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
+ editbox:SetScript("OnEnter", EditBox_OnEnter)
+ editbox:SetScript("OnLeave", EditBox_OnLeave)
+ editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
+ editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
+
+ local widget = {
+ label = label,
+ slider = slider,
+ lowtext = lowtext,
+ hightext = hightext,
+ editbox = editbox,
+ alignoffset = 25,
+ frame = frame,
+ type = Type
+ }
+ for method, func in pairs(methods) do
+ widget[method] = func
+ end
+ slider.obj, editbox.obj = widget, widget
+
+ return AceGUI:RegisterAsWidget(widget)
+end
+
+AceGUI:RegisterWidgetType(Type,Constructor,Version)
diff --git a/ElvUI_Config/Libraries/AceGUI-3.0/widgets/widgets.xml b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/widgets.xml
new file mode 100644
index 0000000..4c67991
--- /dev/null
+++ b/ElvUI_Config/Libraries/AceGUI-3.0/widgets/widgets.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ElvUI_Config/Libraries/Load_Libraries.xml b/ElvUI_Config/Libraries/Load_Libraries.xml
new file mode 100644
index 0000000..dd05573
--- /dev/null
+++ b/ElvUI_Config/Libraries/Load_Libraries.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Chinese_Config.lua b/ElvUI_Config/Locales/Chinese_Config.lua
new file mode 100644
index 0000000..8081f0a
--- /dev/null
+++ b/ElvUI_Config/Locales/Chinese_Config.lua
@@ -0,0 +1,1130 @@
+-- Chinese localization file for zhCN.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "zhCN")
+if not L then return end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "修改动作条设定"
+L["AURAS_DESC"] = "小地图旁的光环图标设置"
+L["BAGS_DESC"] = "调整ElvUI背包设置"
+L["CHAT_DESC"] = "聊天框设置"
+L["DATATEXT_DESC"] = "设定屏幕所显示的部分信息文字"
+L["ELVUI_DESC"] = "ElvUI为一套功能完整, 可用来替换WOW原始介面的套件"
+L["NAMEPLATE_DESC"] = "修改血条设定"
+L["PANEL_DESC"] = "调整左、右聊天框的大小, 此设定将会影响对话与背包框架的大小"
+L["SKINS_DESC"] = "调整外观设定"
+L["TOGGLESKIN_DESC"] = "启用/停用此外观"
+L["TOOLTIP_DESC"] = "鼠标提示信息设定选项"
+L["UNITFRAME_DESC"] = "修改单位框架设定"
+L["SEARCH_SYNTAX_DESC"] = [[With the new addition of LibItemSearch, you now have access to much more advanced item searches. The following is a documentation of the search syntax. See the full explanation at: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Specific Searching:
+ • q:[quality] or quality:[quality]. For instance, q:epic will find all epic items.
+ • l:[level], lvl:[level] or level:[level]. For example, l:30 will find all items with level 30.
+ • t:[search], type:[search] or slot:[search]. For instance, t:weapon will find all weapons.
+ • n:[name] or name:[name]. For instance, typing n:muffins will find all items with names containing "muffins".
+ • s:[set] or set:[set]. For example, s:fire will find all items in equipment sets you have with names that start with fire.
+ • tt:[search], tip:[search] or tooltip:[search]. For instance, tt:binds will find all items that can be bound to account, on equip, or on pickup.
+
+
+Search Operators:
+ • ! : Negates a search. For example, !q:epic will find all items that are NOT epic.
+ • | : Joins two searches. Typing q:epic | t:weapon will find all items that are either epic OR weapons.
+ • & : Intersects two searches. For instance, q:epic & t:weapon will find all items that are epic AND weapons
+ • >, <, <=, => : Performs comparisons on numerical searches. For example, typing lvl: >30 will find all items with level HIGHER than 30.
+
+
+The following search keywords can also be used:
+ • soulbound, bound, bop : Bind on pickup items.
+ • bou : Bind on use items.
+ • boe : Bind on equip items.
+ • boa : Bind on account items.
+ • quest : Quest bound items.]];
+L["TEXT_FORMAT_DESC"] = [[提供一个更改文字格式的方式
+
+例如:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+生命条 / 能量条 格式:
+"current" - 当前数值
+"percent" - 百分比数值
+"current-max" - 当前数值 - 最大数值. 当当前数值等于最大数值时只显示最大数值
+"current-percent" - 当前数值 - 百分比. 当百分比为1时只显示当前数值
+"current-max-percent" - 当前数值 - 最大值 - 百分比, 当当前数值不等于最大值时显示
+"deficit" - 赤字. 当没有赤字时不显示
+
+姓名格式:
+"name:short" - 姓名显示限制于10字节内
+"name:medium" -姓名显示限制于15字节内
+"name:long" - 姓名显示限制于20字节内
+
+空白则为禁用. 如需技术支援请至 http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "动作条翻页"
+L["ActionBars"] = "动作条"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = "允许LBF来处理这个元素的皮肤"
+L["Alpha"] = "透明度"
+L["Anchor Point"] = "定位方向"
+L["Backdrop Spacing"] = "背景间距"
+L["Backdrop"] = "背景"
+L["Button Size"] = "按钮大小"
+L["Button Spacing"] = "按钮间距"
+L["Buttons Per Row"] = "每行按钮数"
+L["Buttons"] = "按钮数"
+L["Change the alpha level of the frame."] = "改变框架透明度"
+L["Color of the actionbutton when not usable."] = "动作条按键不可用时的颜色"
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "当能量不足时(如法力,怒力等)动作条按键的颜色"
+L["Color of the actionbutton when out of range."] = "当超出距离时动作条按键的颜色"
+L["Color of the actionbutton when usable."] = "动作条按键可用时的颜色"
+L["Color when the text is about to expire"] = "即将冷却完毕的数字颜色"
+L["Color when the text is in the days format."] = "以天显示的文字颜色"
+L["Color when the text is in the hours format."] = "以小时显示的文字颜色"
+L["Color when the text is in the minutes format."] = "以分显示的文字颜色"
+L["Color when the text is in the seconds format."] = "以秒显示的文字颜色"
+L["Cooldown Text"] = "冷却文字"
+L["Darken Inactive"] = "未激活时暗化"
+L["Days"] = "天"
+L["Display bind names on action buttons."] = "在动作条按钮上显示键位名称"
+L["Display cooldown text on anything with the cooldown spiral."] = "显示技能冷却时间"
+L["Display macro names on action buttons."] = "在动作条按钮上显示宏名称"
+L["Expiring"] = "即将冷却完毕"
+L["Global Fade Transparency"] = "全局透明渐隐"
+L["Height Multiplier"] = "高度倍增"
+L["Hours"] = "时"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = "如果不锁定动作条, 那么当你试图移动技能时你可能会在鼠标按下技能键时使用技能"
+L["Inherit Global Fade"] = "继承全局渐隐"
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = "继承全局渐隐, 鼠标悬浮、目标、焦点、损失血量、进入战斗会减低不透明度.否则会为全局透明度使用一般动作条的设置"
+L["Key Down"] = "按下施法"
+L["Keybind Mode"] = "键位设置模式"
+L["Keybind Text"] = "键位文字"
+L["LBF Support"] = "LBF支持"
+L["Low Threshold"] = "冷却时间阈值"
+L["Macro Text"] = "宏名称"
+L["Minutes"] = "分"
+L["Mouse Over"] = "鼠标滑过显示"
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "根据此值增加背景的高度或宽度. 一般用来在一个背景框里放置多条动作条"
+L["Not Usable"] = "不可用"
+L["Out of Power"] = "能量不足"
+L["Out of Range"] = "超出范围"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "重置动作条"
+L["Restore the actionbars default settings"] = "恢复此动作条的预设设定"
+L["Seconds"] = "秒"
+L["Show Empty Buttons"] = "显示空白按钮"
+L["The amount of buttons to display per row."] = "每行显示多少个按钮数"
+L["The amount of buttons to display."] = "显示多少个动作条按钮"
+L["The button you must hold down in order to drag an ability to another action button."] = "按住某个键后才能拖动动作条的按钮"
+L["The first button anchors itself to this point on the bar."] = "第一个按钮对齐动作条的方向"
+L["The size of the action buttons."] = "动作条按钮尺寸"
+L["The spacing between the backdrop and the buttons."] = "背景与按钮之间的间隙"
+L["This setting will be updated upon changing stances."] = "这个设置会在改变姿态时更新"
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "冷却时间低于此秒数后将变为红色数字, 并以小数显示, 设为-1来使其不会变为红色"
+L["Toggles the display of the actionbars backdrop."] = "切换动作条显示背景框"
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = "在非战斗, 无目标存在, 满血, 未施法, 无焦点目标存在时的不透明度"
+L["Usable"] = "可用"
+L["Visibility State"] = "可见状态"
+L["Width Multiplier"] = "宽度倍增"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[和宏写法类似, 能根据不同姿态切换动作条.
+ 例如: [combat] 2;]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[和宏写法类似, 能根据不同姿态切换动作条显示或隐藏.
+ 例如: [combat] show;hide]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = "添加一个物品或者匹配语法到屏蔽列表.符合匹配语法的物品将被忽略"
+L["Add Item or Search Syntax"] = "添加物品或者匹配语法"
+L["Adjust the width of the bag frame."] = "调整背包框架宽度"
+L["Adjust the width of the bank frame."] = "调整银行框架宽度"
+L["Ascending"] = "升序"
+L["Bag Sorting"] = "背包排序"
+L["Bag-Bar"] = "背包条"
+L["Bar Direction"] = "背包条排序方向"
+L["Blizzard Style"] = "暴雪样式"
+L["Bottom to Top"] = "底部到顶部"
+L["Button Size (Bag)"] = "背包格子尺寸"
+L["Button Size (Bank)"] = "银行背包格子尺寸"
+L["Clear Search On Close"] = "关闭时清除搜索"
+L["Condensed"] = "巨集"
+L["Descending"] = "降序"
+L["Direction the bag sorting will use to allocate the items."] = "整理背包时物品排序方向."
+L["Disable Bag Sort"] = "禁用背包排序"
+L["Disable Bank Sort"] = "禁用银行排序"
+L["Display Item Level"] = "显示物品等级"
+L["Displays item level on equippable items."] = "显示所有可装备物品的物品等级"
+L["Enable/Disable the all-in-one bag."] = "开/关整合背包"
+L["Enable/Disable the Bag-Bar."] = "启用/禁用背包条"
+L["Full"] = "满"
+L["Global"] = "全局"
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = "你可以在这里添加你想在排序中排除的物品或者匹配语法.想要移除一个物品即需要在列表中点击他们的名字"
+L["Ignored Items and Search Syntax (Global)"] = "被忽略的物品和搜索语法(全局)"
+L["Ignored Items and Search Syntax (Profile)"] = "被忽略的物品和搜索语法(配置文件)"
+L["Item Count Font"] = "物品数目字体"
+L["Item Level Threshold"] = "物品等级阈值"
+L["Item Level"] = "物品等级"
+L["Money Format"] = "金币格式"
+L["Panel Width (Bags)"] = "背包面板宽度"
+L["Panel Width (Bank)"] = "银行面板宽度"
+L["Search Syntax"] = "搜索语法"
+L["Set the size of your bag buttons."] = "设置背包按钮尺寸"
+L["Short (Whole Numbers)"] = "短(完整数字)"
+L["Short"] = "短"
+L["Smart"] = "智能"
+L["Sort Direction"] = "排列方向"
+L["Sort Inverted"] = "倒序"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "此方向决定框架是横排还是竖排"
+L["The direction that the bag frames will grow from the anchor."] = "背包框架将从此方向开始排列"
+L["The display format of the money text that is shown at the top of the main bag."] = "在主背包上方显示的金钱文字的格式"
+L["The frame is not shown unless you mouse over the frame."] = "只在鼠标移经动作列时显示"
+L["The minimum item level required for it to be shown."] = "显示的最低物品等级"
+L["The size of the individual buttons on the bag frame."] = "背包框架单个格子的尺寸"
+L["The size of the individual buttons on the bank frame."] = "银行框架单个格子的尺寸"
+L["The spacing between buttons."] = "两个按钮间的距离"
+L["Top to Bottom"] = "顶部到底部"
+L["Use coin icons instead of colored text."] = "显示硬币图标而不是颜色文字"
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "魔法增益和减法";
+L["Begin a new row or column after this many auras."] = "在这些光环旁开始新的行或列"
+L["Count xOffset"] = "计数X偏移"
+L["Count yOffset"] = "计数Y偏移"
+L["Defines how the group is sorted."] = "定义组排序方式"
+L["Defines the sort order of the selected sort method."] = "定义排序方式的排序方向"
+L["Disabled Blizzard"] = "禁用暴雪框架"
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "阈值渐隐"
+L["Index"] = "索引"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "将你自身施放的增益从整体增益之前或之后分离出来"
+L["Limit the number of rows or columns."] = "最大行数或列数"
+L["Max Wraps"] = "每行最大数"
+L["No Sorting"] = "不排序"
+L["Other's First"] = "他人光环优先"
+L["Remaining Time"] = "剩余时间"
+L["Reminder"] = true
+L["Reverse Style"] = "倒序风格"
+L["Seperate"] = "光环分离"
+L["Set the size of the individual auras."] = "设置每个光环的尺寸"
+L["Sort Method"] = "排序方式"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = "光环图标在第一个方向摆满之后会向下一个方向继续延伸"
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "冷却时间低于此秒数后将变为红色数字以小数显示, 并且图标会渐隐. 设置为-1禁用此功能"
+L["Time xOffset"] = "时间X偏移"
+L["Time yOffset"] = "时间Y偏移"
+L["Time"] = "时间"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = true;
+L["Wrap After"] = "每行行数"
+L["Your Auras First"] = "自身光环优先"
+
+--Chat
+L["Above Chat"] = "聊天框上方"
+L["Adjust the height of your right chat panel."] = "调整右聊天框的高度"
+L["Adjust the width of your right chat panel."] = "调整右聊天框的宽度"
+L["Alerts"] = "提醒"
+L["Allowed Combat Repeat"] = "战斗连续按键修复"
+L["Attempt to create URL links inside the chat."] = "在聊天框中创建超链接"
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "锁定左右聊天框架的位置.禁用此选项将允许你移动聊天框架到任意位置"
+L["Below Chat"] = "聊天框下方"
+L["Chat EditBox Position"] = "对话輸入框位置"
+L["Chat History"] = "聊天历史"
+L["Chat Timestamps"] = true
+L["Class Color Mentions"] = "职业颜色提示"
+L["Custom Timestamp Color"] = "自定义时间戳颜色"
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "鼠标悬停在链接上时显示鼠标提示"
+L["Enable the use of separate size options for the right chat panel."] = "为左右两个聊天框设置不同的材质和尺寸"
+L["Exclude Name"] = "排除名字"
+L["Excluded names will not be class colored."] = "排除的名字将不会使用职业颜色"
+L["Excluded Names"] = "排除的名字"
+L["Fade Chat"] = "对话内容渐隐"
+L["Fade Tabs No Backdrop"] = "隐藏拖出的聊天框"
+L["Fade the chat text when there is no activity."] = "渐隐聊天框内长期不活动的文字"
+L["Fade Undocked Tabs"] = "隐藏分离的聊天框"
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = "当你把一个聊天框拖出聊天背景框的时候会自动隐藏掉,注意这个聊天框并没有被删除,关闭该选项你可以重新找到它"
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = "当你把一个聊天框设置为分离状态时会自动隐藏掉,注意这个聊天框并没有被删除,关闭该选项你可以重新找到它"
+L["Font Outline"] = "字体描边"
+L["Font"] = "字体"
+L["Hide Both"] = "全部隐藏"
+L["Hyperlink Hover"] = "链接悬停"
+L["Keyword Alert"] = "关键字警报"
+L["Keywords"] = "关键字"
+L["Left Only"] = "仅显示左边"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "如果在对话信息中发现如下文字会自动上色该文字. 如果你需要添加多个词必须用逗号分开. 搜索你的名字可使用 %MYNAME%.\n\n例如:\n%MYNAME%, ElvUI, RBGs, Tank"
+L["Lock Positions"] = "锁定位置"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "记录对话历史,当你重载,登录和退出时会恢复你最后一次会话"
+L["No Alert In Combat"] = "战斗中不警报"
+L["Number of messages you scroll for each step."] = "每次滚动的聊天信息数目"
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = "当你在战斗中按下技能键时,有可能你的输入框还处于打开状态,这个功能可以在你按下技能键并且在输入框中输入下列个数字符串却没有放出技能时帮你自动关闭输入框"
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "聊天框滚动到底部所需要的滚动时间(秒)"
+L["Panel Backdrop"] = "聊天框背景"
+L["Panel Height"] = "聊天框高度"
+L["Panel Texture (Left)"] = "聊天框材质 (左)"
+L["Panel Texture (Right)"] = "聊天框材质 (右)"
+L["Panel Width"] = "聊天框宽度"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "对话编辑框位置,如果底部的信息文字被禁用的话,将会强制显示在聊天框顶部."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "单位时间(秒)内屏蔽重复对话信息, 0为禁用此功能"
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = "开启该选项使你在查看聊天历史记录时需要按住Alt+上下键,如果关闭则直接按上下键即可"
+L["Right Only"] = "仅显示右边"
+L["Right Panel Height"] = "右面板高度"
+L["Right Panel Width"] = "右面板宽度"
+L["Scroll Interval"] = "滚动间隔"
+L["Scroll Messages"] = "滚动信息数目"
+L["Separate Panel Sizes"] = "分离框体大小"
+L["Set the font outline."] = "设定字体的描边"
+L["Short Channels"] = "隐藏频道名称"
+L["Shorten the channel names in chat."] = "在对话窗口中隐藏频道名称"
+L["Show Both"] = "全部显示"
+L["Spam Interval"] = "垃圾间隔"
+L["Sticky Chat"] = "记忆对话频道"
+L["Tab Font Outline"] = "标题栏字体描边"
+L["Tab Font Size"] = "标题栏字体尺寸"
+L["Tab Font"] = "标题栏字体"
+L["Tab Panel Transparency"] = "标签面板透明"
+L["Tab Panel"] = "标签面板"
+L["Timestamp Color"] = "时间戳颜色"
+L["Toggle showing of the left and right chat panels."] = "显示/隐藏左右聊天框"
+L["Toggle the chat tab panel backdrop."] = "显示/隐藏聊天框架标签面板背景"
+L["URL Links"] = "网址链接"
+L["Use Alt Key"] = "对话历史Alt键"
+L["Use class color for the names of players when they are mentioned."] = "当玩家名字被提及时使用职业颜色"
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "当你开始输入消息时此选项的启用将会让你保留最后一次对话的频道, 如果关闭将始终使用说话频道"
+L["Whisper Alert"] = "密语警报"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[若要设定聊天框背景, 请将你希望设定为背景的档案置放于 WoW 目录底下的「Textures」资料夹中, 并指定该档名.
+
+请注意:
+- 影像尺寸建议为 256 x 128
+- 在此资料夹新增档案后, 请务必重新启动游戏.
+- 档案必须为 tga 格式.
+
+范例:Interface\AddOns\ElvUI\media\textures\copy
+
+对多数玩家来说, 较简易的方式是将 tga 档放入 WoW 资料夹中, 然后在此处输入档案名称.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "编码:"
+L["Credits"] = "呜谢"
+L["Donations:"] = "捐款:"
+L["ELVUI_CREDITS"] = "我想透过这个特别方式, 向那些协助测试、编码及透过捐款协助过我的人表达感谢, 请曾提供协助的朋友至论坛传私讯给我, 我会将你的名字添加至此处"
+L["Testing:"] = "测试:"
+
+--DataBars
+L["Current - Percent (Remaining)"] = "当前值 - 百分百(剩余)"
+L["Current - Remaining"] = "当前值 - 剩余值"
+L["DataBars"] = "数据条"
+L["Hide In Combat"] = "战斗中隐藏"
+L["Setup on-screen display of information bars."] = "设置各种数据条"
+
+--DataTexts
+L["Battleground Texts"] = "战场信息"
+L["Block Combat Click"] = "战斗中屏蔽点击"
+L["Block Combat Hover"] = "战斗中屏蔽提示"
+L["Blocks all click events while in combat."] = "战斗中禁用点击事件"
+L["Blocks datatext tooltip from showing in combat."] = "战斗中禁用鼠标提示"
+L["BottomLeftMiniPanel"] = "小地图左下内侧"
+L["BottomMiniPanel"] = "小地图底部内侧"
+L["BottomRightMiniPanel"] = "小地图右下内侧"
+L["Datatext Panel (Left)"] = "左侧信息框"
+L["Datatext Panel (Right)"] = "右侧信息框"
+L["DataTexts"] = "信息文字"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "在聊天框下显示用于信息的框架"
+L["Display minimap panels below the minimap, used for datatexts."] = "显示小地图下方的信息框"
+L["Gold Format"] = "金币格式"
+L["left"] = "左"
+L["LeftChatDataPanel"] = "左聊天框"
+L["LeftMiniPanel"] = "小地图左方"
+L["middle"] = "中"
+L["Minimap Panels"] = "小地图栏"
+L["Panel Transparency"] = "面板透明"
+L["Panels"] = "面板"
+L["right"] = "右"
+L["RightChatDataPanel"] = "右聊天框"
+L["RightMiniPanel"] = "小地图右方"
+L["Small Panels"] = "迷你面板"
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = "在信息文字中显示的金钱格式"
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "小地图左上内侧"
+L["TopMiniPanel"] = "小地图顶部内侧"
+L["TopRightMiniPanel"] = "小地图右上内侧"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "处于战场时, 在主信息文字条显示你的战场得分信息"
+L["Word Wrap"] = "自动换行"
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "如果不是同一服务器, 那他必须和你在同一队伍中"
+L["Sends your current profile to your target."] = "发送你的配置文件到当前目标"
+L["Sends your filter settings to your target."] = "发送你的过滤器配置到当前目标"
+L["Share Current Profile"] = "分享当前配置文件"
+L["Share Filters"] = "分享过滤器配置"
+L["This feature will allow you to transfer settings to other characters."] = "此功能将使你设置转移给他角色"
+L["You must be targeting a player."] = "你必须以一名玩家为目标"
+
+--Filters
+L["Reset Aura Filters"] = "重置光环过滤器" --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "自动接受邀请"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "调整仇恨条的位置于左侧或右侧信息面板"
+L["AFK Mode"] = "离开模式"
+L["Announce Interrupts"] = "打断通告"
+L["Announce when you interrupt a spell to the specified chat channel."] = "在指定对话频道通知打断信息"
+L["Attempt to support eyefinity/nvidia surround."] = "尝试支持eyefinity/nvidia surround"
+L["Auto Greed/DE"] = "自动贪婪/分解"
+L["Auto Repair"] = "自动修理"
+L["Auto Scale"] = "自动缩放"
+L["Automatically accept invites from guild/friends."] = "自动接受工会或好友的邀请"
+L["Automatically repair using the following method when visiting a merchant."] = "使用以下方式来自动修理装备"
+L["Automatically scale the User Interface based on your screen resolution"] = "依据屏幕分辨率度自动缩放介面"
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "当你满级时, 自动选择贪婪或分解绿色物品"
+L["Automatically vendor gray items when visiting a vendor."] = "当访问商人时自动出售灰色物品"
+L["Bottom Panel"] = "底部面板"
+L["Chat Bubbles Style"] = "聊天气泡样式"
+L["Chat Bubbles"] = "聊天气泡"
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = "控制像姓名版和团队框架中各数值的小数位数"
+L["Decimal Length"] = "小数位数"
+L["Direction the bar moves on gains/losses"] = "条增加/减少时的方向"
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "显示跨越屏幕底部的面板,仅仅是用于装饰."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "显示跨越屏幕顶部的面板,仅仅是用于装饰."
+L["Display battleground messages in the middle of the screen."] = "屏幕中间显示战场信息"
+L["Enable/Disable the loot frame."] = "开/关物品掉落框架"
+L["Enable/Disable the loot roll frame."] = "开/关掷骰子框架"
+L["Enables the ElvUI Raid Control panel."] = "启用ElvUI团队控制面板"
+L["Enhanced PVP Messages"] = "PVP增强信息"
+L["General"] = "一般"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = "任务框体的高度.增加大小以看到更多目标"
+L["Hide At Max Level"] = "在最高等级时隐藏"
+L["Hide Error Text"] = "隐藏错误文字"
+L["Hide In Vehicle"] = "骑乘时隐藏"
+L["Hides the red error text at the top of the screen while in combat."] = "战斗中隐藏屏幕顶部红字错误信息"
+L["Log Taints"] = "错误记录"
+L["Login Message"] = "登陆信息"
+L["Loot Roll"] = "掷骰"
+L["Loot"] = "拾取"
+L["Lowest Allowed UI Scale"] = "最低允许UI缩放"
+L["Multi-Monitor Support"] = "多显示器支持"
+L["Name Font"] = "名称字体"
+L["Number Prefix"] = "数值缩写"
+L["Party / Raid"] = "小队/团队"
+L["Party Only"] = "仅小队"
+L["Raid Only"] = "仅团队"
+L["Remove Backdrop"] = "去除背景"
+L["Reset all frames to their original positions."] = "重设所有框架至预设位置"
+L["Reset Anchors"] = "重置定位"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "发送ADDON_ACTION_BLOCKED错误至Lua错误框, 这些错误并不重要, 不会影响你的游戏体验. 并且很多这类错误无法被修复. 请只将影响游戏体验的错误发送给我们"
+L["Skin Backdrop (No Borders)"] = "美化背景(无边框)"
+L["Skin Backdrop"] = "美化背景"
+L["Skin the blizzard chat bubbles."] = "美化暴雪对话泡泡"
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "玩家头顶姓名的字体. |cffFF0000警告: 你需要重新开启游戏或重新登录才能使用此功能.|r"
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = "细边框主题会改变所有的外观,使用细边框主题会略微提升性能"
+L["Thin Border Theme"] = "细边框主题"
+L["Toggle Tutorials"] = "教学开关"
+L["Top Panel"] = "顶部面板"
+L["Version Check"] = true;
+L["Watch Frame Height"] = "任务框架高度"
+L["When you go AFK display the AFK screen."] = "当你离开时显示AFK界面"
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = "把该字体设置应用到所有ElvUI设置中去,但是某些设置并不会被改变"
+L["Applies the primary texture to all statusbars."] = "将主要材质应用到所有状态条"
+L["Apply Font To All"] = "应用字体到所有"
+L["Apply Texture To All"] = "应用材质到所有"
+L["Backdrop color of transparent frames"] = "透明框架的背景颜色"
+L["Backdrop Color"] = "背景颜色"
+L["Backdrop Faded Color"] = "背景透明色"
+L["Border Color"] = "边框颜色"
+L["Color some texts use."] = "数值(非文字)使用的颜色"
+L["Colors"] = "颜色"
+L["CombatText Font"] = "战斗文字字体"
+L["Default Font"] = "预设字体"
+L["Font Size"] = "字体大小"
+L["Fonts"] = "字体"
+L["Main backdrop color of the UI."] = "介面背景主色"
+L["Main border color of the UI."] = "UI的主要边框颜色."
+L["Media"] = "材质"
+L["Primary Texture"] = "主要材质"
+L["Replace Blizzard Fonts"] = "替代暴雪字体"
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = "用ElvUI字体设置代替暴雪原有字体设置,如果禁用有可能导致你的UI出问题,默认开启开选项"
+L["Secondary Texture"] = "次要材质"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "设定介面上所有字体的大小, 但不包含本身有独立设定的字体(如单位框架字体、信息文字字体等...)"
+L["Textures"] = "材质"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "战斗信息将使用此字体, |cffFF0000警告:需重启游戏或重新登陆才可使此变更生效.|r"
+L["The font that the core of the UI will use."] = "核心UI所使用的字体"
+L["The texture that will be used mainly for statusbars."] = "此材质主用于状态列上"
+L["This texture will get used on objects like chat windows and dropdown menus."] = "主要用于对话窗口及下拉选单等物件的材质"
+L["Value Color"] = "数值颜色"
+
+--Maps
+L["Adjust the size of the minimap."] = "调整小地图尺寸"
+L["Always Display"] = "总是显示"
+L["Bottom Left"] = "左下"
+L["Bottom Right"] = "右下"
+L["Bottom"] = "下"
+L["Change settings for the display of the location text that is on the minimap."] = "改变小地图所在位置文字的显示设置"
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = "是否启用小地图. |cffFF0000警告: 关掉后你将看不到小地图周围的信息文字.|r"
+L["Instance Difficulty"] = "副本难度"
+L["Left"] = "左"
+L["LFG Queue"] = "随机队列"
+L["Location Text"] = "所在位置"
+L["Make the world map smaller."] = "让世界地图更小"
+L["Maps"] = "地图"
+L["Minimap Buttons"] = "小地图按钮"
+L["Minimap Mouseover"] = "小地图鼠标滑过"
+L["Puts coordinates on the world map."] = "在世界地图上显示坐标"
+L["PvP Queue"] = true
+L["Reset Zoom"] = "重置缩放"
+L["Right"] = "右"
+L["Scale"] = "缩放"
+L["Smaller World Map"] = "更小的世界地图"
+L["Top Left"] = "左上"
+L["Top Right"] = "右上"
+L["Top"] = "上"
+L["World Map Coordinates"] = "世界地图坐标"
+L["X-Offset"] = "X偏移"
+L["Y-Offset"] = "Y偏移"
+
+--Misc
+L["Install"] = "安装"
+L["Run the installation process."] = "执行安装程序"
+L["Toggle Anchors"] = "切换定位开关"
+L["Unlock various elements of the UI to be repositioned."] = "解锁介面上的各种框架来更改位置"
+L["Version"] = "版本"
+
+--NamePlates
+L["# Displayed Auras"] = "显示光环的数量"
+L["Actions"] = "动作"
+L["Add Name"] = "添加名称"
+L["Add Nameplate Filter"] = "添加姓名版过滤器"
+L["Add Regular Filter"] = "添加常规过滤器"
+L["Add Special Filter"] = "添加特殊过滤器"
+L["Always Show Target Health"] = "始终显示目标血量"
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = "当增益剩余时间大于该值时应用该过滤器. 设为0以禁用."
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = "当增益剩余时间小于该值时应用该过滤器. 设为0以禁用."
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = "当减益剩余时间大于该值时应用该过滤器. 设为0以禁用."
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = "当减益剩余时间小于该值时应用该过滤器. 设为0以禁用."
+L["Background Glow"] = "背景发光"
+L["Bad Color"] = "危险颜色"
+L["Bad Scale"] = "危险缩放"
+L["Bad Transition Color"] = "危险过渡颜色"
+L["Base Height for the Aura Icon"] = "光环图标基础高度"
+L["Border Glow"] = "边框发光"
+L["Border"] = "边框"
+L["Cast Bar"] = "施法条"
+L["Cast Color"] = "施法条颜色"
+L["Cast No Interrupt Color"] = "无法打断的颜色"
+L["Cast Time Format"] = "施法时间格式"
+L["Casting"] = "施法"
+L["Channel Time Format"] = "引导法术时间格式"
+L["Clear Filter"] = "清空过滤器"
+L["Color Tanked"] = "被坦住的颜色"
+L["Control enemy nameplates toggling on or off when in combat."] = "控制战斗中敌对姓名板的开启和关闭"
+L["Control friendly nameplates toggling on or off when in combat."] = "控制战斗中友方姓名板的开启和关闭"
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = "控制显示多少光环, 这也会影响光环大小"
+L["Cooldowns"] = "冷却"
+L["Copy settings from another unit."] = "从其他框架中复制设置"
+L["Copy Settings From"] = "复制设置"
+L["Current Level"] = "当前等级"
+L["Default Settings"] = "默认设置"
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "战场或竞技场中, 为已确认为治疗的玩家标上补职图标"
+L["Elite Icon"] = "精英标志"
+L["Enable/Disable the scaling of targetted nameplates."] = "启用/禁用目标姓名板的缩放"
+L["Enabling this will check your health amount."] = "启用后将检查你的血量"
+L["Enemy Combat Toggle"] = "敌对战斗开关"
+L["Enemy NPC Frames"] = "敌对NPC"
+L["Enemy Player Frames"] = "敌对玩家"
+L["Enemy"] = "敌对"
+L["ENEMY_NPC"] = "敌对NPC"
+L["ENEMY_PLAYER"] = "敌对玩家"
+L["Filter already exists!"] = "过滤器已存在!"
+L["Filter Priority"] = "过滤器优先级"
+L["Filters Page"] = "过滤器界面"
+L["Friendly Combat Toggle"] = "友方战斗开关"
+L["Friendly NPC Frames"] = "友方NPC框架"
+L["Friendly Player Frames"] = "友方玩家框架"
+L["FRIENDLY_NPC"] = "友方NPC"
+L["FRIENDLY_PLAYER"] = "友方玩家"
+L["General Options"] = "常规选项"
+L["Good Color"] = "正常颜色"
+L["Good Scale"] = "正常缩放"
+L["Good Transition Color"] = "正常过渡颜色"
+L["Healer Icon"] = "治疗图标"
+L["Health Color"] = "血量颜色"
+L["Health Threshold"] = "血量阈值"
+L["Hide Frame"] = "隐藏框架"
+L["Hide Spell Name"] = "隐藏法术名字"
+L["Hide Time"] = "隐藏时间"
+L["Hide"] = "隐藏"
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = "在施法失败或被打断时施法条保持可见的秒数"
+L["Icon Base Height"] = "图标基础高度"
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = "启用后将会检查光环是否缺失而不是光环是否存在"
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = "启用后要求满足所有光环. 否则只要求任一光环存在即可激活."
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = "启用后要求满足所有冷却. 否则只要求任一冷却存在即可激活"
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = "启用后则过滤器仅仅在单位等级大于等于该值的时候激活"
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = "启用后则过滤器仅仅在单位等级小于等于该值的时候激活"
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = "启用后过滤器仅仅在单位等级符合该值的时候激活"
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = "启用后过滤器仅仅在单位等级符合你的等级的时候激活"
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = "启用后过滤器仅仅在单位施放可打断技能的时候激活"
+L["If enabled then the filter will only activate when you are in combat."] = "启用后过滤器仅仅在你在战斗中的时候激活"
+L["If enabled then the filter will only activate when you are out of combat."] = "启用后过滤器仅仅在你不在战斗中的时候激活"
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = "如果光环和一个数一起列出你需要用它来将其移出列表"
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = "如果列表为空, 并且'可打断'被选中, 那么过滤器会在任何可被打断的施法时激活"
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = "如果这个阈值被设置则单位的血量需要比设定值更高才会将过滤器激活. 设为0以禁用."
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = "如果这个阈值被设置则单位的血量需要比设定值更低才会将过滤器激活. 设为0以禁用."
+L["Instance Type"] = "副本类型"
+L["Interruptible"] = "可打断"
+L["Is Targeted"] = "目标"
+L["LEVEL_BOSS"] = "对首领请设置为-1, 或者设为0以禁用."
+L["Low Health Threshold"] = "低生命值阈值"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = "更低的数值意味着更高的优先级. 过滤器将按照1至100的顺序进行."
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = "姓名板在此设定值下会变黄色, 在设定值一半以下会变红色"
+L["Match Player Level"] = "符合玩家等级"
+L["Maximum Level"] = "最高等级"
+L["Maximum Time Left"] = "最高时间剩余"
+L["Minimum Level"] = "最低等级"
+L["Minimum Time Left"] = "最低时间剩余"
+L["Missing"] = "缺失"
+L["Name Color"] = "姓名颜色"
+L["Name Only"] = "仅姓名"
+L["NamePlates"] = "姓名板(血条)"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = "非目标透明度"
+L["Not Targeted"] = "非目标"
+L["Off Cooldown"] = "冷却外"
+L["On Cooldown"] = "冷却中"
+L["Over Health Threshold"] = "高于血量阈值"
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = "个人光环"
+L["Player Health"] = "玩家血量"
+L["Player in Combat"] = "玩家战斗中"
+L["Player Out of Combat"] = "玩家战斗外"
+L["Reaction Colors"] = "声望"
+L["Reaction Type"] = "声望类型"
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "删除筛选名"
+L["Remove Nameplate Filter"] = "移除姓名版过滤器"
+L["Require All"] = "要求全部"
+L["Reset filter priority to the default state."] = "重置过滤器优先级到默认状态"
+L["Reset Priority"] = "重置优先级"
+L["Return filter to its default state."] = "返回过滤器至默认状态"
+L["Scale of the nameplate that is targetted."] = "缩放选定目标的姓名板"
+L["Select Nameplate Filter"] = "选择姓名版过滤器"
+L["Set Settings to Default"] = "恢复默认设置"
+L["Set the transparency level of nameplates that are not the target nameplate."] = "设定未被选中目标的姓名板的透明度"
+L["Set to either stack nameplates vertically or allow them to overlap."] = "设置将姓名板垂直排列或者允许重叠"
+L["Shortcut to 'Filters' section of the config."] = "一个到'过滤器'菜单的快捷键"
+L["Shortcut to global filters."] = "到全局过滤器的快捷方式"
+L["Shortcuts"] = "快捷键"
+L["Side Arrows"] = "侧面箭头"
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = "样式过滤器"
+L["Tagged NPC"] = "标记的NPC"
+L["Tanked Color"] = "坦克颜色"
+L["Target Indicator Color"] = "目标指示器颜色"
+L["Target Indicator"] = "目标指示器"
+L["Target Scale"] = "目标缩放"
+L["Targeted Nameplate"] = "目标姓名板"
+L["Texture"] = "材质"
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = "这些过滤器不像常规过滤器那样使用一个法术列表, 而是使用魔兽API和部分代码逻辑来决定光环显示与否."
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = "这些过滤器使用一个法术列表来决定光环显示与否. 这些过滤器的内容可以在设置中的'过滤器'选项中更改."
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = "这会重置这个过滤器到初始状态. 你添加到这个过滤器的任何技能都会被移除."
+L["Threat"] = "仇恨"
+L["Time To Hold"] = "停留时间"
+L["Toggle Off While In Combat"] = "战斗时关闭"
+L["Toggle On While In Combat"] = "战斗时启用"
+L["Top Arrow"] = "顶部箭头"
+L["Triggers"] = "触发器"
+L["Under Health Threshold"] = "低于血量阈值"
+L["Unit Type"] = "单位类型"
+L["Use Class Color"] = "使用职业颜色"
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = "使用拖拽的方式调整过滤器优先级, 或者右键移除一个过滤器"
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = "使用Shift+左键来改变友方/敌方/普通状态. 普通状态将允许过滤器检查所有单位. 友方/敌方将只检查对应单位."
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = "当另一个坦克更有效的坦住时姓名板使用被坦住的颜色"
+L["Use Target Glow"] = "目标外框高亮"
+L["Use Target Scale"] = "使用目标缩放"
+L["Use Threat Color"] = "使用仇恨颜色"
+L["You can't remove a default name from the filter, disabling the name."] = "你不能删除过滤器的预设筛选名, 仅能停用此筛选名"
+
+--Profiles Export/Import
+L["Choose Export Format"] = "选择导出格式"
+L["Choose What To Export"] = "选择导出内容"
+L["Decode Text"] = "解码文字"
+L["Error decoding data. Import string may be corrupted!"] = "解码错误.导出字符串可能已损坏!"
+L["Error exporting profile!"] = "导出配置文件失败"
+L["Export Now"] = "现在导出"
+L["Export Profile"] = "导出配置文件"
+L["Exported"] = "已导出"
+L["Filters (All)"] = "过滤器(全部)"
+L["Filters (NamePlates)"] = "过滤器(姓名板)"
+L["Filters (UnitFrames)"] = "过滤器(框架)"
+L["Global (Account Settings)"] = "全局(账号设置)"
+L["Import Now"] = "现在导入"
+L["Import Profile"] = "导入配置文件"
+L["Importing"] = "正在导入"
+L["Plugin"] = "插件"
+L["Private (Character Settings)"] = "个人(角色配置)"
+L["Profile imported successfully!"] = "配置文件导入成功"
+L["Profile Name"] = "配置文件名称"
+L["Profile"] = "配置文件"
+L["Table"] = "表"
+
+--Skins
+L["Achievement Frame"] = "成就"
+L["Alert Frames"] = "警报"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "拍卖"
+L["Barbershop Frame"] = "理发师"
+L["BG Map"] = "战场地图"
+L["BG Score"] = "战场记分"
+L["Calendar Frame"] = "日历框架"
+L["Character Frame"] = "角色"
+L["Debug Tools"] = "除错工具"
+L["Dressing Room"] = "试衣间"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "闲谈"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "公会银行"
+L["Guild Registrar"] = "公会注册"
+L["Help Frame"] = "帮助"
+L["Inspect Frame"] = "观察"
+L["KeyBinding Frame"] = "键位设置"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "拾取"
+L["Macro Frame"] = "宏"
+L["Mail Frame"] = "邮箱"
+L["Merchant Frame"] = "商人"
+L["Mirror Timers"] = "镜像计时器"
+L["Misc Frames"] = "其他"
+L["Petition Frame"] = "回报GM"
+L["PvP Frames"] = "PvP框架"
+L["Quest Frames"] = "任务"
+L["Raid Frame"] = "团队"
+L["Skins"] = "美化外观"
+L["Socket Frame"] = "珠宝插槽"
+L["Spellbook"] = "技能书"
+L["Stable"] = "兽栏"
+L["Tabard Frame"] = "战袍"
+L["Talent Frame"] = "天赋"
+L["Taxi Frame"] = "载具"
+L["Time Manager"] = "时间管理"
+L["Trade Frame"] = "交易"
+L["TradeSkill Frame"] = "专业技能"
+L["Trainer Frame"] = "训练师"
+L["Tutorial Frame"] = true;
+L["World Map"] = "世界地图"
+
+--Tooltip
+L["Always Hide"] = "总是隐藏"
+L["Bags Only"] = "仅背包"
+L["Bags/Bank"] = "背包/银行"
+L["Bank Only"] = "仅银行"
+L["Both"] = "两者"
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = "选择何时显示提示.如果选择了设置键, 你需要按住它来显示提示"
+L["Comparison Font Size"] = "比较字体大小"
+L["Cursor Anchor"] = "鼠标锚点"
+L["Custom Faction Colors"] = "自定义声望颜色"
+L["Display guild ranks if a unit is guilded."] = "当目标有公会时显示其在公会内的等级"
+L["Display how many of a certain item you have in your possession."] = "显示当前物品在你身上的数量."
+L["Display player titles."] = "显示玩家头衔"
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = "当按住shift时展示该玩家的专精和装等,由于需要读取所以不会在指向某玩家时立即更新"
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "在鼠标提示中显示技能或物品的ID."
+L["Guild Ranks"] = "公会等级"
+L["Header Font Size"] = "标题名字大小"
+L["Health Bar"] = "生命条"
+L["Hide tooltip while in combat."] = "战斗时不显示提示"
+L["Inspect Info"] = "更多信息"
+L["Item Count"] = "物品数量"
+L["Never Hide"] = "从不隐藏"
+L["Player Titles"] = "玩家头衔"
+L["Should tooltip be anchored to mouse cursor"] = "提示锚定于鼠标"
+L["Spell/Item IDs"] = "技能/物品ID"
+L["Target Info"] = "目标信息"
+L["Text Font Size"] = "字体大小"
+L["This setting controls the size of text in item comparison tooltips."] = "设置对比框中的文字大小"
+L["Tooltip Font Settings"] = "提示文字设置"
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "显示团队中目标与你目前鼠标提示目标相同的队友"
+
+--UnitFrames
+L["%s and then %s"] = "%s 于 %s"
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "向上"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = "添加一个技能到过滤器.使用法术ID以避免匹配到同名的光环"
+L["Add a spell to the filter."] = "添加一个技能到过滤器"
+L["Add Spell ID or Name"] = "添加技能ID或者名字"
+L["Add SpellID"] = "添加技能ID"
+L["Additional Filter Override"] = "额外过滤器覆盖"
+L["Additional Filter"] = "额外的过滤器"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = "当'不显示非个人光环'开启时允许来自额外过滤器的非个人光环"
+L["Allow Whitelisted Auras"] = "允许白名单中的光环"
+L["An X offset (in pixels) to be used when anchoring new frames."] = "锚定新框架时的X偏移(单位:像素)"
+L["An Y offset (in pixels) to be used when anchoring new frames."] = "锚定新框架时的Y偏移(单位:像素)"
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = "升序或降序"
+L["Assist Frames"] = "助理框架"
+L["Assist Target"] = "助理目标"
+L["At what point should the text be displayed. Set to -1 to disable."] = "在何时显示文本. 设为-1以禁用此功能"
+L["Attach Text To"] = "文字附着于"
+L["Attach To"] = "附加到"
+L["Aura Bars"] = "光环条"
+L["Auto-Hide"] = "自动隐藏"
+L["Bad"] = "危险"
+L["Bars will transition smoothly."] = "状态条平滑增减"
+L["Below"] = "向下"
+L["Blacklist Modifier"] = "黑名单功能键"
+L["Blacklist"] = "黑名单"
+L["Block Auras Without Duration"] = "不显示永久的光环"
+L["Block Blacklisted Auras"] = "不显示黑名单中的光环"
+L["Block Non-Dispellable Auras"] = "只显示可驱散的光环"
+L["Block Non-Personal Auras"] = "只显示个人光环"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "鲜血符文"
+L["Borders"] = "边框"
+L["Buff Indicator"] = "Buff提示器"
+L["Buffs"] = "增益光环"
+L["By Type"] = "类型"
+L["Castbar"] = "施法条"
+L["Center"] = "居中"
+L["Check if you are in range to cast spells on this specific unit."] = "检查你是否在技能有效范围内"
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = "使用UIPARENT来防止它随框体隐藏"
+L["Class Backdrop"] = "生命条背景职业色"
+L["Class Castbars"] = "施法条职业色"
+L["Class Color Override"] = "职业色覆盖"
+L["Class Health"] = "生命条职业色"
+L["Class Power"] = "能量条职业色"
+L["Class Resources"] = "职业能量"
+L["Click Through"] = "点击穿透"
+L["Color all buffs that reduce the unit's incoming damage."] = "减少目标受到伤害的所有 Buff 的颜色"
+L["Color aurabar debuffs by type."] = "按类型显示光环条颜色"
+L["Color castbars by the class of player units."] = "按职业显示施法条颜色"
+L["Color castbars by the reaction type of non-player units."] = "按非玩家单位的声望显示施法条颜色"
+L["Color health by amount remaining."] = "按数值变化血量颜色"
+L["Color health by classcolor or reaction."] = "以职业色显示生命"
+L["Color power by classcolor or reaction."] = "以职业色显示能量"
+L["Color the health backdrop by class or reaction."] = "生命条背景色以职业色显示"
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "如果单位目标的减益光环可被驱散, 加亮显示其生命值"
+L["Color Turtle Buffs"] = "减伤类Buff的颜色"
+L["Color"] = "颜色"
+L["Colored Icon"] = "图标色彩"
+L["Coloring (Specific)"] = "着色(具体)"
+L["Coloring"] = "着色"
+L["Combat Fade"] = "不用时隐藏"
+L["Combat Icon"] = "战斗图标"
+L["Combo Point"] = "连击点"
+L["Combobar"] = true;
+L["Configure Auras"] = "设置光环"
+L["Copy From"] = "复制自"
+L["Count Font Size"] = "计数字体尺寸"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "输入一个名称创建自定义字体样式之后, 你可以在组件的下拉菜单中选择使用"
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "新建一个过滤器, 一旦新建, 每个单位的buff/debuff都能使用"
+L["Create Custom Text"] = true
+L["Create Filter"] = "新建过滤器"
+L["Current - Max | Percent"] = "当前值 - 最大值 | 百分比"
+L["Current - Max"] = "当前值 - 最大值"
+L["Current - Percent"] = "当前值 - 百分比"
+L["Current / Max"] = "当前值 / 最大值"
+L["Current"] = "当前值"
+L["Custom Dead Backdrop"] = "自定义死亡背景"
+L["Custom Health Backdrop"] = "自定义生命条背景"
+L["Custom Texts"] = "自定义字体"
+L["Death"] = "死亡符文"
+L["Debuff Highlighting"] = "减益光环加亮显示"
+L["Debuffs"] = "减益光环"
+L["Decimal Threshold"] = "小数阈值"
+L["Deficit"] = "亏损值"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "删除一个创造的过滤器, 你不能删除内建的过滤器, 只能删除你自已添加的"
+L["Delete Filter"] = "删除过滤器"
+L["Detach From Frame"] = "从框架分离"
+L["Detached Width"] = "分离宽度"
+L["Direction the health bar moves when gaining/losing health."] = "生命条的增减方向"
+L["Disable Debuff Highlight"] = "禁用debuff高亮"
+L["Disabled Blizzard Frames"] = "禁用暴雪框架"
+L["Disabled"] = "禁用"
+L["Disables the focus and target of focus unitframes."] = "禁用焦点和目标的焦点框架"
+L["Disables the player and pet unitframes."] = "禁用玩家和宠物框架"
+L["Disables the target and target of target unitframes."] = "禁用目标和目标的目标框架"
+L["Disconnected"] = "离线"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "在施法状态条的末端显示一个火花材质来区分施法条和背景条"
+L["Display Frames"] = "显示框架"
+L["Display Player"] = "显示玩家"
+L["Display Target"] = "显示目标"
+L["Display Text"] = "显示文本"
+L["Display the castbar icon inside the castbar."] = "在施法条内显示图标"
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = "如果关闭施法条内显示图标,你可以自定义施法条外图标的大小和位置"
+L["Display the combat icon on the unitframe."] = "在单位框架内显示战斗图标"
+L["Display the rested icon on the unitframe."] = "在单位框架上显示充分休息图标"
+L["Display the target of your current cast. Useful for mouseover casts."] = "显示你当前的施法目标. 可以转换成鼠标滑过类型"
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "若为需引导的法术, 在施法条上显示每跳周期伤害.启动此功能后, 针对吸取灵魂这类的法术, 将自动调整显示每跳周期伤害, 并视加速等级增加额外的周期伤害"
+L["Don't display any auras found on the 'Blacklist' filter."] = "不显示任何'黑名单'过滤器中的光环"
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = "不显示高于此时间(单位:秒)的光环.设置为0以禁用"
+L["Don't display auras that are not yours."] = "不显示不是你施放的光环"
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = "不显示低于此时间(单位:秒)的光环.设置为0以禁用"
+L["Don't display auras that cannot be purged or dispelled by your class."] = "不显示你不能驱散的光环"
+L["Don't display auras that have no duration."] = "不显示没有持续时间的光环"
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "下"
+L["Dungeon & Raid Filter"] = "地下城与团队副本过滤器"
+L["Duration Reverse"] = "持续时间反转"
+L["Duration Text"] = "持续时间文字"
+L["Duration"] = "持续时间"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = "启用后将可以在整个团队内排序, 但你不再可以区分不同小队"
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = "启用后翻转未满团队的队伍顺序(起始方向)"
+L["Enemy Aura Type"] = "敌对光环类型"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "非战斗/施法/目标不存在时隐藏单位框架"
+L["Fill"] = "填充"
+L["Filled"] = "全长"
+L["Filter Type"] = "过滤器类型"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "强制关闭"
+L["Force On"] = "强制开启"
+L["Force Reaction Color"] = "强制声望颜色"
+L["Force the frames to show, they will act as if they are the player frame."] = "强制框架显示"
+L["Forces Debuff Highlight to be disabled for these frames"] = "为这些框架强制禁用debuff高亮"
+L["Forces reaction color instead of class color on units controlled by players."] = "对于玩家控制的角色强制使用声望颜色而不是职业颜色"
+L["Format"] = "格式"
+L["Frame Level"] = "框架层次"
+L["Frame Orientation"] = "框架方向"
+L["Frame Strata"] = "框架层级"
+L["Frame"] = "框架"
+L["Frequent Updates"] = "频繁更新"
+L["Friendly Aura Type"] = "友好光环类型"
+L["Friendly"] = "友好"
+L["Frost"] = "冰霜符文"
+L["Glow"] = "闪烁"
+L["Good"] = "安全"
+L["GPS Arrow"] = "位置箭头"
+L["Group By"] = "队伍排列方式"
+L["Grouping & Sorting"] = "分组与排序"
+L["Groups Per Row/Column"] = "每行/列的组数"
+L["Growth direction from the first unitframe."] = "增长方向从第一个头像框架开始"
+L["Growth Direction"] = "增长方向"
+L["Heal Prediction"] = "治疗量预测"
+L["Health Backdrop"] = "生命条背景"
+L["Health Border"] = "生命条边框"
+L["Health By Value"] = "生命条颜色依数值变化"
+L["Health"] = "生命条"
+L["Height"] = "高"
+L["Horizontal Spacing"] = "水平间隔"
+L["Horizontal"] = "水平"
+L["Icon Inside Castbar"] = "施法条内的图标"
+L["Icon Size"] = "图标尺寸"
+L["Icon"] = "图标"
+L["Icon: BOTTOM"] = "图标: 底部"
+L["Icon: BOTTOMLEFT"] = "图标: 底部左侧"
+L["Icon: BOTTOMRIGHT"] = "图标: 底部右侧"
+L["Icon: LEFT"] = "图标: 左侧"
+L["Icon: RIGHT"] = "图标: 右侧"
+L["Icon: TOP"] = "图标: 顶部"
+L["Icon: TOPLEFT"] = "图标: 顶部左侧"
+L["Icon: TOPRIGHT"] = "图标: 顶部右侧"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "若没有启用其他过滤器, 那只会显示'白名单'里面的光环"
+L["If not set to 0 then override the size of the aura icon to this."] = "如果不为0, 此值将覆盖光环图标的尺寸"
+L["If the unit is an enemy to you."] = "如果是你的敌对目标"
+L["If the unit is friendly to you."] = "如果是你的友好目标"
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = "如果你同时激活了很多3D头像你很可能有帧数的影响.如果你有这方面的问题请禁用一部分头像"
+L["Ignore mouse events."] = "忽略鼠标事件"
+L["InfoPanel Border"] = "信息面板边框"
+L["Information Panel"] = "信息面板"
+L["Inset"] = "插入"
+L["Inside Information Panel"] = "插入信息面板"
+L["Interruptable"] = "可打断颜色"
+L["Invert Grouping Order"] = "反转队伍排序"
+L["JustifyH"] = "水平对齐"
+L["Latency"] = "延迟"
+L["Left to Right"] = "左到右"
+L["Main statusbar texture."] = "主状态条材质"
+L["Main Tanks / Main Assist"] = "主坦克/主助理"
+L["Make textures transparent."] = "材质透明"
+L["Match Frame Width"] = "匹配框体宽度"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = "最多"
+L["Max Overflow"] = true
+L["Maximum Duration"] = "最大持续时间"
+L["Method to sort by."] = "排序方式"
+L["Middle Click - Set Focus"] = "鼠标中键 - 设置焦点"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "鼠标中键点击单位框架设置焦点"
+L["Middle"] = "中间"
+L["Minimum Duration"] = "最低持续时间"
+L["Mouseover"] = "鼠标滑过显示"
+L["Name"] = "姓名"
+L["Neutral"] = "中立"
+L["Non-Interruptable"] = "不可打断颜色"
+L["None"] = "无"
+L["Not valid spell id"] = "不正确的技能ID"
+L["Num Rows"] = "行数"
+L["Number of Groups"] = "每队单位数量"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "偏移能量条与生命条的位置, 设为0代表停用"
+L["Offset position for text."] = "偏移文本的位置"
+L["Offset"] = "偏移"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "不在范围内时显示"
+L["Only show when you are mousing over a frame."] = "鼠标滑过时显示"
+L["OOR Alpha"] = "超出距离透明度"
+L["Other Filter"] = "其他过滤器"
+L["Others"] = "他人的"
+L["Overlay the healthbar"] = "头像重叠与生命条上"
+L["Overlay"] = "重叠显示"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "覆盖可见性的设定, 例如: 在10人副本里只显示1队和2队"
+L["Override the default class color setting."] = "覆盖默认的职业色设置"
+L["Owners Name"] = "所有者姓名"
+L["Parent"] = "跟随框架"
+L["Party Pets"] = "队伍宠物"
+L["Party Targets"] = "队伍目标"
+L["Per Row"] = "每行"
+L["Percent"] = "百分比"
+L["Personal"] = "个人的"
+L["Pet Name"] = "宠物名字"
+L["Player Frame Aura Bars"] = "玩家框架光环条"
+L["Portrait"] = "头像"
+L["Position Buffs on Debuffs"] = "增益在减益上"
+L["Position Debuffs on Buffs"] = "减益在减益上"
+L["Position"] = "位置"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "NPC目标将隐藏能量值文字"
+L["Power"] = "能量条"
+L["Powers"] = "能量"
+L["Priority"] = "优先级"
+L["Profile Specific"] = "角色专用"
+L["PvP Icon"] = "PvP图标"
+L["PvP Text"] = "PvP文字"
+L["PVP Trinket"] = "PvP饰品"
+L["Raid Icon"] = "团队图标"
+L["Raid-Wide Sorting"] = "全团队排序"
+L["Raid40 Frames"] = "40人团队框架"
+L["RaidDebuff Indicator"] = "团队副本减益光环标示"
+L["Range Check"] = "距离检查"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "实时更新生命值会占用更多的内存的和CPU, 只推荐治疗角色开启"
+L["Reaction Castbars"] = "声望施法条"
+L["Reactions"] = "声望"
+L["Ready Check Icon"] = "就位确认图标"
+L["Remaining"] = "剩余值"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = "从过滤器中移除一个技能. 当你看见有ID在过滤器中的技能名字时使用技能ID"
+L["Remove a spell from the filter."] = "从过滤器中移除一个技能"
+L["Remove Spell ID or Name"] = "移除技能ID或者名称"
+L["Remove SpellID"] = "移除技能ID"
+L["Rest Icon"] = "充分休息图标"
+L["Restore Defaults"] = "恢复预设"
+L["Right to Left"] = "右到左"
+L["RL / ML Icons"] = "主坦克/主助理图标"
+L["Role Icon"] = "角色定位图标"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = "光环条移动前的剩余时间(秒), 设为0以禁用"
+L["Select a unit to copy settings from."] = "选择从哪单位复制"
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "请选择一个过滤器, 若你启用的是'白名单', 则只显示'白名单'里的光环"
+L["Select Filter"] = "选择过滤器"
+L["Select Spell"] = "选择技能"
+L["Select the display method of the portrait."] = "选择头像的显示方式"
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = "设置过滤器类型. 黑名单将隐藏列表内的任何光环而显示其他. 白名单将显示过滤器内的任何光环而隐藏其他所有光环"
+L["Set the font size for unitframes."] = "设置单位框架字体尺寸"
+L["Set the order that the group will sort."] = "设置组排序的顺序"
+L["Set the orientation of the UnitFrame."] = "设置框架的方向"
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "设置该法术的优先顺序. 请注意, 优先级只用于Raid Debuff模块, 而不是标准的Buff/Debuff模块. 设为0以禁用此功能"
+L["Set the type of auras to show when a unit is a foe."] = "当单位是敌对时设置光环显示的类型"
+L["Set the type of auras to show when a unit is friendly."] = "当单位是友好时设置光环显示的类型"
+L["Sets the font instance's horizontal text alignment style."] = "设置字体实例的水平文本对齐方式"
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "在单位框架中显示即将回复的的预测治疗量, 过量治疗则以不同颜色显示"
+L["Show Aura From Other Players"] = "显示其他玩家的光环"
+L["Show Auras"] = "显示光环"
+L["Show Dispellable Debuffs"] = "显示无法驱散的debuff"
+L["Show When Not Active"] = "显示当前无效的光环"
+L["Size and Positions"] = "大小和位置"
+L["Size of the indicator icon."] = "提示图标大小"
+L["Size Override"] = "尺寸覆盖"
+L["Size"] = "大小"
+L["Smart Aura Position"] = "智能光环位置"
+L["Smart Raid Filter"] = "智能团队过滤"
+L["Smooth Bars"] = "平滑化"
+L["Sort By"] = "排序"
+L["Spaced"] = "留空"
+L["Spacing"] = "间隙"
+L["Spark"] = "火花"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = "层数计数"
+L["Stack Threshold"] = "层数阈值"
+L["Start Near Center"] = "从中心开始"
+L["Statusbar Fill Orientation"] = "状态条填充方向"
+L["StatusBar Texture"] = "状态条材质"
+L["Strata and Level"] = "框架层级和层次"
+L["Style"] = "风格"
+L["Tank Frames"] = "坦克框架"
+L["Tank Target"] = "坦克目标"
+L["Tapped"] = "被攻击"
+L["Target Glow"] = "选中高亮"
+L["Target On Mouse-Down"] = "鼠标按下设为目标"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "按下鼠标时设为目标,而不是松开鼠标按键时. \n\n|cffFF0000警告: 如果使用'Clique'等点击施法插件, 你可能需要调整这些插件的设置"
+L["Text Color"] = "文字颜色"
+L["Text Format"] = "文字格式"
+L["Text Position"] = "文字位置"
+L["Text Threshold"] = "文本阈值"
+L["Text Toggle On NPC"] = "NPC文字显示开关"
+L["Text xOffset"] = "文字X轴偏移"
+L["Text yOffset"] = "文字Y轴偏移"
+L["Text"] = "文本"
+L["Textured Icon"] = "图标纹理"
+L["The alpha to set units that are out of range to."] = "单位框架超出距离的透明度"
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = "减益需要达到这个数量的层数才会显示. 设为0来一直显示它"
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "为了显示设定过的过滤器下面的宏必须启用"
+L["The font that the unitframes will use."] = "单位框架字体"
+L["The initial group will start near the center and grow out."] = "最初的队伍由中心开始增长"
+L["The name you have selected is already in use by another element."] = "你所选的名称已经被另一组件占用"
+L["The object you want to attach to."] = "你想依附的目标"
+L["Thin Borders"] = "细边框"
+L["This dictates the size of the icon when it is not attached to the castbar."] = "指定未吸附在施法条内时图标的尺寸"
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = "这将开启单位框体颜色设置.这些设置会影响所有单位框体"
+L["Threat Display Mode"] = "仇恨显示模式"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = "文字变为小数时的阈值.设为-1以禁用小数"
+L["Ticks"] = "周期伤害"
+L["Time Remaining Reverse"] = "剩余时间反转"
+L["Time Remaining"] = "剩余时间"
+L["Transparent"] = "透明"
+L["Turtle Color"] = "减伤类的颜色"
+L["Unholy"] = "邪恶符文"
+L["Uniform Threshold"] = "统一阈值"
+L["UnitFrames"] = "单位框架"
+L["Up"] = "上"
+L["Use Custom Level"] = "使用自定义层次"
+L["Use Custom Strata"] = "使用自定义层级"
+L["Use Dead Backdrop"] = "死亡背景"
+L["Use Default"] = "使用默认值"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "自定义生命条背景色"
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = "使用配置文件内的增益指示器而不是全局的"
+L["Use thin borders on certain unitframe elements."] = "使用细边框"
+L["Use this backdrop color for units that are dead or ghosts."] = "死亡或灵魂状态背景"
+L["Value must be a number"] = "数值必须为一个数字"
+L["Vertical Orientation"] = "垂直方向"
+L["Vertical Spacing"] = "垂直间隔"
+L["Vertical"] = "垂直"
+L["Visibility"] = "可见性"
+L["What point to anchor to the frame you set to attach to."] = "框架的定位对齐方向"
+L["What to attach the buff anchor frame to."] = "buff定位附加到的框架"
+L["What to attach the debuff anchor frame to."] = "debuff定位附加到的框架"
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "若启用,队伍中将显示玩家"
+L["Whitelist"] = "白名单"
+L["Width"] = "宽"
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = "如果没有debuff则把buff显示在debuff位置"
+L["xOffset"] = "X轴偏移"
+L["yOffset"] = "Y轴偏移"
+L["You can't remove a pre-existing filter."] = "你不能删除一个内建的过滤器"
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "你不能移除一个内建技能, 仅能停用此技能"
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = "按住设置按键+右键单击会把该玩家加入黑名单, 设为无以关闭该功能"
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/English_Config.lua b/ElvUI_Config/Locales/English_Config.lua
new file mode 100644
index 0000000..1412c88
--- /dev/null
+++ b/ElvUI_Config/Locales/English_Config.lua
@@ -0,0 +1,1119 @@
+-- English localization file for enUS and enGB.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0");
+local L = AceLocale:NewLocale("ElvUI", "enUS", true, true);
+if not L then return; end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "Configure the aura icons that appear near the minimap."
+L["BAGS_DESC"] = "Adjust bag settings for ElvUI."
+L["CHAT_DESC"] = "Adjust chat settings for ElvUI."
+L["DATATEXT_DESC"] = "Setup the on-screen display of info-texts."
+L["ELVUI_DESC"] = "ElvUI is a complete User Interface replacement addon for World of Warcraft."
+L["NAMEPLATE_DESC"] = "Modify the nameplate settings."
+L["PANEL_DESC"] = "Adjust the size of your left and right panels, this will effect your chat and bags."
+L["SKINS_DESC"] = "Adjust Skin settings."
+L["TOGGLESKIN_DESC"] = "Enable/Disable this skin."
+L["TOOLTIP_DESC"] = "Setup options for the Tooltip."
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[With the new addition of LibItemSearch, you now have access to much more advanced item searches. The following is a documentation of the search syntax. See the full explanation at: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Specific Searching:
+ • q:[quality] or quality:[quality]. For instance, q:epic will find all epic items.
+ • l:[level], lvl:[level] or level:[level]. For example, l:30 will find all items with level 30.
+ • t:[search], type:[search] or slot:[search]. For instance, t:weapon will find all weapons.
+ • n:[name] or name:[name]. For instance, typing n:muffins will find all items with names containing 'muffins'.
+ • s:[set] or set:[set]. For example, s:fire will find all items in equipment sets you have with names that start with fire.
+ • tt:[search], tip:[search] or tooltip:[search]. For instance, tt:binds will find all items that can be bound to account, on equip, or on pickup.
+
+
+Search Operators:
+ • ! : Negates a search. For example, !q:epic will find all items that are NOT epic.
+ • | : Joins two searches. Typing q:epic | t:weapon will find all items that are either epic OR weapons.
+ • & : Intersects two searches. For instance, q:epic & t:weapon will find all items that are epic AND weapons
+ • >, <, <=, => : Performs comparisons on numerical searches. For example, typing lvl: >30 will find all items with level HIGHER than 30.
+
+
+The following search keywords can also be used:
+ • soulbound, bound, bop : Bind on pickup items.
+ • bou : Bind on use items.
+ • boe : Bind on equip items.
+ • boa : Bind on account items.
+ • quest : Quest bound items."]];
+L["TEXT_FORMAT_DESC"] = [[Provide a string to change the text format.
+
+Examples:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+Health / Power Formats:
+"current" - current amount
+"percent" - percentage amount
+"current-max" - current amount followed by maximum amount, will display only max if current is equal to max
+"current-percent" - current amount followed by percentage amount, will display only max if current is equal to max
+"current-max-percent" - current amount, max amount, followed by percentage amount, will display only max if current is equal to max
+"deficit" - display the deficit value, will display nothing if there is no deficit
+
+Name Formats:
+"name:short" - Name restricted to 10 characters
+"name:medium" - Name restricted to 15 characters
+"name:long" - Name restricted to 20 characters
+
+To disable leave the field blank, if you need more information visit http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = true;
+L["ActionBars"] = true;
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = true;
+L["Alpha"] = true;
+L["Anchor Point"] = true; --also in unitframes
+L["Backdrop Spacing"] = true;
+L["Backdrop"] = true;
+L["Button Size"] = true; --Also used in Bags
+L["Button Spacing"] = true; --Also used in Bags
+L["Buttons Per Row"] = true;
+L["Buttons"] = true;
+L["Change the alpha level of the frame."] = true;
+L["Color of the actionbutton when not usable."] = true;
+L["Color of the actionbutton when out of power (Mana, Rage)."] = true;
+L["Color of the actionbutton when out of range."] = true;
+L["Color of the actionbutton when usable."] = true;
+L["Color when the text is about to expire"] = true;
+L["Color when the text is in the days format."] = true;
+L["Color when the text is in the hours format."] = true;
+L["Color when the text is in the minutes format."] = true;
+L["Color when the text is in the seconds format."] = true;
+L["Cooldown Text"] = true;
+L["Darken Inactive"] = true;
+L["Days"] = true;
+L["Display bind names on action buttons."] = true;
+L["Display cooldown text on anything with the cooldown spiral."] = true;
+L["Display macro names on action buttons."] = true;
+L["Expiring"] = true;
+L["Global Fade Transparency"] = true;
+L["Height Multiplier"] = true;
+L["Hours"] = true;
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = true;
+L["Inherit Global Fade"] = true;
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = true;
+L["Key Down"] = true;
+L["Keybind Mode"] = true;
+L["Keybind Text"] = true;
+L["LBF Support"] = true;
+L["Low Threshold"] = true;
+L["Macro Text"] = true;
+L["Minutes"] = true;
+L["Mouse Over"] = true; --Also used in Bags
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = true;
+L["Not Usable"] = true;
+L["Out of Power"] = true;
+L["Out of Range"] = true;
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = true;
+L["Restore the actionbars default settings"] = true;
+L["Seconds"] = true;
+L["Show Empty Buttons"] = true;
+L["The amount of buttons to display per row."] = true;
+L["The amount of buttons to display."] = true;
+L["The button you must hold down in order to drag an ability to another action button."] = true;
+L["The first button anchors itself to this point on the bar."] = true;
+L["The size of the action buttons."] = true;
+L["The spacing between the backdrop and the buttons."] = true;
+L["This setting will be updated upon changing stances."] = true;
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = true;
+L["Toggles the display of the actionbars backdrop."] = true;
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = true;
+L["Usable"] = true;
+L["Visibility State"] = true;
+L["Width Multiplier"] = true;
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = true;
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = true;
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = true;
+L["Add Item or Search Syntax"] = true;
+L["Adjust the width of the bag frame."] = true;
+L["Adjust the width of the bank frame."] = true;
+L["Ascending"] = true;
+L["Bag Sorting"] = true;
+L["Bag-Bar"] = true;
+L["Bar Direction"] = true;
+L["Blizzard Style"] = true;
+L["Bottom to Top"] = true;
+L["Button Size (Bag)"] = true;
+L["Button Size (Bank)"] = true;
+L["Clear Search On Close"] = true;
+L["Condensed"] = true;
+L["Descending"] = true;
+L["Direction the bag sorting will use to allocate the items."] = true;
+L["Disable Bag Sort"] = true;
+L["Disable Bank Sort"] = true;
+L["Display Item Level"] = true;
+L["Displays item level on equippable items."] = true;
+L["Enable/Disable the all-in-one bag."] = true;
+L["Enable/Disable the Bag-Bar."] = true;
+L["Full"] = true;
+L["Global"] = true;
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = true;
+L["Ignored Items and Search Syntax (Global)"] = true;
+L["Ignored Items and Search Syntax (Profile)"] = true;
+L["Item Count Font"] = true;
+L["Item Level Threshold"] = true;
+L["Item Level"] = true;
+L["Money Format"] = true;
+L["Panel Width (Bags)"] = true;
+L["Panel Width (Bank)"] = true;
+L["Search Syntax"] = true;
+L["Set the size of your bag buttons."] = true;
+L["Short (Whole Numbers)"] = true;
+L["Short"] = true;
+L["Smart"] = true;
+L["Sort Direction"] = true; --Also used in Buffs and Debuffs
+L["Sort Inverted"] = true;
+L["The direction that the bag frames be (Horizontal or Vertical)."] = true;
+L["The direction that the bag frames will grow from the anchor."] = true;
+L["The display format of the money text that is shown at the top of the main bag."] = true;
+L["The frame is not shown unless you mouse over the frame."] = true;
+L["The minimum item level required for it to be shown."] = true;
+L["The size of the individual buttons on the bag frame."] = true;
+L["The size of the individual buttons on the bank frame."] = true;
+L["The spacing between buttons."] = true;
+L["Top to Bottom"] = true;
+L["Use coin icons instead of colored text."] = true;
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = true;
+L["Begin a new row or column after this many auras."] = true;
+L["Count xOffset"] = true;
+L["Count yOffset"] = true;
+L["Defines how the group is sorted."] = true;
+L["Defines the sort order of the selected sort method."] = true;
+L["Disabled Blizzard"] = true;
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = true;
+L["Index"] = true;
+L["Indicate whether buffs you cast yourself should be separated before or after."] = true;
+L["Limit the number of rows or columns."] = true;
+L["Max Wraps"] = true;
+L["No Sorting"] = true;
+L["Other's First"] = true;
+L["Remaining Time"] = true;
+L["Reminder"] = true
+L["Reverse Style"] = true;
+L["Seperate"] = true;
+L["Set the size of the individual auras."] = true;
+L["Sort Method"] = true;
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = true;
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = true;
+L["Time xOffset"] = true;
+L["Time yOffset"] = true;
+L["Time"] = true;
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = true;
+L["Wrap After"] = true;
+L["Your Auras First"] = true;
+
+--Chat
+L["Above Chat"] = true;
+L["Adjust the height of your right chat panel."] = true;
+L["Adjust the width of your right chat panel."] = true;
+L["Alerts"] = true;
+L["Allowed Combat Repeat"] = true;
+L["Attempt to create URL links inside the chat."] = true;
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = true;
+L["Below Chat"] = true;
+L["Chat EditBox Position"] = true;
+L["Chat History"] = true;
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = true;
+L["Custom Timestamp Color"] = true;
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = true;
+L["Enable the use of separate size options for the right chat panel."] = true;
+L["Exclude Name"] = true;
+L["Excluded names will not be class colored."] = true;
+L["Excluded Names"] = true;
+L["Fade Chat"] = true;
+L["Fade Tabs No Backdrop"] = true;
+L["Fade the chat text when there is no activity."] = true;
+L["Fade Undocked Tabs"] = true;
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = true;
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = true;
+L["Font Outline"] = true; --Also used in UnitFrames section
+L["Font"] = true;
+L["Hide Both"] = true;
+L["Hyperlink Hover"] = true;
+L["Keyword Alert"] = true;
+L["Keywords"] = true;
+L["Left Only"] = true;
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = true;
+L["Lock Positions"] = true;
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = true;
+L["No Alert In Combat"] = true;
+L["Number of messages you scroll for each step."] = true;
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = true;
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = true;
+L["Panel Backdrop"] = true;
+L["Panel Height"] = true;
+L["Panel Texture (Left)"] = true;
+L["Panel Texture (Right)"] = true;
+L["Panel Width"] = true;
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = true;
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = true;
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = true;
+L["Right Only"] = true;
+L["Right Panel Height"] = true;
+L["Right Panel Width"] = true;
+L["Scroll Interval"] = true;
+L["Scroll Messages"] = true;
+L["Separate Panel Sizes"] = true;
+L["Set the font outline."] = true; --Also used in UnitFrames section
+L["Short Channels"] = true;
+L["Shorten the channel names in chat."] = true;
+L["Show Both"] = true;
+L["Spam Interval"] = true;
+L["Sticky Chat"] = true;
+L["Tab Font Outline"] = true;
+L["Tab Font Size"] = true;
+L["Tab Font"] = true;
+L["Tab Panel Transparency"] = true;
+L["Tab Panel"] = true;
+L["Timestamp Color"] = true;
+L["Toggle showing of the left and right chat panels."] = true;
+L["Toggle the chat tab panel backdrop."] = true;
+L["URL Links"] = true;
+L["Use Alt Key"] = true;
+L["Use class color for the names of players when they are mentioned."] = true;
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = true;
+L["Whisper Alert"] = true;
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = true;
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = true;
+L["Credits"] = true;
+L["Donations:"] = true;
+L["ELVUI_CREDITS"] = "I would like to give out a special shout out to the following people for helping me maintain this addon with testing and coding and people who also have helped me through donations. Please note for donations I'm only posting the names of people who PM'd me on the forums, if your name is missing and you wish to have your name added please PM me."
+L["Testing:"] = true;
+
+--DataBars
+L["Current - Percent (Remaining)"] = true;
+L["Current - Remaining"] = true;
+L["DataBars"] = true;
+L["Hide In Combat"] = true;
+L["Setup on-screen display of information bars."] = true;
+
+--DataTexts
+L["Battleground Texts"] = true;
+L["Block Combat Click"] = true;
+L["Block Combat Hover"] = true;
+L["Blocks all click events while in combat."] = true;
+L["Blocks datatext tooltip from showing in combat."] = true;
+L["BottomLeftMiniPanel"] = "Minimap BottomLeft (Inside)"
+L["BottomMiniPanel"] = "Minimap Bottom (Inside)"
+L["BottomRightMiniPanel"] = "Minimap BottomRight (Inside)"
+L["Datatext Panel (Left)"] = true;
+L["Datatext Panel (Right)"] = true;
+L["DataTexts"] = true;
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = true;
+L["Display minimap panels below the minimap, used for datatexts."] = true;
+L["Gold Format"] = true;
+L["left"] = "Left"
+L["LeftChatDataPanel"] = "Left Chat"
+L["LeftMiniPanel"] = "Minimap Left"
+L["middle"] = "Middle"
+L["Minimap Panels"] = true;
+L["Panel Transparency"] = true;
+L["Panels"] = true;
+L["right"] = "Right"
+L["RightChatDataPanel"] = "Right Chat"
+L["RightMiniPanel"] = "Minimap Right"
+L["Small Panels"] = true;
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = true;
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap TopLeft (Inside)"
+L["TopMiniPanel"] = "Minimap Top (Inside)"
+L["TopRightMiniPanel"] = "Minimap TopRight (Inside)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = true;
+L["Word Wrap"] = true;
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = true;
+L["Sends your current profile to your target."] = true;
+L["Sends your filter settings to your target."] = true;
+L["Share Current Profile"] = true;
+L["Share Filters"] = true;
+L["This feature will allow you to transfer settings to other characters."] = true;
+L["You must be targeting a player."] = true;
+
+--Filters
+L["Reset Aura Filters"] = true --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = true;
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = true;
+L["AFK Mode"] = true;
+L["Announce Interrupts"] = true;
+L["Announce when you interrupt a spell to the specified chat channel."] = true;
+L["Attempt to support eyefinity/nvidia surround."] = true;
+L["Auto Greed/DE"] = true;
+L["Auto Repair"] = true;
+L["Auto Scale"] = true;
+L["Automatically accept invites from guild/friends."] = true;
+L["Automatically repair using the following method when visiting a merchant."] = true;
+L["Automatically scale the User Interface based on your screen resolution"] = true;
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = true;
+L["Automatically vendor gray items when visiting a vendor."] = true;
+L["Bottom Panel"] = true;
+L["Chat Bubbles Style"] = true;
+L["Chat Bubbles"] = true;
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = true;
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = true;
+L["Display a panel across the top of the screen. This is for cosmetic only."] = true;
+L["Display battleground messages in the middle of the screen."] = true;
+L["Enable/Disable the loot frame."] = true;
+L["Enable/Disable the loot roll frame."] = true;
+L["Enables the ElvUI Raid Control panel."] = true;
+L["Enhanced PVP Messages"] = true;
+L["General"] = true;
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = true;
+L["Hide At Max Level"] = true;
+L["Hide Error Text"] = true;
+L["Hide In Vehicle"] = true;
+L["Hides the red error text at the top of the screen while in combat."] = true;
+L["Log Taints"] = true;
+L["Login Message"] = true;
+L["Loot Roll"] = true;
+L["Loot"] = true;
+L["Lowest Allowed UI Scale"] = true;
+L["Multi-Monitor Support"] = true;
+L["Name Font"] = true;
+L["Number Prefix"] = true;
+L["Party / Raid"] = true;
+L["Party Only"] = true;
+L["Raid Only"] = true;
+L["Remove Backdrop"] = true;
+L["Reset all frames to their original positions."] = true;
+L["Reset Anchors"] = true;
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = true;
+L["Skin Backdrop (No Borders)"] = true;
+L["Skin Backdrop"] = true;
+L["Skin the blizzard chat bubbles."] = true;
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = true;
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = true;
+L["Thin Border Theme"] = true;
+L["Toggle Tutorials"] = true;
+L["Top Panel"] = true;
+L["Version Check"] = true;
+L["Watch Frame Height"] = true;
+L["When you go AFK display the AFK screen."] = true;
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = true;
+L["Applies the primary texture to all statusbars."] = true;
+L["Apply Font To All"] = true;
+L["Apply Texture To All"] = true;
+L["Backdrop color of transparent frames"] = true;
+L["Backdrop Color"] = true;
+L["Backdrop Faded Color"] = true;
+L["Border Color"] = true;
+L["Color some texts use."] = true;
+L["Colors"] = true; --Also used in UnitFrames
+L["CombatText Font"] = true;
+L["Default Font"] = true;
+L["Font Size"] = true; --Also used in UnitFrames
+L["Fonts"] = true;
+L["Main backdrop color of the UI."] = true;
+L["Main border color of the UI."] = true;
+L["Media"] = true;
+L["Primary Texture"] = true;
+L["Replace Blizzard Fonts"] = true;
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = true;
+L["Secondary Texture"] = true;
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = true;
+L["Textures"] = true;
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = true;
+L["The font that the core of the UI will use."] = true;
+L["The texture that will be used mainly for statusbars."] = true;
+L["This texture will get used on objects like chat windows and dropdown menus."] = true;
+L["Value Color"] = true;
+
+--Maps
+L["Adjust the size of the minimap."] = true;
+L["Always Display"] = true;
+L["Bottom Left"] = true;
+L["Bottom Right"] = true;
+L["Bottom"] = true;
+L["Change settings for the display of the location text that is on the minimap."] = true;
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = true;
+L["Instance Difficulty"] = true;
+L["Left"] = true;
+L["LFG Queue"] = true;
+L["Location Text"] = true;
+L["Make the world map smaller."] = true;
+L["Maps"] = true;
+L["Minimap Buttons"] = true;
+L["Minimap Mouseover"] = true;
+L["Puts coordinates on the world map."] = true;
+L["PvP Queue"] = true
+L["Reset Zoom"] = true;
+L["Right"] = true;
+L["Scale"] = true;
+L["Smaller World Map"] = true;
+L["Top Left"] = true;
+L["Top Right"] = true;
+L["Top"] = true;
+L["World Map Coordinates"] = true;
+L["X-Offset"] = true;
+L["Y-Offset"] = true;
+
+--Misc
+L["Install"] = true;
+L["Run the installation process."] = true;
+L["Toggle Anchors"] = true;
+L["Unlock various elements of the UI to be repositioned."] = true;
+L["Version"] = true;
+
+--NamePlates
+L["# Displayed Auras"] = true;
+L["Actions"] = true
+L["Add Name"] = true;
+L["Add Nameplate Filter"] = true
+L["Add Regular Filter"] = true
+L["Add Special Filter"] = true
+L["Always Show Target Health"] = true
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = true
+L["Background Glow"] = true
+L["Bad Color"] = true;
+L["Bad Scale"] = true;
+L["Bad Transition Color"] = true;
+L["Base Height for the Aura Icon"] = true;
+L["Border Glow"] = true
+L["Border"] = true
+L["Cast Bar"] = true;
+L["Cast Color"] = true;
+L["Cast No Interrupt Color"] = true;
+L["Cast Time Format"] = true;
+L["Casting"] = true
+L["Channel Time Format"] = true;
+L["Clear Filter"] = true
+L["Color Tanked"] = true;
+L["Control enemy nameplates toggling on or off when in combat."] = true;
+L["Control friendly nameplates toggling on or off when in combat."] = true;
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = true;
+L["Cooldowns"] = true
+L["Copy settings from another unit."] = true;
+L["Copy Settings From"] = true;
+L["Current Level"] = true
+L["Default Settings"] = true;
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = true;
+L["Elite Icon"] = true
+L["Enable/Disable the scaling of targetted nameplates."] = true;
+L["Enabling this will check your health amount."] = true
+L["Enemy Combat Toggle"] = true;
+L["Enemy NPC Frames"] = true;
+L["Enemy Player Frames"] = true;
+L["Enemy"] = true; --Also used in UnitFrames
+L["ENEMY_NPC"] = "Enemy NPC"
+L["ENEMY_PLAYER"] = "Enemy Player"
+L["Filter already exists!"] = true;
+L["Filter Priority"] = true;
+L["Filters Page"] = true;
+L["Friendly Combat Toggle"] = true;
+L["Friendly NPC Frames"] = true;
+L["Friendly Player Frames"] = true;
+L["FRIENDLY_NPC"] = "Friendly NPC"
+L["FRIENDLY_PLAYER"] = "Friendly Player"
+L["General Options"] = true;
+L["Good Color"] = true;
+L["Good Scale"] = true;
+L["Good Transition Color"] = true;
+L["Healer Icon"] = true;
+L["Health Color"] = true
+L["Health Threshold"] = true
+L["Hide Frame"] = true
+L["Hide Spell Name"] = true;
+L["Hide Time"] = true;
+L["Hide"] = true; --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = true
+L["Icon Base Height"] = true;
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = true
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = true
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = true
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = true
+L["If enabled then the filter will only activate when you are in combat."] = true
+L["If enabled then the filter will only activate when you are out of combat."] = true
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = true
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = true
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["Instance Type"] = true
+L["Interruptible"] = true
+L["Is Targeted"] = true
+L["LEVEL_BOSS"] = "Set level to -1 for boss units or set to 0 to disable."
+L["Low Health Threshold"] = true;
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = true
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = true;
+L["Match Player Level"] = true
+L["Maximum Level"] = true
+L["Maximum Time Left"] = true
+L["Minimum Level"] = true
+L["Minimum Time Left"] = true
+L["Missing"] = true
+L["Name Color"] = true
+L["Name Only"] = true
+L["NamePlates"] = true;
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = true;
+L["Not Targeted"] = true
+L["Off Cooldown"] = true
+L["On Cooldown"] = true
+L["Over Health Threshold"] = true
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = true;
+L["Player Health"] = true
+L["Player in Combat"] = true
+L["Player Out of Combat"] = true
+L["Reaction Colors"] = true;
+L["Reaction Type"] = true
+L["Remove a Name from the list."] = true
+L["Remove Name"] = true;
+L["Remove Nameplate Filter"] = true
+L["Require All"] = true
+L["Reset filter priority to the default state."] = true;
+L["Reset Priority"] = true;
+L["Return filter to its default state."] = true
+L["Scale of the nameplate that is targetted."] = true;
+L["Select Nameplate Filter"] = true
+L["Set Settings to Default"] = true;
+L["Set the transparency level of nameplates that are not the target nameplate."] = true;
+L["Set to either stack nameplates vertically or allow them to overlap."] = true;
+L["Shortcut to 'Filters' section of the config."] = true;
+L["Shortcut to global filters."] = true
+L["Shortcuts"] = true;
+L["Side Arrows"] = true
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = true
+L["Tagged NPC"] = true;
+L["Tanked Color"] = true;
+L["Target Indicator Color"] = true
+L["Target Indicator"] = true
+L["Target Scale"] = true;
+L["Targeted Nameplate"] = true
+L["Texture"] = true
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = true;
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = true;
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = true
+L["Threat"] = true;
+L["Time To Hold"] = true;
+L["Toggle Off While In Combat"] = true;
+L["Toggle On While In Combat"] = true;
+L["Top Arrow"] = true
+L["Triggers"] = true
+L["Under Health Threshold"] = true
+L["Unit Type"] = true
+L["Use Class Color"] = true;
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = true;
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = true;
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = true;
+L["Use Target Glow"] = true;
+L["Use Target Scale"] = true;
+L["Use Threat Color"] = true;
+L["You can't remove a default name from the filter, disabling the name."] = true;
+
+--Profiles Export/Import
+L["Choose Export Format"] = true;
+L["Choose What To Export"] = true;
+L["Decode Text"] = true;
+L["Error decoding data. Import string may be corrupted!"] = true;
+L["Error exporting profile!"] = true;
+L["Export Now"] = true;
+L["Export Profile"] = true;
+L["Exported"] = true;
+L["Filters (All)"] = true;
+L["Filters (NamePlates)"] = true;
+L["Filters (UnitFrames)"] = true;
+L["Global (Account Settings)"] = true;
+L["Import Now"] = true;
+L["Import Profile"] = true;
+L["Importing"] = true;
+L["Plugin"] = true;
+L["Private (Character Settings)"] = true;
+L["Profile imported successfully!"] = true;
+L["Profile Name"] = true;
+L["Profile"] = true;
+L["Table"] = true;
+
+--Skins
+L["Achievement Frame"] = true;
+L["Alert Frames"] = true;
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = true;
+L["BG Map"] = true;
+L["BG Score"] = true;
+L["Barbershop Frame"] = true;
+L["Calendar Frame"] = true;
+L["Character Frame"] = true;
+L["Debug Tools"] = true;
+L["Dressing Room"] = true;
+L["GM Chat"] = true;
+L["Gossip Frame"] = true;
+L["Greeting Frame"] = true;
+L["Guild Bank"] = true;
+L["Guild Registrar"] = true;
+L["Help Frame"] = true;
+L["Inspect Frame"] = true;
+L["KeyBinding Frame"] = true;
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = true;
+L["Macro Frame"] = true;
+L["Mail Frame"] = true;
+L["Merchant Frame"] = true;
+L["Mirror Timers"] = true;
+L["Misc Frames"] = true;
+L["Petition Frame"] = true;
+L["PvP Frames"] = true;
+L["Quest Frames"] = true;
+L["Raid Frame"] = true;
+L["Skins"] = true;
+L["Socket Frame"] = true;
+L["Spellbook"] = true;
+L["Stable"] = true;
+L["Tabard Frame"] = true;
+L["Talent Frame"] = true;
+L["Taxi Frame"] = true;
+L["Time Manager"] = true;
+L["Trade Frame"] = true;
+L["TradeSkill Frame"] = true;
+L["Trainer Frame"] = true;
+L["Tutorial Frame"] = true;
+L["World Map"] = true;
+
+--Tooltip
+L["Always Hide"] = true;
+L["Bags Only"] = true;
+L["Bags/Bank"] = true;
+L["Bank Only"] = true;
+L["Both"] = true;
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = true;
+L["Comparison Font Size"] = true;
+L["Cursor Anchor"] = true;
+L["Custom Faction Colors"] = true;
+L["Display guild ranks if a unit is guilded."] = true;
+L["Display how many of a certain item you have in your possession."] = true;
+L["Display player titles."] = true;
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = true;
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = true;
+L["Guild Ranks"] = true;
+L["Header Font Size"] = true;
+L["Health Bar"] = true;
+L["Hide tooltip while in combat."] = true;
+L["Inspect Info"] = true;
+L["Item Count"] = true;
+L["Never Hide"] = true;
+L["Player Titles"] = true;
+L["Should tooltip be anchored to mouse cursor"] = true;
+L["Spell/Item IDs"] = true;
+L["Target Info"] = true;
+L["Text Font Size"] = true;
+L["This setting controls the size of text in item comparison tooltips."] = true;
+L["Tooltip Font Settings"] = true;
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = true;
+
+--UnitFrames
+L["%s and then %s"] = true;
+L["2D"] = true;
+L["3D"] = true;
+L["Above"] = true;
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = true;
+L["Add a spell to the filter."] = true;
+L["Add Spell ID or Name"] = true;
+L["Add SpellID"] = true;
+L["Additional Filter Override"] = true;
+L["Additional Filter"] = true;
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = true;
+L["Allow Whitelisted Auras"] = true;
+L["An X offset (in pixels) to be used when anchoring new frames."] = true;
+L["An Y offset (in pixels) to be used when anchoring new frames."] = true;
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = true;
+L["Assist Frames"] = true;
+L["Assist Target"] = true;
+L["At what point should the text be displayed. Set to -1 to disable."] = true;
+L["Attach Text To"] = true;
+L["Attach To"] = true;
+L["Aura Bars"] = true;
+L["Auto-Hide"] = true;
+L["Bad"] = true;
+L["Bars will transition smoothly."] = true;
+L["Below"] = true;
+L["Blacklist Modifier"] = true;
+L["Blacklist"] = true;
+L["Block Auras Without Duration"] = true;
+L["Block Blacklisted Auras"] = true;
+L["Block Non-Dispellable Auras"] = true;
+L["Block Non-Personal Auras"] = true;
+L["Block Raid Buffs"] = true;
+L["Blood"] = true;
+L["Borders"] = true;
+L["Buff Indicator"] = true;
+L["Buffs"] = true;
+L["By Type"] = true;
+L["Castbar"] = true;
+L["Center"] = true;
+L["Check if you are in range to cast spells on this specific unit."] = true;
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = true;
+L["Class Backdrop"] = true;
+L["Class Castbars"] = true;
+L["Class Color Override"] = true;
+L["Class Health"] = true;
+L["Class Power"] = true;
+L["Class Resources"] = true;
+L["Click Through"] = true;
+L["Color all buffs that reduce the unit's incoming damage."] = true;
+L["Color aurabar debuffs by type."] = true;
+L["Color castbars by the class of player units."] = true;
+L["Color castbars by the reaction type of non-player units."] = true;
+L["Color health by amount remaining."] = true;
+L["Color health by classcolor or reaction."] = true;
+L["Color power by classcolor or reaction."] = true;
+L["Color the health backdrop by class or reaction."] = true;
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = true;
+L["Color Turtle Buffs"] = true;
+L["Color"] = true;
+L["Colored Icon"] = true;
+L["Coloring (Specific)"] = true;
+L["Coloring"] = true;
+L["Combat Fade"] = true;
+L["Combat Icon"] = true;
+L["Combo Point"] = true;
+L["Combobar"] = true;
+L["Configure Auras"] = true;
+L["Copy From"] = true;
+L["Count Font Size"] = true;
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = true;
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = true;
+L["Create Custom Text"] = true
+L["Create Filter"] = true;
+L["Current - Max | Percent"] = true;
+L["Current - Max"] = true;
+L["Current - Percent"] = true;
+L["Current / Max"] = true;
+L["Current"] = true;
+L["Custom Dead Backdrop"] = true;
+L["Custom Health Backdrop"] = true;
+L["Custom Texts"] = true;
+L["Death"] = true;
+L["Debuff Highlighting"] = true;
+L["Debuffs"] = true;
+L["Decimal Threshold"] = true;
+L["Deficit"] = true;
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = true;
+L["Delete Filter"] = true;
+L["Detach From Frame"] = true;
+L["Detached Width"] = true;
+L["Direction the health bar moves when gaining/losing health."] = true;
+L["Disable Debuff Highlight"] = true;
+L["Disabled Blizzard Frames"] = true;
+L["Disabled"] = true;
+L["Disables the focus and target of focus unitframes."] = true;
+L["Disables the player and pet unitframes."] = true;
+L["Disables the target and target of target unitframes."] = true;
+L["Disconnected"] = true;
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = true;
+L["Display Frames"] = true;
+L["Display Player"] = true;
+L["Display Target"] = true;
+L["Display Text"] = true;
+L["Display the castbar icon inside the castbar."] = true;
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = true;
+L["Display the combat icon on the unitframe."] = true;
+L["Display the rested icon on the unitframe."] = true;
+L["Display the target of your current cast. Useful for mouseover casts."] = true;
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = true;
+L["Don't display any auras found on the 'Blacklist' filter."] = true;
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that are not yours."] = true;
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that cannot be purged or dispelled by your class."] = true;
+L["Don't display auras that have no duration."] = true;
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = true;
+L["Dungeon & Raid Filter"] = true;
+L["Duration Reverse"] = true;
+L["Duration Text"] = true;
+L["Duration"] = true;
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = true;
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = true;
+L["Enemy Aura Type"] = true;
+L["Fade the unitframe when out of combat, not casting, no target exists."] = true;
+L["Fill"] = true;
+L["Filled"] = true;
+L["Filter Type"] = true;
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = true;
+L["Force On"] = true;
+L["Force Reaction Color"] = true;
+L["Force the frames to show, they will act as if they are the player frame."] = true;
+L["Forces Debuff Highlight to be disabled for these frames"] = true;
+L["Forces reaction color instead of class color on units controlled by players."] = true;
+L["Format"] = true;
+L["Frame Level"] = true;
+L["Frame Orientation"] = true;
+L["Frame Strata"] = true;
+L["Frame"] = true;
+L["Frequent Updates"] = true;
+L["Friendly Aura Type"] = true;
+L["Friendly"] = true;
+L["Frost"] = true;
+L["Glow"] = true; --Also used in NamePlates
+L["Good"] = true;
+L["GPS Arrow"] = true;
+L["Group By"] = true;
+L["Grouping & Sorting"] = true;
+L["Groups Per Row/Column"] = true;
+L["Growth direction from the first unitframe."] = true;
+L["Growth Direction"] = true;
+L["Heal Prediction"] = true;
+L["Health Backdrop"] = true;
+L["Health Border"] = true;
+L["Health By Value"] = true;
+L["Health"] = true;
+L["Height"] = true;
+L["Horizontal Spacing"] = true;
+L["Horizontal"] = true; --Also used in bags module
+L["Icon Inside Castbar"] = true;
+L["Icon Size"] = true;
+L["Icon"] = true;
+L["Icon: BOTTOM"] = true;
+L["Icon: BOTTOMLEFT"] = true;
+L["Icon: BOTTOMRIGHT"] = true;
+L["Icon: LEFT"] = true;
+L["Icon: RIGHT"] = true;
+L["Icon: TOP"] = true;
+L["Icon: TOPLEFT"] = true;
+L["Icon: TOPRIGHT"] = true;
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = true;
+L["If not set to 0 then override the size of the aura icon to this."] = true;
+L["If the unit is an enemy to you."] = true;
+L["If the unit is friendly to you."] = true;
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = true;
+L["Ignore mouse events."] = true;
+L["InfoPanel Border"] = true;
+L["Information Panel"] = true;
+L["Inset"] = true;
+L["Inside Information Panel"] = true;
+L["Interruptable"] = true;
+L["Invert Grouping Order"] = true;
+L["JustifyH"] = true;
+L["Latency"] = true;
+L["Left to Right"] = true;
+L["Main statusbar texture."] = true;
+L["Main Tanks / Main Assist"] = true;
+L["Make textures transparent."] = true;
+L["Match Frame Width"] = true;
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true;
+L["Max Bars"] = true;
+L["Max Overflow"] = true;
+L["Maximum Duration"] = true;
+L["Method to sort by."] = true;
+L["Middle Click - Set Focus"] = true;
+L["Middle clicking the unit frame will cause your focus to match the unit."] = true;
+L["Middle"] = true;
+L["Minimum Duration"] = true;
+L["Mouseover"] = true;
+L["Name"] = true; --Also used in Buffs and Debuffs
+L["Neutral"] = true;
+L["Non-Interruptable"] = true;
+L["None"] = true; --Also used in chat
+L["Not valid spell id"] = true;
+L["Num Rows"] = true;
+L["Number of Groups"] = true;
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = true;
+L["Offset position for text."] = true;
+L["Offset"] = true;
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = true;
+L["Only show when you are mousing over a frame."] = true;
+L["OOR Alpha"] = true;
+L["Other Filter"] = true;
+L["Others"] = true;
+L["Overlay the healthbar"] = true;
+L["Overlay"] = true;
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = true;
+L["Override the default class color setting."] = true;
+L["Owners Name"] = true;
+L["Parent"] = true;
+L["Party Pets"] = true;
+L["Party Targets"] = true;
+L["Per Row"] = true;
+L["Percent"] = true;
+L["Personal"] = true;
+L["Pet Name"] = true;
+L["Player Frame Aura Bars"] = true;
+L["Portrait"] = true;
+L["Position Buffs on Debuffs"] = true;
+L["Position Debuffs on Buffs"] = true;
+L["Position"] = true;
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = true;
+L["Power"] = true;
+L["Powers"] = true;
+L["Priority"] = true;
+L["Profile Specific"] = true;
+L["PvP Icon"] = true;
+L["PvP Text"] = true;
+L["PVP Trinket"] = true;
+L["Raid Icon"] = true;
+L["Raid-Wide Sorting"] = true;
+L["Raid40 Frames"] = true;
+L["RaidDebuff Indicator"] = true;
+L["Range Check"] = true;
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = true;
+L["Reaction Castbars"] = true;
+L["Reactions"] = true;
+L["Ready Check Icon"] = true;
+L["Remaining"] = true;
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = true;
+L["Remove a spell from the filter."] = true;
+L["Remove Spell ID or Name"] = true;
+L["Remove SpellID"] = true;
+L["Rest Icon"] = true;
+L["Restore Defaults"] = true; --Also used in Media and ActionBars sections
+L["Right to Left"] = true;
+L["RL / ML Icons"] = true;
+L["Role Icon"] = true;
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = true;
+L["Select a unit to copy settings from."] = true;
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = true;
+L["Select Filter"] = true;
+L["Select Spell"] = true;
+L["Select the display method of the portrait."] = true;
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = true;
+L["Set the font size for unitframes."] = true;
+L["Set the order that the group will sort."] = true;
+L["Set the orientation of the UnitFrame."] = true;
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = true;
+L["Set the type of auras to show when a unit is a foe."] = true;
+L["Set the type of auras to show when a unit is friendly."] = true;
+L["Sets the font instance's horizontal text alignment style."] = true;
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = true;
+L["Show Aura From Other Players"] = true;
+L["Show Auras"] = true;
+L["Show Dispellable Debuffs"] = true;
+L["Show When Not Active"] = true;
+L["Size and Positions"] = true;
+L["Size of the indicator icon."] = true;
+L["Size Override"] = true;
+L["Size"] = true;
+L["Smart Aura Position"] = true;
+L["Smart Raid Filter"] = true;
+L["Smooth Bars"] = true;
+L["Sort By"] = true;
+L["Spaced"] = true;
+L["Spacing"] = true;
+L["Spark"] = true;
+L["Speed in seconds"] = true;
+L["Stack Counter"] = true;
+L["Stack Threshold"] = true;
+L["Start Near Center"] = true;
+L["Statusbar Fill Orientation"] = true;
+L["StatusBar Texture"] = true;
+L["Strata and Level"] = true;
+L["Style"] = true;
+L["Tank Frames"] = true;
+L["Tank Target"] = true;
+L["Tapped"] = true;
+L["Target Glow"] = true;
+L["Target On Mouse-Down"] = true;
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = true;
+L["Text Color"] = true;
+L["Text Format"] = true;
+L["Text Position"] = true;
+L["Text Threshold"] = true;
+L["Text Toggle On NPC"] = true;
+L["Text xOffset"] = true;
+L["Text yOffset"] = true;
+L["Text"] = true;
+L["Textured Icon"] = true;
+L["The alpha to set units that are out of range to."] = true;
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = true;
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = true;
+L["The font that the unitframes will use."] = true;
+L["The initial group will start near the center and grow out."] = true;
+L["The name you have selected is already in use by another element."] = true;
+L["The object you want to attach to."] = true;
+L["Thin Borders"] = true;
+L["This dictates the size of the icon when it is not attached to the castbar."] = true;
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = true;
+L["Threat Display Mode"] = true;
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = true;
+L["Ticks"] = true;
+L["Time Remaining Reverse"] = true;
+L["Time Remaining"] = true;
+L["Transparent"] = true;
+L["Turtle Color"] = true;
+L["Unholy"] = true;
+L["Uniform Threshold"] = true;
+L["UnitFrames"] = true;
+L["Up"] = true;
+L["Use Custom Level"] = true;
+L["Use Custom Strata"] = true;
+L["Use Dead Backdrop"] = true;
+L["Use Default"] = true;
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = true;
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = true;
+L["Use thin borders on certain unitframe elements."] = true;
+L["Use this backdrop color for units that are dead or ghosts."] = true;
+L["Value must be a number"] = true;
+L["Vertical Orientation"] = true;
+L["Vertical Spacing"] = true;
+L["Vertical"] = true; --Also used in bags section
+L["Visibility"] = true;
+L["What point to anchor to the frame you set to attach to."] = true;
+L["What to attach the buff anchor frame to."] = true;
+L["What to attach the debuff anchor frame to."] = true;
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = true;
+L["Whitelist"] = true;
+L["Width"] = true; --Also used in NamePlates module
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = true;
+L["xOffset"] = true;
+L["yOffset"] = true;
+L["You can't remove a pre-existing filter."] = true;
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = true;
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = true;
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/French_Config.lua b/ElvUI_Config/Locales/French_Config.lua
new file mode 100644
index 0000000..55b57ed
--- /dev/null
+++ b/ElvUI_Config/Locales/French_Config.lua
@@ -0,0 +1,1130 @@
+-- French localization file for frFR.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0");
+local L = AceLocale:NewLocale("ElvUI", "frFR");
+if not L then return; end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "Configure les icônes qui apparaissent près de la Minicarte."
+L["BAGS_DESC"] = "Ajuster les paramètres des sacs pour ElvUI."
+L["CHAT_DESC"] = "Ajuste les paramètres du Chat pour ElvUI."
+L["DATATEXT_DESC"] = "Affiche à l'écran des textes d'informations."
+L["ELVUI_DESC"] = "ElvUI est une interface de remplacement complète pour World of Warcraft"
+L["NAMEPLATE_DESC"] = "Modifier la configuration des noms d'unités"
+L["PANEL_DESC"] = "Ajuste la largeur et la hauteur des fenêtres de chat, cela ajuste aussi les sacs."
+L["SKINS_DESC"] = "Ajuste les paramètres d'habillage."
+L["TOGGLESKIN_DESC"] = "Active ou désactive l'habillage ElvUI des éléments ci-dessous."
+L["TOOLTIP_DESC"] = "Configuration des Infobulles."
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[With the new addition of LibItemSearch, you now have access to much more advanced item searches. The following is a documentation of the search syntax. See the full explanation at: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Specific Searching:
+ • q:[quality] or quality:[quality]. For instance, q:epic will find all epic items.
+ • l:[level], lvl:[level] or level:[level]. For example, l:30 will find all items with level 30.
+ • t:[search], type:[search] or slot:[search]. For instance, t:weapon will find all weapons.
+ • n:[name] or name:[name]. For instance, typing n:muffins will find all items with names containing "muffins".
+ • s:[set] or set:[set]. For example, s:fire will find all items in equipment sets you have with names that start with fire.
+ • tt:[search], tip:[search] or tooltip:[search]. For instance, tt:binds will find all items that can be bound to account, on equip, or on pickup.
+
+
+Search Operators:
+ • ! : Negates a search. For example, !q:epic will find all items that are NOT epic.
+ • | : Joins two searches. Typing q:epic | t:weapon will find all items that are either epic OR weapons.
+ • & : Intersects two searches. For instance, q:epic & t:weapon will find all items that are epic AND weapons
+ • >, <, <=, => : Performs comparisons on numerical searches. For example, typing lvl: >30 will find all items with level HIGHER than 30.
+
+
+The following search keywords can also be used:
+ • soulbound, bound, bop : Bind on pickup items.
+ • bou : Bind on use items.
+ • boe : Bind on equip items.
+ • boa : Bind on account items.
+ • quest : Quest bound items.]];
+L["TEXT_FORMAT_DESC"] = [[Entrer une séquence pour changer le format du texte.
+
+Exemples:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+Formats de la Vie / des Ressources:
+"current" - Quantité actuelle
+"percent" - Quantité en pourcentage
+"current-max" - Quantité actuelle maximale, n'affichera seulement la quantité maximale si la quantité actuelle est égale au maximum.
+"current-percent" - Quantité actuelle suivie par quantité en pourcentage, n'affichera seulement la quantité maximale si la quantité actuelle est égale au maximum
+"current-max-percent" - Quantité actuelle, quantité maximale, suivie par quantité en pourcentage, n'affichera seulement la quantité maximale si la quantité actuelle est égale au maximum
+"deficit" - Affiche la valeur du déficit, n'affichera rien si il n'y a pas de déficit
+
+Format des Noms:
+"name:short" - Nom limité à 10 caractères
+"name:medium" - Nom limité à 15 caractères
+"name:long" - Nom limité à 20 caractères
+
+Pour désactiver, laisser le champs vide. Pour plus d'information, merci de visiter http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "Pagination d'action"
+L["ActionBars"] = "Barres d'actions"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = "Autoriser LBF à gérer l'habillage de cet élement."
+L["Alpha"] = "Alpha"
+L["Anchor Point"] = "Point d'ancrage" --also in unitframes
+L["Backdrop Spacing"] = true;
+L["Backdrop"] = "Fond"
+L["Button Size"] = "Taille des boutons"
+L["Button Spacing"] = "Espacement des boutons"
+L["Buttons Per Row"] = "Boutons par ligne"
+L["Buttons"] = "Boutons"
+L["Change the alpha level of the frame."] = "Changer le niveau alpha de la fenêtre."
+L["Color of the actionbutton when not usable."] = true;
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "Couleur du bouton d'action quand il n'y a pas ressource (Mana, Rage)."
+L["Color of the actionbutton when out of range."] = "Couleur du bouton d'action quand hors de portée."
+L["Color of the actionbutton when usable."] = true;
+L["Color when the text is about to expire"] = "Couleur lorsque le texte est sur le point d'expirer."
+L["Color when the text is in the days format."] = "Couleur quand le texte est exprimé en jours."
+L["Color when the text is in the hours format."] = "Couleur quand le texte est exprimé en heure."
+L["Color when the text is in the minutes format."] = "Couleur quand le texte est exprimé en minute."
+L["Color when the text is in the seconds format."] = "Couleur quand le texte est exprimé en seconde."
+L["Cooldown Text"] = "Texte temps de recharge"
+L["Darken Inactive"] = "Foncé Inactif"
+L["Days"] = "Jours"
+L["Display bind names on action buttons."] = "Affiche les noms des raccourcis sur les boutons de la barre d'action."
+L["Display cooldown text on anything with the cooldown spiral."] = "Affiche le temps de recharge au format numérique plutôt que la spirale d'origine."
+L["Display macro names on action buttons."] = "Affiche les noms des macros sur les boutons dans la barre d'action."
+L["Expiring"] = "Expiration"
+L["Global Fade Transparency"] = true;
+L["Height Multiplier"] = "Multiplicateur hauteur"
+L["Hours"] = "Heures"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = true;
+L["Inherit Global Fade"] = true;
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = true;
+L["Key Down"] = "Touche enfoncée"
+L["Keybind Mode"] = "Mode raccourcis"
+L["Keybind Text"] = "Texte des raccourcis"
+L["LBF Support"] = "Support de LFB"
+L["Low Threshold"] = "Seuil minimal"
+L["Macro Text"] = "Texte sur Macro"
+L["Minutes"] = "Minutes"
+L["Mouse Over"] = "Au survol"
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "Multiplie la hauteur ou la largeur de l'arrière-plan par cette valeur. Très utile si vous souhaitez avoir une barre de plus en arrière-plan."
+L["Not Usable"] = true;
+L["Out of Power"] = "Sans ressource"
+L["Out of Range"] = "Hors de portée"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "Restaurer la barre"
+L["Restore the actionbars default settings"] = "Restaure la barre d'actions avec ses paramètres par défaut."
+L["Seconds"] = "Secondes"
+L["Show Empty Buttons"] = true;
+L["The amount of buttons to display per row."] = "Nombre de boutons à afficher par ligne."
+L["The amount of buttons to display."] = "Nombre de boutons à afficher."
+L["The button you must hold down in order to drag an ability to another action button."] = "Définir la touche qui doit être maintenue enfoncée pour pouvoir glisser une capacité sur un autre bouton d'action."
+L["The first button anchors itself to this point on the bar."] = "Ancrage du premier bouton sur le point de la barre."
+L["The size of the action buttons."] = "Taille des boutons d'action."
+L["The spacing between the backdrop and the buttons."] = true;
+L["This setting will be updated upon changing stances."] = "Ce réglage sera activé lors d'un changement de posture"
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "Seuil avant que le texte devienne rouge sous forme de décimal. Mettre -1 pour qu'il ne devienne jamais rouge."
+L["Toggles the display of the actionbars backdrop."] = "Affiche ou non la couleur de fond de la barre d'action."
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = true;
+L["Usable"] = true;
+L["Visibility State"] = "État de visibilité"
+L["Width Multiplier"] = "Multiplicateur largeur"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[Ceci fonctionne comme une macro, vous pouvez exécuter différentes situations pour avoir une pagination de la barre d'actions différente.
+Exemple: [combat] 2;]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[Ceci fonctionne comme une macro, vous pouvez exécuter différentes situations pour afficher ou masquer la barre d'actions différemment.
+Exemple: [combat] show;hide]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = true;
+L["Add Item or Search Syntax"] = true;
+L["Adjust the width of the bag frame."] = "Ajuster la largeur de la fenêtre du sac."
+L["Adjust the width of the bank frame."] = "Ajuster la largeur de la fenêtre du sac de banque."
+L["Ascending"] = "Ascendant"
+L["Bag Sorting"] = "Tri des sacs"
+L["Bag-Bar"] = "Barre des sacs"
+L["Bar Direction"] = "Direction de la barre"
+L["Blizzard Style"] = "Style Blizzard"
+L["Bottom to Top"] = "Du bas vers le haut"
+L["Button Size (Bag)"] = "Taille des boutons (Sac)"
+L["Button Size (Bank)"] = "Taille des boutons (Banque)"
+L["Clear Search On Close"] = true;
+L["Condensed"] = "Condensé"
+L["Descending"] = "Descendant"
+L["Direction the bag sorting will use to allocate the items."] = "Direction du tri du sac qui sera utilisé pour allouer les objets."
+L["Disable Bag Sort"] = true;
+L["Disable Bank Sort"] = true;
+L["Display Item Level"] = "Afficher le niveau d'objet"
+L["Displays item level on equippable items."] = "Afficher le niveau d'objet sur les objets qui peuvent être équipés."
+L["Enable/Disable the all-in-one bag."] = "Activer / désactiver le sac tout-en-un."
+L["Enable/Disable the Bag-Bar."] = "Activer / Désactiver la barre des sacs."
+L["Full"] = "Plein" -- we talk about bags, so full means "plein" instead of "complet"
+L["Global"] = true;
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = true;
+L["Ignored Items and Search Syntax (Global)"] = true;
+L["Ignored Items and Search Syntax (Profile)"] = true;
+L["Item Count Font"] = "Police d'équipement du compteur" --need review
+L["Item Level Threshold"] = "Seuil de niveau d'objet"
+L["Item Level"] = "Niveau d'objet"
+L["Money Format"] = "Format monétaire"
+L["Panel Width (Bags)"] = "Largeur du panneau (Sac)"
+L["Panel Width (Bank)"] = "Largeur du panneau (Banque)"
+L["Search Syntax"] = "Syntaxe pour la recherche"
+L["Set the size of your bag buttons."] = "Définissez la taille de vos boutons de sac."
+L["Short (Whole Numbers)"] = "Court (nombres entiers)"
+L["Short"] = "Court"
+L["Smart"] = "Intelligent"
+L["Sort Direction"] = "Type de direction" --Also used in Buffs and Debuffs
+L["Sort Inverted"] = "Tri inversé"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "La direction des fenêtres de sac (Horizontale ou Verticale)."
+L["The direction that the bag frames will grow from the anchor."] = "La direction que prendra la barre des sacs en partant du point d'ancrage."
+L["The display format of the money text that is shown at the top of the main bag."] = "Le format d'affichage de l'argent que vous avez visible en haut du sac principal."
+L["The frame is not shown unless you mouse over the frame."] = "Le cadre est invisible tant que vous n'avez pas passé votre souris dessus."
+L["The minimum item level required for it to be shown."] = "Le niveau d'objet minimum requis pour être affiché"
+L["The size of the individual buttons on the bag frame."] = "La taille des boutons individuels sur la fenêtre du sac."
+L["The size of the individual buttons on the bank frame."] = "La taille des boutons individuels sur la fenêtre de la banque."
+L["The spacing between buttons."] = "Espacement entre deux boutons."
+L["Top to Bottom"] = "Du haut vers le bas"
+L["Use coin icons instead of colored text."] = "Utiliser les icônes de pièces au lieu du texte coloré."
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "Buffs et Debuffs";
+L["Begin a new row or column after this many auras."] = "Commencer une nouvelle ligne ou colonne après cette limite d'auras."
+L["Count xOffset"] = "Décalage X de la pile"
+L["Count yOffset"] = "Décalage Y de la pile"
+L["Defines how the group is sorted."] = "Définit la façon dont le groupe est trié."
+L["Defines the sort order of the selected sort method."] = "Définit l'ordre de tri selon la méthode choisie (Ascendant/Descendant)"
+L["Disabled Blizzard"] = "Désactiver Blizzard"
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "Seuil du fondu"
+L["Index"] = "Index"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "Indique si les améliorations que vous lancez doivent être séparées avant ou après."
+L["Limit the number of rows or columns."] = "Limiter le nombre de lignes ou de colonnes."
+L["Max Wraps"] = "Retour à la ligne maximale"
+L["No Sorting"] = "Aucun tri"
+L["Other's First"] = "Les autres en premier"
+L["Remaining Time"] = "Temps restant"
+L["Reminder"] = true
+L["Reverse Style"] = "Style inversé"
+L["Seperate"] = "Séparer"
+L["Set the size of the individual auras."] = "Définit la taille de l'aura individuelle."
+L["Sort Method"] = "Méthode de tri"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = "Sens de progression des Auras sur la ligne et comment elles vont se comporter une fois la limite atteinte."
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "Seuil avant que le texte devienne rouge, se met en forme décimale, et l'icône s'estompera. Régler sur -1 pour désactiver."
+L["Time xOffset"] = "Décalage X du temps"
+L["Time yOffset"] = "Décalage Y du temps"
+L["Time"] = "Temps"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = "Quand activé, les icônes des buffs actifs vont s'éclairer au lieu de devenir sombre, quand inactif les icônes des buffs deviendront sombre au lieu de s'éclaircir"
+L["Wrap After"] = "Retour à la ligne après"
+L["Your Auras First"] = "Vos Auras en premier"
+
+--Chat
+L["Above Chat"] = "En-dessus du Chat"
+L["Adjust the height of your right chat panel."] = "Ajuste la hauteur de la fenêtre de discussion de droite."
+L["Adjust the width of your right chat panel."] = "Ajuste la largeur de la fenêtre de discussion de droite."
+L["Alerts"] = "Alertes"
+L["Allowed Combat Repeat"] = true;
+L["Attempt to create URL links inside the chat."] = "Tentative pour créer un lien URL dans les fenêtres de discussion."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "Tentative pour verrouiller les positions gauche et droite du cadre de discussion. La désactivation de cette option vous permet de déplacer la fenêtre de discussion principale où vous le souhaitez."
+L["Below Chat"] = "En-dessous du Chat"
+L["Chat EditBox Position"] = "Position de la fenêtre de saisie du Chat"
+L["Chat History"] = "historique de la discussion"
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = true;
+L["Custom Timestamp Color"] = true;
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "Afficher une infobulle pendant le survol d'un lien d'objet, sort, etc...."
+L["Enable the use of separate size options for the right chat panel."] = "Activer cette option pour utiliser une taille spécifique de la fenêtre de discussion de droite."
+L["Exclude Name"] = true;
+L["Excluded names will not be class colored."] = true;
+L["Excluded Names"] = true;
+L["Fade Chat"] = "Estomper la discussion"
+L["Fade Tabs No Backdrop"] = "Estomper les onglets sans arrière-plan"
+L["Fade the chat text when there is no activity."] = "Estomper la discussion quand il n'y a pas d'activité"
+L["Fade Undocked Tabs"] = "Estompe l'affiche des onglets non groupés"
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = true;
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = true;
+L["Font Outline"] = "Contours extérieurs de la police" --Also used in UnitFrames section
+L["Font"] = "Police"
+L["Hide Both"] = "Masquer les deux"
+L["Hyperlink Hover"] = "Survol des liens"
+L["Keyword Alert"] = "Alerte mots-clés"
+L["Keywords"] = "Mots-clés"
+L["Left Only"] = "Gauche seulement"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "Liste des mots à colorer dans la fenêtre de discussion s'ils y sont trouvés. Si vous souhaitez ajouter plusieurs mots, vous devez séparer le mot avec une virgule. Pour rechercher votre nom actuel, vous pouvez utiliser %MYNAME%.\n\nExemple:\n%MYNAME%, ElvUI, RBG, Tank"
+L["Lock Positions"] = "Verrouiller les positions"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "Active la fenêtre principale de l'historique de discussion. Ainsi quand vous rechargez l'interface ou effectuez une connexion / déconnexion, vous voyez l'historique de la dernière session"
+L["No Alert In Combat"] = "Pas d'alerte en combat"
+L["Number of messages you scroll for each step."] = true;
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = true;
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "Temps en secondes pour faire défiler vers le bas de la fenêtre de discussion si vous ne l'avez pas fait défiler jusqu'en bas."
+L["Panel Backdrop"] = "Arrière-plan de la fenêtre de discussion"
+L["Panel Height"] = "Hauteur de la fenêtre de discussion"
+L["Panel Texture (Left)"] = "Texture de la fenêtre de discussion (Gauche)"
+L["Panel Texture (Right)"] = "Texture de la fenêtre de discussion (Droite)"
+L["Panel Width"] = "Largeur de la fenêtre de discussion"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "Postion du cadre d'écriture de la fenêtre de Chat. Si les Texte d'informations sont désactivés, elle apparaitra au dessus du Chat."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "Empêche l'affichage du même message plus d'une fois dans la fenêtre de discussion durant un laps de temps. Définir sur 0 pour désactiver."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = true;
+L["Right Only"] = "Droite seulement"
+L["Right Panel Height"] = "Hauteur de la fenêtre de discussion de droite"
+L["Right Panel Width"] = "Largeur de la fenêtre de discussion de droite"
+L["Scroll Interval"] = "Intervalle de défilement"
+L["Scroll Messages"] = true;
+L["Separate Panel Sizes"] = "Séparer la taille des fenêtres de discussion."
+L["Set the font outline."] = "Configure le contour extérieur de la police." --Also used in UnitFrames section
+L["Short Channels"] = "Raccourcis canaux"
+L["Shorten the channel names in chat."] = "Minimise le nom des canaux de discussion."
+L["Show Both"] = "Afficher les deux"
+L["Spam Interval"] = "Intervalle contre le Spam"
+L["Sticky Chat"] = "Fenêtre de chat adhésive"
+L["Tab Font Outline"] = "Contour de la police extérieure des onglets"
+L["Tab Font Size"] = "Taille de la police des onglets"
+L["Tab Font"] = "Police des onglets"
+L["Tab Panel Transparency"] = "Transparence de l'étiquette"
+L["Tab Panel"] = "Étiquette de l'onglet"
+L["Timestamp Color"] = true;
+L["Toggle showing of the left and right chat panels."] = "Afficher ou masquer le côté gauche / droit des panneaux de discussion."
+L["Toggle the chat tab panel backdrop."] = "Affiche le fond de l'onglet du panneau de discussion."
+L["URL Links"] = "Liens URL"
+L["Use Alt Key"] = true;
+L["Use class color for the names of players when they are mentioned."] = true;
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "Permet de retenir les derniers messages sur le canal de discussion que vous avez utilisé . Si cette option est désactivé, le canal utilisé par défaut sera Dire."
+L["Whisper Alert"] = "Alerte chuchotement"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[Indiquez un nom de fichier situé dans le répertoire World of Warcraft, le dossier des Textures que vous souhaitez utiliser en fond de panneau.
+
+Notez:
+La taille de l'image recommandée est de 256x128 pixels
+Vous devez redémarrer le jeu après avoir ajouté un fichier dans le dossier.
+Le format du fichier doit être en .tga
+
+Exemple: Interface\AddOns\ElvUI\media\textures\copy
+
+Ou pour la majorité des utilsateurs, il serait plus simple de mettre le fichier tga dans le dossier de World of Warcraft puis de taper son nom ici.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "Codage: "
+L["Credits"] = "Crédits"
+L["Donations:"] = "Donateurs: "
+L["ELVUI_CREDITS"] = "Je voudrais remercier tout spécialement ceux qui m'ont aidé à maintenir cet addon avec les codeurs, testeurs et les personnes qui m’ont aussi aidé via les dons. Veuillez noter que pour les dons, je n’affiche seulement les noms des personnes qui m’ont envoyés un message privé sur le forum. Si votre nom est absent et que vous désirez que je l'ajoute, merci de m’envoyer un message privé."
+L["Testing:"] = "Testeurs: "
+
+--DataBars
+L["Current - Percent (Remaining)"] = true;
+L["Current - Remaining"] = true;
+L["DataBars"] = true;
+L["Hide In Combat"] = true;
+L["Setup on-screen display of information bars."] = "Configuration de l'affichage des différentes barres d'expérience"
+
+--DataTexts
+L["Battleground Texts"] = "Textes des Champs de bataille"
+L["Block Combat Click"] = "Emêcher le clic en combat"
+L["Block Combat Hover"] = "Empêcher le survol en combat"
+L["Blocks all click events while in combat."] = "Empêcher tous les clics d'évenements durant le combat."
+L["Blocks datatext tooltip from showing in combat."] = "Empêcher l'affichage des infobulles des textes d'informations en combat."
+L["BottomLeftMiniPanel"] = "Minimap BottomLeft (Inside)"
+L["BottomMiniPanel"] = "Minimap Bottom (Inside)"
+L["BottomRightMiniPanel"] = "Minimap BottomRight (Inside)"
+L["Datatext Panel (Left)"] = "Panneaux d'informations (Gauche)"
+L["Datatext Panel (Right)"] = "Panneaux d'informations (Droite)"
+L["DataTexts"] = "Textes d'informations"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "Afficher les panneaux de données sous le Chat utilisés pour les textes d'information"
+L["Display minimap panels below the minimap, used for datatexts."] = "Afficher les panneaux sous la minicarte utilisés pour les textes d'information."
+L["Gold Format"] = "Format monétaire"
+L["left"] = "Gauche"
+L["LeftChatDataPanel"] = "Fenêtre de discussion à gauche"
+L["LeftMiniPanel"] = "Minicarte à gauche"
+L["middle"] = "Milieu"
+L["Minimap Panels"] = "Panneaux de la Minicarte"
+L["Panel Transparency"] = "Transparence du panneau"
+L["Panels"] = "Fenêtre"
+L["right"] = "Droite"
+L["RightChatDataPanel"] = "Fenêtre de discussion à droite"
+L["RightMiniPanel"] = "Minicarte à droite"
+L["Small Panels"] = true;
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = "L'affichage du format de l'argent que vous possédez dans le texte d'informations Argent et dans son infobulle."
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap TopLeft (Inside)"
+L["TopMiniPanel"] = "Minimap Top (Inside)"
+L["TopRightMiniPanel"] = "Minimap TopRight (Inside)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "Lorsqu'à l'intérieur d'un Champs de bataille, afficher le tableau des scores personnel dans la barre de textes d'informations principale."
+L["Word Wrap"] = "Césure des mots"
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "Doit être dans le même groupe avec le joueur s'il n'est pas du même serveur."
+L["Sends your current profile to your target."] = "Envoi votre profil actuel à votre cible."
+L["Sends your filter settings to your target."] = "Envoi vos paramètres de filtre à votre cible."
+L["Share Current Profile"] = "Partagez votre profil actuel"
+L["Share Filters"] = "Partagez les filtres"
+L["This feature will allow you to transfer settings to other characters."] = "Cette fonctionnalité vous permettra de transférer les paramètres à d'autres personnages."
+L["You must be targeting a player."] = "Vous devez cibler un joueur."
+
+--Filters
+L["Reset Aura Filters"] = "Réinitialiser les filtres des auras" --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "Invitations automatiques"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "Ajustez la position de la barre de menace sur le panel des textes d'informations à gauche ou à droite."
+L["AFK Mode"] = "Mode AFK"
+L["Announce Interrupts"] = "Annoncer les Interruptions"
+L["Announce when you interrupt a spell to the specified chat channel."] = "Annonce quand vous interrompez un sort dans le canal de chat spécifié."
+L["Attempt to support eyefinity/nvidia surround."] = "Tente de supporter eyefinity/nvidia surround."
+L["Auto Greed/DE"] = "Dez / Cupidité Auto"
+L["Auto Repair"] = "Réparation automatique"
+L["Auto Scale"] = "Échelle Automatique"
+L["Automatically accept invites from guild/friends."] = "Accepter automatiquement les invitations venant d'amis / joueurs de la Guilde."
+L["Automatically repair using the following method when visiting a merchant."] = "Répare automatiquement votre équipement chez le marchand selon le mode de réparation sélectionné."
+L["Automatically scale the User Interface based on your screen resolution"] = "Redimensionne automatiquement l'Interface Utilisateur en fonction de votre résolution d'écran."
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "Choisi automatiquement la cupidité ou le désenchantement (quand il est disponible) sur les objets inhabituels (vert). Ceci ne fonctionne que si vous êtes au niveau maximum."
+L["Automatically vendor gray items when visiting a vendor."] = "Vendre automatiquement les objets gris quand vous rendez visite à un marchand."
+L["Bottom Panel"] = "Bandeau en bas"
+L["Chat Bubbles Style"] = "Style des bulles de discussion"
+L["Chat Bubbles"] = "Bulles de discussion"
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = "Direction que prend la barre quand gain / perte"
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "Affiche un bandeau au bas de l'écran. Option purement cosmétique."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "Affiche un bandeau en haut de l'écran. Option purement cosmétique."
+L["Display battleground messages in the middle of the screen."] = "Afficher le message du champs de bataille au milieu de l'écran"
+L["Enable/Disable the loot frame."] = "Activer / désactiver le cadre de butin."
+L["Enable/Disable the loot roll frame."] = "Activer / désactiver le cadre du tirage au sort du butin."
+L["Enables the ElvUI Raid Control panel."] = true;
+L["Enhanced PVP Messages"] = "Messages PVP améliorés"
+L["General"] = "Général"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = "Hauteur de la fenêtre des suivis d'objectif, augmenter pour afficher plus d'objectifs"
+L["Hide At Max Level"] = true;
+L["Hide Error Text"] = "Cacher les textes d'erreurs"
+L["Hide In Vehicle"] = true;
+L["Hides the red error text at the top of the screen while in combat."] = "Cacher les textes d'erreurs en haut de l'écran en combat."
+L["Log Taints"] = "Journal des corruptions"
+L["Login Message"] = "Message de connexion"
+L["Loot Roll"] = "Cadre de butin"
+L["Loot"] = "Butin"
+L["Lowest Allowed UI Scale"] = true;
+L["Multi-Monitor Support"] = "Support Multi-Moniteur"
+L["Name Font"] = "Nom de la police"
+L["Number Prefix"] = true;
+L["Party / Raid"] = "Groupe / Raid"
+L["Party Only"] = "Groupe seulement"
+L["Raid Only"] = "Raid seulement"
+L["Remove Backdrop"] = "Supprimer le fond"
+L["Reset all frames to their original positions."] = "Réinitialiser les cadres à leurs positions initiales."
+L["Reset Anchors"] = "Réinitialiser les ancres"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "Envoyer les ADDON_ACTION_BLOCKED dans la fenêtre d'erreur LUA. Ces erreurs sont minimes dans la plupart des cas et n'affecteront pas votre expérience de jeu. Tenez compte que nombreuses de celles-ci ne peuvent être fixé. Signalez-les uniquement si cela affecte grandement le jeu."
+L["Skin Backdrop (No Borders)"] = true;
+L["Skin Backdrop"] = "Habiller le fond"
+L["Skin the blizzard chat bubbles."] = "Habillage des bulles de Chat."
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Police qui apparait sur le texte au dessus de la tête des joueurs. |cffFF0000ATTENTION: requiert un redémarrage du jeu ou une reconnexion pour que les changements soient pris en compte.|r"
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = true;
+L["Thin Border Theme"] = true;
+L["Toggle Tutorials"] = "Afficher les tutoriels"
+L["Top Panel"] = "Bandeau en haut"
+L["Version Check"] = true;
+L["Watch Frame Height"] = true;
+L["When you go AFK display the AFK screen."] = "Quand vous êtes AFK, affiche un écran spécial."
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = true;
+L["Applies the primary texture to all statusbars."] = true;
+L["Apply Font To All"] = true;
+L["Apply Texture To All"] = true;
+L["Backdrop color of transparent frames"] = "Couleur de fond pour les cadres estompés."
+L["Backdrop Color"] = "Couleur de fond"
+L["Backdrop Faded Color"] = "Couleur de fond estompé"
+L["Border Color"] = "Couleur de la bordure"
+L["Color some texts use."] = "Couleur utilisée par les Textes d'informations."
+L["Colors"] = "Couleur de ..." --Also used in UnitFrames
+L["CombatText Font"] = "Police des textes de combat"
+L["Default Font"] = "Police par défaut"
+L["Font Size"] = "Taille de la police" --Also used in UnitFrames
+L["Fonts"] = "Polices"
+L["Main backdrop color of the UI."] = "Couleur principale de fond de l'Interface."
+L["Main border color of the UI."] = true;
+L["Media"] = "Média"
+L["Primary Texture"] = "Texture primaire"
+L["Replace Blizzard Fonts"] = "Remplace les polices Blizzard"
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = true;
+L["Secondary Texture"] = "Texture secondaire"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "Définie la taille de la police d'écriture pour toute l'interface utilisateur. Note: Ceci n'affecte pas les modules qui ont leurs propres paramètres (Portait d'unité, Textes d'Informations, etc)"
+L["Textures"] = "Textures"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "La police qui sera utilisée pour les textes de combat. |cffFF0000Note : Ce changement nécessite de relancer le jeu ou d'une reconnexion pour prendre effet.|r"
+L["The font that the core of the UI will use."] = "La police que le cœur de l'Interface utilisera"
+L["The texture that will be used mainly for statusbars."] = "La texture qui sera utilisé principalement pour la barre de statut."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "Cette texture sera utilisée pour les fenêtres de discussion et les menus déroulants."
+L["Value Color"] = "Couleur des Textes d'informations"
+
+--Maps
+L["Adjust the size of the minimap."] = "Ajuster la taille de la minicarte."
+L["Always Display"] = "Toujours afficher"
+L["Bottom Left"] = "En bas à gauche"
+L["Bottom Right"] = "En bas à droite"
+L["Bottom"] = "En bas"
+L["Change settings for the display of the location text that is on the minimap."] = "Modifier les paramètres pour l'affichage du texte d'emplacement sur la minicarte."
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = true;
+L["Instance Difficulty"] = "Difficulté de l'instance"
+L["Left"] = "Gauche"
+L["LFG Queue"] = "Outil raid"
+L["Location Text"] = "Texte de localisation"
+L["Make the world map smaller."] = "Rendre la carte du monde plus petite"
+L["Maps"] = "Cartes"
+L["Minimap Buttons"] = "Bouton de la minimap"
+L["Minimap Mouseover"] = "Au survol de la Minicarte"
+L["Puts coordinates on the world map."] = "Mettre les coordonnées sur la Carte du Monde"
+L["PvP Queue"] = true
+L["Reset Zoom"] = true;
+L["Right"] = "Droite"
+L["Scale"] = "Echelle"
+L["Smaller World Map"] = "Carte du monde plus petite"
+L["Top Left"] = "En haut à gauche"
+L["Top Right"] = "En haut à droite"
+L["Top"] = "En haut"
+L["World Map Coordinates"] = "Coordonnées de la Carte du Monde"
+L["X-Offset"] = true;
+L["Y-Offset"] = true;
+
+--Misc
+L["Install"] = "Installer"
+L["Run the installation process."] = "Démarrer le processus d'installation."
+L["Toggle Anchors"] = "Afficher les ancres"
+L["Unlock various elements of the UI to be repositioned."] = "Déverrouille divers éléments de l'interface utilisateur pour être repositionné."
+L["Version"] = "Version"
+
+--NamePlates
+L["# Displayed Auras"] = "Auras affichées"
+L["Actions"] = "Actions"
+L["Add Name"] = "Ajouter un nom"
+L["Add Nameplate Filter"] = true
+L["Add Regular Filter"] = "Ajouter un filtre"
+L["Add Special Filter"] = "Ajouter un filtre spécial"
+L["Always Show Target Health"] = "Toujours voir la vie de la cible"
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = true
+L["Background Glow"] = "Brillance du fond"
+L["Bad Color"] = true;
+L["Bad Scale"] = true;
+L["Bad Transition Color"] = true;
+L["Base Height for the Aura Icon"] = true;
+L["Border Glow"] = true
+L["Border"] = "Bordure"
+L["Cast Bar"] = "Barre d'incantation"
+L["Cast Color"] = "Couleur d'incantation"
+L["Cast No Interrupt Color"] = true;
+L["Cast Time Format"] = true;
+L["Casting"] = "Incantation"
+L["Channel Time Format"] = true;
+L["Clear Filter"] = true
+L["Color Tanked"] = "Couleur tankée"
+L["Control enemy nameplates toggling on or off when in combat."] = true;
+L["Control friendly nameplates toggling on or off when in combat."] = true;
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = true;
+L["Cooldowns"] = true
+L["Copy settings from another unit."] = "Copier les options d'une autre unité"
+L["Copy Settings From"] = "Copier les options de"
+L["Current Level"] = "Niveau actuel"
+L["Default Settings"] = "Options par défaut"
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "Affiche un icône soigneur sur le ou les soigneur(s) connu(s) à l'intérieur d'un champ de bataille ou arène"
+L["Elite Icon"] = "Icône élite"
+L["Enable/Disable the scaling of targetted nameplates."] = true;
+L["Enabling this will check your health amount."] = true
+L["Enemy Combat Toggle"] = true;
+L["Enemy NPC Frames"] = "PNJ ennemi"
+L["Enemy Player Frames"] = "Joueur ennemi"
+L["Enemy"] = "Ennemi" --Also used in UnitFrames
+L["ENEMY_NPC"] = "PNJ ennemi"
+L["ENEMY_PLAYER"] = "Joueur ennemi"
+L["Filter already exists!"] = "Le filtre existe déjà !"
+L["Filter Priority"] = true
+L["Filters Page"] = true
+L["Friendly Combat Toggle"] = true;
+L["Friendly NPC Frames"] = "PNJ alliés"
+L["Friendly Player Frames"] = "Joueur allié"
+L["FRIENDLY_NPC"] = "PNJ alliés"
+L["FRIENDLY_PLAYER"] = "Joueur allié"
+L["General Options"] = "Options générales"
+L["Good Color"] = true;
+L["Good Scale"] = true;
+L["Good Transition Color"] = true;
+L["Healer Icon"] = "Icône de soigneur"
+L["Health Color"] = true
+L["Health Threshold"] = true
+L["Hide Frame"] = true
+L["Hide Spell Name"] = true;
+L["Hide Time"] = true;
+L["Hide"] = "Masquer" --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = true
+L["Icon Base Height"] = true;
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = true
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = true
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = true
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = true
+L["If enabled then the filter will only activate when you are in combat."] = true
+L["If enabled then the filter will only activate when you are out of combat."] = true
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = true
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = true
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["Instance Type"] = "Type d'instance"
+L["Interruptible"] = "interrompable"
+L["Is Targeted"] = "est ciblé"
+L["LEVEL_BOSS"] = "Set level to -1 for boss units or set to 0 to disable."
+L["Low Health Threshold"] = "Seuil vie faible"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = true
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = true;
+L["Match Player Level"] = true
+L["Maximum Level"] = "Niveau maximum"
+L["Maximum Time Left"] = true
+L["Minimum Level"] = "Niveau minimum"
+L["Minimum Time Left"] = true
+L["Missing"] = "Manquant"
+L["Name Color"] = "Couleur du nom"
+L["Name Only"] = true
+L["NamePlates"] = "Noms"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = true;
+L["Not Targeted"] = "Non ciblé"
+L["Off Cooldown"] = true
+L["On Cooldown"] = true
+L["Over Health Threshold"] = true
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = true;
+L["Player Health"] = true
+L["Player in Combat"] = "Joueur en combat"
+L["Player Out of Combat"] = true
+L["Reaction Colors"] = "Coloration de la réaction"
+L["Reaction Type"] = true
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "Supprimer un nom"
+L["Remove Nameplate Filter"] = true
+L["Require All"] = true
+L["Reset filter priority to the default state."] = true
+L["Reset Priority"] = true
+L["Return filter to its default state."] = true
+L["Scale of the nameplate that is targetted."] = true;
+L["Select Nameplate Filter"] = true
+L["Set Settings to Default"] = true;
+L["Set the transparency level of nameplates that are not the target nameplate."] = true;
+L["Set to either stack nameplates vertically or allow them to overlap."] = true;
+L["Shortcut to 'Filters' section of the config."] = true
+L["Shortcut to global filters."] = true
+L["Shortcuts"] = "Raccourcis"
+L["Side Arrows"] = true
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = true
+L["Tagged NPC"] = "PNJ marqué"
+L["Tanked Color"] = "Couleur tankée"
+L["Target Indicator Color"] = "Couleur de l'indicateur de la cible"
+L["Target Indicator"] = "Indicateur de la cible"
+L["Target Scale"] = "Taille de la cible"
+L["Targeted Nameplate"] = true
+L["Texture"] = true
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = true
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = true
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = true
+L["Threat"] = "Menace"
+L["Time To Hold"] = true
+L["Toggle Off While In Combat"] = true;
+L["Toggle On While In Combat"] = true;
+L["Top Arrow"] = true
+L["Triggers"] = true
+L["Under Health Threshold"] = true
+L["Unit Type"] = true
+L["Use Class Color"] = true;
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = true;
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = true;
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = true;
+L["Use Target Glow"] = true;
+L["Use Target Scale"] = true;
+L["Use Threat Color"] = true;
+L["You can't remove a default name from the filter, disabling the name."] = "Vous ne pouvez pas supprimer un nom qui est par défaut, cependant celui-ci est désormais désactivé."
+
+--Profiles Export/Import
+L["Choose Export Format"] = "Choisissez le format d'exportation"
+L["Choose What To Export"] = "Choisissez quoi exporter"
+L["Decode Text"] = "Texte décodé" --need review
+L["Error decoding data. Import string may be corrupted!"] = "Erreur lors du décodage des données. Celles-ci sont peut être corropues"
+L["Error exporting profile!"] = "Erreur d'exportation du profil"
+L["Export Now"] = "Exporter maintenant"
+L["Export Profile"] = "Exporter le profil"
+L["Exported"] = "Exporté"
+L["Filters (All)"] = "Filres (Tous)"
+L["Filters (NamePlates)"] = "Filtres (Noms d'unités)"
+L["Filters (UnitFrames)"] = "Filtres (Cadres d'unités)"
+L["Global (Account Settings)"] = "Global (Configuration du compte)"
+L["Import Now"] = "Importer maintenant"
+L["Import Profile"] = "Importer le profil"
+L["Importing"] = "Importation"
+L["Plugin"] = "Plugin"
+L["Private (Character Settings)"] = "Privée (Paramètres du personnages)"
+L["Profile imported successfully!"] = "Profil importé avec succès"
+L["Profile Name"] = "Nom du profil"
+L["Profile"] = "Profil"
+L["Table"] = "Tableau"
+
+--Skins
+L["Achievement Frame"] = "Fenêtre des Hauts Faits"
+L["Alert Frames"] = "Fenêtre d'Alerte"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "Fenêtre de l'Hôtel des ventes"
+L["Barbershop Frame"] = "Salon de Coiffure"
+L["BG Map"] = "Carte Champs de bataille"
+L["BG Score"] = "Scores Champs de bataille"
+L["Calendar Frame"] = "Fenêtre du Calendrier"
+L["Character Frame"] = "Fenêtre du Personnage"
+L["Debug Tools"] = "Outils de débogage"
+L["Dressing Room"] = "Cabine d'essayage"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "Fenêtre PNJ"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "Banque de Guilde"
+L["Guild Registrar"] = "Bannière de Guilde"
+L["Help Frame"] = "Fenêtre d'Assistance clientèle"
+L["Inspect Frame"] = "Fenêtre d'Inspection"
+L["KeyBinding Frame"] = "Raccourcis"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "Fenêtre de butin"
+L["Macro Frame"] = "Fenêtre de Macro"
+L["Mail Frame"] = "Fenêtre du Courrier"
+L["Merchant Frame"] = "Marchand"
+L["Mirror Timers"] = "Fenêtre des Timers mirroirs" --need review
+L["Misc Frames"] = "Divers"
+L["Petition Frame"] = "Fenêtre de Charte"
+L["PvP Frames"] = "Fenêtre JcJ"
+L["Quest Frames"] = "Fenêtre de Quête"
+L["Raid Frame"] = "Fenêtre de Raid"
+L["Skins"] = "Habillage"
+L["Socket Frame"] = "Fenêtre de sertissage"
+L["Spellbook"] = "Grimoire"
+L["Stable"] = "Écurie"
+L["Tabard Frame"] = "Tabard"
+L["Talent Frame"] = "Fenêtre des talents"
+L["Taxi Frame"] = "Trajets aériens"
+L["Time Manager"] = "Chronomètre"
+L["Trade Frame"] = "Fenêtre d'échange"
+L["TradeSkill Frame"] = "Métiers"
+L["Trainer Frame"] = "Entraîneur"
+L["Tutorial Frame"] = true;
+L["World Map"] = "Carte du monde"
+
+--Tooltip
+L["Always Hide"] = "Toujours masqué"
+L["Bags Only"] = "Sacs seulement"
+L["Bags/Bank"] = "Sacs / banque"
+L["Bank Only"] = "Banque seulement"
+L["Both"] = "Les deux"
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = true;
+L["Comparison Font Size"] = true;
+L["Cursor Anchor"] = "Ancrage sur le curseur"
+L["Custom Faction Colors"] = "Couleur de la faction"
+L["Display guild ranks if a unit is guilded."] = "Affiche le rang de la guilde si un joueur est guildé"
+L["Display how many of a certain item you have in your possession."] = "Affiche combien vous avez d'objets de ce type en votre possession."
+L["Display player titles."] = "Affiche le titre du joueur"
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = "Affiche la spécialisation et le niveau d'équipement dans l'info-bulle, ceci peut ne pas être mis à jour immédiatement au premier survol de la souris sur l'unité."
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "Affiche le sort ou l'ID de l'objet dans une infobulle quand vous passez votre souris sur le sort ou l'objet."
+L["Guild Ranks"] = "Rangs de la guilde"
+L["Header Font Size"] = true;
+L["Health Bar"] = "Barre de vie"
+L["Hide tooltip while in combat."] = "Masquer toutes les infobulles quand vous êtes en combat."
+L["Inspect Info"] = "Info inspection"
+L["Item Count"] = "Nombre d'objet"
+L["Never Hide"] = "Jamais caché"
+L["Player Titles"] = "Titre du joueur"
+L["Should tooltip be anchored to mouse cursor"] = "L'infobulle doit être ancrée sur le curseur de la souris"
+L["Spell/Item IDs"] = "ID de l'objet / du sort"
+L["Target Info"] = "Info de la cible"
+L["Text Font Size"] = "Police d'écriture du texte"
+L["This setting controls the size of text in item comparison tooltips."] = true;
+L["Tooltip Font Settings"] = true;
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "Dans un groupe de raid, affiche l'infobulle d une personne ciblée par une autre."
+
+--UnitFrames
+L["%s and then %s"] = "%s et alors %s" --Nedd review
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "Au-dessus"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = true;
+L["Add a spell to the filter."] = "Ajouter un sort au filtre."
+L["Add Spell ID or Name"] = true;
+L["Add SpellID"] = "Ajouter l'identifiant d'un sort"
+L["Additional Filter Override"] = true;
+L["Additional Filter"] = "Filtre Additionnels"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = true;
+L["Allow Whitelisted Auras"] = "Permettre les Auras en Liste Blanche"
+L["An X offset (in pixels) to be used when anchoring new frames."] = "Un décalage X (en pixels) à utiliser lors d'un ancrage d'une nouvelle fenêtre." --need review
+L["An Y offset (in pixels) to be used when anchoring new frames."] = "Un décalage Y (en pixels) à utiliser lors d'un ancrage d'une nouvelle fenêtre." --need review
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = "Ordre ascendant ou descendant."
+L["Assist Frames"] = "Cadre des Soutiens"
+L["Assist Target"] = "Cible de soutien"
+L["At what point should the text be displayed. Set to -1 to disable."] = "A quel moment le texte devrait être affiché. Mettre à -1 pour désactiver."
+L["Attach Text To"] = true;
+L["Attach To"] = "Attacher à"
+L["Aura Bars"] = "Barre d'auras"
+L["Auto-Hide"] = "Masquer Automatiquement"
+L["Bad"] = "Mauvais"
+L["Bars will transition smoothly."] = "La transitions des barres seront fluides."
+L["Below"] = "En dessous"
+L["Blacklist Modifier"] = true;
+L["Blacklist"] = "Liste noire"
+L["Block Auras Without Duration"] = "Bloquer les Auras sans durée"
+L["Block Blacklisted Auras"] = "Bloquer les Auras sur liste Noir"
+L["Block Non-Dispellable Auras"] = "Bloquer les Auras non dissipable"
+L["Block Non-Personal Auras"] = "Bloquer les Auras non personnelle"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "Sang"
+L["Borders"] = "Bordures"
+L["Buff Indicator"] = "Indicateur d'amélioration"
+L["Buffs"] = "Améliorations"
+L["By Type"] = "Par Catégorie"
+L["Castbar"] = "Barre d'incantation"
+L["Center"] = "Centrer"
+L["Check if you are in range to cast spells on this specific unit."] = "Vérifie si vous êtes à portée pour incanter des sorts sur ces unités spécifiques."
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = true;
+L["Class Backdrop"] = "Fond selon la classe"
+L["Class Castbars"] = "Barres d'incantation selon la classe"
+L["Class Color Override"] = "Remplacer les couleurs de classes"
+L["Class Health"] = "Santé selon la Classe"
+L["Class Power"] = "Énergie selon la Classe"
+L["Class Resources"] = "Ressources des Classes"
+L["Click Through"] = "Clic à travers"
+L["Color all buffs that reduce the unit's incoming damage."] = "Colorer toutes les améliorations réduisant les dégâts entrants de l'unité."
+L["Color aurabar debuffs by type."] = "Colore les affaiblissement de la barre d'auras par catégorie."
+L["Color castbars by the class of player units."] = true;
+L["Color castbars by the reaction type of non-player units."] = true;
+L["Color health by amount remaining."] = "Colore le cadre selon la vie restante."
+L["Color health by classcolor or reaction."] = "Colore la vie par la couleur de la classe ou par l'aggro."
+L["Color power by classcolor or reaction."] = "Colore l'énergie de la classe par la couleur de la classe ou par l'aggro."
+L["Color the health backdrop by class or reaction."] = "Colore l'arrière-plan de la barre de vie par la couleur de la classe ou par l'aggro."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "Colore la barre de vie de l'unité qui peut être dissipé par vous-même."
+L["Color Turtle Buffs"] = "Colore les améliorations 'Turtle'" -- Not yet official translation for this term
+L["Color"] = "Couleur"
+L["Colored Icon"] = "Icône Coloré"
+L["Coloring (Specific)"] = "Coloration (Spécifique)"
+L["Coloring"] = "Coloration"
+L["Combat Fade"] = "Estomper hors combat"
+L["Combat Icon"] = true;
+L["Combo Point"] = true;
+L["Combobar"] = true;
+L["Configure Auras"] = "Configure les Auras"
+L["Copy From"] = "Copier depuis"
+L["Count Font Size"] = "Taille du texte du décompte" -- is it count when entering in the BattleGround? ;
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "Créer une chaîne de caractères personnalisée. Une fois que vous aurez entré un nom, vous serez en mesure de la sélectionner au sein de la liste déroulante."
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "Créer un filtre, chaque filtre créé peut être configuré dans la section Amélioration / Affaiblissements de chaque unité."
+L["Create Custom Text"] = true
+L["Create Filter"] = "Créer un filtre"
+L["Current - Max | Percent"] = "Actuel Max | Pourcentage"
+L["Current - Max"] = "Actuel - Max"
+L["Current - Percent"] = "Actuel - Pourcent"
+L["Current / Max"] = "Actuel / Max"
+L["Current"] = "Actuel"
+L["Custom Dead Backdrop"] = true;
+L["Custom Health Backdrop"] = "Fond de vie personnalisé"
+L["Custom Texts"] = "Textes personnalisés"
+L["Death"] = "Mort"
+L["Debuff Highlighting"] = "Surbrillance des affaiblissements" --can we traduct "highlighting" by "surbrillance" ? Yes :)
+L["Debuffs"] = "Affaiblissements"
+L["Decimal Threshold"] = "Seuil décimal"
+L["Deficit"] = "Déficit"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "Supprimer un filtre créé. Vous ne pouvez pas supprimer un filtre préexistant mais seulement ceux que vous avez personnalisé."
+L["Delete Filter"] = "Supprimer un filtre"
+L["Detach From Frame"] = "Détacher du cadre"
+L["Detached Width"] = "Largeur de détachement"
+L["Direction the health bar moves when gaining/losing health."] = "Sens de direction de la barre de vie quand vous en gagnez ou perdez."
+L["Disable Debuff Highlight"] = true;
+L["Disabled Blizzard Frames"] = true;
+L["Disabled"] = "Désactivé"
+L["Disables the focus and target of focus unitframes."] = true;
+L["Disables the player and pet unitframes."] = true;
+L["Disables the target and target of target unitframes."] = true;
+L["Disconnected"] = "Déconnecté"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "Affiche une texture lumineuse à la fin de la barre de sort pour aider à montrer la différence de couleur entre la barre de sort et le fond."
+L["Display Frames"] = "Afficher les cadres"
+L["Display Player"] = "Afficher le joueur"
+L["Display Target"] = "Afficher la cible"
+L["Display Text"] = "Afficher le texte"
+L["Display the castbar icon inside the castbar."] = true;
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = true;
+L["Display the combat icon on the unitframe."] = true;
+L["Display the rested icon on the unitframe."] = "Afficher l'icône reposé sur le portrait d'unité"
+L["Display the target of your current cast. Useful for mouseover casts."] = "Afficher la cible de votre incantation en courts. UTile pour les incantations en survol de souris."
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "Affichage des marques de graduation (ticks) sur la barre de lancement de sort. Cela s'ajustera automatiquement pour les sorts comme Drain d'âme qui est basé sur la Hâte."
+L["Don't display any auras found on the 'Blacklist' filter."] = "Ne pas afficher les auras trouvés dans la 'Liste noire' du filtre."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = "Ne pas afficher les auras qui dépassent cette durée (en secondes). Mettre 0 pour désactiver"
+L["Don't display auras that are not yours."] = "Ne pas afficher les auras qui ne sont pas les votres."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that cannot be purged or dispelled by your class."] = "Ne pas afficher les auras qui ne peuvent pas être purgé ou dissipé votre classe." ;
+L["Don't display auras that have no duration."] = "Ne pas afficher les auras qui n'ont pas de durée."
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "En bas"
+L["Dungeon & Raid Filter"] = "Filtres de donjons et de raid"
+L["Duration Reverse"] = "Durée inversée"
+L["Duration Text"] = true;
+L["Duration"] = "Durée"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = "Activer ceci permet d'afficher le raid en entier mais vous ne serez plus en mesure de distinguer les groupes." --need review
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = "Activer ceci inverse l'ordre du groupe quand il n'est pas complet, ceci inversera son ordre de départ" --need review
+L["Enemy Aura Type"] = "Type d'Aura inamical"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "Estompe les cadres d'unités quand vous êtes hors combat, quand vous ne lancez pas un sort, quand vous ne ciblez personne."
+L["Fill"] = "Remplissage"
+L["Filled"] = "Rempli"
+L["Filter Type"] = "Type de filtre"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "Forcer Off"
+L["Force On"] = "Forcer On"
+L["Force Reaction Color"] = true;
+L["Force the frames to show, they will act as if they are the player frame."] = "Forcer l'affichage des cadres, ils agiront comme sur le cadre de joueur."
+L["Forces Debuff Highlight to be disabled for these frames"] = true;
+L["Forces reaction color instead of class color on units controlled by players."] = true;
+L["Format"] = "Format"
+L["Frame Level"] = true;
+L["Frame Orientation"] = true;
+L["Frame Strata"] = true;
+L["Frame"] = "Fenêtre"
+L["Frequent Updates"] = "Mise à Jours fréquentes"
+L["Friendly Aura Type"] = "Type d'Aura amical"
+L["Friendly"] = "Amical"
+L["Frost"] = "Givre"
+L["Glow"] = "Lueur"
+L["Good"] = "Bonne"
+L["GPS Arrow"] = "Flêche GPS"
+L["Group By"] = "Groupe par"
+L["Grouping & Sorting"] = "Regroupement et tri"
+L["Groups Per Row/Column"] = "Nombres de groupes par ligne/colonne"
+L["Growth direction from the first unitframe."] = "Direction de croissance du premier cadre d'unité."
+L["Growth Direction"] = "Direction de la croissance"
+L["Heal Prediction"] = "Soin prévisionnel"
+L["Health Backdrop"] = "Fond de vie personnalisé"
+L["Health Border"] = "Bordure de la santé personnalisée"
+L["Health By Value"] = "Vie par valeur"
+L["Health"] = "Vie"
+L["Height"] = "Hauteur"
+L["Horizontal Spacing"] = "Espace horizontal"
+L["Horizontal"] = "Horizontale" --Also used in bags module
+L["Icon Inside Castbar"] = true;
+L["Icon Size"] = true;
+L["Icon"] = "Icône"
+L["Icon: BOTTOM"] = "Icône: BAS"
+L["Icon: BOTTOMLEFT"] = "Icône: BAS-GAUCHE"
+L["Icon: BOTTOMRIGHT"] = "Icône: BAS-DROITE"
+L["Icon: LEFT"] = "Icône: GAUCHE"
+L["Icon: RIGHT"] = "Icône: DROITE"
+L["Icon: TOP"] = "Icône: HAUT"
+L["Icon: TOPLEFT"] = "Icône: HAUT-GAUCHE"
+L["Icon: TOPRIGHT"] = "Icône: HAUT-DROITE"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "S'il n'y a pas d'autres options de filtres utilisés alors il bloquera quoi que ce soit sur la 'ListeBlanche' du filtre. Sinon il suffira d'ajouter les auras sur la liste blanche en plus de tous les autres paramètres du filtre." --Need review
+L["If not set to 0 then override the size of the aura icon to this."] = "Si ce n'est pas réglé sur 0, alors remplacer la taille de l'icône d'aura à celui ci."
+L["If the unit is an enemy to you."] ="Si l'unité est votre ennemi."
+L["If the unit is friendly to you."] = "Si l'unité vous est amicale."
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = true;
+L["Ignore mouse events."] = "Ignorer les évènements de la souris."
+L["InfoPanel Border"] = true;
+L["Information Panel"] = true;
+L["Inset"] = "Insérer"
+L["Inside Information Panel"] = true;
+L["Interruptable"] = "Interruptible"
+L["Invert Grouping Order"] = "Inverser l'ordre des groupes"
+L["JustifyH"] = "JustifierH"
+L["Latency"] = "Latence"
+L["Left to Right"] = true;
+L["Main statusbar texture."] = "Texture de la barre principale."
+L["Main Tanks / Main Assist"] = "Tank Principal / Assistant Principal"
+L["Make textures transparent."] = "Mettre les textures transparentes."
+L["Match Frame Width"] = "Accorder à la largeur du cadre"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = "Barres max"
+L["Max Overflow"] = true
+L["Maximum Duration"] = "Durée maximum"
+L["Method to sort by."] = true;
+L["Middle Click - Set Focus"] = "Clic milieu - Réglage du Focus"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "Le clic milieu sur une unité positionera le focus sur celle-ci." --need review
+L["Middle"] = true;
+L["Minimum Duration"] = "Durée minimum"
+L["Mouseover"] = "Au survol de la souris"
+L["Name"] = "Nom" --Also used in Buffs and Debuffs
+L["Neutral"] = "Neutre"
+L["Non-Interruptable"] = "Non-interruptible"
+L["None"] = "Aucun" --Also used in chat
+L["Not valid spell id"] = "ID du sort invalide"
+L["Num Rows"] = "Nombre de lignes"
+L["Number of Groups"] = "Nombre de groupes"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "Décalage de la barre de pouvoir à la barre de vie, mettre 0 pour désactiver."
+L["Offset position for text."] = "Décalage de la position du texte."
+L["Offset"] = "Décalage"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "S'affiche seulement quand l'unité est hors de portée."
+L["Only show when you are mousing over a frame."] = "S'affiche seulement quand vous survolez à la souris une fenêtre."
+L["OOR Alpha"] = "Transparence Hors de portée"
+L["Other Filter"] = "Autre filtre"
+L["Others"] = "Autres"
+L["Overlay the healthbar"] = "Superposé sur la barre de vie"
+L["Overlay"] = "Superposition"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "Remplace tout paramètre de visibilité dans certaines situations, Ex: afficher seulement le groupe 1 et 2 quand vous êtes dans un raid à 10 joueurs."
+L["Override the default class color setting."] = "Remplacer les réglages des couleurs de classes par défaut."
+L["Owners Name"] = "Nom des propriétaires"
+L["Parent"] = true;
+L["Party Pets"] = "Familiers des coéquipiers"
+L["Party Targets"] = "Cible des coéquipiers"
+L["Per Row"] = "par ligne"
+L["Percent"] = "Pourcent"
+L["Personal"] = "Personnel"
+L["Pet Name"] = "Nom familier"
+L["Player Frame Aura Bars"] = true;
+L["Portrait"] = "Portrait"
+L["Position Buffs on Debuffs"] = true;
+L["Position Debuffs on Buffs"] = true;
+L["Position"] = "Position"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "Le texte d'énergie sera masqué sur les PNJ ciblés, de plus le nom sera repositionné sur le texte d'énergie."
+L["Power"] = "Énergie"
+L["Powers"] = "Énergies"
+L["Priority"] = "Priorité"
+L["Profile Specific"] = true;
+L["PvP Icon"] = true;
+L["PvP Text"] = true;
+L["PVP Trinket"] = "Bijou PVP"
+L["Raid Icon"] = "Icône de Raid"
+L["Raid-Wide Sorting"] = "Tri du Raid-Large"
+L["Raid40 Frames"] = "Fenêtre de Raid40"
+L["RaidDebuff Indicator"] = "Indicateur d'affaiblissement en Raid"
+L["Range Check"] = "Verifie la portée"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "Mise à jour rapide de la santé, ce qui augmente la charge de la mémoire et du processeur. Recommandé seulement pour les soigneurs."
+L["Reaction Castbars"] = true;
+L["Reactions"] = "Réactions"
+L["Ready Check Icon"] = true;
+L["Remaining"] = "Restant"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = true;
+L["Remove a spell from the filter."] = "Supprimer un sort depuis le filtre."
+L["Remove Spell ID or Name"] = true;
+L["Remove SpellID"] = "Supprimer l'identifiant d'un sort"
+L["Rest Icon"] = "Icône reposé"
+L["Restore Defaults"] = "Restaurer les paramètres par défaut" --Also used in Media and ActionBars sections
+L["Right to Left"] = true;
+L["RL / ML Icons"] = "Icônes RL / ML"
+L["Role Icon"] = "Icône de rôle"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = true;
+L["Select a unit to copy settings from."] = "Sélectionnez les réglages d'un cadre à copier."
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Sélectionnez un filtre additionnel à utiliser. Si le filtre sélectionné est une liste blanche et qu'aucun autres filtres sont utilisés (à l'exception du bloc des Auras Non-Personnels) alors il bloquera quoi que ce soit qui n'est pas dans la liste blanche, sinon il suffira d'ajouter les auras dans la liste blanche en plus de tous les autres paramètres des filtres." -- headache
+L["Select Filter"] = "Sélectionner un filtre"
+L["Select Spell"] = "Sélectionner un sort"
+L["Select the display method of the portrait."] = "Sélectionnez la méthode d'affichage du portrait."
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = true;
+L["Set the font size for unitframes."] = "Configure la taille de la police d'écriture pour les cadres d'unités."
+L["Set the order that the group will sort."] = "Définir l'ordre du groupe qui sera trié"
+L["Set the orientation of the UnitFrame."] = true;
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "Définir l'ordre de priorité du sort, merci de noter que ces priorités ne sont utilisées que pour le mode d'affaiblissement de raid, ce n'est pas un module améliorations / affaiblissement standard. Si vous souhaitez le désactiver, mettez la valeur sur 0."
+L["Set the type of auras to show when a unit is a foe."] = "Définir le type d'auras à afficher quand l'unité est hostile."
+L["Set the type of auras to show when a unit is friendly."] = "Définir le type d'auras à afficher quand l'unité est amical."
+L["Sets the font instance's horizontal text alignment style."] = "Réglages de l'alignement horizontal du texte de la police d'écriture."
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "Affiche une barre sur la prédiction des soins à venir sur le cadre d'unité. Ainsi qu'une barre de couleur légèrement différente pour les soins entrants excédants."
+L["Show Aura From Other Players"] = "N'importe quelle unité"
+L["Show Auras"] = "Afficher les auras"
+L["Show Dispellable Debuffs"] = true;
+L["Show When Not Active"] = "Afficher les manquants"
+L["Size and Positions"] = "Taille et positions"
+L["Size of the indicator icon."] = "Taille de l'indicateur de l'icône."
+L["Size Override"] = "Forcer la taille"
+L["Size"] = "Taille"
+L["Smart Aura Position"] = true;
+L["Smart Raid Filter"] = "Filtre intelligent de Raid"
+L["Smooth Bars"] = "Barres fluides"
+L["Sort By"] = true;
+L["Spaced"] = "Espacé"
+L["Spacing"] = true;
+L["Spark"] = "Lueur"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = true;
+L["Stack Threshold"] = "Seuil de stack"
+L["Start Near Center"] = "Démarrer près du centre"
+L["Statusbar Fill Orientation"] = true;
+L["StatusBar Texture"] = "Texture de la barre d'état."
+L["Strata and Level"] = true;
+L["Style"] = "Style" --Need review
+L["Tank Frames"] = "Cadre des Tanks"
+L["Tank Target"] = "Cible de Tank"
+L["Tapped"] = "Collé"
+L["Target Glow"] = true;
+L["Target On Mouse-Down"] = "Cibler lors d'un appui sur le clic (et non pas en relachant le clic)" --Need review
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "Cible les unités avec un appui sur le clic souris plutôt qu'au relâchement du clic. \n\n|cffFF0000Attention: Si vous utilisez l'addon 'Clique' vous devrez peut-être ajuster vos paramètres de clic lors du changement de celui-ci."
+L["Text Color"] = "Couleur du texte"
+L["Text Format"] = "Format du texte"
+L["Text Position"] = "Position du texte"
+L["Text Threshold"] = "Seuil du texte"
+L["Text Toggle On NPC"] = "Afficher le texte des PNJ"
+L["Text xOffset"] = "Décalage de l'axe X du texte"
+L["Text yOffset"] = "Décalage de l'axe Y du texte"
+L["Text"] = "Texte"
+L["Textured Icon"] = "Texture de l'icône"
+L["The alpha to set units that are out of range to."] = "Règle la transparence des unités hors de portée."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = "Le debuff doit atteindre ce nombre de stacks pour être affiché. Mettre à 0 pour toujours afficher le débuff"
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "La macro suivante doit être cochée pour que le groupe soit affiché, en plus de la configuration des filtres."
+L["The font that the unitframes will use."] = "Police utilisée par défaut pour les cadres d'unités."
+L["The initial group will start near the center and grow out."] = "Le premier groupe commence à proximité du centre et s'en développe hors."
+L["The name you have selected is already in use by another element."] = "Le nom que vous avez sélectionné est déjà utilisé par un autre élément."
+L["The object you want to attach to."] = "L'objet que vous souhaitez attacher à."
+L["Thin Borders"] = true;
+L["This dictates the size of the icon when it is not attached to the castbar."] = true;
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = true;
+L["Threat Display Mode"] = "Affichage du Mode de Menace."
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = "Seuil avant que le texte ne s'affiche sous forme décimale. Mettre à -1 pour désactiver l'affichage en décimal."
+L["Ticks"] = "Ticks"
+L["Time Remaining Reverse"] = "Temps restant inversé"
+L["Time Remaining"] = "Temps restant"
+L["Transparent"] = "Transparent"
+L["Turtle Color"] = "Couleur 'Turtle'" -- Same
+L["Unholy"] = "Sacré"
+L["Uniform Threshold"] = true;
+L["UnitFrames"] = "Cadre d'unité"
+L["Up"] = "Haut"
+L["Use Custom Level"] = true;
+L["Use Custom Strata"] = true;
+L["Use Dead Backdrop"] = true;
+L["Use Default"] = "Utiliser par défaut"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "Utilise une couleur personnalisé pour colorer le fond de la barre de vie au lieu d'utiliser la couleur par défaut."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = true;
+L["Use thin borders on certain unitframe elements."] = true;
+L["Use this backdrop color for units that are dead or ghosts."] = true;
+L["Value must be a number"] = "La valeur doit être un nombre"
+L["Vertical Orientation"] = true;
+L["Vertical Spacing"] = "Espace vertical"
+L["Vertical"] = "Verticale" --Also used in bags section
+L["Visibility"] = "Visibilité"
+L["What point to anchor to the frame you set to attach to."] = "Quel point d'ancrage sur le cadre vous choisissez à attacher."
+L["What to attach the buff anchor frame to."] = "Choisissez à quoi vous voulez attacher les améliorations sur le cadre."
+L["What to attach the debuff anchor frame to."] = "Choisissez à quoi vous voulez attacher les affaiblissements sur le cadre."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "Quand coché, l'en-tête est affiché lorsque le joueur n'est pas dans un raid."
+L["Whitelist"] = "Liste blanche"
+L["Width"] = "Largeur" --Also used in NamePlates module
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = true;
+L["xOffset"] = "Décalage de l'axe X"
+L["yOffset"] = "Décalage de l'axe Y" --Another variation in bags section Y Offset
+L["You can't remove a pre-existing filter."] = "Vous ne pouvez pas supprimer un filtre préexistant."
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "Vous ne pouvez pas supprimer un sort du filtre qui est par défaut.configurer le sort en 'désactivé'."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = true;
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/German_Config.lua b/ElvUI_Config/Locales/German_Config.lua
new file mode 100644
index 0000000..0a5450f
--- /dev/null
+++ b/ElvUI_Config/Locales/German_Config.lua
@@ -0,0 +1,1131 @@
+-- German localization file for deDE.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "deDE")
+if not L then return end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Konfiguriere die Einstellungen für die Aktionsleisten."
+L["AURAS_DESC"] = "Konfiguriere die Symbole für die Stärkungs- und Schwächungszauber nahe der Minimap."
+L["BAGS_DESC"] = "Konfiguriere die Einstellungen für die Taschen."
+L["CHAT_DESC"] = "Anpassen der Chateinstellungen für ElvUI."
+L["DATATEXT_DESC"] = "Bearbeite die Anzeige der Infotexte."
+L["ELVUI_DESC"] = "ElvUI ist ein komplettes Benutzerinterface für World of Warcraft."
+L["NAMEPLATE_DESC"] = "Konfiguriere die Einstellungen für die Namensplaketten."
+L["PANEL_DESC"] = "Stellt die Größe der linken und rechten Leisten ein, dies hat auch Einfluss auf den Chat und die Taschen."
+L["SKINS_DESC"] = "Passe die Einstellungen für externe Addon Skins/Optionen an."
+L["TOGGLESKIN_DESC"] = "Aktiviere/Deaktiviere diesen Skin."
+L["TOOLTIP_DESC"] = "Konfiguriere die Einstellungen für Tooltips."
+L["UNITFRAME_DESC"] = "Konfiguriere die Einstellungen für die Einheitenfenster."
+L["SEARCH_SYNTAX_DESC"] = [[Mit der Ergänzung von LibItemSearch, kannst du jetzt erweitert nach Gegenständen suchen. Nachfolgend findest du eine Dokumentation des Suchsyntax. Die volle Erklärung findest du hier: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Spezifische Suche:
+ • q:[quality] oder quality:[quality]. Beispielsweise q:episch findet alle epischen Gegenstände.
+ • l:[level], lvl:[level] oder level:[level]. Zum Beispiel: l:30 findet alle Gegenstände mit Level 30.
+ • t:[suche], type:[suche] oder slot:[suche]. Beispielsweise t:waffe findet alle Waffen.
+ • n:[name] oder name:[name]. Beispielsweise wenn du n:muffins eintippst, findest du alle Gegenstände die "muffins" im Namen haben.
+ • s:[set] oder set:[set]. Zum Beispiel: s:feuer findet alle Gegenstände eines Ausrüstungssets mit Feuer im Namen.
+ • tt:[suche], tip:[suche] oder tooltip:[suche]. Beispielsweise tt:gebunden findet alle Gegenstände die am Account, beim Aufheben oder beim Ausrüsten gebunden sind.
+
+
+Suchoperatoren:
+ • ! : Negiert eine Suche. Zum Beispiel !q:episch findet alle Gegenstände die NICHT episch sind.
+ • | : Kombiniert zwei Suchen. q:episch | t:waffe findet alle Gegenstände die episch ODER Waffen sind.
+ • & : Teilt zwei Suchen. Beispielsweise q:episch & t:waffen findet alle Gegenstände die episch UND Waffen sind.
+ • >, <, <=, => : Führt eine numerische Suche durch. Zum Beispiel: lvl: >30 findet alle Gegenstände mit Level 30 oder HÖHER.
+
+
+Die folgenden Suchbegriffe können auch benutzt werden:
+ • soulbound, bound, bop : Beim Aufheben gebundene Gegenstände.
+ • bou : Beim Benutzen gebundene Gegenstände.
+ • boe : Beim Ausrüsten gebundene Gegenstände.
+ • boa : An den Account gebundene Gegenstände.
+ • quest : Gebundene Quest Gegenstände.]];
+L["TEXT_FORMAT_DESC"] = [[Wähle eine Zeichenfolge um das Textformat zu ändern.
+
+Beispiele:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+Leben / Kraft Formate:
+"current" - Aktueller Wert
+"percent" - Prozentualer Wert
+"current-max" - Aktueller Wert gefolgt von dem maximalen Wert. Es wird nur der Maximale Wert anzeigt, wenn der aktuelle Wert auch das Maximum ist
+"current-percent" - Aktueller Wert gefolgt von dem prozentualen Wert. Es wird nur der maximale Wert angezeigt, wenn der aktuelle Wert auch das Maximum ist
+"current-max-percent" - Aktueller Wert, Maximaler Wert, gefolgt von dem prozentualen Wert. Es wird nur der maximale Wert angezeigt, wenn der aktuelle Wert auch das Maximum ist
+"deficit" - Zeigt das Defizit. Es wird nichts angezeigt, wenn kein Defizit vorhanden ist
+
+Namensformate:
+"name:short" - Name auf 10 Zeichen beschränkt
+"name:medium" - Name auf 15 Zeichen beschränkt
+"name:long" - Name auf 20 Zeichen beschränkt
+
+Zum Deaktvieren lasse das Feld leer. Brauchst du mehr Informationen besuche http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "Seitenwechsel der Aktionsleisten"
+L["ActionBars"] = "Aktionsleisten"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = "Erlaubt LBF das Gestalten dieser Elememte."
+L["Alpha"] = "Alpha"
+L["Anchor Point"] = "Ankerpunkt" --also in unitframes
+L["Backdrop Spacing"] = "Hintergrund Abstand"
+L["Backdrop"] = "Hintergrund"
+L["Button Size"] = "Größe der Tasten" --Also used in Bags
+L["Button Spacing"] = "Abstand der Tasten" --Also used in Bags
+L["Buttons Per Row"] = "Tasten pro Zeile"
+L["Buttons"] = "Tasten"
+L["Change the alpha level of the frame."] = "Ändere den Alphakanal des Fensters."
+L["Color of the actionbutton when not usable."] = "Farbe der Aktionsleisten wenn nicht nutzbar."
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "Die Farbe der Aktionstasten, wenn keine Kraft, wie z.B. Mana, Wut."
+L["Color of the actionbutton when out of range."] = "Die Farbe der Aktionstasten, wenn das Ziel außer Reichweite ist."
+L["Color of the actionbutton when usable."] = "Farbe der Aktionsleisten wenn nutzbar."
+L["Color when the text is about to expire"] = "Färbe den Text in dieser Farbe, wenn er in Kürze abläuft."
+L["Color when the text is in the days format."] = "Färbe den Text in dieser Farbe, wenn er Tagen angezeigt wird."
+L["Color when the text is in the hours format."] = "Färbe den Text in dieser Farbe, wenn er in Stunden angezeigt wird."
+L["Color when the text is in the minutes format."] = "Färbe den Text in dieser Farbe, wenn er sich im Minutenformat angezeigt wird."
+L["Color when the text is in the seconds format."] = "Färbe den Text in dieser Farbe, wenn er in Sekunden angezeigt wird."
+L["Cooldown Text"] = "Abklingzeittext"
+L["Darken Inactive"] = "Inaktives verdunkeln"
+L["Days"] = "Tage"
+L["Display bind names on action buttons."] = "Zeige Tastaturbelegungen auf der Aktionsleiste an."
+L["Display cooldown text on anything with the cooldown spiral."] = "Zeige die Abklingzeit auf allen Tasten mit Hilfe iner animierten Spirale."
+L["Display macro names on action buttons."] = "Zeige Makronamen auf der Aktionsleiste an."
+L["Expiring"] = "Auslaufend"
+L["Global Fade Transparency"] = "Globales Transparenz verblassen"
+L["Height Multiplier"] = "Höhenmultiplikator"
+L["Hours"] = "Stunden"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = "Wenn du die Aktionsleisten entsperrst und versuchst einen Zauber zu verschieben, wird voraussichtlich der Zauber ausgelöst beim drücken anstatt beim loslassen der Taste."
+L["Inherit Global Fade"] = "Globales verblassen vererben"
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = "Vererbt das globale Verblassen, mouseover, anvisieren, Focus setzen, Gesundheit verlieren, Kampf betreten wird die Transparenz entfernen. Andernfalls wird das Transparenzlevel, in den allgemeinen Einstellungen der Aktionsleisten, globales verblassen Alpha verwendet."
+L["Key Down"] = "Aktion bei Tastendruck"
+L["Keybind Mode"] = "Tastaturbelegung"
+L["Keybind Text"] = "Tastaturbelegungstext"
+L["LBF Support"] = "LBF Unterstützung"
+L["Low Threshold"] = "Niedrige CD-Schwelle"
+L["Macro Text"] = "Makrotext"
+L["Minutes"] = "Minuten"
+L["Mouse Over"] = "Mouseover" --Also used in Bags
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "Multipliziere die Höhe und die Breite des Hintergrundes. Das ist nützlich, wenn du mehr als eine Leiste hinter einem Hintergrund haben möchtest."
+L["Not Usable"] = "Nicht nutzbar"
+L["Out of Power"] = "Keine Kraft"
+L["Out of Range"] = "Außer Reichweite"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "Leiste zurücksetzen"
+L["Restore the actionbars default settings"] = "Wiederherstellung der vordefinierten Aktionsleisteneinstellung"
+L["Seconds"] = "Sekunden"
+L["Show Empty Buttons"] = "Zeige leere Tasten"
+L["The amount of buttons to display per row."] = "Anzahl der Aktionstasten in einer Reihe."
+L["The amount of buttons to display."] = "Anzahl der angezeigten Aktionstasten."
+L["The button you must hold down in order to drag an ability to another action button."] = "Die Taste, die du gedrückt halten musst, um eine Fähigkeit zu einer anderen Aktionstaste zu ziehen."
+L["The first button anchors itself to this point on the bar."] = "Der erste Aktionstaste dockt an diesen Punkt in der Leiste an."
+L["The size of the action buttons."] = "Die Größe der Aktionstasten."
+L["The spacing between the backdrop and the buttons."] = "Der Abstand zwischen dem Hintergrund und den Tasten."
+L["This setting will be updated upon changing stances."] = "Diese Einstellungen werden bei Gestaltwandel aktualisiert"
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "CD-Schwelle bevor der Text rot wird. Setze diesen Wert auf -1, wenn er nie rot werden soll"
+L["Toggles the display of the actionbars backdrop."] = "Aktiviere den Hintergrund der Aktionsleisten."
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = "Transparenz Level wenn nicht im Kampf, kein Ziel ausgewählt, volle Gesundheit, nicht am Zaubern und kein Fokus existiert."
+L["Usable"] = "Nutzbar"
+L["Visibility State"] = "Sichbarkeitszustand"
+L["Width Multiplier"] = "Breitenmultiplikator"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[Dieses funktioniert wie ein Makro, du kannst verschiedene Situationen haben um die Aktionsleiste zu wechseln.
+ Beispiel: [combat] 2;]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[Dieses funktioniert wie ein Makro, du kannst verschiedene Situationen haben um die Aktionsleiste ein-/auszublenden.
+ Beispiel: [combat] show;hide]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = "Füge ein Gegenstand oder ein Suchoperator zu der Ignorierliste hinzu. Gegenstände die auf den Suchoperator zutreffen werden ignoriert."
+L["Add Item or Search Syntax"] = "Füge Gegenstand oder Suchoperator hinzu"
+L["Adjust the width of the bag frame."] = "Passe die Breite des Taschenfensters an."
+L["Adjust the width of the bank frame."] = "Passe die Breite des Bankfensters an."
+L["Ascending"] = "Aufsteigend"
+L["Bag Sorting"] = "Taschen Sortierung"
+L["Bag-Bar"] = "Taschenleiste"
+L["Bar Direction"] = "Ausrichtung Leiste"
+L["Blizzard Style"] = "Blizzard Stil"
+L["Bottom to Top"] = "Von unten nach oben"
+L["Button Size (Bag)"] = "Tasten Größe (Tasche)"
+L["Button Size (Bank)"] = "Tasten Größe (Bank)"
+L["Clear Search On Close"] = "Leere Suche beim Schließen"
+L["Condensed"] = "Gekürzt"
+L["Descending"] = "Absteigend"
+L["Direction the bag sorting will use to allocate the items."] = "Die Richtung, in welche die Gegenstände in den Taschen sortiert werden."
+L["Disable Bag Sort"] = "Deaktiviere Taschensortierung"
+L["Disable Bank Sort"] = "Deaktiviere Banksortierung"
+L["Display Item Level"] = "Itemlevel anzeigen"
+L["Displays item level on equippable items."] = "Zeigt das Itemlevel für ausrüstbare Gegenstände an."
+L["Enable/Disable the all-in-one bag."] = "Einschalten/Ausschalten der zusammengefassten Tasche."
+L["Enable/Disable the Bag-Bar."] = "Aktiviere/Deaktiviere die Taschenleiste."
+L["Full"] = "Voll"
+L["Global"] = true;
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = "Hier kannst du Gegenstände oder Suchbedingungen vom Suchen ausschließen. Um ein Gegenstand zu entfernen, klicke einfach auf den Namen in der Liste."
+L["Ignored Items and Search Syntax (Global)"] = "Ignorierte Gegenstände oder Suchoperatoren (Global)"
+L["Ignored Items and Search Syntax (Profile)"] = "Ignorierte Gegenstände oder Suchoperatoren (Profil)"
+L["Item Count Font"] = "Gegenstandszähler Schriftart"
+L["Item Level Threshold"] = "Itemlevel Schwellenwert"
+L["Item Level"] = "Itemlevel"
+L["Money Format"] = "Geldformat"
+L["Panel Width (Bags)"] = "Leistenbreite (Taschen)"
+L["Panel Width (Bank)"] = "Leistenbreite (Bank)"
+L["Search Syntax"] = "Suchsyntax"
+L["Set the size of your bag buttons."] = "Setze die Größe der Taschen Taste."
+L["Short (Whole Numbers)"] = "Kurz (ganze Zahlen)"
+L["Short"] = "Kurz"
+L["Smart"] = "Elegant"
+L["Sort Direction"] = "Sortierrichtung" --Also used in Buffs and Debuffs
+L["Sort Inverted"] = "Umgekehrtes sortieren"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "Die Ausrichtung der Leiste (Horizontal oder Vertikal)."
+L["The direction that the bag frames will grow from the anchor."] = "Die Richtung in welche das Fenster vom Ankerpunkt aus wächst (Horizontal oder Vertikal)."
+L["The display format of the money text that is shown at the top of the main bag."] = "Das Anzeigeformat für Gold oben an der Haupttasche."
+L["The frame is not shown unless you mouse over the frame."] = "Das Fenster ist nicht sichtbar, außer man bewegt die Maus darüber."
+L["The minimum item level required for it to be shown."] = "Das minimale Itemlevel um angezeigt zu werden."
+L["The size of the individual buttons on the bag frame."] = "Die Größe der einzelnen Tasten auf dem Taschenfenster."
+L["The size of the individual buttons on the bank frame."] = "Die Größe der einzelnen Tasten auf dem Bankfenster."
+L["The spacing between buttons."] = "Der Abstand zwischen den Tasten."
+L["Top to Bottom"] = "Von oben nach unten"
+L["Use coin icons instead of colored text."] = "Benutze Währungssymbole anstatt von farbigem Text."
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "Buffs und Debuffs";
+L["Begin a new row or column after this many auras."] = "Beginne nach so vielen Stärkungszaubern eine neue Reihe oder Spalte."
+L["Count xOffset"] = "Den Versatz auf der X-Achse zählen"
+L["Count yOffset"] = "Den Versatz auf der Y-Achse zählen"
+L["Defines how the group is sorted."] = "Lege fest, wie die Gruppe sortiert wird."
+L["Defines the sort order of the selected sort method."] = "Legt die Sortierreihenfolge der ausgewählten Sortiermethode fest."
+L["Disabled Blizzard"] = "Blizzard deaktivieren"
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "Zeit bis zum verblassen"
+L["Index"] = "Index"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "Wenn du einen Stärkungszauber auf dich selber wirkst, zeige diesen zuerst in der Leiste."
+L["Limit the number of rows or columns."] = "Beschränkung für die Anzahl an Leisten oder Spalten."
+L["Max Wraps"] = "Maximale Leisten"
+L["No Sorting"] = "Nicht Sortieren"
+L["Other's First"] = "Andere zuerst"
+L["Remaining Time"] = "Verbleibende Zeit anzeigen"
+L["Reminder"] = true
+L["Reverse Style"] = "Stil umkehren"
+L["Seperate"] = "Seperat"
+L["Set the size of the individual auras."] = "Lege die Größe der individuellen Stärkungszauber fest."
+L["Sort Method"] = "Sortiermethode"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = "Die Richtung, die Aura wird wachsen wird und dann die Richtung dei Sie wachsen wird, nachdem sie die Grenze nach Wrap erreichen."
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "Die Schwelle bevor der Text rot und das Symbol verblassen wird (in Dezimalform). Setze sie auf -1 um die Schwelle zu deaktivieren."
+L["Time xOffset"] = "Zeit X-Versatz"
+L["Time yOffset"] = "Zeit Y-Versatz"
+L["Time"] = "Zeit"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = "Wenn diese Option aktiviert wird, leuchten die Symbole für aktive Stärkungszauber auf und inaktive Stärkungszauber werden dunkler. Ansonsten leuchten die Symbole für inaktive Stärkungszauber auf und aktive Stärkungszauber werden dunkler."
+L["Wrap After"] = "Neue Reihe/Spalte beginnen"
+L["Your Auras First"] = "Deine Auren zuerst"
+
+--Chat
+L["Above Chat"] = "Über dem Chat"
+L["Adjust the height of your right chat panel."] = "Passe die Höhe des rechten Chatfensters an."
+L["Adjust the width of your right chat panel."] = "Passe die Breite des rechten Chatfensters an."
+L["Alerts"] = "Alarme"
+L["Allowed Combat Repeat"] = "Erlaubte Kampf Wiederholungen"
+L["Attempt to create URL links inside the chat."] = "Eine Möglichkeit um Internet-Links im Chat anzuzeigen."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "Fixiere das rechte und linke Chatfenster. Deaktiviere diese Option um das Hauptchatfenster nach Belieben zu verschieben."
+L["Below Chat"] = "Unter dem Chat"
+L["Chat EditBox Position"] = "Position der Texteingabeleiste"
+L["Chat History"] = "Chatverlauf"
+L["Chat Timestamps"] = true
+L["Class Color Mentions"] = "Erwähnung in Klassenfarbe"
+L["Custom Timestamp Color"] = "Benutzerdefinierte Zeitstempel Farbe"
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "Zeigt den Hyperlink Tooltip beim Überfahren eines Hyperlinks."
+L["Enable the use of separate size options for the right chat panel."] = "Benutze getrennte Größenoptionen für das rechte Chatfenster."
+L["Exclude Name"] = "Ausgeschlossener Name"
+L["Excluded names will not be class colored."] = "Ausgeschlossene Namen werden nicht in Klassenfarbe erscheinen."
+L["Excluded Names"] = "Ausgeschlossene Namen"
+L["Fade Chat"] = "Chat Verblassen"
+L["Fade Tabs No Backdrop"] = "Verblasst Tabs ohne Hintergrund"
+L["Fade the chat text when there is no activity."] = "Lässt den Chat Text verblassen, wenn keine Aktivität besteht."
+L["Fade Undocked Tabs"] = "Verblasst nicht angedockte Tabs"
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = "Verblasst den Text für die Chat Tabs, die nicht angedockt sind und deren Hintergrund deaktiviert ist."
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = "Verblasst den Text für die Chat Tabs, die nicht am linken oder rechten Chat angedockt sind."
+L["Font Outline"] = "Kontur der Schriftart" --Also used in UnitFrames section
+L["Font"] = "Schriftart"
+L["Hide Both"] = "Verstecke Beide"
+L["Hyperlink Hover"] = "Hyperlink Hover"
+L["Keyword Alert"] = "Stichwort Alarm"
+L["Keywords"] = "Stichwort"
+L["Left Only"] = "Nur Links"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "Liste der Wörter die farblich im Chat erscheinen, wenn sie in einer Nachricht gefunden werden. Wenn du möchtest, kannst du mehrere Wörter hinzufügen. Diese müssen durch ein Komma getrennt werden. Um deinen momentanen Namen zu suchen, benutze %MYNAME%.\n\nBeispiel:\n%MYNAME%, ElvUI, RBGs, Tank"
+L["Lock Positions"] = "Positionen fixieren"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "Sichert den Chatverlauf der Hauptchatfenster. Wenn du dein UI neulädst oder einloggst, siehst du den Chatverlauf der letzten Sitzung."
+L["No Alert In Combat"] = "Kein Alarm im Kampf"
+L["Number of messages you scroll for each step."] = "Anzahl der Nachrichten die mit jeden Schritt gescrollt werden."
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = "Anzahl der wiederholten Zeichen im Kampf, bevor das Chateingabefeld automatisch schließt."
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "Anzahl der Sekunden um im Chatfenster nach unten zu scrollen, wenn du nicht komplett nach unten gescrollt bist."
+L["Panel Backdrop"] = "Fensterhintergrund"
+L["Panel Height"] = "Fensterhöhe"
+L["Panel Texture (Left)"] = "Fenstertextur (Links)"
+L["Panel Texture (Right)"] = "Fenstertextur (Rechts)"
+L["Panel Width"] = "Leistenbreite"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "Position der Texteingabeleiste. Sind die Infotexte deaktiviert, dann wird diese über dem Chat angebracht."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "Verhindert, dass die gleiche Nachricht im Chat mehr als einmal, innerhalb dieser festgelegten Anzahl von Sekunden, angezeigt wird. Auf Null setzen um diese Option zu deaktivieren."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = "Erfordert dass die Alt-Taste gedrückt wird, um mit den Mauszeiger durch die Nachrichten zu scrollen."
+L["Right Only"] = "Nur Rechts"
+L["Right Panel Height"] = "Rechte Fensterhöhe"
+L["Right Panel Width"] = "Rechte Fensterbreite"
+L["Scroll Interval"] = "Scroll-Interval"
+L["Scroll Messages"] = "Scroll Nachrichten"
+L["Separate Panel Sizes"] = "Getrennte Chatfenster Größenoptionen"
+L["Set the font outline."] = "Setzt die Schrift auf Outline." --Also used in UnitFrames section
+L["Short Channels"] = "Kurze Kanäle"
+L["Shorten the channel names in chat."] = "Kürze Kanalnamen im Chat."
+L["Show Both"] = "Zeige Beide"
+L["Spam Interval"] = "Spam-Interval"
+L["Sticky Chat"] = "Kanal merken"
+L["Tab Font Outline"] = "Tab Schriftkontur"
+L["Tab Font Size"] = "Tab Schriftgröße"
+L["Tab Font"] = "Tab Schriftart"
+L["Tab Panel Transparency"] = "Tableisten Transparenz"
+L["Tab Panel"] = "Tableiste anzeigen"
+L["Timestamp Color"] = "Zeitstempel Farbe"
+L["Toggle showing of the left and right chat panels."] = "Aktiviere den Hintergrund des linken und rechten Chatfensters"
+L["Toggle the chat tab panel backdrop."] = "Aktiviere den Hintergrund der oberen Tableisten der Chatfenster"
+L["URL Links"] = "URL Links"
+L["Use Alt Key"] = "Benutze Alt-Taste"
+L["Use class color for the names of players when they are mentioned."] = "Benutze Klassenfarben von Spielernamen, wenn sie erwähnt werden."
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "Beim Öffnen der Texteingabeleiste wird dem Kanal beigetreten, in den zu letzt geschrieben wurde. Wenn diese Option deaktiviert ist, wird standardmäßig der SAGEN-Kanal beim öffnen der Texteingabeleiste aufgerufen."
+L["Whisper Alert"] = "Flüster Alarm"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[Gib einen Dateinamen im World of Warcraft Verzeichnis an. Textures Ordner, den du als Fensterhintergrund eingestellt haben willst.
+
+Bitte beachten:
+-Als Bildgröße 256x128 wird empfohlen.
+-Du musst das Spiel komplett neu starten, nachdem du die Datei hinzugefügt hast.
+-Der Dateityp muss im Format tga sein.
+
+Zum Beispiel: Interface\AddOns\ElvUI\media\textures\copy
+
+Für die meisten Anwender ist es allerdigns einfacher, eine tga-Datei in ihren WoW-Ordner abzulegen. Anschließend kann man den Namen der Datei hier eingeben.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "Programmierung:"
+L["Credits"] = "Danksagung"
+L["Donations:"] = "Spenden:"
+L["ELVUI_CREDITS"] = "Ich möchte mich hier bei folgenden Personen bedanken, die durch ihre tatkräftige Unterstützung beim Testen und Coden, sowie durch Spenden, sehr geholfen haben. Bitte beachten: Für Spenden poste ich nur die Namen, die mich im Forum via PM angeschrieben haben. Sollte dein Name fehlen und du möchtest deinen Namen hinzugefügt haben, schreib mir bitte eine PM im Forum."
+L["Testing:"] = "Tester:"
+
+--DataBars
+L["Current - Percent (Remaining)"] = "Aktuell - Prozent (Verleibend)"
+L["Current - Remaining"] = "Aktuell - Verbleibend"
+L["DataBars"] = "Informationsleisten"
+L["Hide In Combat"] = "Im Kampf ausblenden"
+L["Setup on-screen display of information bars."] = "Einstellung der Informationsleisten."
+
+--DataTexts
+L["Battleground Texts"] = "Schlachtfeld-Infotexte"
+L["Block Combat Click"] = "Blockiere Klicks im Kampf"
+L["Block Combat Hover"] = "Blockiere Hovereffekt im Kampf"
+L["Blocks all click events while in combat."] = "Blockiere alle Klickevents im Kampf."
+L["Blocks datatext tooltip from showing in combat."] = "Blockiere Infotextetooltips im Kampf."
+L["BottomLeftMiniPanel"] = "Minimap Untenlinks (Innen)"
+L["BottomMiniPanel"] = "Minimap Unten (Innen)"
+L["BottomRightMiniPanel"] = "Minimap Untenrechts (Innen)"
+L["Datatext Panel (Left)"] = "Infotextleiste (Links)"
+L["Datatext Panel (Right)"] = "Infotextleiste (Rechts)"
+L["DataTexts"] = "Infotexte"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "Zeige die Infoleisten unter dem Chat, benutzt für Infotexte."
+L["Display minimap panels below the minimap, used for datatexts."] = "Zeige Minimap Leisten unter der Minimap, benutzt für Infotexte."
+L["Gold Format"] = "Gold-Format"
+L["left"] = "Links"
+L["LeftChatDataPanel"] = "Linker Chat"
+L["LeftMiniPanel"] = "Minimap Links"
+L["middle"] = "Mitte"
+L["Minimap Panels"] = "Minimap Leisten"
+L["Panel Transparency"] = "Panel Transparenz"
+L["Panels"] = "Leisten"
+L["right"] = "Rechts"
+L["RightChatDataPanel"] = "Rechter Chat"
+L["RightMiniPanel"] = "Minimap Rechts"
+L["Small Panels"] = "Schmale Leisten"
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = "Das Anzeigeformat für Gold in den Haupt-Infoleisten und Tooltips."
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap Obenlinks (Innen)"
+L["TopMiniPanel"] = "Minimap Oben (Innen)"
+L["TopRightMiniPanel"] = "Minimap Obenrechts (Innen)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "Zeige innerhalb eines Schlachtfeldes persönliche Statistiken in den Haupt-Infoleisten."
+L["Word Wrap"] = "Zeilenumbruch"
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "Du musst mit dem Spieler in einer Gruppe sein wenn dieser nicht auf deinem Server ist wie du."
+L["Sends your current profile to your target."] = "Sende dein momentanes Profil an dein Ziel."
+L["Sends your filter settings to your target."] = "Sende deine Filter Einstellungen an dein Ziel."
+L["Share Current Profile"] = "Teile das momentane Profil"
+L["Share Filters"] = "Teile Filter"
+L["This feature will allow you to transfer settings to other characters."] = "Dieses Feature erlaubt es dir Einstellungen an andere Charaktere zu schicken."
+L["You must be targeting a player."] = "Du musst einen Spieler anvisiert haben."
+
+--Filters
+L["Reset Aura Filters"] = "Setze Aurafilter zurück" --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "Einladungen akzeptieren"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "Bestimme die Position der Bedrohungsleiste in den rechten oder linken Infotextleisten."
+L["AFK Mode"] = "AFK Modus"
+L["Announce Interrupts"] = "Unterbrechungen ankündigen"
+L["Announce when you interrupt a spell to the specified chat channel."] = "Melde über den angegebenen Chatkanal einen unterbrochenen Zauber."
+L["Attempt to support eyefinity/nvidia surround."] = "Versucht Eyefinity/NVIDIA Surround zu unterstützen"
+L["Auto Greed/DE"] = "Auto-Gier/DE"
+L["Auto Repair"] = "Auto-Reparatur"
+L["Auto Scale"] = "Auto-Skalierung"
+L["Automatically accept invites from guild/friends."] = "Automatisch Einladungen von Gildenmitgliedern/Freunden akzeptieren"
+L["Automatically repair using the following method when visiting a merchant."] = "Repariere automatisch deine Ausrüstungsgegenstände, wenn du eine der folgenden Methoden auswählst."
+L["Automatically scale the User Interface based on your screen resolution"] = "Automatische Skalierung des Interfaces, angepasst an deine Bildschirmeinstellung"
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "Automatisch Gier oder Entzauberung auf Gegenstände von grüner Qualität wählen (sofern verfügbar). Das funktioniert nur, wenn du die maximale Stufe erreicht hast."
+L["Automatically vendor gray items when visiting a vendor."] = "Automatischer Verkauf von grauen Gegenständen bei einem Händlerbesuch."
+L["Bottom Panel"] = "Untere Leiste"
+L["Chat Bubbles Style"] = "Sprechblasen Stil"
+L["Chat Bubbles"] = "Sprechblasen"
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = "Kontrolliert die Anzahl der Dezimalstellen in den Werten auf den Namensplaketten und Einheitenfenstern."
+L["Decimal Length"] = "Dezimalstellen"
+L["Direction the bar moves on gains/losses"] = "Richtung in die der Balken wächst/sinkt"
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "Zeige eine Leiste am unterem Bildschirmrand. Das ist rein kosmetisch."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "Zeige eine Leiste am oberen Bildschirmrand. Das ist rein kosmetisch."
+L["Display battleground messages in the middle of the screen."] = "Zeigt Schlachtfeld Nachrichten in der Mitte des Bildschirms."
+L["Enable/Disable the loot frame."] = "Aktiviere/Deaktiviere das Beutefenster."
+L["Enable/Disable the loot roll frame."] = "Aktiviere/Deaktiviere das Beutewürfelfenster."
+L["Enables the ElvUI Raid Control panel."] = "Aktiviert das ElvUI Raid Control Panel."
+L["Enhanced PVP Messages"] = "Erweiterte PvP Nachrichten"
+L["General"] = "Allgemein"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = "Höhe des Questfenster. Größe verändern um mehr Ziele zu sehen."
+L["Hide At Max Level"] = "Auf max. Level vestecken"
+L["Hide Error Text"] = "Fehlertext verstecken"
+L["Hide In Vehicle"] = "Im Fahrzeug verstecken"
+L["Hides the red error text at the top of the screen while in combat."] = "Den roten Fehlertext im oberen Teil des Bildschirms im Kampf verstecken"
+L["Log Taints"] = "Log Fehler"
+L["Login Message"] = "Login Nachricht"
+L["Loot Roll"] = "Würfelfenster"
+L["Loot"] = "Beute"
+L["Lowest Allowed UI Scale"] = "Niedrigste erlaubte UI Skalierung"
+L["Multi-Monitor Support"] = "Multi-Monitor-Unterstützung"
+L["Name Font"] = "Schriftart von Spielernamen"
+L["Number Prefix"] = "Nummern-Präfix"
+L["Party / Raid"] = "Gruppe / Schlachtzug"
+L["Party Only"] = "Nur in der Gruppe"
+L["Raid Only"] = "Nur im Schlachtzug"
+L["Remove Backdrop"] = "Hintergrund entfernen"
+L["Reset all frames to their original positions."] = "Setze alle Einheiten an ihre ursprüngliche Position zurück."
+L["Reset Anchors"] = "Ankerpunkte zurücksetzen"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "Sende ADDON_ACTION_BLOCKED Fehler zum Lua-Fehlerfenster. Diese Fehler sind weniger wichtig und werden deine Spielleistung nicht beeinflussen. Viele dieser Fehler können nicht beseitigt werden. Bitte melde diese Fehler nur, wenn es einen Defekt im Spiel verursacht."
+L["Skin Backdrop (No Borders)"] = "Skin für den Hintergrund (kein Rahmen)"
+L["Skin Backdrop"] = "Skin für den Hintergrund"
+L["Skin the blizzard chat bubbles."] = "Skin die Blizzard Chat Sprechblasen."
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Die Schrift, die über den Köpfen der Spieler auftaucht. |cffFF0000WARNUNG: Das benötigt einen Neustart des Spiels oder einen Relog um in Effekt zu treten.|r"
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = "Das Dünne Rahmen Theme ändert das gesamte Erscheinungsbild deines UI. Das Benutzten des Dünnen Rahmen Theme ist ein kleiner performance Schub gegenüber dem traditionellen Layout."
+L["Thin Border Theme"] = "Dünner Rahmen Theme"
+L["Toggle Tutorials"] = "Tutorial starten"
+L["Top Panel"] = "Obere Leiste"
+L["Version Check"] = true;
+L["Watch Frame Height"] = "Questfenster Höhe"
+L["When you go AFK display the AFK screen."] = "AFK Bildschirm anzeigen wenn du AFK bist."
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = "Wendet die Schrift und Schriftgröße überall im Interface an. Hinweis: Einige Schriftarten werden übersprungen, weil sie eine kleinere Schriftgröße als Standard haben."
+L["Applies the primary texture to all statusbars."] = "Wendet die Primäre Textur auf alle Statusbars an."
+L["Apply Font To All"] = "Schriftart auf alles anwenden."
+L["Apply Texture To All"] = "Textur auf alles anwenden"
+L["Backdrop color of transparent frames"] = "Hintergrundfarbe von transparenten Fenstern"
+L["Backdrop Color"] = "Hintergrundfarbe"
+L["Backdrop Faded Color"] = "Transparente Hintergrundfarbe"
+L["Border Color"] = "Rahmenfarbe"
+L["Color some texts use."] = "Allgemeine Farbe der meisten Texte"
+L["Colors"] = "Farben" --Also used in UnitFrames
+L["CombatText Font"] = "Schriftart vom Kampftext"
+L["Default Font"] = "Allgemeine Schriftart"
+L["Font Size"] = "Schriftgröße" --Also used in UnitFrames
+L["Fonts"] = "Schrift"
+L["Main backdrop color of the UI."] = "Allgemeine Hintergrundfarbe der Benutzeroberfläche."
+L["Main border color of the UI."] = "Allgemeine Randfarbe des UI."
+L["Media"] = "Medien"
+L["Primary Texture"] = "Primäre Textur"
+L["Replace Blizzard Fonts"] = "Blizzard Schriftarten überschreiben"
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = "Ersetzt die Standard Blizzard Schriftarten in verschiedenen Fenstern und Leisten mit den im Medienbereich des ElvUI Config gewählten Schriftenarten. (NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this.) Standardmäßig aktiviert."
+L["Secondary Texture"] = "Sekundäre Textur"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "Setze die Größe für die Schriftart der gesamten Benutzeroberfläche fest. Notiz: Dies hat keinen Einfluss auf Optionen, die ihre eigenen Einstellungen haben (Einheitenfenster Schrift, Infotext Schrift, ect..)"
+L["Textures"] = "Texturen"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Die Schriftart des Kampftextes. |cffFF0000WARNUNG: Nach der änderung dieser Option muss das Spiel neu gestartet werden.|r"
+L["The font that the core of the UI will use."] = "Die Schriftart, die hauptsächlich vom UI verwendet wird."
+L["The texture that will be used mainly for statusbars."] = "Diese Textur wird vorallem für Statusbars verwendet."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "Diese Textur wird für Objekte wie Chatfenster und Dropdown-Menüs benutzt."
+L["Value Color"] = "Farbwert"
+
+--Maps
+L["Adjust the size of the minimap."] = "Stelle die Größe der Minimap ein."
+L["Always Display"] = "Immer anzeigen"
+L["Bottom Left"] = "Unten links"
+L["Bottom Right"] = "Unten rechts"
+L["Bottom"] = "Unten"
+L["Change settings for the display of the location text that is on the minimap."] = "Ändere die Einstellungen für die Anzeige des Umgebungstextes an der Minimap."
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = "Aktiviere/Deaktiviere die Minimap. |cffFF0000Warnung: Durch diese Einstellung wird verhindert dass die Infotextleisten an der Minimap angezeigt werden.|r"
+L["Instance Difficulty"] = "Instanz Schwierigkeitsgrad"
+L["Left"] = "Links"
+L["LFG Queue"] = "LFG Warteschlange"
+L["Location Text"] = "Umgebungstext"
+L["Make the world map smaller."] = "Macht die Weltkarte kleiner."
+L["Maps"] = "Karten"
+L["Minimap Buttons"] = "Minimap Tasten"
+L["Minimap Mouseover"] = "Minimap Mouseover"
+L["Puts coordinates on the world map."] = "Platziert Koordinaten auf der Weltkarte."
+L["PvP Queue"] = true
+L["Reset Zoom"] = "Zoom zurücksetzen"
+L["Right"] = "Rechts"
+L["Scale"] = "Skalierung"
+L["Smaller World Map"] = "Kleinere Weltkarte"
+L["Top Left"] = "Oben links"
+L["Top Right"] = "Oben rechts"
+L["Top"] = "Oben"
+L["World Map Coordinates"] = "Weltkarten Koordinaten"
+L["X-Offset"] = "X-Versatz"
+L["Y-Offset"] = "Y-Versatz"
+
+--Misc
+L["Install"] = "Installation"
+L["Run the installation process."] = "Startet den Installationsprozess."
+L["Toggle Anchors"] = "Ankerpunkte umschalten"
+L["Unlock various elements of the UI to be repositioned."] = "Schalte verschiedene Elemente der Benutzeroberfläche frei um sie neu zu positionieren."
+L["Version"] = "Version"
+
+--NamePlates
+L["# Displayed Auras"] = "# angezeigte Auren"
+L["Actions"] = "Aktionen"
+L["Add Name"] = "Name hinzufügen"
+L["Add Nameplate Filter"] = "Füge Namensplaketten Filter hinzu"
+L["Add Regular Filter"] = "Füge regulären Filter hinzu"
+L["Add Special Filter"] = "Füge speziellem Filter hinzu"
+L["Always Show Target Health"] = "Zeige immer Ziel Gesundheit"
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = "Diesen Filter anwenden, wenn die Dauer von einem Stärkungszauber größer als dieses ist. Setze auf 0 um zu deaktivieren."
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = "Diesen Filter anwenden, wenn die Dauer von einem Stärkungszauber kleiner als dieses ist. Setze auf 0 um zu deaktivieren."
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = "Diesen Filter anwenden, wenn die Dauer von einem Schwächungszauber größer als dieses ist. Setze auf 0 um zu deaktivieren."
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = "Diesen Filter anwenden, wenn die Dauer von einem Schwächungszauber kleiner als dieses ist. Setze auf 0 um zu deaktivieren."
+L["Background Glow"] = "Hintergrund Leuchten"
+L["Bad Color"] = "Schlechte Farbe"
+L["Bad Scale"] = "Schlechte Skalierung"
+L["Bad Transition Color"] = "Schlechte Übergangsfarbe"
+L["Base Height for the Aura Icon"] = "Grundhöhe der Auren Symbole"
+L["Border Glow"] = "Rahmen Leuchten"
+L["Border"] = "Rand"
+L["Cast Bar"] = "Zauberleiste"
+L["Cast Color"] = "Zauberfarbe"
+L["Cast No Interrupt Color"] = "Nicht unterbrechbare Zauberfarbe"
+L["Cast Time Format"] = "Zauber Zeitformat"
+L["Casting"] = "Zaubernd"
+L["Channel Time Format"] = "Kanalisierung Zeitformat"
+L["Clear Filter"] = "Filter leeren"
+L["Color Tanked"] = "Färbe angetankt"
+L["Control enemy nameplates toggling on or off when in combat."] = "Legt fest ob die Namensplaketten im Kampf für Gegner ein- oder ausgeblendet werden."
+L["Control friendly nameplates toggling on or off when in combat."] = "Legt fest ob die Namensplaketten im Kampf für freundliche Einheiten ein- oder ausgeblendet werden."
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = "Legt fest wieviele Auren angezeigt werden. Dieses beeinflusst auch die Größe der Auren."
+L["Cooldowns"] = true --No need to translate
+L["Copy settings from another unit."] = "Kopiere Einstellungen von einer anderen Einheit."
+L["Copy Settings From"] = "Kopiere Einstellungen von"
+L["Current Level"] = "Aktuelles Level"
+L["Default Settings"] = "Standard Einstellungen"
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "Zeige auf Schlachtfeldern oder in Arenen ein Heilersymbol über Heilern an."
+L["Elite Icon"] = "Elite Symbol"
+L["Enable/Disable the scaling of targetted nameplates."] = "Aktiviere/Deaktiviere die Skalierung von anvisierten Namensplaketten."
+L["Enabling this will check your health amount."] = "Wenn aktiviert wird dein Lebenswert überprüft."
+L["Enemy Combat Toggle"] = "Im Kampf für Gegner umschalten"
+L["Enemy NPC Frames"] = "Gegnerische NPC Rahmen"
+L["Enemy Player Frames"] = "Gegnerische Spieler Rahmen"
+L["Enemy"] = "Gegner" --Also used in UnitFrames
+L["ENEMY_NPC"] = "Gegnerischer NPC"
+L["ENEMY_PLAYER"] = "Gegnerischer Spieler"
+L["Filter already exists!"] = "Filter existiert bereits!"
+L["Filter Priority"] = "Filter Priorität"
+L["Filters Page"] = "Filter Seite"
+L["Friendly Combat Toggle"] = "Im Kampf für freundliche umschalten"
+L["Friendly NPC Frames"] = "Freundliche NPC Rahmen"
+L["Friendly Player Frames"] = "Freundliche Spieler Rahmen"
+L["FRIENDLY_NPC"] = "Freundlicher NPC"
+L["FRIENDLY_PLAYER"] = "Freundlicher Spieler"
+L["General Options"] = "Allgemeine Optionen"
+L["Good Color"] = "Gute Farbe"
+L["Good Scale"] = "Gute Skalierung"
+L["Good Transition Color"] = "Gute Übergangsfarbe"
+L["Healer Icon"] = "Heilersymbol"
+L["Health Color"] = "Gesundheitsfarbe"
+L["Health Threshold"] = "Gesundheit Schwellwert"
+L["Hide Frame"] = "Verstecke Fenster"
+L["Hide Spell Name"] = "Verstecke Zaubername"
+L["Hide Time"] = "Verstecke Zeit"
+L["Hide"] = "Verstecken" --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = "Wieviele Sekunden die Zauberleiste sichtbar bleibt, nachdem ein Zauber abgebrochen oder unterbrochen wurde."
+L["Icon Base Height"] = "Symbol Grundhöhe"
+L["Icon Position"] = "Symbol Position"
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = "Wenn aktiviert, wird überprüft ob Auren fehlen anstatt vorhanden zu sein auf der Einheit."
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = "Wenn aktiviert, benötigt es alle Auren um den Filter zu aktivieren. Andererseits benötigt es nur eine von den Auren um den Filter zu aktivieren."
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = "Wenn aktiviert, benötigt es alle Cooldowns um den Filter zu aktivieren. Ansonsten benötigt es einen Cooldown um zu aktiveren."
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = "Wenn eingeschaltet, wird der Filter nur aktiviert wenn das Level der Einheit gleich oder höher diesem Level ist."
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = "Wenn eingeschaltet, wird der Filter nur aktiviert wenn das Level der Einheit gleich oder niedriger diesem Level ist."
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = "Wenn aktiviert, wird der Filter nur aktiviert wenn das Level der Einheit diesem Wert entspricht."
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = "Wenn eingeschaltet, wird der Filter nur aktiviert wenn das Level er Einheit deinem Level entspricht."
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = "Wenn eingeschaltet, wird der Filter nur aktiviert wenn die Einheit einen unterbrechbaren Zauber wirkt."
+L["If enabled then the filter will only activate when you are in combat."] = "Wenn eingeschaltet, wird der Filter nur aktiviert wenn du im Kampf bist."
+L["If enabled then the filter will only activate when you are out of combat."] = "Wenn eingeschaltet, wird der Filter nur aktiviert, wenn du nicht im Kampf bist."
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = "Wenn die Aura mit einer Nummer aufgeführt ist, dann musst du sie benutzten um sie aus der Liste zu entfernen."
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = "Wenn die Liste leer ist, und 'Unterbrechbar' ist ausgewählt, wird der Filter aktiviert bei jedem Zauber der unterbrechbar ist."
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = "Wenn dieser Schwellenwert genutzt wird, muss die Gesundheit höher sein als dieser Wert um den Filter zu aktivieren. Setze auf 0 um zu deaktiveren."
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = "Wenn dieser Schwellenwert genutzt wird, muss die Gesundheit niedriger sein als dieser Wert um den Filter zu aktivieren. Setze auf 0 um zu deaktiveren."
+L["Instance Type"] = "Instanz Typ"
+L["Interruptible"] = "Unterbrechbar"
+L["Is Targeted"] = "Ist anvisiert"
+L["LEVEL_BOSS"] = "Setze das Level auf -1 für Boss Einheiten oder auf 0 um zu deaktivieren"
+L["Low Health Threshold"] = "Niedrige Lebensbedrohung"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = "Niedrigere Nummern bedeuten eine höhere Priorität. Filter werden von 1 bis 100 verarbeitet."
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = "Färbe das Einheitenfensterleuchten gelb, wenn es unter diesen Prozentwert des Lebens sinkt. Es wird Rot angezeigt, wenn es die Hälfte des Wertes erreicht."
+L["Match Player Level"] = "Entspreche Spieler Level"
+L["Maximum Level"] = "Maximale Level"
+L["Maximum Time Left"] = "Maximale Zeit verbleibend"
+L["Minimum Level"] = "Minimale Level"
+L["Minimum Time Left"] = "Minimale Zeit verbleibend"
+L["Missing"] = "Fehlend"
+L["Name Color"] = "Namen Farbe"
+L["Name Only"] = "Nur Name"
+L["NamePlates"] = "Namensplaketten"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = "Transparenz nicht ausgewählter Ziele"
+L["Not Targeted"] = "Nicht anvisiert"
+L["Off Cooldown"] = "Benutzbar"
+L["On Cooldown"] = "Auf Abklingzeit"
+L["Over Health Threshold"] = "Über den Gesundheit Schwellenwert"
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = "Persönliche Auren"
+L["Player Health"] = "Spieler Gesundheit"
+L["Player in Combat"] = "Spieler im Kampf"
+L["Player Out of Combat"] = "Spieler nicht im Kampf"
+L["Reaction Colors"] = "Reaktionsfarbe"
+L["Reaction Type"] = "Reaktion Typ"
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "Name entfernen"
+L["Remove Nameplate Filter"] = "Entferne Namensplaketten Filter"
+L["Require All"] = "Benötigt alle"
+L["Reset filter priority to the default state."] = "Setze die Filter Priorität auf Standard zurück."
+L["Reset Priority"] = "Setze die Priorität zurück"
+L["Return filter to its default state."] = "Setzt den Filter auf Standard zurück."
+L["Scale of the nameplate that is targetted."] = "Skalierung der Namensplaketten ausgewählter Einheiten."
+L["Select Nameplate Filter"] = "Wähle den Namensplaketten Filter"
+L["Set Settings to Default"] = "Setzte die Einstellungen auf Standard"
+L["Set the scale of the nameplate."] = "Bestimme die Skalierung der Namensplaketten."
+L["Set the transparency level of nameplates that are not the target nameplate."] = "Transparenzlevel von Namensplaketten die nicht ausgewählt sind."
+L["Set to either stack nameplates vertically or allow them to overlap."] = "Namensplaketten übereinander stapeln oder überlappen."
+L["Shortcut to 'Filters' section of the config."] = "Verknüpfung zur 'Filter' Sektion in den Einstellungen."
+L["Shortcut to global filters."] = "Verknüpfung zu Globalen Filter"
+L["Shortcuts"] = "Verknüpfungen"
+L["Side Arrows"] = "Seitliche Pfeile"
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = "Stil Filter"
+L["Tagged NPC"] = "Ausgewählter NPC"
+L["Tanked Color"] = "Angetankte Farbe"
+L["Target Indicator Color"] = "Ziel Indikator Farbe"
+L["Target Indicator"] = "Ziel Indikator"
+L["Target Scale"] = "Ziel Skalierung"
+L["Targeted Nameplate"] = "Ausgewählte Namensplaketten"
+L["Texture"] = "Textur"
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = "Diese Filter benutzen keine Liste von Zaubern wie die regulären Filter. Sie benutzen anstatt die WoW API um festzustellen ob eine Aura erlaubt oder geblockt wird."
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = "Diese Filter nutzen eine Liste von Zaubern um festzustellen ob eine Aura erlaubt oder geblockt wird. Der Inhalt dieses Filter kann in der 'Filter' Sektion der Konfiguration bearbeitet werden."
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = "Dieses wird den Inhalt des Filters auf Standard zurücksetzen. Jeder Zauber den du zum Filter hinzugefügt hast wird gelöscht."
+L["Threat"] = "Bedrohung"
+L["Time To Hold"] = "Anzeigezeit"
+L["Toggle Off While In Combat"] = "Im Kampf ausblenden"
+L["Toggle On While In Combat"] = "Im Kampf einblenden"
+L["Top Arrow"] = "Oberer Pfeil"
+L["Triggers"] = "Auslöser"
+L["Under Health Threshold"] = "Unter Gesundheit Schwellenwert"
+L["Unit Type"] = "Einheiten Typ"
+L["Use Class Color"] = "Benutze Klassenfarbe"
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = "Benutze Drag und Drop um die Filter Priorität zu arrangieren oder rechts klick um einen Filter zu entfernen."
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = "Benutze Shift+Linksklick um zwischen freundlichem oder freindlichen Status umzuschalten. Normaler Status erlaubt den Filter alle Einheiten zu überprüfen. Freundlicher Status überprüft nur freundliche Einheiten. Feindliche überprüft nur feindliche Einheiten."
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = "Benutze 'Angetankte Farbe' für die Namensplakette, wenn die Einheit von einem anderen Tank getankt wird."
+L["Use Target Glow"] = "Benutze Ziel Leuchten"
+L["Use Target Scale"] = "Benutze Ziel Skalierung"
+L["Use Threat Color"] = "Benutze Bedrohungsfarbe"
+L["You can't remove a default name from the filter, disabling the name."] = "Du kannst keinen Standardnamen entfernen, schalte den Namen aus."
+
+--Profiles Export/Import
+L["Choose Export Format"] = "Wähle Export Format"
+L["Choose What To Export"] = "Wähle aus, was exportiert werden soll"
+L["Decode Text"] = "Entschlüsselter Text"
+L["Error decoding data. Import string may be corrupted!"] = "Fehler beim entschlüsseln der Daten. Die importierende Zeichenfolge scheint beschädigt zu sein!"
+L["Error exporting profile!"] = "Fehler beim Exportieren des Profils!"
+L["Export Now"] = "Jetzt exportieren"
+L["Export Profile"] = "Exportiere Profil"
+L["Exported"] = "Exportiert"
+L["Filters (All)"] = "Filter (Alle)"
+L["Filters (NamePlates)"] = "Filter (Namensplaketten)"
+L["Filters (UnitFrames)"] = "Filter (Einheitenfenster)"
+L["Global (Account Settings)"] = "Globale (Account Einstellungen)"
+L["Import Now"] = "Jetzt importieren"
+L["Import Profile"] = "Importiere Profil"
+L["Importing"] = "Importiere"
+L["Plugin"] = true; -- no need to translate
+L["Private (Character Settings)"] = "Private (Charakter Einstellungen)"
+L["Profile imported successfully!"] = "Profil erfolgreich importiert!"
+L["Profile Name"] = "Profil Name"
+L["Profile"] = "Profil"
+L["Table"] = "Tabelle"
+
+--Skins
+L["Achievement Frame"] = "Erfolgsfenster"
+L["Alert Frames"] = "Alarmfenster"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "Auktionsfenster"
+L["Barbershop Frame"] = "Barbier Fenster"
+L["BG Map"] = "Schlachtfeldkarte"
+L["BG Score"] = "Schlachtfeldpunkte"
+L["Calendar Frame"] = "Kalender Fenster"
+L["Character Frame"] = "Charakterfenster"
+L["Debug Tools"] = "Debug Tools"
+L["Dressing Room"] = "Ankleideraum"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "Begrüßungsfenster"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "Gildenbank"
+L["Guild Registrar"] = "Gildenregister"
+L["Help Frame"] = "Hilfefenster"
+L["Inspect Frame"] = "Betrachten Fenster"
+L["KeyBinding Frame"] = "Tastenbelegungsfenster"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "Beutefenster"
+L["Macro Frame"] = "Makro Fenster"
+L["Mail Frame"] = "Post Fenster"
+L["Merchant Frame"] = "Handelsfenster"
+L["Mirror Timers"] = "Spiegel Zeitgeber"
+L["Misc Frames"] = "Verschiedene Fenster"
+L["Petition Frame"] = "Abstimmungsfenster"
+L["PvP Frames"] = "Pvp Fenster"
+L["Quest Frames"] = "Quest Fenster"
+L["Raid Frame"] = "Schlachtzugsfenster"
+L["Skins"] = "Skins"
+L["Socket Frame"] = "Sockel Fenster"
+L["Spellbook"] = "Zauberbuch"
+L["Stable"] = "Stall"
+L["Tabard Frame"] = "Wappenrockfenster"
+L["Talent Frame"] = "Talentfenster"
+L["Taxi Frame"] = "Flugroutenfenster"
+L["Time Manager"] = "Zeitmanager"
+L["Trade Frame"] = "Handelsfenster"
+L["TradeSkill Frame"] = "Berufsfenster"
+L["Trainer Frame"] = "Lehrerfenster"
+L["Tutorial Frame"] = true;
+L["World Map"] = "Weltkarte"
+
+--Tooltip
+L["Always Hide"] = "Immer verstecken"
+L["Bags Only"] = "Nur Taschen"
+L["Bags/Bank"] = "Taschen/Bank"
+L["Bank Only"] = "Nur Bank"
+L["Both"] = "Beide"
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = "Wählt aus wann der Tooltip angezeigt wird. Wenn ein Modifikator ausgewählt ist, dann musst du ihn gedrückt halten um den Tooltip anzuzeigen."
+L["Comparison Font Size"] = "Vergleich Schriftgröße"
+L["Cursor Anchor"] = "Zeigeranker"
+L["Custom Faction Colors"] = "Benutzerdefinierte Fraktionsfarben"
+L["Display guild ranks if a unit is guilded."] = "Zeige Gildenränge von Spielern die in einer Gilde sind."
+L["Display how many of a certain item you have in your possession."] = "Zeige wie viele sich von dem ausgewählten Gegenstand in deinem Besitz befinden."
+L["Display player titles."] = "Zeige Spielertitel."
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = "Zeige die Spezialisierung und das Itemlevel des Spielers im Tooltip an, wird vielleicht nicht direkt aktualisiert"
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "Zeige die ID des Zaubers oder des Gegenstands an, wenn du mit der Maus über einen Zauber oder Fegenstand ziehst."
+L["Guild Ranks"] = "Gildenränge"
+L["Header Font Size"] = "Kopfzeile Schriftgröße"
+L["Health Bar"] = "Lebensleiste"
+L["Hide tooltip while in combat."] = "Verstecke den Tooltip während des Kampfes."
+L["Inspect Info"] = "Informationen betrachten"
+L["Item Count"] = "Gegenstandsanzahl"
+L["Never Hide"] = "Niemals verstecken"
+L["Player Titles"] = "Spielertitel"
+L["Should tooltip be anchored to mouse cursor"] = "Soll das Tooltip an den Mauszeiger geankert werden"
+L["Spell/Item IDs"] = "Zauber/Gegenstand IDs"
+L["Target Info"] = "Ziel Info"
+L["Text Font Size"] = "Text Schriftgröße"
+L["This setting controls the size of text in item comparison tooltips."] = "Diese Einstellung kontrolliert die Größe der Schrift vom Text im Item Vergleichs-Tooltip."
+L["Tooltip Font Settings"] = "Tooltip Schrifteinstellung"
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "Zeige ob jemand aus deiner Gruppe/Schlachtzug die Tooltip-Einheit ins Ziel genommen hat."
+
+--UnitFrames
+L["%s and then %s"] = "%s und dann %s"
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "Oben"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = "Zauber zum Filter hinzufügen. Benutze Zauber ID wenn du nicht möchtest, dass Zauber hinzugefügt werden die alle den selben Namen haben."
+L["Add a spell to the filter."] = "Zauber zum Filter hinzufügen"
+L["Add Spell ID or Name"] = "Zauber ID oder Name hinzufügen"
+L["Add SpellID"] = "ZauberID hinzufügen"
+L["Additional Filter Override"] = "Zusätzlicher Filter überschreiben"
+L["Additional Filter"] = "Zusätzlicher Filter"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = "Erlaube nicht-persönliche Auren vom zusätzlichen Filter wenn 'Blocke Nicht-Persönliche Auren' aktiviert ist."
+L["Allow Whitelisted Auras"] = "Erlaube Whitelisted Auren"
+L["An X offset (in pixels) to be used when anchoring new frames."] = "X-Versatz (in Pixeln) der verwendet werden soll um neue Fenster zu ankern"
+L["An Y offset (in pixels) to be used when anchoring new frames."] = "Y-Versatz (in Pixeln) der verwendet werden soll um neue Fenster zu ankern"
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = "Aufsteigende oder Absteigende Reihenfolge"
+L["Assist Frames"] = "Assistent Fenster"
+L["Assist Target"] = "Assistent Ziel"
+L["At what point should the text be displayed. Set to -1 to disable."] = "An welchen Punkt sollte der text angezeigt werden. Auf -1 setzen um es zu deaktivieren."
+L["Attach Text To"] = "Text anfügen an"
+L["Attach To"] = "Anfügen an"
+L["Aura Bars"] = "Auren Leisten"
+L["Auto-Hide"] = "Automatisch verstecken"
+L["Bad"] = "Schlecht"
+L["Bars will transition smoothly."] = "Sanfter Übergang der Leisten."
+L["Below"] = "Unten"
+L["Blacklist Modifier"] = "Schwarze Liste Modifikator"
+L["Blacklist"] = "Schwarze Liste"
+L["Block Auras Without Duration"] = "Blocke Auren ohne Laufzeit"
+L["Block Blacklisted Auras"] = "Blocke Auren der schwarzen Liste"
+L["Block Non-Dispellable Auras"] = "Blocke Nicht-Bannbare Auren"
+L["Block Non-Personal Auras"] = "Blocke Nicht-Persönliche Auren"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "Blut"
+L["Borders"] = "Umrandungen"
+L["Buff Indicator"] = "Buff Indikator"
+L["Buffs"] = "Stärkungszauber"
+L["By Type"] = "Nach Typ"
+L["Castbar"] = "Zauberleiste"
+L["Center"] = "Zentrum"
+L["Check if you are in range to cast spells on this specific unit."] = "Überprüfe ob du dich in Reichweite befindest, um einen Zauber auf eine spezifische Einheit zu wirken."
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = "Wähle UIPARENT um zu verhindern dass es mit dem Einheitenfenster versteckt wird."
+L["Class Backdrop"] = "Klassen Hintergrund"
+L["Class Castbars"] = "Klassen Zauberleisten"
+L["Class Color Override"] = "Klassenfarben überschreiben"
+L["Class Health"] = "Klassen Gesundheit"
+L["Class Power"] = "Klassen Kraft"
+L["Class Resources"] = "Klassenressourcen"
+L["Click Through"] = "Klicke hindurch"
+L["Color all buffs that reduce the unit's incoming damage."] = "Färbe alle Stärkungszauber die den einkommenden Schaden der Einheit verringern."
+L["Color aurabar debuffs by type."] = "Färbe Schwächungszauber nach Typ."
+L["Color castbars by the class of player units."] = "Fäbre die Zauberleiste entsprechend ihrer Klasse."
+L["Color castbars by the reaction type of non-player units."] = "Färbe die Zauberleiste entsprechend der Reaktion der Einheit."
+L["Color health by amount remaining."] = "Färbe die Gesundheitsleiste entsprechend der aktuell verbleibenden Lebenspunkte"
+L["Color health by classcolor or reaction."] = "Gesundheitsfarbe nach Klassenfarbe oder Reaktion."
+L["Color power by classcolor or reaction."] = "Färbe die Kraftleiste entsprechend ihrer Klasse."
+L["Color the health backdrop by class or reaction."] = "Färbe den Gesundheitshintergrund nach Klasse oder Reaktion."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "Aktiviere die Hervorhebung von Einheitenfenstern, wenn ein von dir bannbarer Schwächungszauber vorhanden ist."
+L["Color Turtle Buffs"] = "Färbe Turtle Stärkungszauber"
+L["Color"] = "Farbe"
+L["Colored Icon"] = "Buntes Symbol"
+L["Coloring (Specific)"] = "Färben (Spezifisch)"
+L["Coloring"] = "Färben"
+L["Combat Fade"] = "Im Kampf einblenden"
+L["Combat Icon"] = "Kampfsymbol"
+L["Combo Point"] = "Kombopunkt"
+L["Combobar"] = true;
+L["Configure Auras"] = "Konfiguriere Auren"
+L["Copy From"] = "Kopieren von"
+L["Count Font Size"] = "Schriftart Größe der Anzahl"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "Erstelle einen benutzerdefinierten Anzeigetext. Sobald du einen Namen eingibst, wirst du ihn von der Dropdown-Liste auswählen können."
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "Erstelle einen Filter. Ist dieser Filter einmal erstellt, kann er bei jeder Einheit im Bereich Stärkungszauber/Schwächungszauber ausgewählt werden."
+L["Create Custom Text"] = true
+L["Create Filter"] = "Filter erstellen"
+L["Current - Max | Percent"] = "Aktuell - Maximal | Prozent"
+L["Current - Max"] = "Aktuell - Maximal"
+L["Current - Percent"] = "Aktuell - Prozent"
+L["Current / Max"] = "Aktuell / Maximal"
+L["Current"] = "Aktuell"
+L["Custom Dead Backdrop"] = "Benutzerdefinierte Hintergrundfarbe vom Tod"
+L["Custom Health Backdrop"] = "Benutzerdefinierte Hintergrundfarbe vom Leben"
+L["Custom Texts"] = "Benutzerdefinierte Texte"
+L["Death"] = "Todesrunen"
+L["Debuff Highlighting"] = "Hervorhebung von Schwächungszaubern"
+L["Debuffs"] = "Schwächungszauber"
+L["Decimal Threshold"] = "Dezimaler Schwellenwert"
+L["Deficit"] = "Unterschied"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "Entferne einen erstellten Filter. Es können nur benutzerdefinierte Filter entfernt werden."
+L["Delete Filter"] = "Filter löschen"
+L["Detach From Frame"] = "Vom Fenster lösen"
+L["Detached Width"] = "Freistehendes Breite"
+L["Direction the health bar moves when gaining/losing health."] = "Richtung in die sich die Lebensleiste aufbaut, wenn man Leben gewinnt oder verliert."
+L["Disable Debuff Highlight"] = "Deaktiviere Schwächungszauber-Hervorhebung"
+L["Disabled Blizzard Frames"] = "Deaktivierte Blizzard Fenster"
+L["Disabled"] = "Deaktivieren"
+L["Disables the focus and target of focus unitframes."] = "Deaktiviert das Fokus und Fokus-Ziel Einheitenfenster."
+L["Disables the player and pet unitframes."] = "Deaktiviert das Spieler und Begleiter Einheitenfenster."
+L["Disables the target and target of target unitframes."] = "Deaktiviert das Ziel und Ziel des Ziels Einheitenfenster."
+L["Disconnected"] = "Nicht Verbunden"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "Zeigt eine funkelnde Textur am Ende des Zauberbalken um den Unterschied zwischen Zauberbalken und Hintergrund zu verdeutlichen."
+L["Display Frames"] = "Zeige Fenster"
+L["Display Player"] = "Zeige Spieler"
+L["Display Target"] = "Zeige Ziel"
+L["Display Text"] = "Zeige Text"
+L["Display the castbar icon inside the castbar."] = "Zeigt das Zauberleisten Symbol in der Zauberleiste."
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = "Zeige die Zauberleiste im Information Panel, das Symbol wird ausserhalb des Einheitenfenster angezeigt."
+L["Display the combat icon on the unitframe."] = "Zeige das Kampfsymbol auf den Einheitenfenster."
+L["Display the rested icon on the unitframe."] = "Zeige das Ausgeruht-Symbol auf den Einheitenfenstern."
+L["Display the target of your current cast. Useful for mouseover casts."] = "Zeige das Ziel deines derzeitigen Zaubers, für Mouseover Zauber nützlich"
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "Anzeige der Zauberbalkenticks für kanalisierte Zauber. Dies ändert sich automatisch für Zauber wie Seelendieb, wenn zusätzliche Ticks durch einen hohen Tempowert entstehen."
+L["Don't display any auras found on the 'Blacklist' filter."] = "Zeige keinerlei Auren die sich im 'Schwarzenlisten' filter befinden."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = "Keine Auren anzeigen die länger als diese Dauer (in Sekunden) sind"
+L["Don't display auras that are not yours."] = "Zeige keine Auren die nicht von dir sind."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = "Zeige keine Auren die kürzer als die Dauer (in Sekunden) sind. Auf 0 stellen um zu deaktivieren."
+L["Don't display auras that cannot be purged or dispelled by your class."] = "Zeige keine Auren die nicht von deiner Klasse entzaubert oder gereinigt werden kann."
+L["Don't display auras that have no duration."] = "Zeige keine Auren die keine Laufzeit haben."
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "Hinunter"
+L["Dungeon & Raid Filter"] = "Instanz & Schlachtzug Filter"
+L["Duration Reverse"] = "Dauer umkehren"
+L["Duration Text"] = "Dauer Text"
+L["Duration"] = "Dauer"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = "Aktivieren dieses Punktes erlaubt Raidweites sortieren, allerdings wirst du nicht zwischen Gruppen unterscheiden können"
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = "Aktivieren dieses Punktes kehrt die Gruppierungsrichtung um wenn der Raid nicht voll ist, die Startrichtung wird ebenfalls umgekehrt"
+L["Enemy Aura Type"] = "Feindlicher Aurentyp"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "Blende die Haupteinheitenfenster aus, wenn du dich nicht im Kampf befindest, keine Zauber wirkst oder kein Ziel anvisierst."
+L["Fill"] = "Füllen"
+L["Filled"] = "Gefüllt"
+L["Filter Type"] = "Filter Typ"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "Gezwungen aus"
+L["Force On"] = "Gezwungen an"
+L["Force Reaction Color"] = "Erzwinge Reaktionsfarbe"
+L["Force the frames to show, they will act as if they are the player frame."] = "Zwinge die Fenster sichtbar zu werden. Diese Fenster werden sich wie das Spielerfenster verhalten."
+L["Forces Debuff Highlight to be disabled for these frames"] = "Erzwinge die deaktivierung der Schwächungszauber-Hervorhebung für diese Fenster"
+L["Forces reaction color instead of class color on units controlled by players."] = "Erzwinge Reaktionsfarbe anstatt Klassenfarbe auf übernommene Einheiten."
+L["Format"] = "Formatierung"
+L["Frame Level"] = "Fenster Ebene"
+L["Frame Orientation"] = "Fenster Ausrichtung"
+L["Frame Strata"] = "Fenster Schicht"
+L["Frame"] = "Fenster"
+L["Frequent Updates"] = "Häufigkeit der Aktualisierung"
+L["Friendly Aura Type"] = "Freundlicher Aurentyp"
+L["Friendly"] = "Freundlich"
+L["Frost"] = "Frost"
+L["Glow"] = "Glanz"
+L["Good"] = "Gut"
+L["GPS Arrow"] = "GPS Pfeil"
+L["Group By"] = "Gruppiert durch"
+L["Grouping & Sorting"] = "Gruppierung und Sortierung"
+L["Groups Per Row/Column"] = "Gruppen per Reihe/Spalte"
+L["Growth direction from the first unitframe."] = "Wachstumsrichtung von dem ersten Einheitenfenster."
+L["Growth Direction"] = "Wachstumsrichtung"
+L["Heal Prediction"] = "Eingehende Heilung"
+L["Health Backdrop"] = "Gesundheitshintergrund"
+L["Health Border"] = "Gesundheitsumrandung"
+L["Health By Value"] = "Gesundheit nach dem Wert"
+L["Health"] = "Leben"
+L["Height"] = "Höhe"
+L["Horizontal Spacing"] = "Horizontaler Abstand"
+L["Horizontal"] = "Horizontal" --Also used in bags module
+L["Icon Inside Castbar"] = "Symbol innerhalb Zauberleiste"
+L["Icon Size"] = "Symbol Größe"
+L["Icon"] = "Symbol"
+L["Icon: BOTTOM"] = "Symbol: UNTEN"
+L["Icon: BOTTOMLEFT"] = "Symbol: UNTENLINKS"
+L["Icon: BOTTOMRIGHT"] = "Symbol: UNTENRECHTS"
+L["Icon: LEFT"] = "Symbol: LINKS"
+L["Icon: RIGHT"] = "Symbol: RECHTS"
+L["Icon: TOP"] = "Symbol: OBEN"
+L["Icon: TOPLEFT"] = "Symbol: OBENLINKS"
+L["Icon: TOPRIGHT"] = "Symbol: OBENRECHTS"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Wenn du keine anderen Filteroptionen verwendest werden alle Filter blockiert die nicht im 'Weisenfilter' stehen, sonst füge einfach Auren der Weisenliste hinzu zusätzlich zu den anderen Filter Einstellungen."
+L["If not set to 0 then override the size of the aura icon to this."] = "Wenn dieser Wert nicht auf 0 gesetzt wird, dann überschreibt dieser die größe des Aurensymbols."
+L["If the unit is an enemy to you."] = "Wenn die Einheit feindlich zu dir ist."
+L["If the unit is friendly to you."] = "Wenn die Einheit freundlich zu dir ist."
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = "Wenn du viele 3D Portraits aktiviert hast, wird es voraussichtlich enorm auf deine FPS auswirken. Deaktiviere bitte einige 3D Portraits sollte das der Fall sein."
+L["Ignore mouse events."] = "Ignoriere Maus Events."
+L["InfoPanel Border"] = "InfoPanel Rand"
+L["Information Panel"] = true; -- no need to translate
+L["Inset"] = "Einsatz"
+L["Inside Information Panel"] = "Im Information Panel"
+L["Interruptable"] = "Unterbrechbar"
+L["Invert Grouping Order"] = "Gruppierungsreihenfolge umkehren"
+L["JustifyH"] = "RechtfertigenH"
+L["Latency"] = "Latenz"
+L["Left to Right"] = "Links nach Rechts"
+L["Main statusbar texture."] = "Haupt-Statusleisten Textur"
+L["Main Tanks / Main Assist"] = "Haupt Tank / Haupt Assistent"
+L["Make textures transparent."] = "Mache Texturen transparent."
+L["Match Frame Width"] = "Passende Fensterbreite"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = "Leisten Anzahl"
+L["Max Overflow"] = true
+L["Maximum Duration"] = "Maximale Dauer"
+L["Method to sort by."] = "Methode nach dem sortiert werden soll."
+L["Middle Click - Set Focus"] = "Mittelklick - Setze Fokus"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "Mittelklicken des Einheitenfensters passt deinen Fokus an die Einheit an."
+L["Middle"] = "Mitte"
+L["Minimum Duration"] = "Minimale Dauer"
+L["Mouseover"] = "Mouseover"
+L["Name"] = "Name" --Also used in Buffs and Debuffs
+L["Neutral"] = "Neutral"
+L["Non-Interruptable"] = "Nicht-Unterbrechbar"
+L["None"] = "Kein" --Also used in chat
+L["Not valid spell id"] = "Keine gültige Zauber ID"
+L["Num Rows"] = "Anzahl der Reihen"
+L["Number of Groups"] = "Nummer der Gruppen"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "Versatz der Powerleiste zu der Lebensleiste. Setze es auf 0 um den Versatz zu deaktivieren."
+L["Offset position for text."] = "Versatz Positionen für Texte."
+L["Offset"] = "Versatz"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "Nur zeigen wenn die Einheit nicht in Reichweite ist."
+L["Only show when you are mousing over a frame."] = "Nur zeigen wenn du mit der Maus über dem Fenster bist."
+L["OOR Alpha"] = "Außer Reichweite Alpha"
+L["Other Filter"] = "Anderer Filter"
+L["Others"] = "Andere"
+L["Overlay the healthbar"] = "Überblendung der Gesundheitsleiste"
+L["Overlay"] = "Überblenden"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "Überschreibe alle benutzerdefinierten Einstellungen für die Sichtbarkeit in bestimmten Situationen. Beispiel: Zeige nur Gruppe 1 und 2 in einer 10er-Instanz."
+L["Override the default class color setting."] = "Überschreibe die Standard Klassenfarben Einstellungen"
+L["Owners Name"] = "Name des Besitzers"
+L["Parent"] = true; -- no need to translate
+L["Party Pets"] = "Gruppenbegleiter"
+L["Party Targets"] = "Gruppenziele"
+L["Per Row"] = "Pro Reihe"
+L["Percent"] = "Prozent"
+L["Personal"] = "Persönlich"
+L["Pet Name"] = "Name des Pets"
+L["Player Frame Aura Bars"] = "Spielerfenster Aurenleiste"
+L["Portrait"] = "Portrait"
+L["Position Buffs on Debuffs"] = "Positioniere Stärkungszauber zu Schwächungszauber"
+L["Position Debuffs on Buffs"] = "Positioniere Schwächungszauber zu Stärkungszauber"
+L["Position"] = "Position"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "Der Krafttext wird bei NPC-Zielen automatisch verborgen, zusätzlich wird der Namenstext relativ zu dem Energie/Mana-Ankerpunkt umpositioniert."
+L["Power"] = "Kraft"
+L["Powers"] = "Kräfte"
+L["Priority"] = "Priorität"
+L["Profile Specific"] = "Profilspezifisch"
+L["PvP Icon"] = "PvP Symbol"
+L["PvP Text"] = true; -- no need to translate
+L["PVP Trinket"] = "PVP Schmuck"
+L["Raid Icon"] = "Schlachtzugssymbol"
+L["Raid-Wide Sorting"] = "Raidweite Sortierung"
+L["Raid40 Frames"] = "40er Schlachtzugsfenster"
+L["RaidDebuff Indicator"] = "RaidDebuff Indikator"
+L["Range Check"] = "Entfernungcheck"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "Schnelle Aktualisierung der Lebensleiste. Benutzt mehr Speicher und Prozessorleistung. Nur für Heiler zu empfehlen."
+L["Reaction Castbars"] = "Reaktion Zauberleiste"
+L["Reactions"] = "Reaktionen"
+L["Ready Check Icon"] = "Bereitschaftssymbol"
+L["Remaining"] = "Verbleibend"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = "Entferne Zauber vom Filter. Benutze die Zauber ID, wenn du die ID siehst als Teil vom Zaubernamen im Filter."
+L["Remove a spell from the filter."] = "Entfernt einen Zauber aus dem Filter."
+L["Remove Spell ID or Name"] = "Entferne Zauber ID oder Name"
+L["Remove SpellID"] = "Entferne Zauber ID"
+L["Rest Icon"] = "Ausgeruht-Symbol"
+L["Restore Defaults"] = "Standard wiederherstellen" --Also used in General and ActionBars sections
+L["Right to Left"] = "Rechts nach Links"
+L["RL / ML Icons"] = "RL / ML Symbole"
+L["Role Icon"] = "Rollensymbol"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = "Verbleibende Sekunden auf der Aura bis sie sich bewegt. Auf 0 setzen zum deaktivieren."
+L["Select a unit to copy settings from."] = "Wähle eine Einheit um Einstellungen zu kopieren."
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Wähle einen Filter zum zusätzlichen verwenden. Wenn der ausgewählte Filter in einer Weisenliste ist und keine anderen Filter verwendet werden (mit Ausnahme von Blocke Nicht- Persönliche Auren), dann wird alles was nicht auf der Weisenliste steht blockiert, sonst füge einfach Auren der Weisenliste hinzu zusäzlich zu den anderen Filter Einstellungen."
+L["Select Filter"] = "Filter auswählen"
+L["Select Spell"] = "Zauber auswählen"
+L["Select the display method of the portrait."] = "Wähle das Anzeigemethode für das Portrait."
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = "Wähle den Filtertyp. Blacklist versteckt alle Auren in der Liste und zeigt den Rest an. Whitelist zeigt alle Auren in der Liste an und versteckt den Rest."
+L["Set the font size for unitframes."] = "Wähle die Schriftart für die Einheitenfenster."
+L["Set the order that the group will sort."] = "Wähle die Richtung in welche die Gruppe sortiert werden soll."
+L["Set the orientation of the UnitFrame."] = "Setzt die Ausrichtung des Einheitenfensters."
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "Wähle die Priorität des Zaubers. Bitte beachte, dass sich die Priorität nur auf das Schlachtzugsschwächungszauber-Modul auswirkt und nicht auf das Standard-Stärkungs/Schwächungszauber-Modul. Möchtest du es deaktivieren, dann setze es auf 0."
+L["Set the type of auras to show when a unit is a foe."] = "Wähle den Aurentyp, der angezeigt werden soll, wenn das Ziel feindlich ist."
+L["Set the type of auras to show when a unit is friendly."] = "Wähle den Aurentyp, der angezeigt werden soll, wenn das Ziel freundlich ist."
+L["Sets the font instance's horizontal text alignment style."] = "Wähle die Schriftart Instanz horizontal zur Ausrichtung des Textes Stils."
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "Zeige eingehende Heilung im Einheitenfenster. Zeigt eine etwas anders farbige Leiste für eingehende Überheilung."
+L["Show Aura From Other Players"] = "Zeige Auren von anderen Spielern"
+L["Show Auras"] = "Zeige Auren"
+L["Show Dispellable Debuffs"] = "Zeige stehlbare Schwächungszauber"
+L["Show When Not Active"] = "Zeige, wenn nicht aktiv"
+L["Size and Positions"] = "Größe und Positionen"
+L["Size of the indicator icon."] = "Größe des Anzeigesymbole."
+L["Size Override"] = "Größe überschreiben"
+L["Size"] = "Größe"
+L["Smart Aura Position"] = "Intelligente Aurenposition"
+L["Smart Raid Filter"] = "Intelligenter Raid-Filter"
+L["Smooth Bars"] = "Sanfte Leistenübergänge"
+L["Sort By"] = "Sortieren nach"
+L["Spaced"] = "Abgetrennt"
+L["Spacing"] = "Abstand"
+L["Spark"] = "Funken"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = "Stapel Zähler"
+L["Stack Threshold"] = "Stapel Schwellenwert"
+L["Start Near Center"] = "Starte nahe der Mitte"
+L["Statusbar Fill Orientation"] = "Füllrichtung der Statusleiste"
+L["StatusBar Texture"] = "Statusleistentextur"
+L["Strata and Level"] = "Schicht und Ebene"
+L["Style"] = "Stil"
+L["Tank Frames"] = "Tank Fenster"
+L["Tank Target"] = "Tank Ziel"
+L["Tapped"] = "Angeschlagen"
+L["Target Glow"] = "Ziel Leuchten"
+L["Target On Mouse-Down"] = "Ziel bei Maus-Runter"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "Nimmt die Einheit ins Ziel bei Maus-Runter anstatt bei Maus-Hoch. |cffFF0000Warnung: Wenn du das Addon 'Clique' benutzt musst du das auch in den Clique Einstellungen ändern wenn du das hier benutzt."
+L["Text Color"] = "Text Farbe"
+L["Text Format"] = "Textformat"
+L["Text Position"] = "Text Position"
+L["Text Threshold"] = "Text Schwelle"
+L["Text Toggle On NPC"] = "Textumschalter auf NPCs"
+L["Text xOffset"] = "Text X-Versatz"
+L["Text yOffset"] = "Text Y-Versatz"
+L["Text"] = "Text"
+L["Textured Icon"] = "Texturiertes Symbol"
+L["The alpha to set units that are out of range to."] = "Setzt den Alphabereich für Einheiten, die ausserhalb deiner Reichweite sind."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = "Der Schwächungszauber muss erst den angegebenen Wert erreichen um angezeigt zu werden. 0 zeigt den Schwächungszauber immer an."
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "Das folgende Makro muss wahr sein um die Gruppe anzuzeigen. Dies gilt zusätzlich zu jeglichem Filter der möglicherweise bereits eingestellt ist."
+L["The font that the unitframes will use."] = "Die Schriftart, welche die Einheitenfenster benutzen sollen."
+L["The initial group will start near the center and grow out."] = "Die anfängliche Gruppe wird nahe der Mitte starten und dann wachsen"
+L["The name you have selected is already in use by another element."] = "Den Namen den du ausgewählt hast, wird bereits von einem anderem Element benutzt."
+L["The object you want to attach to."] = "Das Objekt, das du anhängen willst"
+L["Thin Borders"] = "Dünne Rahmen"
+L["This dictates the size of the icon when it is not attached to the castbar."] = "Dieses zwingt die Größe des Symbols wenn es nicht an der Zauberleiste angehängt ist."
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = "Dieses öffnet die Farbeinstellung für die Einheitenfenster. Diese Einstellungen wirken sich auf alle Einheitenfenster aus."
+L["Threat Display Mode"] = "Bedrohungs Anzeige Modus"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = "Schwellenwert bevor der Text in die Dezimalform wechselt. Auf -1 setzen, um Dezimalstellen zu deaktivieren."
+L["Ticks"] = "Ticks"
+L["Time Remaining Reverse"] = "Zeit verbleibend umkehren"
+L["Time Remaining"] = "Zeit verbleibend"
+L["Transparent"] = "Transparent"
+L["Turtle Color"] = "Turtle Farbe"
+L["Unholy"] = "Unheilig"
+L["Uniform Threshold"] = "Einheitlicher Schwellenwert"
+L["UnitFrames"] = "Einheitenfenster"
+L["Up"] = "Hinauf"
+L["Use Custom Level"] = "Benutze benutzerdefinierte Ebene"
+L["Use Custom Strata"] = "Benutze benutzerdefinierte Schicht"
+L["Use Dead Backdrop"] = "Benutze Hintergrundfarbe vom Tod"
+L["Use Default"] = "Benutze Standard"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "Wähle eine eigene Hintergrundfarbe, andernfalls wird die aktuelle Gesundheitsleistenfarbe verwendet."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = "Benutze den Profilspezifischen 'Buff Indikator (Profil)' anstatt des globalen Filter 'Buff Indikator'."
+L["Use thin borders on certain unitframe elements."] = "Benutze dünne Rahmen auf bestimmten Einheitenfenster Elementen."
+L["Use this backdrop color for units that are dead or ghosts."] = "Benutze diese Hintergrundfarbe für Einheiten die Tod oder als Geist sind."
+L["Value must be a number"] = "Der Wert muss eine Zahl sein"
+L["Vertical Orientation"] = "Vertikale Ausrichtung"
+L["Vertical Spacing"] = "Vertikaler Abstand"
+L["Vertical"] = "Vertikal" --Also used in bags section
+L["Visibility"] = "Sichtbarkeit"
+L["What point to anchor to the frame you set to attach to."] = "Welchen Punkt für das verankern der Fenster möchtest du wählen."
+L["What to attach the buff anchor frame to."] = "Wo die Stärkungszauber angehängt werden sollen."
+L["What to attach the debuff anchor frame to."] = "Wo die Schwächungszauber angehängt werden sollen."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "Wenn aktiv und sich der Spieler nicht in einem Raid befindet, dann wird das angezeigt."
+L["Whitelist"] = "Weiße Liste"
+L["Width"] = "Breite" --Also used in NamePlates module
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = "Zeigt Stärkungszauber auf der Position der Schwächungszauber, wenn kein Schwächungszauber aktiv ist und vice versa."
+L["xOffset"] = "X-Versatz"
+L["yOffset"] = "Y-Versatz" --Another variation in bags section Y Offset
+L["You can't remove a pre-existing filter."] = "Du kannst einen vorgefertigten Filter nicht löschen."
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "Du kannst keinen Filter entfernen, der nicht von dir selbst hinzugefügt wurde. Setzte den Zauber einfach auf deaktiviert."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = "Du musst den Modifikator gedrückt halten um mit rechtsklick auf ein Symbol es zur Schwarzen Liste hinzuzufügen. Setzte auf 'Kein' um die Funktion zu deaktivieren."
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Korean_Config.lua b/ElvUI_Config/Locales/Korean_Config.lua
new file mode 100644
index 0000000..b971d68
--- /dev/null
+++ b/ElvUI_Config/Locales/Korean_Config.lua
@@ -0,0 +1,1178 @@
+-- Korean localization file for koKR.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "koKR")
+if not L then return end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "미니맵 근처에 표시되는 버프/디버프 아이콘에 관련된 옵션들입니다."
+L["BAGS_DESC"] = "통합가방과 가방바에 관련된 옵션들입니다."
+L["CHAT_DESC"] = "채팅과 패널에 관련된 옵션들입니다."
+L["DATATEXT_DESC"] = "정보문자에 관련된 옵션들입니다."
+L["ELVUI_DESC"] = "ElvUI는 WoW에서 지원하는 대부분의 기능을 대체하는 통합 애드온입니다."
+L["NAMEPLATE_DESC"] = "이름표에 관련된 옵션들입니다."
+L["PANEL_DESC"] = "좌우 패널의 크기를 조절합니다. 이 값에 따라 고정되어 있는 채팅창과 통합가방/은행 프레임의 크기도 변경됩니다."
+L["SKINS_DESC"] = "다른 애드온이나 게임 내 여러 프레임에 체크 시 스킨을 적용합니다."
+L["TOGGLESKIN_DESC"] = "체크 시 해당 프레임에 스킨을 사용합니다."
+L["TOOLTIP_DESC"] = "툴팁에 관련된 옵션들입니다."
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[
+
+ 각종 가방에서 검색기능을 사용할 때, 다음의 명령어들을 활용하면
+ 자신이 원하는 조건에 맞는 아이템들만 검색하도록 할 수 있습니다.
+
+ |cff2eb7e4<< 특정형 >>|r
+ |cffceff00■|r q:등급 / quality:등급
+ - 영어로 쓴 등급을 가지는 아이템들만 검색합니다.
+ - 예) |cffceff00q:영웅|r 으로 검색하면 보라템들만 하이라이트 됩니다.
+ - 등급 키 : |cffA8A8A8일반|r, |cff15B300고급|r, |cff0091F2희귀|r, |cffC891FA영웅,|r |cffFF8000전설|r, |cffE6CC80계승|r
+
+ |cffceff00■|r l:템렙 / lvl:템렙 / level:템렙
+ - 입력한 숫자에 딱 맞는 템렙의 아이템들만 검색됩니다.
+
+ |cffceff00■|r t:아이템종류 / type:아이템종류 / slot:아이템종류
+ - 입력한 글자를 포함하는 종류인 아이템들만 표시합니다.
+ - 예) |cffceff00t:양손|r 으로 검색하면 양손 둔기, 양손 도검 등이 검색될 수 있습니다.
+
+ |cffceff00■|r n:이름 / name:이름
+ - 입력한 글자가 아이템 이름에 포함된 것들만 표시합니다.
+
+ |cffceff00■|r s:세트이름 / set:세트이름
+ - 입력한 글자가 포함됀 장비세트에 소속된 아이템들만 표시합니다.
+
+
+ |cff2eb7e4<< 조건부여 >>|r
+ |cffceff00■|r ! (느낌표)
+ - 적은 조건을 제외하도록 합니다.
+ - 예) |cffceff00!q:영웅|r 을 사용하면 영웅등급이 아닌 모든 아이템들이 표시됩니다.
+
+ |cffceff00■|r | (백스페이스 옆 \키를 쉬프트)
+ - 여러 조건을 이어 붙였을 때, 각 조건 중 하나라도 만족하면 표시합니다.
+ - 예) |cffceff00q:영웅|t:무기|r 를 입력하면 영웅 등급인 아이템과 무기 종류인 아이템이 표시됩니다.
+
+ |cffceff00■|r & (쉬프트 7)
+ - 여러 조건을 이어 붙였을 때, 모든 조건을 만족하면 표시합니다.
+ - 예) |cffceff00q:영웅&t:무기|r 를 입력하면 영웅 등급이면서 무기 종류의 아이템만 표시됩니다.
+
+ |cffceff00■|r >, <, >=, <=
+ - 숫자 조건을 제어합니다.
+ - 예) |cffceff00lvl:>30|r 을 입력하면 템렙이 30을 초과하는 아이템들만 표시합니다.
+
+
+ |cff2eb7e4<< 예약어 >>|r
+ - soulbound, bound, bop : 획득시 귀속 아이템을 표시합니다.
+ - bou : 사용시 귀속 아이템을 표시합니다.
+ - boe : 착용 시 귀속 아이템을 표시합니다.
+ - boa : 계정 귀속 아이템을 표시합니다.
+ - quest : 퀘스트 아이템을 표시합니다.]]
+
+L["TEXT_FORMAT_DESC"] = [[글자가 표시되는 형식을 변경할 수 있습니다.
+
+
+|cff2eb7e4< 예시 >|r
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+
+[healthcolor][health:current-max]
+
+[powercolor][power:current]
+
+
+|cff2eb7e4< health(생명력) / power(자원) 형식 >|r
+|cffceff00current|r : 현재 수치
+
+|cffceff00percent|r : 현재 양을 %로 표시
+
+|cffceff00current-max|r : [현재 수치]-[최대값]
+
+|cffceff00current-percent|r : [현재 수치]-[%]
+
+|cffceff00current-max-percent|r : [현재 수치]-[최대값]-[%]
+
+|cffceff00deficit|r : 손실치만 표시하며 현재 수치가 최대치이면 표시하지 않음
+
+
+|cff2eb7e4< name(이름) 형식 >|r
+|cffceff00name:short|r : 최대 10글자
+|cffceff00name:medium|r : 최대 15글자
+|cffceff00name:long|r : 최대 20글자
+
+표시하고 싶지 않으면 빈칸으로 두면 되며, 자세한 정보는 |cff2eb7e4www.tukui.org|r 에서 확인하세요.]];
+
+--ActionBars
+L["Action Paging"] = "페이지 자동전환 조건"
+L["ActionBars"] = "행동단축바"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = true;
+L["Alpha"] = "투명도"
+L["Anchor Point"] = "첫 번째 요소 위치"
+L["Backdrop Spacing"] = true;
+L["Backdrop"] = "배경"
+L["Button Size"] = "버튼 크기"
+L["Button Spacing"] = "버튼 간격"
+L["Buttons Per Row"] = "한 줄당 버튼 수"
+L["Buttons"] = "버튼 수"
+L["Change the alpha level of the frame."] = "해당 프레임의 투명한 수준을 결정합니다."
+L["Color of the actionbutton when not usable."] = true;
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "버튼에 배치된 행동에 필요한 자원(마나, 분노 )이 부족하면 아이콘에 이 색상이 덧칠됩니다."
+L["Color of the actionbutton when out of range."] = "대상이 버튼에 배치된 행동에 필요한 사정거리보다 밖에 있으면 아이콘에 이 색상이 덧칠됩니다."
+L["Color of the actionbutton when usable."] = true;
+L["Color when the text is about to expire"] = "버튼에 배치된 행동의 재사용 대기시간이 초읽기 상태일 경우 글자색"
+L["Color when the text is in the days format."] = "버튼에 배치된 행동의 재사용 대기시간이 일 단위일 경우 글자색"
+L["Color when the text is in the hours format."] = "버튼에 배치된 행동의 재사용 대기시간이 시간 단위일 경우 글자색"
+L["Color when the text is in the minutes format."] = "버튼에 배치된 행동의 재사용 대기시간이 분 단위일 경우 글자색"
+L["Color when the text is in the seconds format."] = "버튼에 배치된 행동의 재사용 대기시간이 초 단위일 경우 글자색"
+L["Cooldown Text"] = "재사용 대기시간 설정"
+L["Darken Inactive"] = "킨 태세만 아이콘 표시"
+L["Days"] = "일 단위 색상"
+L["Display bind names on action buttons."] = "버튼에 지정된 단축키를 표시할지 여부를 결정합니다."
+L["Display cooldown text on anything with the cooldown spiral."] = "재사용 대기시간을 가진 모든 것에 시간을 표시합니다."
+L["Display macro names on action buttons."] = "버튼에 배치된 매크로의 이름을 표시할지 여부를 결정합니다."
+L["Expiring"] = "초읽기 색상"
+L["Global Fade Transparency"] = true;
+L["Height Multiplier"] = "배경 세로길이 배율"
+L["Hours"] = "시간 단위 색상"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = true;
+L["Inherit Global Fade"] = true;
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = true;
+L["Key Down"] = "단축키를 누를 때 실행"
+L["Keybind Mode"] = "단축키 설정 모드"
+L["Keybind Text"] = "단축키 표시"
+L["LBF Support"] = true;
+L["Low Threshold"] = "초읽기 시작 시점"
+L["Macro Text"] = "매크로 이름 표시"
+L["Minutes"] = "분 단위 색상"
+L["Mouse Over"] = "마우스오버 시 표시"
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "이 값 만큼 배경의 길이가 배로 늘어납니다. 배경 하나에 여러 행동단축바를 올리고 싶은 경우에 유용합니다."
+L["Not Usable"] = true;
+L["Out of Power"] = "자원 부족"
+L["Out of Range"] = "사정거리 밖"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "기본값으로 초기화"
+L["Restore the actionbars default settings"] = "이 행동단축바에 대한 모든 수치를 기본값으로 되돌립니다."
+L["Seconds"] = "초 단위 색상"
+L["Show Empty Buttons"] = true;
+L["The amount of buttons to display per row."] = "한 줄에 배치할 버튼의 수를 결정합니다."
+L["The amount of buttons to display."] = "표시할 버튼의 총 개수를 결정합니다."
+L["The button you must hold down in order to drag an ability to another action button."] = "이 키를 누른 상태로 아이콘을 드래그해야 행동단축바에서 기술이 빠져나와 없애거나 옮길 수 있습니다."
+L["The first button anchors itself to this point on the bar."] = "첫 번째 요소를 기준으로 나머지가 나열됩니다."
+L["The size of the action buttons."] = "각각의 행동단축바 버튼의 크기를 결정합니다."
+L["The spacing between the backdrop and the buttons."] = true;
+L["This setting will be updated upon changing stances."] = "이 설정은 태세를 바꿔야 업데이트 됩니다."
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "이 값 이하로 시간이 내려가면 시간이 소숫점 단위 초읽기 형태로 표시됩니다.|n|n-1로 설정하면 이 기능을 사용하지 않습니다."
+L["Toggles the display of the actionbars backdrop."] = "행동단축바의 배경을 표시할지 여부를 결정합니다."
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = true;
+L["Usable"] = true;
+L["Visibility State"] = "표시 자동전환 조건"
+L["Width Multiplier"] = "배경 가로길이 배율"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[이곳에 작성한 조건(예를 들어 전투여부)에 따라 이 행동단축바의 페이지를 자동으로 전환시킬 수 있습니다.
+
+매크로처럼 작성하세요.
+
+|cff2eb7e4< 예시 >|r
+|cffceff00[combat]2;1|r
+ : 전투에 돌입하면 2번 페이지로 변경, 전투가 끝나면 1번 페이지로 변경 ]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[이곳에 작성한 조건(예를 들어 전투여부)에 따라 이 행동단축바를 자동으로 숨기거나 표시할 수 있게 해줍니다.
+
+매크로처럼 작성하세요.
+
+|cff2eb7e4< 예시 >|r
+|cffceff00[combat]show;hide|r
+ : 전투에 돌입하면 표시, 전투가 끝나면 숨김]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = true;
+L["Add Item or Search Syntax"] = true;
+L["Adjust the width of the bag frame."] = "통합가방 프레임의 가로길이를 결정합니다."
+L["Adjust the width of the bank frame."] = "통합은행 프레임의 가로길이를 결정합니다."
+L["Ascending"] = "오름차순"
+L["Bag Sorting"] = true;
+L["Bag-Bar"] = "가방바"
+L["Bar Direction"] = "바 방향"
+L["Blizzard Style"] = "블리자드 기본"
+L["Bottom to Top"] = "상단 아래쪽으로 이동"
+L["Button Size (Bag)"] = "슬롯 크기 (가방)"
+L["Button Size (Bank)"] = "슬롯 크기 (은행)"
+L["Clear Search On Close"] = true;
+L["Condensed"] = "간략하게"
+L["Descending"] = "내림차순"
+L["Direction the bag sorting will use to allocate the items."] = "정렬기능을 실행할 때 체크 시 아이템이 가방칸의 우측하단을, 체크 해제 시 좌측상단을 기준으로 모아서 정렬됩니다."
+L["Disable Bag Sort"] = true;
+L["Disable Bank Sort"] = true;
+L["Display Item Level"] = "템렙 표시"
+L["Displays item level on equippable items."] = "착용 가능한 아이템의 경우 아이템 슬롯에 템렙을 표시합니다."
+L["Enable/Disable the all-in-one bag."] = "통합가방 기능을 사용할지 여부를 결정합니다."
+L["Enable/Disable the Bag-Bar."] = "가방바를 사용할지 여부를 결정합니다."
+L["Full"] = "전체"
+L["Global"] = true;
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = true;
+L["Ignored Items and Search Syntax (Global)"] = true;
+L["Ignored Items and Search Syntax (Profile)"] = true;
+L["Item Count Font"] = true;
+L["Item Level Threshold"] = "템렙표시 커트라인"
+L["Item Level"] = "아이템 레벨"
+L["Money Format"] = "소지금 표시방법"
+L["Panel Width (Bags)"] = "통합가방 프레임 가로길이"
+L["Panel Width (Bank)"] = "통합은행 프레임 가로길이"
+L["Search Syntax"] = "아이템 검색법"
+L["Set the size of your bag buttons."] = "가방바에서 슬롯의 크기를 결정합니다."
+L["Short (Whole Numbers)"] = "골드만"
+L["Short"] = "짧게"
+L["Smart"] = "스마트"
+L["Sort Direction"] = "정렬 방법"
+L["Sort Inverted"] = "아래로 정렬"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "가방바를 가로로 나열할지, 세로로 나열할지 결정합니다."
+L["The direction that the bag frames will grow from the anchor."] = "가방바의 슬롯이 시작점을 기준으로 슬롯번호순으로 나열할지, 역순으로 나열할지 결정합니다."
+L["The display format of the money text that is shown at the top of the main bag."] = "통합가방 상단에 표시되는 보유 골드의 표시 방법을 결정합니다."
+L["The frame is not shown unless you mouse over the frame."] = "커서를 갖다 댔을(마우스오버) 시에만 표시됩니다."
+L["The minimum item level required for it to be shown."] = "아이템에 표시되는 템렙의 표시기준 최저치를 결정합니다."
+L["The size of the individual buttons on the bag frame."] = "통합가방 프레임의 슬롯크기를 결정합니다."
+L["The size of the individual buttons on the bank frame."] = "통합은행 프레임의 슬롯크기를 결정합니다."
+L["The spacing between buttons."] = "버튼 사이의 간격을 설정합니다."
+L["Top to Bottom"] = "위에서 아래로"
+L["Use coin icons instead of colored text."] = "골드 이미지를 글자가 아닌 아이콘으로 표시합니다."
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "버프와 디버프";
+L["Begin a new row or column after this many auras."] = "한 줄에 아이콘이 이 값보다 많으면 다음 줄에 배치합니다."
+L["Count xOffset"] = "중첩수 x 좌표"
+L["Count yOffset"] = "중첩수 y 좌표"
+L["Defines how the group is sorted."] = "오라를 어떤 기준으로 정렬할지를 결정합니다."
+L["Defines the sort order of the selected sort method."] = "기준을 바탕으로 하여 어떤 순서로 정렬할지를 결정합니다."
+L["Disabled Blizzard"] = "기본 오라창 미사용"
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "초읽기 시작 시점"
+L["Index"] = "종류"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "스스로 걸은 효과를 남이 걸어준 효과보다 먼저 나열할지, 후에 나열할지, 구분하지 않을지를 결정합니다."
+L["Limit the number of rows or columns."] = "표시줄 수를 제한해 최종적으로 보여줄 오라의 총 개수를 제한합니다."
+L["Max Wraps"] = "표시줄 최대 수"
+L["No Sorting"] = "구분하지 않음"
+L["Other's First"] = "남이 걸어준 효과 먼저"
+L["Remaining Time"] = "지속시간 표시"
+L["Reminder"] = true
+L["Reverse Style"] = "보유 시 강조 스타일"
+L["Seperate"] = "시전자 구분 정렬"
+L["Set the size of the individual auras."] = "오라 아이콘의 크기를 결정합니다."
+L["Sort Method"] = "정렬 기준"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = "오라가 어느 방향으로 나열되고, 다음 줄을 어느 방향에 배치할지 결정합니다."
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "이 값 이하로 시간이 내려가면 시간이 소숫점 단위 초읽기 형태로 표시되며 깜박이기 시작합니다.|n|n-1로 설정하면 이 기능을 사용하지 않습니다."
+L["Time xOffset"] = "시간 x 좌표"
+L["Time yOffset"] = "시간 y 좌표"
+L["Time"] = "시간"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = "해당 시너지버프를 가지고 있을 때 아이콘을 활성화하는 방식입니다."
+L["Wrap After"] = "한 줄에 표시할 오라 수"
+L["Your Auras First"] = "내가 걸은 효과 먼저"
+
+--Chat
+L["Above Chat"] = "채팅창 위에 배치"
+L["Adjust the height of your right chat panel."] = "우측 패널의 세로길이를 결정합니다."
+L["Adjust the width of your right chat panel."] = "우측 패널의 가로길이를 결정합니다."
+L["Alerts"] = "알림"
+L["Allowed Combat Repeat"] = true;
+L["Attempt to create URL links inside the chat."] = "대화 내역에 URL 주소가 있으면 강조하고 클릭 시 복사할 수 있게끔 합니다."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "좌우측 패널에 채팅창 고정 여부를 결정합니다. 체크 해제 시 좌측에 고정된 기본 채팅창도 움직일 수 있습니다."
+L["Below Chat"] = "채팅창 아래에 배치"
+L["Chat EditBox Position"] = "대화입력창 위치"
+L["Chat History"] = "이전 채팅내역 기억"
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = true;
+L["Custom Timestamp Color"] = true;
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "각종 링크에 커서를 갖다 댄(마우스오버) 동안에 링크에 대한 툴팁을 표시합니다."
+L["Enable the use of separate size options for the right chat panel."] = "좌우 패널의 크기를 따로 설정하도록 합니다."
+L["Exclude Name"] = true;
+L["Excluded names will not be class colored."] = true;
+L["Excluded Names"] = true;
+L["Fade Chat"] = "오래된 메시지 숨기기"
+L["Fade Tabs No Backdrop"] = true;
+L["Fade the chat text when there is no activity."] = "시간이 오래 지난 이전의 메시지를 채팅창에서 보이지 않게 합니다. 삭제하는 것은 아니니 마우스 휠링으로 안보이게 한 이전의 메시지를 다시 확인할 수 있습니다."
+L["Fade Undocked Tabs"] = "채팅탭 숨기기"
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = "좌우 패널에 삽입되지 않은 다른 채팅창들의 채팅탭을 숨깁니다."
+L["Font Outline"] = "글꼴 외곽선"
+L["Font"] = "글꼴"
+L["Hide Both"] = "둘 다 숨기기"
+L["Hyperlink Hover"] = "링크 툴팁 표시"
+L["Keyword Alert"] = "키워드 발견 시 소리로 알림"
+L["Keywords"] = "강조할 키워드"
+L["Left Only"] = "좌측 배경만 표시"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "이 곳에 키워드를 적으면 모든 대화내용에서 해당 키워드를 발견 시 색깔을 입혀 강조합니다. 쉼표(,) 로 구분해서 작성하세요.|n|n내 이름을 강조하고 싶으면 |cff2eb7e4%MYNAME%|r 을 사용하면 됩니다."
+L["Lock Positions"] = "패널에 채팅창 고정"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "애드온 리로드나 로그아웃 이전의 채팅내역을 보존하여 접속했을 때 보여줍니다."
+L["No Alert In Combat"] = true;
+L["Number of messages you scroll for each step."] = true;
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = true;
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "채팅창의 스크롤이 맨 아래가 아니라면 이 값 만큼 시간이 지났을 때 맨 아래로 자동 스크롤링 됩니다."
+L["Panel Backdrop"] = "패널 배경 표시"
+L["Panel Height"] = "패널 세로길이"
+L["Panel Texture (Left)"] = "패널 텍스쳐 (왼쪽)"
+L["Panel Texture (Right)"] = "패널 텍스쳐 (오른쪽)"
+L["Panel Width"] = "패널 가로길이"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "대화 입력창의 위치를 결정합니다. 만약 정보문자 항목에서 패널에 정보문자를 표시하지 않게 해놨다면 위치가 채팅창 위로 고정됩니다."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "같은 내용의 메시지는 이 값만큼 정해진 시간 내에선 한번만 보여줍니다.|n|n0으로 설정하면 이 기능을 끕니다."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = true;
+L["Right Only"] = "우측 배경만 표시"
+L["Right Panel Height"] = "우측 패널 세로길이"
+L["Right Panel Width"] = "우측 패널 가로길이"
+L["Scroll Interval"] = "자동 스크롤링 시간"
+L["Scroll Messages"] = true;
+L["Separate Panel Sizes"] = "좌우패널 크기 따로설정"
+L["Set the font outline."] = "글꼴의 외곽선을 결정합니다."
+L["Short Channels"] = "채널명 요약"
+L["Shorten the channel names in chat."] = "채팅창의 채널명을 간추려 표시합니다."
+L["Show Both"] = "둘 다 배경 표시"
+L["Spam Interval"] = "중복메시지 제한 기간"
+L["Sticky Chat"] = "채널 고정"
+L["Tab Font Outline"] = "채팅탭 글꼴 외곽선"
+L["Tab Font Size"] = "채팅탭 글꼴 크기"
+L["Tab Font"] = "채팅탭 글꼴"
+L["Tab Panel Transparency"] = "탭을 반투명하게"
+L["Tab Panel"] = "패널 탭 표시"
+L["Timestamp Color"] = true;
+L["Toggle showing of the left and right chat panels."] = "패널의 배경 표시 여부를 결정합니다."
+L["Toggle the chat tab panel backdrop."] = "패널 상단에 위치한 탭 부분의 표시 여부를 결정합니다."
+L["URL Links"] = "URL 주소 강조"
+L["Use Alt Key"] = true;
+L["Use class color for the names of players when they are mentioned."] = true;
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "이전에 말한 채널을 계속 유지할지 여부를 결정합니다.|n|n체크 해제 시 대화입력창을 열 때마다 일반 채널로 설정됩니다."
+L["Whisper Alert"] = "귓말이 오면 소리로 알림"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[패널 배경에 그림을 입히고 싶으면 위치와 파일명를 이곳에 입력해야 합니다.
+
+|cff2eb7e4< 예시 >|r
+|cffceff00Interface/AddOns/ElvUI/media/textures/|cff2eb7e4TestImage|r
+- 위의 주소로 된 texture 폴더 안 TestImage.tga 그림을 불러옴
+- 위의 주소는 \ 대신 / 를 사용한 것. 직접 적을 땐 반드시 \ 로 주소구분
+
+|cff2eb7e4< 주의 >|r
+- 256 X 128 크기 권장
+- 그림을 와우 설치 폴더 안에 넣고 게임을 재시작해야 적용 가능
+- 확장자는 .tga 포맷만 가능
+
+간단히는 그림을 와우 설치 폴더에 넣은후 파일명만 적으세요.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "|cff2eb7e4< 개발자 >|r"
+L["Credits"] = "제작자"
+L["Donations:"] = "|cff2eb7e4< 기부자 >|r"
+L["ELVUI_CREDITS"] = "저는 이 애드온의 유지와 개발 코딩에 도움을 주거나 기부를 한 분들께 특별히 감사하고 싶습니다. 포럼에서 저에게 개인적으로 메일을 준 분들에힌해 이름만 표기했으며만약 당신의 이름이 누락되어 있고 명단에 당신의 이름을 표기하고 하는 분들은 Elv에게 개인적인 메일을 보내주시기 바랍니다. "
+L["Testing:"] = "|cff2eb7e4< 테스터 >|r"
+
+--DataBars
+L["Current - Percent (Remaining)"] = true;
+L["Current - Remaining"] = true;
+L["DataBars"] = true;
+L["Hide In Combat"] = true;
+L["Setup on-screen display of information bars."] = true;
+
+--DataTexts
+L["Battleground Texts"] = "전장에서 표시전환"
+L["Block Combat Click"] = true;
+L["Block Combat Hover"] = true;
+L["Blocks all click events while in combat."] = true;
+L["Blocks datatext tooltip from showing in combat."] = true;
+L["BottomLeftMiniPanel"] = "Minimap BottomLeft (Inside)"
+L["BottomMiniPanel"] = "Minimap Bottom (Inside)"
+L["BottomRightMiniPanel"] = "Minimap BottomRight (Inside)"
+L["Datatext Panel (Left)"] = "좌측 정보문자 탭 사용"
+L["Datatext Panel (Right)"] = "우측 정보문자 탭 사용"
+L["DataTexts"] = "정보문자"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "패널의 하단에 정보문자 탭을 추가합니다. 이 탭에 정보문자가 있게 됩니다."
+L["Display minimap panels below the minimap, used for datatexts."] = "미니맵 하단에 2개의 정보문자를 추가합니다."
+L["Gold Format"] = "골드 표시방법"
+L["left"] = "왼쪽"
+L["LeftChatDataPanel"] = "좌측 패널 정보문자 탭"
+L["LeftMiniPanel"] = "미니맵 왼쪽 정보문자"
+L["middle"] = "중앙"
+L["Minimap Panels"] = "미니맵 정보문자 사용"
+L["Panel Transparency"] = "탭을 반투명하게"
+L["Panels"] = "패널"
+L["right"] = "오른쪽"
+L["RightChatDataPanel"] = "우측 패널 정보문자 탭"
+L["RightMiniPanel"] = "미니맵 오른쪽 정보문자"
+L["Small Panels"] = true;
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = "정보문자와 툴팁에서 표시될 골드의 형식을 결정합니다."
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap TopLeft (Inside)"
+L["TopMiniPanel"] = "Minimap Top (Inside)"
+L["TopRightMiniPanel"] = "Minimap TopRight (Inside)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "전장 안에 있는 경우 주 정보문자에 자신의 각종 점수들을 표시하게 합니다."
+L["Word Wrap"] = true;
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "대상으로 잡은 유저가 타 서버 유저라면 반드시 그 유저와 파티를 맻고 있어야 합니다."
+L["Sends your current profile to your target."] = "대상에게 지금 활성화되어 있는 프로필 설정을 전송합니다."
+L["Sends your filter settings to your target."] = "대셍에게 지금 사용하고 있는 필터 설정을 전송합니다."
+L["Share Current Profile"] = "프로필설정 전송"
+L["Share Filters"] = "필터설정 전송"
+L["This feature will allow you to transfer settings to other characters."] = "전송 기능을 통해 대상에게 자신의 설정을 넘겨줄 수 있습니다."
+L["You must be targeting a player."] = "유저를 대상으로 잡은 후에 시도해야 합니다."
+
+--Filters
+L["Reset Aura Filters"] = true --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "지인의 초대 자동수락"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "위협수치 바를 어느 패널의 정보문자 탭에 배치할지 결정합니다."
+L["AFK Mode"] = "자리비움 모드"
+L["Announce Interrupts"] = "차단 성공시 알림"
+L["Announce when you interrupt a spell to the specified chat channel."] = "주문 차단에 성공하면 여기에서 설정한 채널로 차단성공을 알립니다."
+L["Attempt to support eyefinity/nvidia surround."] = "다중모니터 기술인 아이피니티 기능이나 nvidia 서라운드 기능 지원을 적용합니다."
+L["Auto Greed/DE"] = "자동 차비/추출 선택"
+L["Auto Repair"] = "자동 수리"
+L["Auto Scale"] = "UI크기 자동조절"
+L["Automatically accept invites from guild/friends."] = "길드원이나 친구가 플레이어를 파티를 초대하면 자동으로 수락합니다."
+L["Automatically repair using the following method when visiting a merchant."] = "수리가 가능한 상점을 열면 이 옵션에서 선택한 자금으로 장비를 자동 수리합니다."
+L["Automatically scale the User Interface based on your screen resolution"] = "현재의 화면 해상도에 따라 자동으로 UI의 크기를 조절합니다."
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "녹템 주사위창이 뜨면 자동으로 차비나 마력추출을 선택합니다. 이 기능은 오로지 만렙 캐릭터에서만 동작합니다."
+L["Automatically vendor gray items when visiting a vendor."] = "상점이 열리면 잡동사니를 자동으로 판매합니다."
+L["Bottom Panel"] = "하단 패널 표시"
+L["Chat Bubbles Style"] = "말풍선 디자인"
+L["Chat Bubbles"] = true;
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = "바의 증감방향을 결정합니다."
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "화면 하단에 꾸미기 용도의 바를 생성합니다."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "화면 상단에 꾸미기 용도의 바를 생성합니다."
+L["Display battleground messages in the middle of the screen."] = true;
+L["Enable/Disable the loot frame."] = "주사위 굴림 및 전리품 획득 확인창의 사용 여부를 결정합니다.|n|n이 창은 |cff2eb7e4/loot|r 명령어로 볼 수 있습니다."
+L["Enable/Disable the loot roll frame."] = "ElvUI 디자인의 입찰 / 차비 / 마력추출을 선택하는 주사위 굴림창 사용 여부를 결정합니다."
+L["Enables the ElvUI Raid Control panel."] = true;
+L["Enhanced PVP Messages"] = true;
+L["General"] = "일반"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = "퀘스트프레임의 길이를 결정합니다."
+L["Hide At Max Level"] = true;
+L["Hide Error Text"] = "전투중 에러 숨기기"
+L["Hide In Vehicle"] = true;
+L["Hides the red error text at the top of the screen while in combat."] = "화면 중앙 상단에 뜨는 여러 에러메시지(ex : 사정거리 부족)를 전투 중에는 띄우지 않게 합니다."
+L["Log Taints"] = "Taint 에러 표시"
+L["Login Message"] = "로그인 메세지 표시"
+L["Loot Roll"] = "주사위 굴림창"
+L["Loot"] = "전리품 확인창"
+L["Lowest Allowed UI Scale"] = true;
+L["Multi-Monitor Support"] = "다중모니터 지원"
+L["Name Font"] = "캐릭터 이름 글꼴"
+L["Number Prefix"] = true;
+L["Party / Raid"] = "파티&레이드 채널로"
+L["Party Only"] = "파티채널만"
+L["Raid Only"] = "레이드채널만"
+L["Remove Backdrop"] = "표시하지 않음"
+L["Reset all frames to their original positions."] = "ElvUI 에서 움직일 수 있는 모든 프레임의 위치를 기본 위치로 초기화합니다."
+L["Reset Anchors"] = "위치 초기화"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "애드온 기능이 막히는 에러도 오류확인창에 등록합니다. 이런 에러들은 중요하지 않거나 게임플레이에 영향을 미치지 않는 것들이 대부분입니다. 게다가 이런 에러들은 대부분 고칠 수 없는 것들입니다.|n|n발견되는 에러가 게임플레이에 지장이 될 경우에만 에러보고를 해주세요."
+L["Skin Backdrop (No Borders)"] = true;
+L["Skin Backdrop"] = "반투명 스킨적용"
+L["Skin the blizzard chat bubbles."] = "말풍선에 디자인을 변경해 스킨을 입힐지, 혹은 투명하게 하여 안보이게 할지 결정합니다."
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "화면상에서 캐릭터 위에 표시되는 이름, 길드, 칭호 등의 글꼴을 변경합니다.|n|n|cffff0000WARNING|r|n이 설정은 리로드가 아닌 캐릭터에 재접속하야 적용됩니다."
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = true;
+L["Thin Border Theme"] = true;
+L["Toggle Tutorials"] = "애드온 튜토리얼 확인"
+L["Top Panel"] = "상단 패널 표시"
+L["Version Check"] = true;
+L["Watch Frame Height"] = "퀘스트프레임 세로길이"
+L["When you go AFK display the AFK screen."] = "자리비움 시 UI가 자리비움모드로 전환됩니다."
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = true;
+L["Applies the primary texture to all statusbars."] = true;
+L["Apply Font To All"] = true;
+L["Apply Texture To All"] = true;
+L["Backdrop color of transparent frames"] = "ElvUI에서 생성하는 모든 반투명한 프레임의 배경 색상과 투명도를 결정합니다."
+L["Backdrop Color"] = "배경 색상"
+L["Backdrop Faded Color"] = "반투명 배경 색상"
+L["Border Color"] = "테두리 색상"
+L["Color some texts use."] = "일부 문자나 프레임을 강조할 때 이 색상을 사용합니다."
+L["Colors"] = "색상"
+L["CombatText Font"] = "전투 상황 글꼴"
+L["Default Font"] = "기본 글꼴"
+L["Font Size"] = "글꼴 크기"
+L["Fonts"] = "글꼴"
+L["Main backdrop color of the UI."] = "ElvUI에서 생성하는 모든 불투명한 프레임의 배경 색상을 결정합니다."
+L["Main border color of the UI."] = true;
+L["Media"] = "미디어"
+L["Primary Texture"] = "주 텍스쳐"
+L["Replace Blizzard Fonts"] = "블리자드 폰트 교체"
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = "기본적으로 지정되는 대부분의 블리자드프레임 내 글자들의 폰트를 여기서 설정하는 폰트로 바꿉니다."
+L["Secondary Texture"] = "보조 텍스쳐"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "ElvUI에서 쓰이는 모든 글꼴 크기를 결정합니다.|n|n개인적으로 글꼴 크기를 지정할 수 있는 곳은 적용되지 않습니다."
+L["Textures"] = "텍스처"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "화면상에서 전투 상황에 관련된 글자에 적용되는 글꼴입니다.|n|n|cffff0000WARNING|r|n이 설정은 리로드가 아닌 캐릭터에 재접속하야 적용됩니다."
+L["The font that the core of the UI will use."] = "ElvUI에서 쓰이는 모든 글자의 글꼴을 결정합니다.|n|n개인적으로 글꼴을 지정할 수 있는 곳은 적용되지 않습니다."
+L["The texture that will be used mainly for statusbars."] = "기본적으로 상태바 같은 곳에서 입혀지는 텍스쳐입니다."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "채팅창이나 메뉴 같은 프레임에 입혀지는 텍스쳐입니다."
+L["Value Color"] = "강조 색상"
+
+--Maps
+L["Adjust the size of the minimap."] = "미니맵의 크기를 결정합니다."
+L["Always Display"] = "항상 표시"
+L["Bottom Left"] = "하단 좌측"
+L["Bottom Right"] = "하단 우측"
+L["Bottom"] = "하단 중앙"
+L["Change settings for the display of the location text that is on the minimap."] = "미니맵 상단에 있는 지역이름의 표시방법을 결정합니다."
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = true;
+L["Instance Difficulty"] = "인스 난이도"
+L["Left"] = "왼쪽"
+L["LFG Queue"] = "파티찾기 표시기"
+L["Location Text"] = "지역이름 표시 방법"
+L["Make the world map smaller."] = "월드맵을 작게 표시합니다."
+L["Maps"] = true;
+L["Minimap Buttons"] = "미니맵 버튼"
+L["Minimap Mouseover"] = "마우스오버 때만 표시"
+L["Puts coordinates on the world map."] = true;
+L["PvP Queue"] = true
+L["Reset Zoom"] = true;
+L["Right"] = "오른쪽"
+L["Scale"] = "크기"
+L["Smaller World Map"] = "월드맵 축소"
+L["Top Left"] = "상단 좌측"
+L["Top Right"] = "상단 우측"
+L["Top"] = "상단 중앙"
+L["World Map Coordinates"] = true;
+L["X-Offset"] = true;
+L["Y-Offset"] = true;
+
+--Misc
+L["Install"] = "설치"
+L["Run the installation process."] = "ElvUI의 설치 프로세스를 실행합니다."
+L["Toggle Anchors"] = "프레임 이동 모드"
+L["Unlock various elements of the UI to be repositioned."] = "ElvUI에서 위치를 조정할 수 있는 프레임들을 움직이는 이동 모드를 실행합니다."
+L["Version"] = "버전"
+
+--NamePlates
+L["# Displayed Auras"] = true;
+L["Actions"] = true
+L["Add Name"] = "이름표 필터 추가"
+L["Add Nameplate Filter"] = true
+L["Add Regular Filter"] = true
+L["Add Special Filter"] = true
+L["Always Show Target Health"] = true
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = true
+L["Background Glow"] = true
+L["Bad Color"] = true;
+L["Bad Scale"] = true;
+L["Bad Transition Color"] = true;
+L["Base Height for the Aura Icon"] = true;
+L["Border Glow"] = true
+L["Border"] = true
+L["Cast Bar"] = "시전바"
+L["Cast Color"] = true;
+L["Cast No Interrupt Color"] = true;
+L["Cast Time Format"] = true;
+L["Casting"] = true
+L["Channel Time Format"] = true;
+L["Clear Filter"] = true
+L["Color Tanked"] = true;
+L["Control enemy nameplates toggling on or off when in combat."] = true;
+L["Control friendly nameplates toggling on or off when in combat."] = true;
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = true;
+L["Cooldowns"] = true
+L["Copy settings from another unit."] = true;
+L["Copy Settings From"] = true;
+L["Current Level"] = true
+L["Default Settings"] = true;
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "전장이나 투기장에서 유닛이 힐러인 경우 이름표에 힐러 아이콘을 표시합니다."
+L["Elite Icon"] = true
+L["Enable/Disable the scaling of targetted nameplates."] = true;
+L["Enabling this will check your health amount."] = true
+L["Enemy Combat Toggle"] = true;
+L["Enemy NPC Frames"] = true;
+L["Enemy Player Frames"] = true;
+L["Enemy"] = "적군" --Also used in UnitFrames
+L["ENEMY_NPC"] = "Enemy NPC"
+L["ENEMY_PLAYER"] = "Enemy Player"
+L["Filter already exists!"] = "이미 그 이름의 필터가 존재합니다!"
+L["Filter Priority"] = true;
+L["Filters Page"] = true;
+L["Friendly Combat Toggle"] = true;
+L["Friendly NPC Frames"] = true;
+L["Friendly Player Frames"] = true;
+L["FRIENDLY_NPC"] = "우호적인 NPC"
+L["FRIENDLY_PLAYER"] = "우호적인 플레이어"
+L["General Options"] = true;
+L["Good Color"] = true;
+L["Good Scale"] = true;
+L["Good Transition Color"] = true;
+L["Healer Icon"] = "힐러 아이콘 표시"
+L["Health Color"] = true
+L["Health Threshold"] = true
+L["Hide Frame"] = true
+L["Hide Spell Name"] = true;
+L["Hide Time"] = true;
+L["Hide"] = "숨기기" --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = true
+L["Icon Base Height"] = true;
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = true
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = true
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = true
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = true
+L["If enabled then the filter will only activate when you are in combat."] = true
+L["If enabled then the filter will only activate when you are out of combat."] = true
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = true
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = true
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["Instance Type"] = true
+L["Interruptible"] = true
+L["Is Targeted"] = true
+L["LEVEL_BOSS"] = "Set level to -1 for boss units or set to 0 to disable."
+L["Low Health Threshold"] = "낮은 생명력 임계점"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = true
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = true;
+L["Match Player Level"] = true
+L["Maximum Level"] = true
+L["Maximum Time Left"] = true
+L["Minimum Level"] = true
+L["Minimum Time Left"] = true
+L["Missing"] = true
+L["Name Color"] = true
+L["Name Only"] = true
+L["NamePlates"] = "이름표"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = true;
+L["Not Targeted"] = true
+L["Off Cooldown"] = true
+L["On Cooldown"] = true
+L["Over Health Threshold"] = true
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = true;
+L["Player Health"] = true
+L["Player in Combat"] = true
+L["Player Out of Combat"] = true
+L["Reaction Colors"] = true;
+L["Reaction Type"] = true
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "이름표 필터 제거"
+L["Remove Nameplate Filter"] = true
+L["Require All"] = true
+L["Reset filter priority to the default state."] = true;
+L["Reset Priority"] = true;
+L["Return filter to its default state."] = true
+L["Scale of the nameplate that is targetted."] = true;
+L["Select Nameplate Filter"] = true
+L["Set Settings to Default"] = true;
+L["Set the transparency level of nameplates that are not the target nameplate."] = true;
+L["Set to either stack nameplates vertically or allow them to overlap."] = true;
+L["Shortcut to 'Filters' section of the config."] = true;
+L["Shortcut to global filters."] = true
+L["Shortcuts"] = true;
+L["Side Arrows"] = true
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = true
+L["Tagged NPC"] = "선점된 유닛"
+L["Tanked Color"] = true;
+L["Target Indicator Color"] = true
+L["Target Indicator"] = true
+L["Target Scale"] = true;
+L["Targeted Nameplate"] = true
+L["Texture"] = true
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = true;
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = true;
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = true
+L["Threat"] = "위협"
+L["Time To Hold"] = true
+L["Toggle Off While In Combat"] = true;
+L["Toggle On While In Combat"] = true;
+L["Top Arrow"] = true
+L["Triggers"] = true
+L["Under Health Threshold"] = true
+L["Unit Type"] = true
+L["Use Class Color"] = true;
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = true;
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = true;
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = true;
+L["Use Target Glow"] = true;
+L["Use Target Scale"] = true;
+L["Use Threat Color"] = true;
+L["You can't remove a default name from the filter, disabling the name."] = "기본으로 있었던 이름 필터는 제거할 수 없습니다. 비활성화 처리하세요."
+
+--Profiles Export/Import
+L["Choose Export Format"] = true;
+L["Choose What To Export"] = true;
+L["Decode Text"] = true;
+L["Error decoding data. Import string may be corrupted!"] = true;
+L["Error exporting profile!"] = true;
+L["Export Now"] = true;
+L["Export Profile"] = true;
+L["Exported"] = true;
+L["Filters (All)"] = true;
+L["Filters (NamePlates)"] = true;
+L["Filters (UnitFrames)"] = true;
+L["Global (Account Settings)"] = true;
+L["Import Now"] = true;
+L["Import Profile"] = true;
+L["Importing"] = true;
+L["Plugin"] = true;
+L["Private (Character Settings)"] = true;
+L["Profile imported successfully!"] = true;
+L["Profile Name"] = true;
+L["Profile"] = true;
+L["Table"] = true;
+
+--Skins
+L["Achievement Frame"] = "업적창"
+L["Alert Frames"] = "알림 프레임"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "경매장"
+L["Barbershop Frame"] = "미용실"
+L["BG Map"] = "전장 맵"
+L["BG Score"] = "전장 점수판"
+L["Calendar Frame"] = "달력"
+L["Character Frame"] = "캐릭터 창"
+L["Debug Tools"] = "오류 확인 창"
+L["Dressing Room"] = "아이템 미리보기 창"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "NPC 대화 창"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "길드 은행"
+L["Guild Registrar"] = "길드 등록"
+L["Help Frame"] = "도움말"
+L["Inspect Frame"] = "살펴보기 창"
+L["KeyBinding Frame"] = "단축키 설정 창"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "루팅 창"
+L["Macro Frame"] = "매크로 창"
+L["Mail Frame"] = "우편함"
+L["Merchant Frame"] = "상인 창"
+L["Mirror Timers"] = true;
+L["Misc Frames"] = "기타 프레임"
+L["Petition Frame"] = "GM 요청 창"
+L["PvP Frames"] = "PvP 창"
+L["Quest Frames"] = "퀘스트 창"
+L["Raid Frame"] = "공격대 프레임"
+L["Skins"] = "스킨"
+L["Socket Frame"] = "보석홈 UI"
+L["Spellbook"] = "마법책 프레임"
+L["Stable"] = "소환수 보관창"
+L["Tabard Frame"] = "휘장 프레임"
+L["Talent Frame"] = "특성 창"
+L["Taxi Frame"] = "그리폰/와이번 창"
+L["Time Manager"] = "시계 창"
+L["Trade Frame"] = "거래창"
+L["TradeSkill Frame"] = "전문기술 창"
+L["Trainer Frame"] = "기술전문가 창"
+L["Tutorial Frame"] = true;
+L["World Map"] = "세계 지도"
+
+--Tooltip
+L["Always Hide"] = "표시하지 않음"
+L["Bags Only"] = "가방 안에만"
+L["Bags/Bank"] = true;
+L["Bank Only"] = "은행 안에만"
+L["Both"] = "가방, 은행 모두"
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = true;
+L["Comparison Font Size"] = true;
+L["Cursor Anchor"] = "툴팁을 마우스에 표시"
+L["Custom Faction Colors"] = "반응색 개인설정"
+L["Display guild ranks if a unit is guilded."] = "길드명과 함께 길드 등급도 표시합니다."
+L["Display how many of a certain item you have in your possession."] = "현재 툴팁으로 보고있는 아이템을 여러개 갖고 있다면 갯수를 표시합니다."
+L["Display player titles."] = "이름에 칭호도 표시합니다."
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = "Shift를 누른 상태로 유저에게 마우스를 대면 특성과 아이템레벨도 표시합니다. 표시하는데 시간이 조금 필요합니다."
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "아이템과 주문 툴팁에 각각의 ID를 표시합니다."
+L["Guild Ranks"] = "길드 내 등급 표시"
+L["Header Font Size"] = true;
+L["Health Bar"] = "생명력바"
+L["Hide tooltip while in combat."] = "전투 중에는 툴팁을 표시하지 않게 합니다."
+L["Inspect Info"] = "특성/아이템레벨 표시"
+L["Item Count"] = "아이템 갯수 표시"
+L["Never Hide"] = "항시 표시"
+L["Player Titles"] = "칭호 표시"
+L["Should tooltip be anchored to mouse cursor"] = "마우스에 툴팁을 표시합니다.|n|n체크 해제 시 프레임 이동 모드에서 툴팁 위치에 표시됩니다."
+L["Spell/Item IDs"] = "아이템/주문 ID 표시"
+L["Target Info"] = "대상선택 정보"
+L["Text Font Size"] = true;
+L["This setting controls the size of text in item comparison tooltips."] = true;
+L["Tooltip Font Settings"] = true;
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "누구를 대상으로 잡고 있는지, 누가 이 유닛을 대상으로 잡았는지에 대한 정보를 툴팁에 추가합니다."
+
+--UnitFrames
+L["%s and then %s"] = "%s 이후 %s"
+L["2D"] = "이미지"
+L["3D"] = "3d 모델"
+L["Above"] = "프레임 위로"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = true;
+L["Add a spell to the filter."] = "필터에 주문을 추가합니다."
+L["Add Spell ID or Name"] = true;
+L["Add SpellID"] = "주문 ID 추가"
+L["Additional Filter Override"] = true;
+L["Additional Filter"] = "추가적용할 필터"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = true;
+L["Allow Whitelisted Auras"] = "요구목록에 있는건 표시"
+L["An X offset (in pixels) to be used when anchoring new frames."] = "기준 프레임에서 가로로 얼마만큼 떨어져 있을지를 결정합니다."
+L["An Y offset (in pixels) to be used when anchoring new frames."] = "기준 프레임에서 세로로 얼마만큼 떨어져 있을지를 결정합니다."
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = true;
+L["Assist Frames"] = "지원공격 전담 프레임"
+L["Assist Target"] = "지원공격 전담 프레임"
+L["At what point should the text be displayed. Set to -1 to disable."] = "이 값보다 시간이 낮아지면 글자가 표시됩니다.|n|n-1로 설정하면 이 기능을 사용하지 않습니다."
+L["Attach Text To"] = true;
+L["Attach To"] = "기준 프레임"
+L["Aura Bars"] = "클래스타이머"
+L["Auto-Hide"] = "자동으로 숨기기"
+L["Bad"] = "나쁨"
+L["Bars will transition smoothly."] = "바의 증감을 부드럽게 표현합니다."
+L["Below"] = "프레임 아래로"
+L["Blacklist Modifier"] = true;
+L["Blacklist"] = "차단 목록"
+L["Block Auras Without Duration"] = "지속시간이 없으면 제외"
+L["Block Blacklisted Auras"] = "차단목록에 있는건 제외"
+L["Block Non-Dispellable Auras"] = "해제할 수 없으면 제외"
+L["Block Non-Personal Auras"] = "남이 걸은 건 제외"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "혈기"
+L["Borders"] = "테두리"
+L["Buff Indicator"] = "버프 알람"
+L["Buffs"] = "버프"
+L["By Type"] = "종류에 따라서"
+L["Castbar"] = "시전바"
+L["Center"] = "정 중앙"
+L["Check if you are in range to cast spells on this specific unit."] = "이 유닛이 사거리 밖에 있으면 투명도를 적용합니다.|n|n체크를 해제하면 거리에 상관없이 투명도를 적용하지 않습니다."
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = true;
+L["Class Backdrop"] = "배경에 직업색상 적용"
+L["Class Castbars"] = "직업색상 사용"
+L["Class Color Override"] = "직업색 적용 여부"
+L["Class Health"] = "직업색상 사용"
+L["Class Power"] = "직업색상 사용"
+L["Class Resources"] = "직업별 특수 자원바"
+L["Click Through"] = "마우스 무시"
+L["Color all buffs that reduce the unit's incoming damage."] = "유닛이 입는 데미지를 줄이는 모든 생존류 기술에 이 색상을 적용합니다."
+L["Color aurabar debuffs by type."] = "디버프 종류에 따라서 클래스타이머의 색상을 따로 입힙니다.|n|n예로 독계열 디버프는 초록색 바로 표시되게 됩니다."
+L["Color castbars by the class of player units."] = true;
+L["Color castbars by the reaction type of non-player units."] = true;
+L["Color health by amount remaining."] = "기존에 설정된 색상에서 생명력이 줄어들 때 마다 점차 빨간색으로 변화합니다."
+L["Color health by classcolor or reaction."] = "생명력 색상을 직업색으로 변경합니다."
+L["Color power by classcolor or reaction."] = "자원 색상을 직업색으로 변경합니다."
+L["Color the health backdrop by class or reaction."] = "직업이나 관계에 따라 생명력 배경의 색상을 변경합니다."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "플레이어가 해제할 수 있는 디버프를 가졌다면 생명력바에 색상을 입혀 강조합니다."
+L["Color Turtle Buffs"] = "생존기류 따로 색상지정"
+L["Color"] = "색상"
+L["Colored Icon"] = "색상자 아이콘"
+L["Coloring (Specific)"] = "색상 설정 (지정)"
+L["Coloring"] = "색상 설정 (공통)"
+L["Combat Fade"] = "평상시 숨기기"
+L["Combat Icon"] = true;
+L["Combo Point"] = true;
+L["Combobar"] = true;
+L["Configure Auras"] = "오라 설정"
+L["Copy From"] = "복사해오기"
+L["Count Font Size"] = "중첩수 글꼴 크기"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "유닛프레임에 새로운 문자 영역을 추가합니다. 빈칸에 새 문자영역 제목을 입력하고 Enter 키를 누르면 우측하단의 목록에서 선택할 수 있게 됩니다."
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "각 유닛의 버프/디버프에 필터를 생성합니다."
+L["Create Custom Text"] = true
+L["Create Filter"] = "필터 생성"
+L["Current - Max | Percent"] = "현재값 - 최대값 | %"
+L["Current - Max"] = "현재값 - 최대값"
+L["Current - Percent"] = "현재값 - %"
+L["Current / Max"] = "현재값 / 최대값"
+L["Current"] = "현재값"
+L["Custom Dead Backdrop"] = true;
+L["Custom Health Backdrop"] = "고정 배경색 사용"
+L["Custom Texts"] = "사용자지정 문자"
+L["Death"] = "죽음"
+L["Debuff Highlighting"] = "해제가능한 디버프 강조"
+L["Debuffs"] = "디버프"
+L["Decimal Threshold"] = "소수점표시 기준"
+L["Deficit"] = "부족"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "생성된 필터를 제거합니다. 단, 추가로 생성한 필터만 제거가 가능합니다."
+L["Delete Filter"] = "필터 삭제"
+L["Detach From Frame"] = "유닛프레임에서 분리"
+L["Detached Width"] = "분리했을 때 가로길이"
+L["Direction the health bar moves when gaining/losing health."] = "생명력의 증감 방향을 결정합니다. (가로/세로)"
+L["Disable Debuff Highlight"] = true;
+L["Disabled Blizzard Frames"] = true;
+L["Disabled"] = "미사용"
+L["Disables the focus and target of focus unitframes."] = true;
+L["Disables the player and pet unitframes."] = true;
+L["Disables the target and target of target unitframes."] = true;
+L["Disconnected"] = "오프라인"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "시전바와 배경의 구분을 위해 시전바의 끝부분에 반짝임 텍스쳐를 표시합니다."
+L["Display Frames"] = "프레임 표시"
+L["Display Player"] = "플레이어 표시"
+L["Display Target"] = "시전 목표 표시"
+L["Display Text"] = "남은시간 표시"
+L["Display the castbar icon inside the castbar."] = true;
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = true;
+L["Display the combat icon on the unitframe."] = true;
+L["Display the rested icon on the unitframe."] = "휴식 아이콘을 표시할지 여부를 결정합니다."
+L["Display the target of your current cast. Useful for mouseover casts."] = "현재 캐스팅중인 기술의 목표를 기술명에 표기합니다. 마우스오버로 기술을 시전할 때 대상을 파악하기 좋습니다."
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "시전바에 시전되는 주문의 틱을 표시합니다. 영혼 흡수나 가속이 추가되는 주문에 따라 틱이 자동 조절됩니다."
+L["Don't display any auras found on the 'Blacklist' filter."] = "차단 목록에 등록되어 있는 효과들을 표시하지 않게 합니다."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = "이 값보다 긴 시간(초단위)의 효과들을 표시하지 않습니다.|n|n0으로 설정하면 이 기능을 사용하지 않습니다."
+L["Don't display auras that are not yours."] = "플레이어가 직접 건 것이 아닌 효과들을 표시하지 않게 합니다."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that cannot be purged or dispelled by your class."] = "플레이어가 직접 끄거나 해제할 수 없는 종류의 효과들을 표시하지 않게 합니다."
+L["Don't display auras that have no duration."] = "지속시간이 무한인 효과들을 표시하지 않게 합니다.|n|n즉, 유효시간이 있는 효과들만 보이게 됩니다."
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "아래로"
+L["Dungeon & Raid Filter"] = true;
+L["Duration Reverse"] = "총 지속시간이 짧은 순"
+L["Duration Text"] = true;
+L["Duration"] = "총 지속시간이 긴 순"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = "파티가 가득 차 있지 않아도 다음 파티의 유저를 끌어와 빈칸 없이 나열합니다. 파티구별하기가 힘들다는 단점이 있습니다."
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = "유닛프레임의 배치를 역순으로 정렬합니다."
+L["Enemy Aura Type"] = "적군일 때 표시 계열"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "평상시에 유닛프레임을 표시하지 않습니다.|n|n전투에 돌입하거나 캐스팅을 시작하거나 대상이 존재하거나 마우스를 갖다 댈 때에만 프레임이 드러납니다."
+L["Fill"] = "채우기"
+L["Filled"] = "하단에 깔기"
+L["Filter Type"] = "필터 종류"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "적용하지 않음"
+L["Force On"] = "강제 적용"
+L["Force Reaction Color"] = "반응색 강제설정"
+L["Force the frames to show, they will act as if they are the player frame."] = "해당 프레임의 유닛이 지금 있는 것처럼 강제로 표시하게 합니다."
+L["Forces Debuff Highlight to be disabled for these frames"] = true;
+L["Forces reaction color instead of class color on units controlled by players."] = "유저에 의해 조종되는 유닛의 색을 직업색이 아닌 반응색으로 강제지정합니다."
+L["Format"] = "형식"
+L["Frame Level"] = true;
+L["Frame Orientation"] = true;
+L["Frame Strata"] = true;
+L["Frame"] = "유닛프레임"
+L["Frequent Updates"] = "자주 업데이트"
+L["Friendly Aura Type"] = "아군일 때 표시 계열"
+L["Friendly"] = "아군"
+L["Frost"] = "냉기"
+L["Glow"] = "후광"
+L["Good"] = "좋음"
+L["GPS Arrow"] = "GPS 방향표시기"
+L["Group By"] = "그룹짓는 방법"
+L["Grouping & Sorting"] = "그룹/정렬 방법"
+L["Groups Per Row/Column"] = "한 줄 당 그룹 배치수"
+L["Growth direction from the first unitframe."] = "이 그룹에 속한 유닛들이 1번을 기준으로 어느 방향을 향해 나열될지 결정합니다."
+L["Growth Direction"] = "나열 방향"
+L["Heal Prediction"] = "예상 치유량"
+L["Health Backdrop"] = "생명력 배경"
+L["Health Border"] = "체력바 테두리만"
+L["Health By Value"] = "생명력에 비례한 색상"
+L["Health"] = "생명력"
+L["Height"] = "세로 길이"
+L["Horizontal Spacing"] = "수평 간격"
+L["Horizontal"] = "가로"
+L["Icon Inside Castbar"] = true;
+L["Icon Size"] = true;
+L["Icon"] = "아이콘 표시"
+L["Icon: BOTTOM"] = "아이콘 - 하단중앙"
+L["Icon: BOTTOMLEFT"] = "아이콘 - 좌측하단"
+L["Icon: BOTTOMRIGHT"] = "아이콘 - 우측하단"
+L["Icon: LEFT"] = "아이콘 - 좌측"
+L["Icon: RIGHT"] = "아이콘 - 우측"
+L["Icon: TOP"] = "아이콘 - 상단중앙"
+L["Icon: TOPLEFT"] = "아이콘 - 좌측상단"
+L["Icon: TOPRIGHT"] = "아이콘 - 우측상단"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "아무 필터설정을 하지 않았으면 오로지 요구목록에 등록한 효과들만 보여줍니다.|n|n다른 필터설정을 했다면 그 결과에 요구목록에 등록한 효과들을 추가로 보여줍니다."
+L["If not set to 0 then override the size of the aura icon to this."] = "아이콘의 가로세로 길이를 결정합니다.|n|n이 값이 0이면 아이콘이 유닛프레임의 가로길이에 한 줄에 표시할 갯수만큼 들어갈 정도의 크기가 됩니다."
+L["If the unit is an enemy to you."] = "만약 유닛이 적군이라면"
+L["If the unit is friendly to you."] = "만약 유닛이 아군이라면"
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = true;
+L["Ignore mouse events."] = "아이콘이 마우스에 전혀 반응하지 않도록 합니다. 클릭 입력도 아이콘을 통과하게 됩니다."
+L["InfoPanel Border"] = true;
+L["Information Panel"] = true;
+L["Inset"] = "내부에 분리"
+L["Inside Information Panel"] = true;
+L["Interruptable"] = "차단이 가능한 기술"
+L["Invert Grouping Order"] = "역순정렬"
+L["JustifyH"] = "글자 가로 정렬방법"
+L["Latency"] = "지연 시간 표시"
+L["Left to Right"] = true;
+L["Main statusbar texture."] = "시전바, 클래스타이머 등의 텍스쳐를 결정합니다."
+L["Main Tanks / Main Assist"] = "방어/지원 담당자"
+L["Make textures transparent."] = "색상을 반투명하게 합니다."
+L["Match Frame Width"] = "프레임 너비와 맞춤"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = "바 최대갯수"
+L["Max Overflow"] = true
+L["Maximum Duration"] = "지속시간 제한"
+L["Method to sort by."] = true;
+L["Middle Click - Set Focus"] = "휠클릭으로 주시 설정"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "마우스 휠로 이 프레임을 클릭하면 유닛을 주시 대상으로 잡습니다."
+L["Middle"] = true;
+L["Minimum Duration"] = true;
+L["Mouseover"] = "마우스오버 시 표시"
+L["Name"] = "이름"
+L["Neutral"] = "중립"
+L["Non-Interruptable"] = "차단할 수 없는 기술"
+L["None"] = "없음"
+L["Not valid spell id"] = "유효한 주문 ID가 아닙니다."
+L["Num Rows"] = "최대 표시 줄 개수"
+L["Number of Groups"] = "그룹 수"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "디자인 설정을 무시하고 자원바를 생명력바 뒤로 겹친 후, 드러남 정도를 결정합니다.|n|n0으로 설정하면 겹치지 않고 디자인 설정대로 배치합니다."
+L["Offset position for text."] = "위치 기준점에서부터 얼마나 떨어진 곳에 문자를 배치할지 결정합니다."
+L["Offset"] = "생명력바와 겹쳐 표시"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "사정거리 밖에 있을 때에만 이 기능을 보이게 합니다."
+L["Only show when you are mousing over a frame."] = "마우스를 갖다 댔을(마우스오버) 때에만 이 기능을 보이게 합니다."
+L["OOR Alpha"] = "사거리 밖 투명도"
+L["Other Filter"] = true;
+L["Others"] = "다른 유저"
+L["Overlay the healthbar"] = "생명력바에 덮어 씌워 표시합니다."
+L["Overlay"] = "덮어씌우기"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "현재 입던해있는 던전의 상태에 맞춰 표시할 파티수를 자동으로 제한합니다.|n|n예로 10인 인스안에 있으면 1,2파티만 표시됩니다."
+L["Override the default class color setting."] = "이 유닛프레임의 체력바에만 직업색을 적용하도록 따로 설정하는 것이 가능합니다."
+L["Owners Name"] = "주인 이름"
+L["Parent"] = true;
+L["Party Pets"] = "파티원 소환수"
+L["Party Targets"] = "파티원의 대상"
+L["Per Row"] = "한 줄에 표시할 아이콘 수"
+L["Percent"] = "%"
+L["Personal"] = "플레이어"
+L["Pet Name"] = "펫 이름"
+L["Player Frame Aura Bars"] = true;
+L["Portrait"] = "초상화"
+L["Position Buffs on Debuffs"] = true;
+L["Position Debuffs on Buffs"] = true;
+L["Position"] = "위치"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "유닛이 NPC라면 자원 글자를 숨기고 그 위치에 이름을 표시합니다."
+L["Power"] = "자원"
+L["Powers"] = "자원 (마나, 분노, 기력...)"
+L["Priority"] = "우선도"
+L["Profile Specific"] = true;
+L["PvP Icon"] = true;
+L["PvP Text"] = true;
+L["PVP Trinket"] = "PvP 장신구"
+L["Raid Icon"] = "레이드 아이콘"
+L["Raid-Wide Sorting"] = "빈칸없이 나열"
+L["Raid40 Frames"] = "레이드프레임 (40인)"
+L["RaidDebuff Indicator"] = "공격대 주요 디버프 표시기"
+L["Range Check"] = "거리에 따른 투명도 적용"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "생명력 수치 업데이트를 평소보다 더 빠르게 하지만 메모리와 CPU점유율이 더 증가하는 기능입니다. 힐러일 경우에만 추천합니다."
+L["Reaction Castbars"] = true;
+L["Reactions"] = "관계"
+L["Ready Check Icon"] = true;
+L["Remaining"] = "남은 시간"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = true;
+L["Remove a spell from the filter."] = "필터에서 주문을 제거합니다."
+L["Remove Spell ID or Name"] = true;
+L["Remove SpellID"] = "주문 ID 삭제"
+L["Rest Icon"] = "휴식 아이콘"
+L["Restore Defaults"] = "기본값 복원"
+L["Right to Left"] = true;
+L["RL / ML Icons"] = "공대장/전리품담당자 아이콘"
+L["Role Icon"] = "역할 아이콘"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = true;
+L["Select a unit to copy settings from."] = "이 옵션에서 선택하는 유닛프레임의 설정을 복사하여 프레임에 적용합니다."
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "위의 필터 설정에 추가적으로 이 옵션에서 선택한 필터를 적용합니다."
+L["Select Filter"] = "필터 선택"
+L["Select Spell"] = "주문 선택"
+L["Select the display method of the portrait."] = "초상화 표시 방법을 결정합니다."
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = true;
+L["Set the font size for unitframes."] = "유닛프레임 내에서 쓰이는 모든 글자의 크기를 결정합니다."
+L["Set the order that the group will sort."] = "이 유닛프레임에서 그룹을 어떤 기준으로 묶을지를 결정합니다.|n|n|cffceff00해석불완전|r : 기능을 제가 아직 확인해보지 못했습니다."
+L["Set the orientation of the UnitFrame."] = true;
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "효과의 우선도를 결정합니다. 값이 높을 수록 우선적으로 표시하는데 이 기능은 오로지 Raid Debuff 필터에서만 동작합니다.|n|n0으로 설정하면 이 기능을 사용하지 않습니다."
+L["Set the type of auras to show when a unit is a foe."] = "해당 유닛이 적대적일 때 표시할 오라 형태를 결정합니다."
+L["Set the type of auras to show when a unit is friendly."] = "해당 유닛이 우호적일 때 표시할 오라 형태를 결정합니다."
+L["Sets the font instance's horizontal text alignment style."] = "문자의 가로 정렬 방법을 결정합니다."
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "생명력바에 예상 치유량을 표시합니다."
+L["Show Aura From Other Players"] = "다른 유저가 걸어준 버프도 표시"
+L["Show Auras"] = "오라아이콘 표시"
+L["Show Dispellable Debuffs"] = true;
+L["Show When Not Active"] = "효과가 없을 때 표시"
+L["Size and Positions"] = "크기와 위치 관련"
+L["Size of the indicator icon."] = "표시기 아이콘 크기"
+L["Size Override"] = "아이콘 크기"
+L["Size"] = "크기"
+L["Smart Aura Position"] = true;
+L["Smart Raid Filter"] = "스마트 레이드 필터"
+L["Smooth Bars"] = "부드러운 증감"
+L["Sort By"] = true;
+L["Spaced"] = "외부에 작게 분리"
+L["Spacing"] = true;
+L["Spark"] = "반짝임"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = true;
+L["Stack Threshold"] = "중첩 기준점"
+L["Start Near Center"] = "가운데 정렬"
+L["Statusbar Fill Orientation"] = true;
+L["StatusBar Texture"] = "바 텍스쳐"
+L["Strata and Level"] = true;
+L["Style"] = "디자인"
+L["Tank Frames"] = "방어전담 프레임"
+L["Tank Target"] = "방어전담 프레임"
+L["Tapped"] = "선점되었을 때의 색상"
+L["Target Glow"] = true;
+L["Target On Mouse-Down"] = "마우스를 누를 때 작동"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "마우스를 뗄 때 대상으로 잡는 게 아니라 마우스를 누를 때에 대상으로 잡습니다.|n|n|cff2eb7e4Clique|r 애드온을 쓰고 있다면 이 설정을 바꾼 후에 Clique 설정도 다시 해야 합니다."
+L["Text Color"] = "글자 색"
+L["Text Format"] = "글자 형식"
+L["Text Position"] = "위치 기준"
+L["Text Threshold"] = "글자 표시 임계점"
+L["Text Toggle On NPC"] = "NPC면 자원에 이름표시"
+L["Text xOffset"] = "글자 x 좌표"
+L["Text yOffset"] = "글자 y 좌표"
+L["Text"] = "글자 표시"
+L["Textured Icon"] = "스킬이미지 아이콘"
+L["The alpha to set units that are out of range to."] = "유닛이 사거리 밖에 있다면 프레임에 이 투명도를 적용합니다."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = "여기서 설정한 값만큼 중첩되어야 디버프가 표시됩니다. 0으로 설정하면 항상 보이게 됩니다."
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "체크시 그룹의 표시 설정이 설정됩니다. 필터를 추가해서 수정이 가능합니다."
+L["The font that the unitframes will use."] = "유닛프레임의 글꼴입니다."
+L["The initial group will start near the center and grow out."] = "위치의 가운데에서부터 유닛프레임을 배치하기 시작합니다."
+L["The name you have selected is already in use by another element."] = "입력한 제목의 문자영역이 이미 있습니다. 다른 제목을 입력하세요."
+L["The object you want to attach to."] = "이 요소가 어느 프레임을 기준으로 배치될지를 결정합니다."
+L["Thin Borders"] = true;
+L["This dictates the size of the icon when it is not attached to the castbar."] = true;
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = true;
+L["Threat Display Mode"] = "어그로획득 표시방법"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = "소숫점으로 표시하게 될 기준점을 결정합니다. -1로 지정 시 작동하지 않습니다."
+L["Ticks"] = "주문 틱 표시"
+L["Time Remaining Reverse"] = "남은시간이 짧은 순으로"
+L["Time Remaining"] = "남은시간이 긴 순으로"
+L["Transparent"] = "반투명화"
+L["Turtle Color"] = "생존기 색상"
+L["Unholy"] = "부정"
+L["Uniform Threshold"] = true;
+L["UnitFrames"] = "유닛프레임"
+L["Up"] = "위로"
+L["Use Custom Level"] = true;
+L["Use Custom Strata"] = true;
+L["Use Dead Backdrop"] = true;
+L["Use Default"] = "기존 설정대로"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "생명력 바의 배경을 다른 설정을 무시하고 아래에서 지정한 색상만 사용합니다."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = true;
+L["Use thin borders on certain unitframe elements."] = true;
+L["Use this backdrop color for units that are dead or ghosts."] = true;
+L["Value must be a number"] = "값으로 숫자만 입력할 수 있습니다."
+L["Vertical Orientation"] = true;
+L["Vertical Spacing"] = "수직 간격"
+L["Vertical"] = "세로"
+L["Visibility"] = "표시"
+L["What point to anchor to the frame you set to attach to."] = "첫 번째 버튼을 기준으로 나머지 아이콘들이 나열됩니다."
+L["What to attach the buff anchor frame to."] = "첫 번째 버튼 위치가 어느 프레임을 기준으로 할지를 결정합니다."
+L["What to attach the debuff anchor frame to."] = "첫 디버프 위치가 어느 프레임을 기준으로 할지를 결정합니다."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "활성화시, 공격대에 속해있지 않아도 플레이어를 표시합니다."
+L["Whitelist"] = "요구 목록"
+L["Width"] = "가로 길이"
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = true;
+L["xOffset"] = "X 좌표"
+L["yOffset"] = "Y 좌표"
+L["You can't remove a pre-existing filter."] = "기존 필터를 제거할 수 없습니다."
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "기본 필터에 설정된 기본 주문들은 삭제할 수 없습니다. 대신 비활성화는 가능합니다."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = true;
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Load_Locales.xml b/ElvUI_Config/Locales/Load_Locales.xml
new file mode 100644
index 0000000..491cae9
--- /dev/null
+++ b/ElvUI_Config/Locales/Load_Locales.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Portuguese_Config.lua b/ElvUI_Config/Locales/Portuguese_Config.lua
new file mode 100644
index 0000000..35b8feb
--- /dev/null
+++ b/ElvUI_Config/Locales/Portuguese_Config.lua
@@ -0,0 +1,1130 @@
+-- Portuguese localization file for ptBR.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "ptBR")
+if not L then return end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "Configurar os ícones das auras que aparecem perto do minimapa."
+L["BAGS_DESC"] = "Ajustar definições das bolsas para a ElvUI."
+L["CHAT_DESC"] = "Adjustar definições do bate-papo para o ElvUI."
+L["DATATEXT_DESC"] = "Configurar a exibição no ecrã (monitor) dos textos de informação."
+L["ELVUI_DESC"] = "A ElvUI é um Addon completo de substituição da interface original do World of Warcraft."
+L["NAMEPLATE_DESC"] = "Modificar as definições das Placas de Identificação."
+L["PANEL_DESC"] = "Ajustar o tamanho dos painéis da esquerda e direita, isto irá afetar suas bolsas e bate-papo."
+L["SKINS_DESC"] = "Ajustar definições de Aparências."
+L["TOGGLESKIN_DESC"] = "Ativa/Desativa a aparência deste quadro."
+L["TOOLTIP_DESC"] = "Opções de configuração para a Tooltip."
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[With the new addition of LibItemSearch, you now have access to much more advanced item searches. The following is a documentation of the search syntax. See the full explanation at: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Specific Searching:
+ • q:[quality] or quality:[quality]. For instance, q:epic will find all epic items.
+ • l:[level], lvl:[level] or level:[level]. For example, l:30 will find all items with level 30.
+ • t:[search], type:[search] or slot:[search]. For instance, t:weapon will find all weapons.
+ • n:[name] or name:[name]. For instance, typing n:muffins will find all items with names containing "muffins".
+ • s:[set] or set:[set]. For example, s:fire will find all items in equipment sets you have with names that start with fire.
+ • tt:[search], tip:[search] or tooltip:[search]. For instance, tt:binds will find all items that can be bound to account, on equip, or on pickup.
+
+
+Search Operators:
+ • ! : Negates a search. For example, !q:epic will find all items that are NOT epic.
+ • | : Joins two searches. Typing q:epic | t:weapon will find all items that are either epic OR weapons.
+ • & : Intersects two searches. For instance, q:epic & t:weapon will find all items that are epic AND weapons
+ • >, <, <=, => : Performs comparisons on numerical searches. For example, typing lvl: >30 will find all items with level HIGHER than 30.
+
+
+The following search keywords can also be used:
+ • soulbound, bound, bop : Bind on pickup items.
+ • bou : Bind on use items.
+ • boe : Bind on equip items.
+ • boa : Bind on account items.
+ • quest : Quest bound items.]];
+L["TEXT_FORMAT_DESC"] = [[Fornece uma sting para mudar o formato do texto.
+
+Examples:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+Formatos de Vida / Poder:
+"current" - Quantidade Actual
+"percent" - Quantidade de Percentagem
+"current-max" - Quantidade actual seguida pela quantidade máxima, será exibida apenas a máxima se a actual for igual à máxima
+"current-percent" - Quantidade actual seguida pela quantidade em percentagem, será exibida apenas a máxima se a actual for igual à máxima
+"current-max-percent" - Quantidade actual, quantidade máxima seguida por quantidade em percentagem, será exibida apenas a máxima se a actual for igual à máxima
+"deficit" - Exibir o valor em falta, nao será exibido nada se não houver nada em falta
+
+Formato de Nomes:
+"name:short" - Nome restringido a 10 caracteres
+"name:medium" - Nome restringido a 15 caracteres
+"name:long" - Nome restringido a 20 caracteres
+
+Para desactivar deixe o espaço em branco, se precisar de mais informações visite o site http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "Paginação da Barra de Ação"
+L["ActionBars"] = "Barras de Ações"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = true;
+L["Alpha"] = "Transparência"
+L["Anchor Point"] = "Ponto de Fixação"
+L["Backdrop Spacing"] = true;
+L["Backdrop"] = "Fundo"
+L["Button Size"] = "Tamanho do botão"
+L["Button Spacing"] = "Espaçamento do botão"
+L["Buttons Per Row"] = "Botões por linha"
+L["Buttons"] = "Botões"
+L["Change the alpha level of the frame."] = "Mudar o nível de transparência do quadro."
+L["Color of the actionbutton when not usable."] = true;
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "Cor do botão de ação quando sem poder (Mana, Raiva)."
+L["Color of the actionbutton when out of range."] = "Cor do botão de ação quando fora de alcance."
+L["Color of the actionbutton when usable."] = true;
+L["Color when the text is about to expire"] = "Cor do texto quando está quase a expirar."
+L["Color when the text is in the days format."] = "Cor do texto quando está em formato de dias."
+L["Color when the text is in the hours format."] = "Cor do texto quando está em formato de horas."
+L["Color when the text is in the minutes format."] = "Cor do texto quando está em formato de minutos."
+L["Color when the text is in the seconds format."] = "Cor do texto quando está em formato de segundos."
+L["Cooldown Text"] = "Texto do Tempo de Recarga"
+L["Darken Inactive"] = "Escurecer Inativos"
+L["Days"] = "Dias"
+L["Display bind names on action buttons."] = "Exibir atalhos nos botões de ação."
+L["Display cooldown text on anything with the cooldown spiral."] = "Exibir texto do tempo de recarga para tudo que tenha espiral de recarga."
+L["Display macro names on action buttons."] = "Exibir nomes das macros nos botões de ação."
+L["Expiring"] = "Expirando"
+L["Global Fade Transparency"] = true;
+L["Height Multiplier"] = "Multiplicador de Altura"
+L["Hours"] = "Horas"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = true;
+L["Inherit Global Fade"] = true;
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = true;
+L["Key Down"] = "Tecla pressionada"
+L["Keybind Mode"] = "Modo de Teclas de Atalho"
+L["Keybind Text"] = "Texto das Teclas de Atalho"
+L["LBF Support"] = true;
+L["Low Threshold"] = "Baixo Limiar"
+L["Macro Text"] = "Texto das Macros"
+L["Minutes"] = "Minutos"
+L["Mouse Over"] = "Com o Rato (Mouse) por cima"
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "Multiplicar a altura ou comprimento do fundo por este valor. Muito útil se desejar ter mais que uma barra por trás de um fundo."
+L["Not Usable"] = true;
+L["Out of Power"] = "Sem Poder"
+L["Out of Range"] = "Fora de Alcance"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "Restaurar Barra"
+L["Restore the actionbars default settings"] = "Restaurar as configurações padrões das barras de ações"
+L["Seconds"] = "Segundos"
+L["Show Empty Buttons"] = true;
+L["The amount of buttons to display per row."] = "Quantidade de botões a serem exibidos por linha."
+L["The amount of buttons to display."] = "Quantidade de botões a serem exibidos"
+L["The button you must hold down in order to drag an ability to another action button."] = "Botão que deve ser pressionado para permitir o arrastar uma habilidade para outro botão de acção"
+L["The first button anchors itself to this point on the bar."] = "O primeiro botão fixa-se a este ponto da barra"
+L["The size of the action buttons."] = "Tamanho dos botões de ação."
+L["The spacing between the backdrop and the buttons."] = true;
+L["This setting will be updated upon changing stances."] = "Essa configuração atualizará ao trocar posturas."
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "Limiar antes do texto se tornar vermelho e em forma décimal. Definir -1 para nunca se tornar vermelho"
+L["Toggles the display of the actionbars backdrop."] = "Mostra/Oculta o fundo das barras de acção"
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = true;
+L["Usable"] = true;
+L["Visibility State"] = "Estado de Visibilidade"
+L["Width Multiplier"] = "Multiplicador de Comprimento"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+Example: [combat] 2;]] ] = [[Isto funciona como uma macro, você pode executar várias situações para que a barra de ação pagine de forma diferente.
+Exemplo: [combat] 2;]];
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+Example: [combat] show;hide]] ] = [[Isto funciona como uma macro, você pode executar várias situações para mostrar/ocultar a barra de ação de forma diferente.
+Exemplo: [combat] show;hide]];
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = true;
+L["Add Item or Search Syntax"] = true;
+L["Adjust the width of the bag frame."] = "Ajusta a largura do quadro das bolsas."
+L["Adjust the width of the bank frame."] = "Ajusta a largura do quadro do banco."
+L["Ascending"] = "Ascendente"
+L["Bag Sorting"] = true;
+L["Bag-Bar"] = "Barra das Bolsas"
+L["Bar Direction"] = "Direção da Barra"
+L["Blizzard Style"] = true;
+L["Bottom to Top"] = "De baixo para cima"
+L["Button Size (Bag)"] = "Tamanho do Botão (Bolsas)"
+L["Button Size (Bank)"] = "Tamanho do Botão (Banco)"
+L["Clear Search On Close"] = true;
+L["Condensed"] = true;
+L["Descending"] = "Descendente"
+L["Direction the bag sorting will use to allocate the items."] = "Direção que o organizador de bolsas irá usar para distribuir os itens."
+L["Disable Bag Sort"] = true;
+L["Disable Bank Sort"] = true;
+L["Display Item Level"] = true;
+L["Displays item level on equippable items."] = true;
+L["Enable/Disable the all-in-one bag."] = "Ativar/Desativar a Bolsa tudo-em-um."
+L["Enable/Disable the Bag-Bar."] = "Ativar/Desativar a Barra das Bolsas."
+L["Full"] = true;
+L["Global"] = true;
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = true;
+L["Ignored Items and Search Syntax (Global)"] = true;
+L["Ignored Items and Search Syntax (Profile)"] = true;
+L["Item Count Font"] = true;
+L["Item Level Threshold"] = true;
+L["Item Level"] = true;
+L["Money Format"] = true;
+L["Panel Width (Bags)"] = "Largura do Painel (Bolsas)"
+L["Panel Width (Bank)"] = "Largura do Painel (Banco)"
+L["Search Syntax"] = true;
+L["Set the size of your bag buttons."] = "Define o tamanho dos botões das Bolsas"
+L["Short (Whole Numbers)"] = true;
+L["Short"] = true;
+L["Smart"] = true;
+L["Sort Direction"] = "Direção de organização"
+L["Sort Inverted"] = "Oganizar Invertido"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "Direcção em que os quadros das bolsas são (Horizontal ou Vertical)."
+L["The direction that the bag frames will grow from the anchor."] = "Direcção para qual as barras crescerão a partir do seu Fixador."
+L["The display format of the money text that is shown at the top of the main bag."] = true;
+L["The frame is not shown unless you mouse over the frame."] = "A não ser que passe com o rato (mouse) por cima do quadro, este não será mostrado."
+L["The minimum item level required for it to be shown."] = true;
+L["The size of the individual buttons on the bag frame."] = "O tamanho individual de botões dentro do quadro das bolsas."
+L["The size of the individual buttons on the bank frame."] = "O tamanho individual de botões dentro do quadro do banco."
+L["The spacing between buttons."] = "Espaçamento entre botões."
+L["Top to Bottom"] = "De cima para baixo"
+L["Use coin icons instead of colored text."] = true;
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "Buffs e Debuffs";
+L["Begin a new row or column after this many auras."] = "Começar uma nova coluna ou linha depois dessa quantia de auras."
+L["Count xOffset"] = true;
+L["Count yOffset"] = true;
+L["Defines how the group is sorted."] = "Define como o grupo é organizado"
+L["Defines the sort order of the selected sort method."] = "Define a ordem de organização do método escolhido"
+L["Disabled Blizzard"] = true;
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "Limiar para Desvanecer"
+L["Index"] = "Índice"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "Indica se os buffs que lança em si próprio devem ser separados antes ou depois."
+L["Limit the number of rows or columns."] = "Limitar o número de linhas ou colunas."
+L["Max Wraps"] = "Enrolamentos Máximos"
+L["No Sorting"] = "Não organizado"
+L["Other's First"] = "De outros primeiro"
+L["Remaining Time"] = "Tempo restante"
+L["Reminder"] = true
+L["Reverse Style"] = true;
+L["Seperate"] = "Separar"
+L["Set the size of the individual auras."] = "Definir o tamanho das auras individuais."
+L["Sort Method"] = "Método de organização"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = true;
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "Limiar antes do texto se tornar vermelho, mudar para forma décimal e o ícone desvanecer. Definir -1 para desativar."
+L["Time xOffset"] = true;
+L["Time yOffset"] = true;
+L["Time"] = "Tempo"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = true;
+L["Wrap After"] = "Enrolar depois"
+L["Your Auras First"] = "Suas auras primeiro"
+
+--Chat
+L["Above Chat"] = "Acima do Bate-papo"
+L["Adjust the height of your right chat panel."] = true;
+L["Adjust the width of your right chat panel."] = true;
+L["Alerts"] = true;
+L["Allowed Combat Repeat"] = true;
+L["Attempt to create URL links inside the chat."] = "Tentar criar links URL dentro do bate-papo."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "Tentar bloquear a posição dos painéis do bate-papo esquerdo e direito. Desativar esta opção permitirá mover os painéis de bate-papo para qualquer lugar que desejar."
+L["Below Chat"] = "Abaixo do Bate-papo"
+L["Chat EditBox Position"] = "Posição da caixa de edição do bate-papo"
+L["Chat History"] = "Histórico do bate-papo"
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = true;
+L["Custom Timestamp Color"] = true;
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "Exibir a tooltip de um hyperlink quando pairar por cima deste."
+L["Enable the use of separate size options for the right chat panel."] = true;
+L["Exclude Name"] = true;
+L["Excluded names will not be class colored."] = true;
+L["Excluded Names"] = true;
+L["Fade Chat"] = "Desvanecer o bate-papo"
+L["Fade Tabs No Backdrop"] = true;
+L["Fade the chat text when there is no activity."] = "Desvanece o texto do bate-papo quando não há atividade."
+L["Fade Undocked Tabs"] = true;
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = true;
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = true;
+L["Font Outline"] = "Contorno da Fonte"
+L["Font"] = "Fonte"
+L["Hide Both"] = "Esconder Ambos"
+L["Hyperlink Hover"] = "Pairar no hyperlink"
+L["Keyword Alert"] = "Alerta de palavra-chave"
+L["Keywords"] = "Palavras-chave"
+L["Left Only"] = "Somente Esquerda"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "Lista de palavras a colorir se encontrada numa mensagem. Se desejar adicionar multiplas palavras deverá separa-las com uma vírgula. Para procurar pelo seu nome actual pode usar %MYNAME%.\n\nExemplo:\n%MYNAME%, ElvUI, RBGs, Tank"
+L["Lock Positions"] = "Travar Posições"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "Armazenar o histórico dos quadros principais do bate-papo. Para que possa ver o histórico de sua última sessão ao relogar ou conectar e desconectar."
+L["No Alert In Combat"] = true;
+L["Number of messages you scroll for each step."] = true;
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = true;
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "Tempo, em segundos, para rolar o bate-papo até ao fim caso nao tenha rolado completamente."
+L["Panel Backdrop"] = "Fundo do Painel"
+L["Panel Height"] = "Altura do Painel"
+L["Panel Texture (Left)"] = "Textura do Painel (Esquerdo)"
+L["Panel Texture (Right)"] = "Textura do Painel (Direito)"
+L["Panel Width"] = "Comprimento do Painel"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "A posição da caixa de edição do bate-papo, será forçada para cima do bate-papo se os textos informativos estiverem desativados."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "Prevenir que as mesmas mensagens sejam exibidas no bate-papo mais que uma vez dentro desta quantidade de segundos, definir 0 para desativar."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = true;
+L["Right Only"] = "Somente Direita"
+L["Right Panel Height"] = true;
+L["Right Panel Width"] = true;
+L["Scroll Interval"] = "Intervalo de Rolar"
+L["Scroll Messages"] = true;
+L["Separate Panel Sizes"] = true;
+L["Set the font outline."] = "Definir o contorno de fonte."
+L["Short Channels"] = "Abreviar os Canáis"
+L["Shorten the channel names in chat."] = "Abreviar o nome dos canáis no bate-papo."
+L["Show Both"] = "Mostrar Ambos"
+L["Spam Interval"] = "Intervalo de Spam"
+L["Sticky Chat"] = "Lembrar Canal"
+L["Tab Font Outline"] = "Contorno da fonte da Guia"
+L["Tab Font Size"] = "Tamanho da fonte da Guia"
+L["Tab Font"] = "Fonte da Guia"
+L["Tab Panel Transparency"] = "Transparência do painel da Guia"
+L["Tab Panel"] = "Painel da Guia"
+L["Timestamp Color"] = true;
+L["Toggle showing of the left and right chat panels."] = "Mostrar/Ocultar os painéis de conversação da esquerda e direita."
+L["Toggle the chat tab panel backdrop."] = "Mostrar/ocultar o fundo da guia do bate-papo."
+L["URL Links"] = "Links URL"
+L["Use Alt Key"] = true;
+L["Use class color for the names of players when they are mentioned."] = true;
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "Ter esta opção ativada significa que sempre que escrever algo será usado o último canal no qual escreveu. Se a opção estiver desativada escreverá sempre no canal padrão DIZER"
+L["Whisper Alert"] = "Alerta de Sussurro"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[Especificar o nome de um ficheiro (arquivo) localizado na diretório do WoW. Ficheiros de textura que deseje ter como fundo dos painéis.
+
+Atenção:
+-O tamanho de imagem recomendado é 256x128
+-Deve reiniciar o jogo completamente depois de adicionar um ficheiro à pasta.
+-O ficheiro tem de ser em formato tga.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Para a maioria dos usuários seria mais fácil simplesmente copiar o ficheiro tga na pasta do WoW e depois escrever o nome dele aqui.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "Codificação:"
+L["Credits"] = "Créditos"
+L["Donations:"] = "Doações:"
+L["ELVUI_CREDITS"] = "Gostaria de agradecer especialmente às seguintes pessoas por me ajudarem a manter este addon, quer testando, codificando, ou através de doações. Em relação às doações, esta lista contém apenas o nome das pessoas que me contataram através de mensagem privada nos forums, se o seu nome está em falta e gostaria de o ver adicionado, por favor contate-me por mensagem privada."
+L["Testing:"] = "Testar:"
+
+--DataBars
+L["Current - Percent (Remaining)"] = true;
+L["Current - Remaining"] = true;
+L["DataBars"] = true;
+L["Hide In Combat"] = true;
+L["Setup on-screen display of information bars."] = true;
+
+--DataTexts
+L["Battleground Texts"] = "Textos do Campo de Batalha"
+L["Block Combat Click"] = true;
+L["Block Combat Hover"] = true;
+L["Blocks all click events while in combat."] = true;
+L["Blocks datatext tooltip from showing in combat."] = true;
+L["BottomLeftMiniPanel"] = "Minimap BottomLeft (Inside)"
+L["BottomMiniPanel"] = "Minimap Bottom (Inside)"
+L["BottomRightMiniPanel"] = "Minimap BottomRight (Inside)"
+L["Datatext Panel (Left)"] = "Painel de Textos Informativos (Esquerdo)"
+L["Datatext Panel (Right)"] = "Painel de Textos Informativos (Direito)"
+L["DataTexts"] = "Textos Informativos"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "Mostra painéis abaixo do bate-papo, usados para textos informativos."
+L["Display minimap panels below the minimap, used for datatexts."] = "Exibir painéis abaixo do minimapa, usados para textos informativos."
+L["Gold Format"] = true;
+L["left"] = "esquerda"
+L["LeftChatDataPanel"] = "Bate-papo esquerdo."
+L["LeftMiniPanel"] = "Minimapa - esquerda"
+L["middle"] = "meio"
+L["Minimap Panels"] = "Painéis do Minimapa"
+L["Panel Transparency"] = "Transparência do Painel"
+L["Panels"] = "Painéis"
+L["right"] = "direita"
+L["RightChatDataPanel"] = "Bate-papo direito"
+L["RightMiniPanel"] = "Minimapa - direita"
+L["Small Panels"] = true;
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = true;
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap TopLeft (Inside)"
+L["TopMiniPanel"] = "Minimap Top (Inside)"
+L["TopRightMiniPanel"] = "Minimap TopRight (Inside)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "Exibir informação do placar pessoal nos textos informativos principais quando dentro de um Campo de Batalha"
+L["Word Wrap"] = true;
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "É necessário estar em grupo com o jogador se ele não é do mesmo reino que você."
+L["Sends your current profile to your target."] = "Envia seu perfil atual para seu alvo."
+L["Sends your filter settings to your target."] = "Envia as configurações de filtro para seu alvo."
+L["Share Current Profile"] = "Compartilhar Perfil Atual"
+L["Share Filters"] = "Compartilhar Filtros"
+L["This feature will allow you to transfer settings to other characters."] = "Este recurso permite enviar sus configurações a outros personagens."
+L["You must be targeting a player."] = "É necessário ter um jogador como alvo."
+
+--Filters
+L["Reset Aura Filters"] = true --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "Aceitar Convites"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "Ajustar a posição da barra de agro para os painéis de texto informativos da esquerda ou da direita."
+L["AFK Mode"] = true;
+L["Announce Interrupts"] = "Anunciar Interrupções"
+L["Announce when you interrupt a spell to the specified chat channel."] = "Anunciar quando interromper um feitiço para o canal de bate-papo especificado."
+L["Attempt to support eyefinity/nvidia surround."] = true;
+L["Auto Greed/DE"] = "Escolher Ganância/Desencantar automaticamente"
+L["Auto Repair"] = "Reparar automaticamente"
+L["Auto Scale"] = "Dimensionar automaticamente"
+L["Automatically accept invites from guild/friends."] = "Aceitar convites de pessoas da lista de amigos ou guilda automaticamente"
+L["Automatically repair using the following method when visiting a merchant."] = "Reparar automaticamente usando o seguinte método ao visitar um vendedor."
+L["Automatically scale the User Interface based on your screen resolution"] = "Dimensionar automaticamente a interface com base na sua resolução do ecrã (monitor)."
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "Selecionar automaticamente ganância ou desencantar (quando disponível) em itens de qualidade verde. Funciona apenas se estiver no nível máximo."
+L["Automatically vendor gray items when visiting a vendor."] = "Vender itens cinzentos automaticamente quando visitar um vendedor"
+L["Bottom Panel"] = "Painel Infeior"
+L["Chat Bubbles Style"] = "Estilo dos Balões de Fala"
+L["Chat Bubbles"] = true;
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = true;
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "Mostra um painel na parte inferior da tela. Apenas para efeito cosmético."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "Mostra um painel na parte superior da tela. Apenas para efeito cosmético."
+L["Display battleground messages in the middle of the screen."] = true;
+L["Enable/Disable the loot frame."] = "Ativar/Desativar painel de saques."
+L["Enable/Disable the loot roll frame."] = "Ativar/Desativar painel de disputa de saques"
+L["Enables the ElvUI Raid Control panel."] = true;
+L["Enhanced PVP Messages"] = true;
+L["General"] = "Geral"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = true;
+L["Hide At Max Level"] = true;
+L["Hide Error Text"] = "Esconder Texto de Erro"
+L["Hide In Vehicle"] = true;
+L["Hides the red error text at the top of the screen while in combat."] = "Esconde o texto de erro vermelho do topo da tela quando em combate."
+L["Log Taints"] = "Capturar Problemas"
+L["Login Message"] = "Mensagem de Entrada"
+L["Loot Roll"] = "Disputa de Saques"
+L["Loot"] = "Saque"
+L["Lowest Allowed UI Scale"] = true;
+L["Multi-Monitor Support"] = true;
+L["Name Font"] = "Fonte de Nomes"
+L["Number Prefix"] = true;
+L["Party / Raid"] = true;
+L["Party Only"] = true;
+L["Raid Only"] = true;
+L["Remove Backdrop"] = "Remover Fundo"
+L["Reset all frames to their original positions."] = "Restaurar todos os quadros para as posições originais"
+L["Reset Anchors"] = "Restaurar Fixadores"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "Mandar os erros de AÇÃO do ADDON BLOQUEADA para o quadro de erros de Lua. Estes erros são, na maioria das vezes, pouco importantes e não irão afetar o seu desempenho de jogo. Muitos destes erros nao podem ser reparados. Por favor denuncie estes erros apenas se notar problemas no desempenho do jogo."
+L["Skin Backdrop (No Borders)"] = true;
+L["Skin Backdrop"] = "Redesenhar o Fundo"
+L["Skin the blizzard chat bubbles."] = "Redesenhar os balões de conversação da Blizzard"
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "A fonte do texto que aparece sobre a cabeça dos jogadores. |cffFF0000ATENÇÃO: Para esta alteração fazer efeito é necessário que o jogo seja reiniciado ou relogado.|r"
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = true;
+L["Thin Border Theme"] = true;
+L["Toggle Tutorials"] = "Ativar Tutoriais"
+L["Top Panel"] = "Painel Superior"
+L["Version Check"] = true;
+L["Watch Frame Height"] = true;
+L["When you go AFK display the AFK screen."] = true;
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = true;
+L["Applies the primary texture to all statusbars."] = true;
+L["Apply Font To All"] = true;
+L["Apply Texture To All"] = true;
+L["Backdrop color of transparent frames"] = "Cor de fundo de Painéis transparentes"
+L["Backdrop Color"] = "Cor de fundo"
+L["Backdrop Faded Color"] = "Cor de fundo desvanecida"
+L["Border Color"] = "Cor da borda"
+L["Color some texts use."] = "Cores que alguns textos usam."
+L["Colors"] = "Cores"
+L["CombatText Font"] = "Fonte do texto de Combate"
+L["Default Font"] = "Fonte Padrão"
+L["Font Size"] = "Tamanho da Fonte"
+L["Fonts"] = "Fontes"
+L["Main backdrop color of the UI."] = "Cor básica para fundo da interface."
+L["Main border color of the UI."] = true;
+L["Media"] = "Mídia"
+L["Primary Texture"] = "Textura principal"
+L["Replace Blizzard Fonts"] = true;
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = true;
+L["Secondary Texture"] = "Textura secundária"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "Define o tamanho da fonte para toda a Interface. Nota: Isto nao afeta coisas que tenham suas prórpias opções de fonte (Quadros de Unidade, Textos Informativos, etc..)"
+L["Textures"] = "Texturas"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Fonte que o texto de combate usará. |cffFF0000AVISO: Para que as mudanças sejam efetuadas é necessário reiniciar ou relogar o jogo."
+L["The font that the core of the UI will use."] = "Fonte que o núcleo da interface usará."
+L["The texture that will be used mainly for statusbars."] = "Textura que será usada principalmente para a barras de estado."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "Esta textura será usada em objetos como janelas de bate-papo e menus de suspensão."
+L["Value Color"] = "Cor dos Valores"
+
+--Maps
+L["Adjust the size of the minimap."] = "Ajustar o tamanho do minimapa."
+L["Always Display"] = "Exibir sempre"
+L["Bottom Left"] = true;
+L["Bottom Right"] = true;
+L["Bottom"] = true;
+L["Change settings for the display of the location text that is on the minimap."] = "Alterar as configurações de exibição do texto de localização que está no minimapa."
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = true;
+L["Instance Difficulty"] = true;
+L["Left"] = "Esquerda"
+L["LFG Queue"] = true;
+L["Location Text"] = "Texto de Localização"
+L["Make the world map smaller."] = true;
+L["Maps"] = true;
+L["Minimap Buttons"] = true;
+L["Minimap Mouseover"] = "Passar com o rato(mouse) sobre o minimapa"
+L["Puts coordinates on the world map."] = true;
+L["PvP Queue"] = true
+L["Reset Zoom"] = true;
+L["Right"] = "Direita"
+L["Scale"] = true;
+L["Smaller World Map"] = true;
+L["Top Left"] = true;
+L["Top Right"] = true;
+L["Top"] = true;
+L["World Map Coordinates"] = true;
+L["X-Offset"] = true;
+L["Y-Offset"] = true;
+
+--Misc
+L["Install"] = "Instalação"
+L["Run the installation process."] = "Execute o processo de instalação."
+L["Toggle Anchors"] = "Mostrar/Ocultar Fixadores"
+L["Unlock various elements of the UI to be repositioned."] = "Destravar vários elementos da interface para serem reposicionados."
+L["Version"] = "Versão"
+
+--NamePlates
+L["# Displayed Auras"] = true;
+L["Actions"] = true
+L["Add Name"] = "Adicionar Nome"
+L["Add Nameplate Filter"] = true
+L["Add Regular Filter"] = true
+L["Add Special Filter"] = true
+L["Always Show Target Health"] = true
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = true
+L["Background Glow"] = true
+L["Bad Color"] = true;
+L["Bad Scale"] = true;
+L["Bad Transition Color"] = true;
+L["Base Height for the Aura Icon"] = true;
+L["Border Glow"] = true
+L["Border"] = true
+L["Cast Bar"] = true;
+L["Cast Color"] = true;
+L["Cast No Interrupt Color"] = true;
+L["Cast Time Format"] = true;
+L["Casting"] = true
+L["Channel Time Format"] = true;
+L["Clear Filter"] = true
+L["Color Tanked"] = true;
+L["Control enemy nameplates toggling on or off when in combat."] = true;
+L["Control friendly nameplates toggling on or off when in combat."] = true;
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = true;
+L["Cooldowns"] = true
+L["Copy settings from another unit."] = true;
+L["Copy Settings From"] = true;
+L["Current Level"] = true
+L["Default Settings"] = true;
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "Mostra um ícone de Curandeiro sobre curandeiros conhecidosem campos de batalha ou arenas."
+L["Elite Icon"] = true
+L["Enable/Disable the scaling of targetted nameplates."] = true;
+L["Enabling this will check your health amount."] = true
+L["Enemy Combat Toggle"] = true;
+L["Enemy NPC Frames"] = true;
+L["Enemy Player Frames"] = true;
+L["Enemy"] = "Inimigo" --Also used in UnitFrames
+L["ENEMY_NPC"] = "Enemy NPC"
+L["ENEMY_PLAYER"] = "Enemy Player"
+L["Filter already exists!"] = "O filtro já existe!"
+L["Filter Priority"] = true;
+L["Filters Page"] = true;
+L["Friendly Combat Toggle"] = true;
+L["Friendly NPC Frames"] = true;
+L["Friendly Player Frames"] = true;
+L["FRIENDLY_NPC"] = "PNJ Aliado"
+L["FRIENDLY_PLAYER"] = "Jogador Aliado"
+L["General Options"] = true;
+L["Good Color"] = true;
+L["Good Scale"] = true;
+L["Good Transition Color"] = true;
+L["Healer Icon"] = "Ícone de Curador"
+L["Health Color"] = true
+L["Health Threshold"] = true
+L["Hide Frame"] = true
+L["Hide Spell Name"] = true;
+L["Hide Time"] = true;
+L["Hide"] = "Esconder" --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = true
+L["Icon Base Height"] = true;
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = true
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = true
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = true
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = true
+L["If enabled then the filter will only activate when you are in combat."] = true
+L["If enabled then the filter will only activate when you are out of combat."] = true
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = true
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = true
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["Instance Type"] = true
+L["Interruptible"] = true
+L["Is Targeted"] = true
+L["LEVEL_BOSS"] = "Set level to -1 for boss units or set to 0 to disable."
+L["Low Health Threshold"] = "Limiar de Vida Baixa"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = true
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = true;
+L["Match Player Level"] = true
+L["Maximum Level"] = true
+L["Maximum Time Left"] = true
+L["Minimum Level"] = true
+L["Minimum Time Left"] = true
+L["Missing"] = true
+L["Name Color"] = true
+L["Name Only"] = true
+L["NamePlates"] = "Placas de Identificação"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = true;
+L["Not Targeted"] = true
+L["Off Cooldown"] = true
+L["On Cooldown"] = true
+L["Over Health Threshold"] = true
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = true;
+L["Player Health"] = true
+L["Player in Combat"] = true
+L["Player Out of Combat"] = true
+L["Reaction Colors"] = true;
+L["Reaction Type"] = true
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "Remover Nome"
+L["Remove Nameplate Filter"] = true
+L["Require All"] = true
+L["Reset filter priority to the default state."] = true;
+L["Reset Priority"] = true;
+L["Return filter to its default state."] = true
+L["Scale of the nameplate that is targetted."] = true;
+L["Select Nameplate Filter"] = true
+L["Set Settings to Default"] = true;
+L["Set the transparency level of nameplates that are not the target nameplate."] = true;
+L["Set to either stack nameplates vertically or allow them to overlap."] = true;
+L["Shortcut to 'Filters' section of the config."] = true;
+L["Shortcut to global filters."] = true
+L["Shortcuts"] = true;
+L["Side Arrows"] = true
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = true
+L["Tagged NPC"] = true;
+L["Tanked Color"] = true;
+L["Target Indicator Color"] = true
+L["Target Indicator"] = true
+L["Target Scale"] = true;
+L["Targeted Nameplate"] = true
+L["Texture"] = true
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = true;
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = true;
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = true
+L["Threat"] = "Agro"
+L["Time To Hold"] = true
+L["Toggle Off While In Combat"] = true;
+L["Toggle On While In Combat"] = true;
+L["Top Arrow"] = true
+L["Triggers"] = true
+L["Under Health Threshold"] = true
+L["Unit Type"] = true
+L["Use Class Color"] = true;
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = true;
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = true;
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = true;
+L["Use Target Glow"] = true;
+L["Use Target Scale"] = true;
+L["Use Threat Color"] = true;
+L["You can't remove a default name from the filter, disabling the name."] = "Não pode remover um nome padrão do filtro, desativando o nome."
+
+--Profiles Export/Import
+L["Choose Export Format"] = true;
+L["Choose What To Export"] = true;
+L["Decode Text"] = true;
+L["Error decoding data. Import string may be corrupted!"] = true;
+L["Error exporting profile!"] = true;
+L["Export Now"] = true;
+L["Export Profile"] = true;
+L["Exported"] = true;
+L["Filters (All)"] = true;
+L["Filters (NamePlates)"] = true;
+L["Filters (UnitFrames)"] = true;
+L["Global (Account Settings)"] = true;
+L["Import Now"] = true;
+L["Import Profile"] = true;
+L["Importing"] = true;
+L["Plugin"] = true;
+L["Private (Character Settings)"] = true;
+L["Profile imported successfully!"] = true;
+L["Profile Name"] = true;
+L["Profile"] = true;
+L["Table"] = true;
+
+--Skins
+L["Achievement Frame"] = "Conquistas"
+L["Alert Frames"] = "Alertas"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "Casa de Leilões"
+L["Barbershop Frame"] = "Barbearia"
+L["BG Map"] = "Mapa do CB"
+L["BG Score"] = "Placar do CB"
+L["Calendar Frame"] = "Calendário"
+L["Character Frame"] = "Personagem"
+L["Debug Tools"] = "Ferramentas de Depuração"
+L["Dressing Room"] = "Provador"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "Fofocas"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "Banco da Guilda"
+L["Guild Registrar"] = "Registrar Guilda"
+L["Help Frame"] = "Ajuda"
+L["Inspect Frame"] = "Inspeção"
+L["KeyBinding Frame"] = "Atalhos"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "Saques"
+L["Macro Frame"] = "Macros"
+L["Mail Frame"] = "Correio"
+L["Merchant Frame"] = "Comerciante"
+L["Mirror Timers"] = true;
+L["Misc Frames"] = "Diversos"
+L["Petition Frame"] = "Petição"
+L["PvP Frames"] = "JxJ"
+L["Quest Frames"] = "Missões"
+L["Raid Frame"] = "Quadro de Raide"
+L["Skins"] = "Aparências"
+L["Socket Frame"] = "Engaste"
+L["Spellbook"] = "Grimório"
+L["Stable"] = "Estábulo"
+L["Tabard Frame"] = "Tabardo"
+L["Talent Frame"] = "Talentos"
+L["Taxi Frame"] = "Taxi"
+L["Time Manager"] = "Relógio"
+L["Trade Frame"] = "Negociar"
+L["TradeSkill Frame"] = "Profissões"
+L["Trainer Frame"] = "Instrutores"
+L["Tutorial Frame"] = true;
+L["World Map"] = "Mapa-múndi"
+
+--Tooltip
+L["Always Hide"] = "Sempre Ocultar"
+L["Bags Only"] = true;
+L["Bags/Bank"] = true;
+L["Bank Only"] = true;
+L["Both"] = true;
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = true;
+L["Comparison Font Size"] = true;
+L["Cursor Anchor"] = true;
+L["Custom Faction Colors"] = true;
+L["Display guild ranks if a unit is guilded."] = "Mostrar o Posto da guilda se a unidade possuir uma."
+L["Display how many of a certain item you have in your possession."] = "Mostra quantos de certo item você possui."
+L["Display player titles."] = "Mostrar títulos dos jogadores."
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = true;
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "Quando pairar o rato (mouse) sobre Itens ou Feitiços, mostra o ID destes na tooltip."
+L["Guild Ranks"] = "Posto na Guilda"
+L["Header Font Size"] = true;
+L["Health Bar"] = true;
+L["Hide tooltip while in combat."] = "Esconder tooltip em combate"
+L["Inspect Info"] = true;
+L["Item Count"] = "Contador de Item"
+L["Never Hide"] = "Nunca Esconder"
+L["Player Titles"] = "Títulos dos Jogadores"
+L["Should tooltip be anchored to mouse cursor"] = true;
+L["Spell/Item IDs"] = "IDs de Feitiços/Itens"
+L["Target Info"] = true;
+L["Text Font Size"] = true;
+L["This setting controls the size of text in item comparison tooltips."] = true;
+L["Tooltip Font Settings"] = true;
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "Exibe se alguém em sua raide tem como alvo a unidade da tooltip."
+
+--UnitFrames
+L["%s and then %s"] = "%s e depois %s"
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "Acima"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = true;
+L["Add a spell to the filter."] = "Adicionar um feitiço ao filtro."
+L["Add Spell ID or Name"] = true;
+L["Add SpellID"] = "Adicionar SpellID"
+L["Additional Filter Override"] = true;
+L["Additional Filter"] = "Filtro adicional"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = true;
+L["Allow Whitelisted Auras"] = "Permitir Auras da Lista Branca"
+L["An X offset (in pixels) to be used when anchoring new frames."] = true;
+L["An Y offset (in pixels) to be used when anchoring new frames."] = true;
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = true;
+L["Assist Frames"] = "Quadros de Assistentes"
+L["Assist Target"] = "Alvo do Assistente"
+L["At what point should the text be displayed. Set to -1 to disable."] = "Em qual ponto o texto deve ser mostrado. Defina como -1 para desabilitar."
+L["Attach Text To"] = true;
+L["Attach To"] = "Anexar ao"
+L["Aura Bars"] = "Barras de Auras"
+L["Auto-Hide"] = "Auto-Esconder"
+L["Bad"] = "Mau"
+L["Bars will transition smoothly."] = "Barras terão transição suave."
+L["Below"] = "Abaixo"
+L["Blacklist Modifier"] = true;
+L["Blacklist"] = "Lista negra"
+L["Block Auras Without Duration"] = "Bloquear Auras sem Duração"
+L["Block Blacklisted Auras"] = "Bloquear Auras da Lista Negra"
+L["Block Non-Dispellable Auras"] = "Bloquear Auras não Dissipáveis"
+L["Block Non-Personal Auras"] = "Bloquear Auras não Pessoais"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "Sangue"
+L["Borders"] = "Bordas"
+L["Buff Indicator"] = "Indicador de Bônus"
+L["Buffs"] = "Bônus"
+L["By Type"] = "Por tipo"
+L["Castbar"] = "Barra de lançamento"
+L["Center"] = "Centro"
+L["Check if you are in range to cast spells on this specific unit."] = "Verifica se você esta em alcance para lançar fetiços nessa unidade específica."
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = true;
+L["Class Backdrop"] = "Fundo por classe"
+L["Class Castbars"] = "Barras de Lançamento da Classe"
+L["Class Color Override"] = "Sobrescrever Cor da Classe"
+L["Class Health"] = "Vida por Classe"
+L["Class Power"] = "Poder por classe"
+L["Class Resources"] = "Recursos de Classe"
+L["Click Through"] = "Clicar através"
+L["Color all buffs that reduce the unit's incoming damage."] = "Colorir todos os bônus que reduzem o dano recebido pela unidade."
+L["Color aurabar debuffs by type."] = "Colorir penalidades da barra de auras por tipo."
+L["Color castbars by the class of player units."] = true;
+L["Color castbars by the reaction type of non-player units."] = true;
+L["Color health by amount remaining."] = "Colorir a vida pela quantidade restante."
+L["Color health by classcolor or reaction."] = "Colorir a vida pela cor da classe ou reação."
+L["Color power by classcolor or reaction."] = "Colorir poder pela cor da classe ou reação."
+L["Color the health backdrop by class or reaction."] = "Colorir o fundo da vida pela cor da classe ou reação."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "Colorir a barra de vida se existir uma penalidade que você possa dissipar."
+L["Color Turtle Buffs"] = "Colorir bônus de Tartaruga"
+L["Color"] = "Cor"
+L["Colored Icon"] = "Ícone Colorido"
+L["Coloring (Specific)"] = "Coloração (Específica)"
+L["Coloring"] = "Coloração"
+L["Combat Fade"] = "Desvanecer em Combate"
+L["Combat Icon"] = true;
+L["Combo Point"] = true;
+L["Combobar"] = true;
+L["Configure Auras"] = "Configurar Auras"
+L["Copy From"] = "Copiar de"
+L["Count Font Size"] = "Tamanho da Fonte do Contador"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "Criar uma fonte personalizada. Assim que meter um nome você será capaz de seleciona-la da lista de elementos"
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "Criar um filtro, uma vez criado o filtro pode ser definido dentro da seção dos bônus/penalidades de cada unidade."
+L["Create Custom Text"] = true
+L["Create Filter"] = "Criar filtro"
+L["Current - Max | Percent"] = "Atual - Máximo | Porcentagem"
+L["Current - Max"] = "Atual - Máximo"
+L["Current - Percent"] = "Atual - Porcentagem"
+L["Current / Max"] = "Atual / Máximo"
+L["Current"] = "Atual"
+L["Custom Dead Backdrop"] = true;
+L["Custom Health Backdrop"] = "Fundo de vida personalizada"
+L["Custom Texts"] = "Textos Personalizados"
+L["Death"] = "Morte"
+L["Debuff Highlighting"] = "Destacar Penalidades"
+L["Debuffs"] = "Penalidades"
+L["Decimal Threshold"] = true;
+L["Deficit"] = "Défice"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "Excluir um filtro criado, você não pode excluir filtros pré-existentes, apenas aqueles personalizados."
+L["Delete Filter"] = "Apagar Filtro"
+L["Detach From Frame"] = "Destacar do Quadro"
+L["Detached Width"] = "Largura quando Destacado"
+L["Direction the health bar moves when gaining/losing health."] = "Direção em que a barra da vida se move quando se ganha/perde vida."
+L["Disable Debuff Highlight"] = true;
+L["Disabled Blizzard Frames"] = true;
+L["Disabled"] = "Desativar"
+L["Disables the focus and target of focus unitframes."] = true;
+L["Disables the player and pet unitframes."] = true;
+L["Disables the target and target of target unitframes."] = true;
+L["Disconnected"] = "Desconectado"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "Exibir uma textura de faísca no fim da Barra de Lançamento para ajudar a diferenciar a barra de lançamento e o fundo."
+L["Display Frames"] = "Exibir Quadros"
+L["Display Player"] = "Exibir Jogador"
+L["Display Target"] = "Mostrar Alvo"
+L["Display Text"] = "Mostrar Texto"
+L["Display the castbar icon inside the castbar."] = true;
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = true;
+L["Display the combat icon on the unitframe."] = true;
+L["Display the rested icon on the unitframe."] = "Exibir o ícone de descansando no quadro de unidade."
+L["Display the target of your current cast. Useful for mouseover casts."] = "Mostra os alvos do seu lançamento atual. Útil para lançamentos mouseover."
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "Exibir marcas na barra de lançamento para feitiços canalizados. Isto irá se ajustar automaticamente para feitiços como Drenar Alma e adicionará ticks baseado na Aceleração."
+L["Don't display any auras found on the 'Blacklist' filter."] = "Não mostra nenhuma aura encontrada no filtro 'Lista Negra'."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that are not yours."] = "Não mostra auras que não são suas."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that cannot be purged or dispelled by your class."] = "Não mostra auras que não podem ser dissipadas pela sua classe."
+L["Don't display auras that have no duration."] = "Não mostra auras sem duração."
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "Baixo"
+L["Dungeon & Raid Filter"] = true;
+L["Duration Reverse"] = "Duração Reversa"
+L["Duration Text"] = true;
+L["Duration"] = "Duração"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = true;
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = true;
+L["Enemy Aura Type"] = "Tipo de Aura do Inimigo"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "Desvanecer o quadro de unidade quando fora de combate, nao está lançando, nao tem um alvo."
+L["Fill"] = "Preencher"
+L["Filled"] = "Preenchido"
+L["Filter Type"] = "Tipo de filtro"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "Forçado Desligado"
+L["Force On"] = "Forçado Ligado"
+L["Force Reaction Color"] = true;
+L["Force the frames to show, they will act as if they are the player frame."] = "Forçar os quadros para aparecerem, irão se comportar como se fossem o quadro do jogador."
+L["Forces Debuff Highlight to be disabled for these frames"] = true;
+L["Forces reaction color instead of class color on units controlled by players."] = true;
+L["Format"] = "Formato"
+L["Frame Level"] = true;
+L["Frame Orientation"] = true;
+L["Frame Strata"] = true;
+L["Frame"] = "Quadro"
+L["Frequent Updates"] = "Atualizações frequentes"
+L["Friendly Aura Type"] = "Tipo de Aura para Aliado"
+L["Friendly"] = "Aliado"
+L["Frost"] = "Gélido"
+L["Glow"] = "Brilhar"
+L["Good"] = "Bom"
+L["GPS Arrow"] = true;
+L["Group By"] = "Agrupar por"
+L["Grouping & Sorting"] = true;
+L["Groups Per Row/Column"] = "Grupos por Linha/Coluna"
+L["Growth direction from the first unitframe."] = "Direção de crescimento a partir do primeiro quado de unidade."
+L["Growth Direction"] = "Direção de crescimento"
+L["Heal Prediction"] = "Curas por vir"
+L["Health Backdrop"] = "Fundo da Vida"
+L["Health Border"] = "Borda da Vida"
+L["Health By Value"] = "Vida por Valor"
+L["Health"] = "Vida"
+L["Height"] = "Altura"
+L["Horizontal Spacing"] = "Espamento Horizontal"
+L["Horizontal"] = "Horizontal"
+L["Icon Inside Castbar"] = true;
+L["Icon Size"] = true;
+L["Icon"] = "Ícone"
+L["Icon: BOTTOM"] = "Ícone: ABAIXO"
+L["Icon: BOTTOMLEFT"] = "Ícone: ABAIXO-ESQUERDA"
+L["Icon: BOTTOMRIGHT"] = "Ícone: ABAIXO-DIREITA"
+L["Icon: LEFT"] = "Ícone: ESQUERDA"
+L["Icon: RIGHT"] = "Ícone: DIREITA"
+L["Icon: TOP"] = "Ícone: ACIMA"
+L["Icon: TOPLEFT"] = "Ícone: ACIMA-ESQUERDA"
+L["Icon: TOPRIGHT"] = "Ícone: ACIMA-DIREITA"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Se nenhuma outra opção de filtro estiver em uso então bloqueará qualquer coisa que não esteja no filtro 'Lista Branca', caso contrário simplesmente adicionará auras da lista branca em adição às outras configurações de filtros."
+L["If not set to 0 then override the size of the aura icon to this."] = "Se não definido 0 então sobrescreve o tamanho da aura para este."
+L["If the unit is an enemy to you."] = "Se a unidade for um inimigo seu."
+L["If the unit is friendly to you."] = "Se a unidade for um aliado seu."
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = true;
+L["Ignore mouse events."] = "Ignorar eventos do rato (mouse)."
+L["InfoPanel Border"] = true;
+L["Information Panel"] = true;
+L["Inset"] = "Margem"
+L["Inside Information Panel"] = true;
+L["Interruptable"] = "Interrompível"
+L["Invert Grouping Order"] = "Inverter a Ordem de Agrupamento"
+L["JustifyH"] = "JustificarH"
+L["Latency"] = "Latência"
+L["Left to Right"] = true;
+L["Main statusbar texture."] = "Textura princiapal da barra de estado."
+L["Main Tanks / Main Assist"] = "Tanque Principal / Assistente Princial"
+L["Make textures transparent."] = "Deixar as texturas transparentes."
+L["Match Frame Width"] = "Igualar comprimento do quadro"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = true;
+L["Max Overflow"] = true
+L["Maximum Duration"] = true;
+L["Method to sort by."] = true;
+L["Middle Click - Set Focus"] = "Clique Meio - Defenir foco"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "Clicar com o botão do meio no quadro da unidade fará o foco ser defenido para esta unidade."
+L["Middle"] = true;
+L["Minimum Duration"] = true;
+L["Mouseover"] = "Mouseover"
+L["Name"] = "Nome"
+L["Neutral"] = "Neutro"
+L["Non-Interruptable"] = "Não interrompível"
+L["None"] = "Nenhum"
+L["Not valid spell id"] = "Identificação (id) do feitiço não é valida"
+L["Num Rows"] = "Número de linhas"
+L["Number of Groups"] = "Número de Grupos"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "A distância entre barra de poder e a barra de vida, definir 0 para desactivar."
+L["Offset position for text."] = "Deslocamento da posição do texto"
+L["Offset"] = "Distância"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "Somente mostra quando a unidade não está ao alcance."
+L["Only show when you are mousing over a frame."] = "Somente mostra quando você está com o mouse sobre um quadro."
+L["OOR Alpha"] = "Transparência Fora de Alcance"
+L["Other Filter"] = true;
+L["Others"] = "Outros"
+L["Overlay the healthbar"] = "Sobrepor a barra de vida"
+L["Overlay"] = "Sobrepor"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "Sobrescrever qualquer visibilidade personalizada em certas situações, Ex: Mostrar apenas grupo 1 e 2 dentro de uma instância de 10 pessoas."
+L["Override the default class color setting."] = "Sobrescreve a configuração de cor de classe padrão."
+L["Owners Name"] = true;
+L["Parent"] = true;
+L["Party Pets"] = "Ajudantes do Grupo"
+L["Party Targets"] = "Alvos do Grupo"
+L["Per Row"] = "Por Linha"
+L["Percent"] = "Porcentagem"
+L["Personal"] = "Pessoal"
+L["Pet Name"] = true;
+L["Player Frame Aura Bars"] = true;
+L["Portrait"] = "Retrato"
+L["Position Buffs on Debuffs"] = true;
+L["Position Debuffs on Buffs"] = true;
+L["Position"] = "Posição"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "Em PNJs o texto de poder não será mostrado, em adição o texto de nome será reposicionado para o ponto de fixação do texto de poder."
+L["Power"] = "Poder"
+L["Powers"] = "Poderes"
+L["Priority"] = "prioridade"
+L["Profile Specific"] = true;
+L["PvP Icon"] = true;
+L["PvP Text"] = true;
+L["PVP Trinket"] = "Berloque de JXJ"
+L["Raid Icon"] = "Icone de Raide"
+L["Raid-Wide Sorting"] = true;
+L["Raid40 Frames"] = true;
+L["RaidDebuff Indicator"] = "Indicador das Penalidades da Raide"
+L["Range Check"] = "Checar Alcance"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "Atualizar rapidamente a vida, usa mais memória e CPU. Apenas recomendado para curandeiros."
+L["Reaction Castbars"] = true;
+L["Reactions"] = "Reações"
+L["Ready Check Icon"] = true;
+L["Remaining"] = "Restante"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = true;
+L["Remove a spell from the filter."] = "Remover um feitiço do filtro."
+L["Remove Spell ID or Name"] = true;
+L["Remove SpellID"] = "Remover SpellID"
+L["Rest Icon"] = "ìcone de descansar"
+L["Restore Defaults"] = "Restaurar ao Padrão"
+L["Right to Left"] = true;
+L["RL / ML Icons"] = "Icons LR / MS"
+L["Role Icon"] = "Ícone do papel"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = true;
+L["Select a unit to copy settings from."] = "Selecione uma unidade para que se copiem as definições!"
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Seleciona um filtro adicional para uso. Se o filtro selecionado for um do tipo 'lista branca' e nenhum outro filtro for usado (com exeção do Bloquerar Auras não Pessoais) então irá bloquear qualquer coisa que não esteja na lista branca, caso contrário irá adicionar auras da lista branca em adição a qualquer outra configuração de filtro."
+L["Select Filter"] = "Seleccionar filtros"
+L["Select Spell"] = "Seleccionar feitiço"
+L["Select the display method of the portrait."] = "Seleciona o método de exibição do retrato."
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = true;
+L["Set the font size for unitframes."] = "Define o tamanho da fonte para o quadro de unidades."
+L["Set the order that the group will sort."] = "Define a ordem em que o grupo vai se organizar."
+L["Set the orientation of the UnitFrame."] = true;
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "Define a ordem prioritária dos feitiços, por favor note que prioridades só são usadas o modo de Penalidades de Raide, não para o modo normal de bônus/penalidades."
+L["Set the type of auras to show when a unit is a foe."] = "Define o tipo de auras a serem mostradas quando a unidade é um inimigo."
+L["Set the type of auras to show when a unit is friendly."] = "Define o tipo de auras a serem mostradas quando a unidade é aliada."
+L["Sets the font instance's horizontal text alignment style."] = "Define o estilo de alinhamento horizontal da instância da fonte."
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "Mostra a barra de predicção de cura no quadro de unidade. Também exibe uma barra com uma cor ligeiramente diferente para a predicção de sobrecura."
+L["Show Aura From Other Players"] = "Mostrar Auras de outros Jogadores"
+L["Show Auras"] = "Mostrar Auras"
+L["Show Dispellable Debuffs"] = true;
+L["Show When Not Active"] = "Mostrar Quando Não Ativo"
+L["Size and Positions"] = true;
+L["Size of the indicator icon."] = "Tamanho do ícone indicador."
+L["Size Override"] = "Sobrescrever Tamanho"
+L["Size"] = "Tamanho"
+L["Smart Aura Position"] = true;
+L["Smart Raid Filter"] = "Filtro de Raide inteligente"
+L["Smooth Bars"] = "Barras suaves"
+L["Sort By"] = true;
+L["Spaced"] = "Espaçado"
+L["Spacing"] = true;
+L["Spark"] = "Faísca"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = true;
+L["Stack Threshold"] = true;
+L["Start Near Center"] = "Começar perto do Centro"
+L["Statusbar Fill Orientation"] = true;
+L["StatusBar Texture"] = "Textura da barra de estado"
+L["Strata and Level"] = true;
+L["Style"] = "Estilo"
+L["Tank Frames"] = "Quadro do Tanques"
+L["Tank Target"] = "Alvo do Tanque"
+L["Tapped"] = "Reservado"
+L["Target Glow"] = true;
+L["Target On Mouse-Down"] = "Selecionar ao Pressionar o Mouse"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "Seleciona unidades ao pressionar o mouse em ves de ao soltar. \n\n|cffFF0000Atenção: Se você estiver usando o addon 'Clique' poderá ter que ajustá-lo quando alterar essa opção."
+L["Text Color"] = "Cor do Texto"
+L["Text Format"] = "Formato de texto"
+L["Text Position"] = "Posição do Texto"
+L["Text Threshold"] = "Limiar do Texto"
+L["Text Toggle On NPC"] = "Texto ligado no PNJ"
+L["Text xOffset"] = "Distãncia X do Texto"
+L["Text yOffset"] = "Distância Y do Texto"
+L["Text"] = "Texto"
+L["Textured Icon"] = "Ícone Texturizado"
+L["The alpha to set units that are out of range to."] = "A trasparência a definir para unidades que estão fora de alcance."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = true;
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "A macro seguinte tem de ser verdadeira para que o grupo seja mostrado, em adição a qualquer outro filtro que possa já estar definido."
+L["The font that the unitframes will use."] = "A fonte que os quadros de unidades usarão."
+L["The initial group will start near the center and grow out."] = "O grupo inicial começara perto do centro e crescerá para fora."
+L["The name you have selected is already in use by another element."] = "O nome que escolheu já está a ser usado noutro elemento."
+L["The object you want to attach to."] = "O objeto ao qual você quer anexar."
+L["Thin Borders"] = true;
+L["This dictates the size of the icon when it is not attached to the castbar."] = true;
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = true;
+L["Threat Display Mode"] = "Modo de Exebição de Ameaça"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = true;
+L["Ticks"] = "Ticks"
+L["Time Remaining Reverse"] = "Tempo Remanescente Reverso"
+L["Time Remaining"] = "Tempo Remanescente"
+L["Transparent"] = "Transparente"
+L["Turtle Color"] = "Cor para Tartaruga"
+L["Unholy"] = "Profano"
+L["Uniform Threshold"] = true;
+L["UnitFrames"] = "Quadro de Unidades"
+L["Up"] = "Acima"
+L["Use Custom Level"] = true;
+L["Use Custom Strata"] = true;
+L["Use Dead Backdrop"] = true;
+L["Use Default"] = "usar Padrão"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "Usar a cor de fundo da vida personalizada em vez de um multiplo da cor de vida principal."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = true;
+L["Use thin borders on certain unitframe elements."] = true;
+L["Use this backdrop color for units that are dead or ghosts."] = true;
+L["Value must be a number"] = "O valor tem de ser um número"
+L["Vertical Orientation"] = true;
+L["Vertical Spacing"] = "Espaçamento Vertical"
+L["Vertical"] = "Vertical"
+L["Visibility"] = "Visibilidade"
+L["What point to anchor to the frame you set to attach to."] = "Qual é o ponto a fixar ao quadro que você definiu para ser anexado."
+L["What to attach the buff anchor frame to."] = "Ao que anexar o quadro fixador dos Bônus."
+L["What to attach the debuff anchor frame to."] = "Ao que anexar o quadro fixador das Penalidades."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "Quando verdade, o cabeçalho inclui o jogador quando não está em Raide."
+L["Whitelist"] = "Lista Branca"
+L["Width"] = "Comprimento"
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = true;
+L["xOffset"] = "Distância X"
+L["yOffset"] = "Distância Y"
+L["You can't remove a pre-existing filter."] = "Você não pode remover um filtro pré-existente."
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "Você não pode remover um feitiço de um filtro padrão que não seja um feitiço personalizado. Em vez disso definindo feitiço para falso."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = true;
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Russian_Config.lua b/ElvUI_Config/Locales/Russian_Config.lua
new file mode 100644
index 0000000..d7b73b6
--- /dev/null
+++ b/ElvUI_Config/Locales/Russian_Config.lua
@@ -0,0 +1,1130 @@
+-- Russian localization file for ruRU.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "ruRU")
+if not L then return; end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "Настройка иконок эффектов, находящихся у миникарты."
+L["BAGS_DESC"] = "Настройки сумок ElvUI"
+L["CHAT_DESC"] = "Настройте отображение чата ElvUI."
+L["DATATEXT_DESC"] = "Установка отображения информационных текстов."
+L["ELVUI_DESC"] = "ElvUI это аддон для полной замены пользовательского интерфейса World of Warcraft."
+L["NAMEPLATE_DESC"] = "Настройки индикаторов здоровья."
+L["PANEL_DESC"] = "Регулирование размеров левой и правой панелей. Это окажет эффект на чат и сумки."
+L["SKINS_DESC"] = "Установки скинов"
+L["TOGGLESKIN_DESC"] = "Включить/выключить этот скин."
+L["TOOLTIP_DESC"] = "Опций подсказки"
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[С добавлением библиотеки LibItemSearch, у вас появился доступ к большему количеству поисковых запросов. Здесь представлена документация по синтаксису поисковых запросов. Полная инструкция доступна по адресу: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Специфический поик:
+ • q:[качество] или quality:[качество]. Например, q:эпическое покажет все предметы эпического качества (слово "эпическое" не обязательно вводить до конца).
+ • l:[уровень], lvl:[уровень] or level:[уровень]. Например, l:30 покажет все предметы с уровнем 30. Это относитя именно к уровню предметов, а не требуемому уровню персонажа.
+ • t:[запрос], type:[запрос] or slot:[запрос]. Например, t:оружие покажет все предметы, являющиеся оружием.
+ • n:[имя] or name:[имя]. Например, n:muffins покажет все предметы, в имени которых соержится "muffins".
+ • s:[набор] or set:[набор]. Например, s:fire покажет предметы из наборов экипировки, название которых начинается с "fire".
+ • tt:[запрос], tip:[запрос] or tooltip:[запрос]. Например, tt:уникальный покажет все предметы, которые являются уникальными или уникальными использующимися.
+
+
+Операторы поиска:
+ • ! : Обращает результат поиска. Например, !q:эпическое покажет все НЕ эпические предметы.
+ • | : Объединет запросы. Например, "q:эпическое | t:оружие" отобразит все предметы эпического качества ИЛИ являющиеся оружием.
+ • & : Суммирует запросы. Например, "q:эпическое & t:оружие" отобразит все оружие эпического качества.
+ • >, <, <=, => : сразнения для численных запросов. Например, запрос "lvl: >30" покажет все предметы с уровнем выше 30.
+
+
+Также могут быть использованы следующие параметры:
+ • soulbound, bound, bop : персональные при поднятии.
+ • bou : персональные при использовании.
+ • boe : персональные при одевании.
+ • boa : привязоные к учетной записи.
+ • quest : специальные предметы для заданий.]];
+L["TEXT_FORMAT_DESC"] = [[Строка для изменения вида текста.
+
+Примеры:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+Форматы здоровья/резурсов:
+"current" - текущее значение
+"percent" - значение в процентах
+"current-max" - текущее значение, за которым идет максимальное значение. Будет отображать только максимальное значение, если текущее равно ему.
+"current-percent" - текущее значение, за которым идет значение в процентах.Будет отображать только максимальное значение, если текущее равно ему.
+"current-max-percent" - текущее значение, максимальное значение, за которым идет значение в процентах, Будет отображать только максимальное значение, если текущее равно ему.
+"deficit" - отображает значение недостающего до максимума здоровья/ресурса. Не будет отображать ничего, если текущее значение равно максимальному.
+
+Форматы имени:
+"name:short" - Имя с ограничением длины в 10 символов
+"name:medium" - Имя с ограничением длины в 15 символов
+"name:long" - Имя с ограничением длины в 20 символов
+
+Для отключения оставьте поле пустым, для дополнительной информации посетите http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "Переключение панелей"
+L["ActionBars"] = "Панели команд"
+L["Action button keybinds will respond on key down, rather than on key up"] = "Способности будут задействоваться, когда пользователь нажимает, а не отпускает клавишу."
+L["Allow LBF to handle the skinning of this element."] = "Разрешить LBF обрабатывать этот элемент."
+L["Alpha"] = "Прозрачность"
+L["Anchor Point"] = "Точка фиксации"
+L["Backdrop Spacing"] = "Отступ фона"
+L["Backdrop"] = "Фон"
+L["Button Size"] = "Размер кнопок"
+L["Button Spacing"] = "Отступ кнопок"
+L["Buttons Per Row"] = "Кнопок в ряду"
+L["Buttons"] = "Кнопок"
+L["Change the alpha level of the frame."] = "Изменяет прозрачность этого элемента"
+L["Color of the actionbutton when not usable."] = "Цвет кнопок, которые невозможно использовать."
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "Цвет кнопок на панелях команд, когда не хватает ресурса (маны, ярости)"
+L["Color of the actionbutton when out of range."] = "Цвет кнопок панелей команд, когда цель вне радиуса действия"
+L["Color of the actionbutton when usable."] = "Цвет кнопок, которые можно использовать."
+L["Color when the text is about to expire"] = "Цвет текста почти завершившегося восстановления."
+L["Color when the text is in the days format."] = "Цвет текста времени восстановления в днях."
+L["Color when the text is in the hours format."] = "Цвет текста времени восстановления в часах."
+L["Color when the text is in the minutes format."] = "Цвет текста времени восстановления в минутах."
+L["Color when the text is in the seconds format."] = "Цвет текста времени восстановления в секундах."
+L["Cooldown Text"] = "Текст восстановления"
+L["Darken Inactive"] = "Неактивные затенены"
+L["Days"] = "Дни"
+L["Display bind names on action buttons."] = "Отображать назначенные клавиши на кнопках."
+L["Display cooldown text on anything with the cooldown spiral."] = "Отображать время восстановления на кнопках/предметах."
+L["Display macro names on action buttons."] = "Отображать названия макросов на кнопках."
+L["Expiring"] = "Завершение"
+L["Global Fade Transparency"] = "Глобальная прозрачность"
+L["Height Multiplier"] = "Множитель высоты"
+L["Hours"] = "Часы"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = "Если вы разблокируете панели, а затем попытаетесь переместить заклинание, оно может быть применено мгновенно, если включено применение при нажатии."
+L["Inherit Global Fade"] = "Использовать глобальную прозрачность"
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = "Использовать глобальную прозрачность. Наведение мыши, наличие цели, фокуса, потеря здоровья и вступление в бой уберут прозрачность. В остальных случаях будет использоваться уровень прозрачности из общих настроек панелей команд."
+L["Key Down"] = "При нажатии клавиши"
+L["Keybind Mode"] = "Назначить клавиши"
+L["Keybind Text"] = "Текст клавиш"
+L["LBF Support"] = "Поддержка LBF"
+L["Low Threshold"] = "Минимальное значение"
+L["Macro Text"] = "Названия макросов"
+L["Minutes"] = "Минуты"
+L["Mouse Over"] = "При наведении" --Also used in Bags
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "Умножает высоту или ширину фона панели на это значение. Это полезно, когда Вы хотите иметь более одной панели на данном фоне."
+L["Not Usable"] = "Нельзя использовать"
+L["Out of Power"] = "Мало ресурса"
+L["Out of Range"] = "Вне радиуса"
+L["Pick Up Action Key"] = "Клавиша перетаскивания"
+L["Restore Bar"] = "Восстановить панель"
+L["Restore the actionbars default settings"] = "Восстанавливает настройки панели по умолчанию."
+L["Seconds"] = "Секунды"
+L["Show Empty Buttons"] = "Показывать пустые кнопки"
+L["The amount of buttons to display per row."] = "Количество кнопок в каждом ряду"
+L["The amount of buttons to display."] = "Количество отображаемых кнопок."
+L["The button you must hold down in order to drag an ability to another action button."] = "Кнопка, которую вы должны деражть нажатой для перемещения способностей на панелях команд."
+L["The first button anchors itself to this point on the bar."] = "Первая кнопка прикрепляется к этой точке панели"
+L["The size of the action buttons."] = "Размер кнопок панели команд."
+L["The spacing between the backdrop and the buttons."] = "Расстояние между фоном панели и кнопками."
+L["This setting will be updated upon changing stances."] = "Эта настройка вступит в силу при смене стойки."
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "Время, после которого текст станет красным и начнет отображать доли секунды. Установите -1, чтобы не отображать текст в такой форме."
+L["Toggles the display of the actionbars backdrop."] = "Включить отображение фона панели команд."
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = "Уровень прозрачности вне боя, без цели, без фокуса, с полным здоровьем и без произношения заклинаний."
+L["Usable"] = "Можно использовать"
+L["Visibility State"] = "Статус отображения"
+L["Width Multiplier"] = "Множитель ширины"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[Работает как макрос. Вы можете задать различные условия для отображения разных панелей.
+ Пример: [combat] 2;]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[Работает как макрос. Вы можете задать различные условия для показа/скрытия панели.
+ Пример: [combat] show;hide]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = "Добавить предмет или синтаксис поиска в список игнорируемых. Предметы, соответствующие синтаксису, буду игнорироваться."
+L["Add Item or Search Syntax"] = "Добавить предмет или синтаксис поиска"
+L["Adjust the width of the bag frame."] = "Установить размер фрейма сумок"
+L["Adjust the width of the bank frame."] = "Установить размер фрейма банка"
+L["Ascending"] = "Восходящее"
+L["Bag Sorting"] = "Сортировка сумок"
+L["Bag-Bar"] = "Панель сумок"
+L["Bar Direction"] = "Направление панели"
+L["Blizzard Style"] = "Стиль Blizzard"
+L["Bottom to Top"] = "Снизу вверх"
+L["Button Size (Bag)"] = "Размер слотов сумок"
+L["Button Size (Bank)"] = "Размер слотов банка"
+L["Clear Search On Close"] = "Сбрасывать поиск при закрытии"
+L["Condensed"] = "Через запятую"
+L["Descending"] = "Нисходящее"
+L["Direction the bag sorting will use to allocate the items."] = "Направление расположения предметов при сортировке."
+L["Disable Bag Sort"] = "Отключить сортировку сумок"
+L["Disable Bank Sort"] = "Отключить сортировку банка"
+L["Display Item Level"] = "Отображать уровень предметов"
+L["Displays item level on equippable items."] = "Отображает уровень предметов, которые можно надеть."
+L["Enable/Disable the all-in-one bag."] = "Включить/выключить режим сумки 'все в одной'. "
+L["Enable/Disable the Bag-Bar."] = "Включить/выключить панель сумок"
+L["Full"] = "Полный"
+L["Global"] = "Глобальный"
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = "Здесь вы можете добавить предметы или запросы поиска, которые вы хотите исключить из сортировки. Для удаления предмета просто кликните на его имени в списке."
+L["Ignored Items and Search Syntax (Global)"] = "Игнорируемые предметы и синтаксис (Глобальный)"
+L["Ignored Items and Search Syntax (Profile)"] = "Игнорируемые предметы и синтаксис (Профиль)"
+L["Item Count Font"] = "Шрифт кол-ва предметов"
+L["Item Level Threshold"] = "Ограничение уровня предметов"
+L["Item Level"] = "Уровень предметов"
+L["Money Format"] = "Формат денег"
+L["Panel Width (Bags)"] = "Ширина сумок"
+L["Panel Width (Bank)"] = "Ширина банка"
+L["Search Syntax"] = "Синтаксис поиска"
+L["Set the size of your bag buttons."] = "Установите размер кнопок на панели."
+L["Short (Whole Numbers)"] = "Короткий (целые)"
+L["Short"] = "Короткий"
+L["Smart"] = "Умный"
+L["Sort Direction"] = "Направление сортировки" --Also used in Buffs and Debuffs
+L["Sort Inverted"] = "Инвертированная сортировка"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "Расположение сумок (горизонтально или вертикально)"
+L["The direction that the bag frames will grow from the anchor."] = "Направление, в котором будут расположены кнопки сумок относительно фиксатора."
+L["The display format of the money text that is shown at the top of the main bag."] = "Формат отображения текста золота в верхней части основной сумки."
+L["The frame is not shown unless you mouse over the frame."] = "Отображать только при наведении мыши."
+L["The minimum item level required for it to be shown."] = "Минимальный уровень предмета, который будет показан в сумках."
+L["The size of the individual buttons on the bag frame."] = "Размер каждого слота в сумок"
+L["The size of the individual buttons on the bank frame."] = "Размер каждого слота в банке"
+L["The spacing between buttons."] = "Расстояние между кнопками"
+L["Top to Bottom"] = "Сверху вниз"
+L["Use coin icons instead of colored text."] = "Использовать иконки монет вместо окрашенного текста."
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "Баффы и дебаффы";
+L["Begin a new row or column after this many auras."] = "Начинать новый ряд/столбец после этого количества аур."
+L["Count xOffset"] = "Отступ стаков по X"
+L["Count yOffset"] = "Отступ стаков по Y"
+L["Defines how the group is sorted."] = "Определяет условия сортировки"
+L["Defines the sort order of the selected sort method."] = "Определяет порядок в выбранном методе сортировки."
+L["Disabled Blizzard"] = "Отключить ауры Blizzard"
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "Значение мерцания"
+L["Index"] = "Порядок наложения"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "Определяет должны ли Ваши баффы находиться отдельно перед или после остальных."
+L["Limit the number of rows or columns."] = "Определяет максимальное количество рядов/столбцов."
+L["Max Wraps"] = "Максимум рядов"
+L["No Sorting"] = "Без сортировки"
+L["Other's First"] = "Сначала чужие"
+L["Remaining Time"] = "Оставшееся время"
+L["Reminder"] = true
+L["Reverse Style"] = "Обратное затенение"
+L["Seperate"] = "Разделение"
+L["Set the size of the individual auras."] = "Устанавливает размер аур"
+L["Sort Method"] = "Метод сортировки"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = "Направление роста аур и сторона с которой будет добавляться новый ряд."
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "Пороговое значение, после которого цвет текста изменится на красный и начнет показывать десятые доли секунд, а иконка начнет мигать. Установите на -1 для отключения"
+L["Time xOffset"] = "Отступ времени по X"
+L["Time yOffset"] = "Отступ времени по Y"
+L["Time"] = "Время"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = "Если активно, то иконки имеющихся баффов будут яркими, а отсутствующих затемненными."
+L["Wrap After"] = "Размер ряда"
+L["Your Auras First"] = "Сначала свои"
+
+--Chat
+L["Above Chat"] = "Над чатом"
+L["Adjust the height of your right chat panel."] = "Настроить высоту правой панели чата"
+L["Adjust the width of your right chat panel."] = "Настроить ширину правой панели чата."
+L["Alerts"] = "Оповещения"
+L["Allowed Combat Repeat"] = "Повторяющиеся символы"
+L["Attempt to create URL links inside the chat."] = "Пытаться создавать интернет-ссылки в чате."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "Закрепляет позиции левого и правого чата к соответственным панелям. Отключение этой опции позволит перемещать чат независимо от них."
+L["Below Chat"] = "Под чатом"
+L["Chat EditBox Position"] = "Позиция поля ввода"
+L["Chat History"] = "История чата"
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = "Упоминания цветом класса"
+L["Custom Timestamp Color"] = "Свой цвет времени"
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "Отображать подсказку ссылки на при наведении на нее мыши. Действует на предметы, достижения, сохранения подземелий и тд."
+L["Enable the use of separate size options for the right chat panel."] = "Включить использование отдельных настроек ширины и высоты для правой панели чата."
+L["Exclude Name"] = "Исключить имя"
+L["Excluded names will not be class colored."] = "Исключенные имена не окрашиваются в цвет класса"
+L["Excluded Names"] = "Исключенные имена"
+L["Fade Chat"] = "Затухание чата"
+L["Fade Tabs No Backdrop"] = "Затухание без фона"
+L["Fade the chat text when there is no activity."] = "Исчезновение строк чата при отсутствии аткивности"
+L["Fade Undocked Tabs"] = "Затухание незакрепленных"
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = "Исчезновение текста на вкладках, закрепленных на какой-либо из панелей чата, при отключенном фоне."
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = "Заставляет текст на вкладках, не закрепленных на правой или левой панелях чата, исчезать до наведения курсора."
+L["Font Outline"] = "Граница шрифта" --Also used in UnitFrames section
+L["Font"] = "Шрифт"
+L["Hide Both"] = "Скрыть оба"
+L["Hyperlink Hover"] = "Подсказка над ссылками"
+L["Keyword Alert"] = "Звук ключевых слов"
+L["Keywords"] = "Ключевые слова"
+L["Left Only"] = "Только левый"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "Список слов для окрашивания, если они обнаружены в чате. Если Вы хотите добавить несколько слов, то разделяйте их запятыми. Для поиска имени Вашего текущего персонажа используйте %MYNAME%.\n\nПример:\n%MYNAME%, ElvUI, РБГ, Танк"
+L["Lock Positions"] = "Закрепить"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "Записывать содержимое основных чатов. Таким образом, после перезагрузки интерфейса или входа/выхода из игры, Вы увидите сообщения из прошлой сессии."
+L["No Alert In Combat"] = "Без оповещений в бою"
+L["Number of messages you scroll for each step."] = "Количество сообщений, прокручивающихся за шаг."
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = "Кол-во одинаковых символов введенных в бою, после которого поле ввода автоматически закроется."
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "Время в секундах, через которое чат автоматически покрутится вниз до конца, если Вы не сделаете это вручную."
+L["Panel Backdrop"] = "Фон панелей"
+L["Panel Height"] = "Высота панели"
+L["Panel Texture (Left)"] = "Текстура левой панели"
+L["Panel Texture (Right)"] = "Текстура правой панели"
+L["Panel Width"] = "Ширина панели"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "Позиция поля ввода для чата. Если инфо-тексты отключены, оно всегда будет над чатом."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "Предотвращает появление одинаковых сообщения в чате чаще указанного количества секунд. Установите на нуль для отключения."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = "Требовать зажатой клавиши Alt для перемещения курсора или переключения между предыдущими отправленными сообщениями."
+L["Right Only"] = "Только правый"
+L["Right Panel Height"] = "Высота правого чата"
+L["Right Panel Width"] = "Ширина правого чата"
+L["Scroll Interval"] = "Интервал прокрутки"
+L["Scroll Messages"] = "Прокручивание сообщений"
+L["Separate Panel Sizes"] = "Разные размеры панелей"
+L["Set the font outline."] = "Устанавливает границу шрифта."
+L["Short Channels"] = "Короткие каналы"
+L["Shorten the channel names in chat."] = "Сокращать названия каналов чата."
+L["Show Both"] = "Показать оба"
+L["Spam Interval"] = "Интервал спама"
+L["Sticky Chat"] = "Клейкий чат"
+L["Tab Font Outline"] = "Граница шрифта вкладок"
+L["Tab Font Size"] = "Размер шрифта вкладок"
+L["Tab Font"] = "Шрифт вкладок"
+L["Tab Panel Transparency"] = "Прозрачность панели вкладок"
+L["Tab Panel"] = "Панель вкладок"
+L["Timestamp Color"] = "Цвет времени"
+L["Toggle showing of the left and right chat panels."] = "Переключить отображение панелей чата."
+L["Toggle the chat tab panel backdrop."] = "Показать/скрыть фон панели под вкладками чата"
+L["URL Links"] = "Интернет-ссылки"
+L["Use Alt Key"] = "Использовать Alt"
+L["Use class color for the names of players when they are mentioned."] = "Окрашивать имена игроков цветом их класса."
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "При открытии строки ввода сообщения, если эта опция включена, будет выбран последний канал, в который Вы писали. В противном случае всегда будет установлен канал 'сказать'."
+L["Whisper Alert"] = "Звук шепота"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[Укажите имя файла в папке World of Warcraft, который Вы хотите использовать в качестве фона панелей.
+
+Пожалуйста, учтите:
+-Рекомендованный размер изображения 256x128
+-Вы должны полностью перезапустить игру после добавления нового файла в папку.
+-Тип файла должен быть tga.
+
+Пример: Interface\AddOns\ElvUI\media\textures\copy
+
+Для большинства пользователей будет легче просто положить tga файл в папку игры, а затем написать имя файла здесь.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "Написание кода:"
+L["Credits"] = "Благодарности"
+L["Donations:"] = "Финансовая поддержка:"
+L["ELVUI_CREDITS"] = "Я бы хотел выделить следующих людей, которые помогли мне в разработке аддона тестированием, кодингом и поддержкой при помощи донаций. Пожалуйста, отметьте, что в разделе донаций я написал имена людей, написавших мне в ЛС на форуме. Если Ваше имя пропущено, и Вы хотите его видеть, отправьте мне сообщение."
+L["Testing:"] = "Тестирование:"
+
+--DataBars
+L["Current - Percent (Remaining)"] = "Текущий - Процент (Осталось)"
+L["Current - Remaining"] = "Текущий - Осталось"
+L["DataBars"] = "Инфо-полосы"
+L["Hide In Combat"] = "Скрывать в бою"
+L["Setup on-screen display of information bars."] = "Контролирует отображение информационных полос."
+
+--DataTexts
+L["Battleground Texts"] = "Текст ПБ"
+L["Block Combat Click"] = "Блокировать нажатия в бою"
+L["Block Combat Hover"] = "Блокировать подсказки в бою"
+L["Blocks all click events while in combat."] = "Блокирует действия по клику в бою."
+L["Blocks datatext tooltip from showing in combat."] = "Скрывает подказки инфо-текстов в бою."
+L["BottomLeftMiniPanel"] = "Миникарта снизу слева (внутри)"
+L["BottomMiniPanel"] = "Миникарта снизу (внутри)"
+L["BottomRightMiniPanel"] = "Миникарта снизу справа (внутри)"
+L["Datatext Panel (Left)"] = "Панель информации (левая)"
+L["Datatext Panel (Right)"] = "Панель информации (правая)"
+L["DataTexts"] = "Инфо-тексты"
+L["Date Format"] = "Формат даты"
+L["Display data panels below the chat, used for datatexts."] = "Отображать панели под чатом, используется для инфо-текстов"
+L["Display minimap panels below the minimap, used for datatexts."] = "Отображать панели информационных текстов под миникартой."
+L["Gold Format"] = "Формат золота"
+L["left"] = "Слева"
+L["LeftChatDataPanel"] = "Левая панель чата"
+L["LeftMiniPanel"] = "Миникарта, слева"
+L["middle"] = "В центре"
+L["Minimap Panels"] = "Информация у миникарты"
+L["Panel Transparency"] = "Прозрачность панели"
+L["Panels"] = "Панели"
+L["right"] = "Справа"
+L["RightChatDataPanel"] = "Правая панель чата"
+L["RightMiniPanel"] = "Миникарта, справа"
+L["Small Panels"] = "Малые панели"
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = "Формат отображения золота на инфо-тексте золота и его подсказке."
+L["Time Format"] = "Формат времени"
+L["TopLeftMiniPanel"] = "Миникарта сверху слева (внутри)"
+L["TopMiniPanel"] = "Миникарта сверху (внутри)"
+L["TopRightMiniPanel"] = "Миникарта сверху справа (внутри)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "На полях боя отображать личную информацию на основных полосах инфо-текстов"
+L["Word Wrap"] = "Перенос слов"
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "Вы должны быть в группе в данным игроком, если он не с Вашего сервера."
+L["Sends your current profile to your target."] = "Отправить текущий профиль цели."
+L["Sends your filter settings to your target."] = "Отправить Ваши фильтры цели."
+L["Share Current Profile"] = "Передать текущий профиль"
+L["Share Filters"] = "Передать фильтры"
+L["This feature will allow you to transfer settings to other characters."] = "Эта функция позволит Вам передавать свои настройки другим персонажам."
+L["You must be targeting a player."] = "Целью должен быть игрок."
+
+--Filters
+L["Reset Aura Filters"] = "Сбросить фильтры аур" --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "Принимать приглашения"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "Изменяет позицию полосы угрозы"
+L["AFK Mode"] = "Режим АФК"
+L["Announce Interrupts"] = "Объявлять о прерываниях"
+L["Announce when you interrupt a spell to the specified chat channel."] = "Объявлять о прерванных Вами заклинаниях в указанный канал чата."
+L["Attempt to support eyefinity/nvidia surround."] = "Пытаться поддерживать eyefinity/nvidia surround"
+L["Auto Greed/DE"] = "Авто. не откажусь/распылить"
+L["Auto Repair"] = "Автоматический ремонт"
+L["Auto Scale"] = "Автоматический масштаб"
+L["Automatically accept invites from guild/friends."] = "Автоматически принимать приглашения в группу от друзей и гильдии."
+L["Automatically repair using the following method when visiting a merchant."] = "Автоматически чинить экипировку за счет выбранного источника при посещении торговца."
+L["Automatically scale the User Interface based on your screen resolution"] = "Автоматически масштабировать UI в зависимости от вашего разрешения"
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "Автоматически выбирать \"не откажусь\" или \"распылить\" (когда доступно) при розыгрыше предметов зеленого качества. Эта опция работает, только если вы максимального уровня."
+L["Automatically vendor gray items when visiting a vendor."] = "Автоматически продавать предметы серого качества при посещении торговца."
+L["Bottom Panel"] = "Нижняя панель"
+L["Chat Bubbles Style"] = "Стиль облачков сообщений"
+L["Chat Bubbles"] = "Облачка сообщений"
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = "направление заполнения полосы"
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "Отображать панель на нижней границе экрана. Это косметический элемент."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "Отображать панель на верхней границе экрана. Это косметический элемент."
+L["Display battleground messages in the middle of the screen."] = "Отображать сообщения полей боя в центре экрана."
+L["Enable/Disable the loot frame."] = "Включить/выключить окно добычи ElvUI."
+L["Enable/Disable the loot roll frame."] = "Включить/выключить фрейм распределения добычи ElvUI."
+L["Enables the ElvUI Raid Control panel."] = "Включает панель управления рейдом ElvUI."
+L["Enhanced PVP Messages"] = "Улущенные PvP сообщения"
+L["General"] = "Общие"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = "Высота списка заданий. Увеличение размера позволить видеть большее количество."
+L["Hide At Max Level"] = "Прятать на максимальном уровне"
+L["Hide Error Text"] = "Прятать сообщения об ошибках"
+L["Hide In Vehicle"] = "Прятать в транспорте"
+L["Hides the red error text at the top of the screen while in combat."] = "Скрывать красный текст ошибок вверху экрана в бою."
+L["Log Taints"] = "Отслеживать недочеты"
+L["Login Message"] = "Сообщение загрузки"
+L["Loot Roll"] = "Раздел добычи"
+L["Loot"] = "Добыча"
+L["Lowest Allowed UI Scale"] = "Наименьший возможный масштаб"
+L["Multi-Monitor Support"] = "Поддержка нескольких мониторов"
+L["Name Font"] = "Шрифт имени"
+L["Number Prefix"] = "Сокращения значений"
+L["Party / Raid"] = "Группа / Рейд"
+L["Party Only"] = "Только группа"
+L["Raid Only"] = "Только рейд"
+L["Remove Backdrop"] = "Скрыть фон"
+L["Reset all frames to their original positions."] = "Установить все фреймы на позиции по умолчанию"
+L["Reset Anchors"] = "Сбросить позиции"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "Отображать ошибки типа ADDON_ACTION_BLOCKED в фрейме ошибок lua. Эти ошибки в большинстве случаев не сильно важны и не влияют на производительность. Также многие из этих ошибок не могут быть исправлены. Пожалуйста, сообщайте об этих ошибках только если Вы заметите дефект в игре."
+L["Skin Backdrop (No Borders)"] = "Стилизовать фон (без границ)"
+L["Skin Backdrop"] = "Стилизовать фон"
+L["Skin the blizzard chat bubbles."] = "Стилизовать облачка сообщения Blizzard"
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Шрифт, которым будет написан текст над головами игроков. |cffFF0000ВНИМАНИЕ: Необходим перезапуск игры или релог для начала действия этой настройки.|r"
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = "Тонкие границы изменят общий вид интерфейса. Это небольшое улучшение производительности относительно традиционного вида."
+L["Thin Border Theme"] = "Тонкие границы"
+L["Toggle Tutorials"] = "Показать помощь"
+L["Top Panel"] = "Верхняя панель"
+L["Version Check"] = "Проверка версии"
+L["Watch Frame Height"] = "Высота списка заданий"
+L["When you go AFK display the AFK screen."] = "Отображать специальный экран, когда вы переходите в состояние \"Отсутствует\"."
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = "Применить этот шрифт ко всем элементам интерфейса. Некоторые шрифты будут пропущены из-за более мелкого размера по умолчанию."
+L["Applies the primary texture to all statusbars."] = "Применяет основную текстуу ко всем полосам состояния."
+L["Apply Font To All"] = "Применить ко всем шрифтам"
+L["Apply Texture To All"] = "Применить ко всем текстурам"
+L["Backdrop color of transparent frames"] = "Цвет фона прозрачных фреймов"
+L["Backdrop Color"] = "Цвет фона"
+L["Backdrop Faded Color"] = "Цвет прозрачного фона"
+L["Border Color"] = "Цвет окантовки"
+L["Color some texts use."] = "Цвет некоторых текстов."
+L["Colors"] = "Цвета" --Also in UnitFrames
+L["CombatText Font"] = "Шрифт текста боя"
+L["Default Font"] = "Шрифт по умолчанию"
+L["Font Size"] = "Размер шрифта" --Also in UnitFrames
+L["Fonts"] = "Шрифты"
+L["Main backdrop color of the UI."] = "Основной цвет фона интерфейса."
+L["Main border color of the UI."] = "Основной цвет окантовок."
+L["Media"] = "Медиа"
+L["Primary Texture"] = "Основная текстура"
+L["Replace Blizzard Fonts"] = "Заменять шрифты Blizzard"
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = "Заменяет шрифты, используемые Blizzard по умолчанию на различных панелях и фреймах, шрифтами, установленными в секции \"Медиа\" (этой секции). Любые дочерние шрифты к заменяемым, также будут изменены. Включено по умолчанию."
+L["Secondary Texture"] = "Вторичная текстура"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "Установите размер шрифта для всего интерфейса. Это не действует на элементы с собственными настройками шрифтов (например, рамки юнитов)."
+L["Textures"] = "Текстуры"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Шрифт текста боя. |cffFF0000ВНИМАНИЕ: это действие потребует перезапуска игры или повторного входа в мир.|r"
+L["The font that the core of the UI will use."] = "Шрифт для основного интерфейса."
+L["The texture that will be used mainly for statusbars."] = "Эта текстура будет использоваться в основном для полос состояния."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "Эта текстура будет использоваться для таких объектов как окно чата и выпадающие меню."
+L["Value Color"] = "Цвет значений"
+
+--Maps
+L["Adjust the size of the minimap."] = "Изменяет размер миникарты"
+L["Always Display"] = "Всегда отображать"
+L["Bottom Left"] = "Внизу слева"
+L["Bottom Right"] = "Внизу справа"
+L["Bottom"] = "Внизу"
+L["Change settings for the display of the location text that is on the minimap."] = "Изменяет опции отображения названия локации на миникарте"
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = "Включить/выключить миникарту. |cffFF0000АХТУНГ: отключение карты уберет и соответственные инфо-тексты.|r"
+L["Instance Difficulty"] = "Сложность подземелья"
+L["Left"] = "Левый"
+L["LFG Queue"] = "Очередь"
+L["Location Text"] = "Текст локации"
+L["Make the world map smaller."] = "Сделать карту мира меньше. Она больше не будет занимать весь экран в увеличенном варианте."
+L["Maps"] = "Карты"
+L["Minimap Buttons"] = "Кнопки миникарты"
+L["Minimap Mouseover"] = "При наведении мыши"
+L["Puts coordinates on the world map."] = "Добавляет координаты на карту мира."
+L["PvP Queue"] = "Очередь ПвП"
+L["Reset Zoom"] = "Сброс приближения"
+L["Right"] = "Правый"
+L["Scale"] = "Масштаб"
+L["Smaller World Map"] = "Маленькая карта мира"
+L["Top Left"] = "Вверху слева"
+L["Top Right"] = "Вверху справа"
+L["Top"] = "Вверху"
+L["World Map Coordinates"] = "Координаты карты мира"
+L["X-Offset"] = "Отступ по X"
+L["Y-Offset"] = "Отступ по Y"
+
+--Misc
+L["Install"] = "Установка"
+L["Run the installation process."] = "Запустить процесс установки"
+L["Toggle Anchors"] = "Показать фиксаторы"
+L["Unlock various elements of the UI to be repositioned."] = "Разблокировать элементы интерфейса для их перемещения."
+L["Version"] = "Версия"
+
+--NamePlates
+L["# Displayed Auras"] = "Кол-во аур"
+L["Actions"] = "Действия"
+L["Add Name"] = "Добавить имя"
+L["Add Nameplate Filter"] = "Добавить фильтр индикаторов"
+L["Add Regular Filter"] = "Добавить обычный фильтр"
+L["Add Special Filter"] = "Добавить специальный фильтр"
+L["Always Show Target Health"] = "Всегда показывать здоровье цели"
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = "Применять фильтр, если оставшееся время баффа больше указанного. Установите на 0 для отключения."
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = "Применять фильтр, если оставшееся время баффа меньше указанного. Установите на 0 для отключения."
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = "Применять фильтр, если оставшееся время дебаффа больше указанного. Установите на 0 для отключения."
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = "Применять фильтр, если оставшееся время дебаффа меньше указанного. Установите на 0 для отключения."
+L["Background Glow"] = "Фоновое свечение"
+L["Bad Color"] = "Плохой цвет"
+L["Bad Scale"] = "Плохой масштаб"
+L["Bad Transition Color"] = "Цвет плохого перехода"
+L["Base Height for the Aura Icon"] = "Базовая высота иконок аур"
+L["Border Glow"] = "Свечение границы"
+L["Border"] = "Граница"
+L["Cast Bar"] = "Полоса заклинаний"
+L["Cast Color"] = "Цвет полосы заклинаний"
+L["Cast No Interrupt Color"] = "Цвет непрерываемого"
+L["Cast Time Format"] = "Формат времени заклинания"
+L["Casting"] = "Заклинания"
+L["Channel Time Format"] = "Формат времени поддерживаемого"
+L["Clear Filter"] = "Очистить фильтр"
+L["Color Tanked"] = "Окрашивать танкуемых"
+L["Control enemy nameplates toggling on or off when in combat."] = "Контроллирует показ/скрытие вражеских индикаторов в бою."
+L["Control friendly nameplates toggling on or off when in combat."] = "Контроллирует показ/скрытие дружеских индикаторов в бою."
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = "Контроллирует кол-во отображаемых эффектов. Также влияет на размер иконок."
+L["Cooldowns"] = "Восстановление"
+L["Copy settings from another unit."] = "Скопировать настройки с другого юнита."
+L["Copy Settings From"] = "Скопировать из"
+L["Current Level"] = "Текущий уровень"
+L["Default Settings"] = "Умолчания"
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "Отображать иконки лекаря над известными целителями на полях боя и аренах"
+L["Elite Icon"] = "Иконки элиты"
+L["Enable/Disable the scaling of targetted nameplates."] = "Включить/выключить масштабирование индикатора цели."
+L["Enabling this will check your health amount."] = "Если включено, будет проверять значение вашего здоровья."
+L["Enemy Combat Toggle"] = "Переключение в бою (враги)"
+L["Enemy NPC Frames"] = "Враждебные НИП"
+L["Enemy Player Frames"] = "Враждебные игроки"
+L["Enemy"] = "Враг" --Also used in UnitFrames
+L["ENEMY_NPC"] = "Enemy NPC"
+L["ENEMY_PLAYER"] = "Enemy Player"
+L["Filter already exists!"] = "Фильтр уже существует!"
+L["Filter Priority"] = "Приоритет фильтров"
+L["Filters Page"] = "Фильтры"
+L["Friendly Combat Toggle"] = "Переключение в бою (друзья)"
+L["Friendly NPC Frames"] = "Дружественные НИП"
+L["Friendly Player Frames"] = "Дружественные игроки"
+L["FRIENDLY_NPC"] = "Дружественный НИП"
+L["FRIENDLY_PLAYER"] = "Дружественный игрок"
+L["General Options"] = "Общие"
+L["Good Color"] = "Хороший цвет"
+L["Good Scale"] = "Хороший масштаб"
+L["Good Transition Color"] = "Цвет хорошего перехода"
+L["Healer Icon"] = "Иконки лекарей"
+L["Health Color"] = "Цвет здоровья"
+L["Health Threshold"] = "Значение здоровья"
+L["Hide Frame"] = "Скрыть рамку"
+L["Hide Spell Name"] = "Скрыть название заклинания"
+L["Hide Time"] = "Скрыть время"
+L["Hide"] = "Скрыть" --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = "После прерывания или отмены, полоса заклинаний будет оставаться видимой указаное количество секунд."
+L["Icon Base Height"] = "Базовая высота иконки"
+L["Icon Position"] = "Позиция иконки"
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = "Если включено, то будет проверять отсутствие ауры вместо ее наличия."
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = "Если включено, то для активации фильтра потребуется наличие всех аур. В противном случае наличия любой из списка."
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = "Если включено, то для активации фильтра потребуется наличие всех кулдаунов. В противном случае наличия любой из списка."
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = "Если включено, то фильтр будет акитивирован, когда уровень юнита больше либо равен этому числу."
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = "Если включено, то фильтр будет акитивирован, когда уровень юнита меньше либо равен этому числу."
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = "Если включено, то фильтр будет акитивирован, когда уровень юнита равен этому числу."
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = "Если включено, то фильтр будет акитивирован, когда уровень юнита равен вашему."
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = "Если включено, то фильтр будет акитивирован, когда юнит произносит прерываемое заклинание."
+L["If enabled then the filter will only activate when you are in combat."] = "Если включено, фильтр будет активирован только когда вы в бою."
+L["If enabled then the filter will only activate when you are out of combat."] = "Если включено, фильтр будет активирован только когда вы вне боя."
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = "Если аура добавлена номером, то для удаления потребуется номер."
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = 'Если список пуст и "Прерываемые" включено, то фильтр будет активирован при произнесении люблго прерываемого заклинания.'
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = "Если используется, то уровень здоровья юнита должен быть выше указанного, чтобы фильтр активировался."
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = "Если используется, то уровень здоровья юнита должен быть ниже указанного, чтобы фильтр активировался."
+L["Instance Type"] = "Тип подземелья"
+L["Interruptible"] = "Прерываемые"
+L["Is Targeted"] = "Взят в цель"
+L["LEVEL_BOSS"] = "Установите на -1 для боссов или 0 для отключения."
+L["Low Health Threshold"] = "Пороговое значение здоровья"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = "Меньшее значение = большему приоритету. Фильтры обрабатываются в порядке от 1 к 100."
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = "Заставляет индикатор подсвечиваться желтым при установленном проценте здоровья. При достижении половины этого значения свечение станет красным."
+L["Match Player Level"] = "Соответсвие уровню игрока"
+L["Maximum Level"] = "Максимальный уровень"
+L["Maximum Time Left"] = "Максимум оставшегося времени"
+L["Minimum Level"] = "Минимальный уровень"
+L["Minimum Time Left"] = "Минимум оставшегося времени"
+L["Missing"] = "Отсутствует"
+L["Name Color"] = "Цвет имени"
+L["Name Only"] = "Только имя"
+L["NamePlates"] = "Индикаторы здоровья"
+L["Nameplate Motion Type"] = "Размещение индикаторов здоровья"
+L["Non-Target Transparency"] = "Прозрачность не цели"
+L["Not Targeted"] = "Не взят в цель"
+L["Off Cooldown"] = "не восстанавливается"
+L["On Cooldown"] = "Восстанавливается"
+L["Over Health Threshold"] = "Более значения здоровья"
+L["Overlapping Nameplates"] = "Наложение"
+L["Personal Auras"] = "Личные ауры"
+L["Player Health"] = "Здоровье игрока"
+L["Player in Combat"] = "Игрок в бою"
+L["Player Out of Combat"] = "Игрок вне боя"
+L["Reaction Colors"] = "Цвета отношений"
+L["Reaction Type"] = "Тип реакции"
+L["Remove a Name from the list."] = "Удалить имя из списка."
+L["Remove Name"] = "Удалить имя"
+L["Remove Nameplate Filter"] = "Удалить фильтр индикаторов"
+L["Require All"] = "Все"
+L["Reset filter priority to the default state."] = "Сбросить приоритеты фильтров на значение по умолчанию."
+L["Reset Priority"] = "Сбросить приоритеты"
+L["Return filter to its default state."] = "Вернуть фильтры к значениям по умолчанию."
+L["Scale of the nameplate that is targetted."] = "Масштаб индикатора цели."
+L["Select Nameplate Filter"] = "Выбрать фильтр индикаторов"
+L["Set Settings to Default"] = "Сбросить настройки на умолчания"
+L["Set the transparency level of nameplates that are not the target nameplate."] = "Устанавливает степень прозрачности для индикаторов юнитов, не являющихся вашей целью."
+L["Set to either stack nameplates vertically or allow them to overlap."] = "Выстраивать индикаторы в столбик или позволить им накладываться друг на друга."
+L["Shortcut to 'Filters' section of the config."] = "Ярлык для секицц фильтров в настройках."
+L["Shortcut to global filters."] = "Ярлык для глобальных фильтров"
+L["Shortcuts"] = "Ярлыки"
+L["Side Arrows"] = "Стрелки по сторонам"
+L["Stacking Nameplates"] = "Друг над другом"
+L["Style Filter"] = "Фильтры стиля"
+L["Tagged NPC"] = "Чужой НИП"
+L["Tanked Color"] = "Цвет танкуемого"
+L["Target Indicator Color"] = "Цвет индикатора цели"
+L["Target Indicator"] = "Индикатор цели"
+L["Target Scale"] = "Масштаб цели"
+L["Targeted Nameplate"] = "Индиатор цели"
+L["Texture"] = "Текстура"
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = "Эти фильтры не используют список заклинаний, в отличие от обычных фильтро. Вместо этого они используют WoW API и логические операции для определения отображения аур."
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = "Эти фильтры используют списки заклинаний для определения стоит ли блокироват ь ауру. Их можно изменить в разделе 'Фильтры' окна настроек."
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = "Это сбросит фильтр на умолчания. Любые заклинания, добавленные в этот фильтр, будут удалены."
+L["Threat"] = "Угроза"
+L["Time To Hold"] = "Время задержки"
+L["Toggle Off While In Combat"] = "Включать в бою"
+L["Toggle On While In Combat"] = "Отключить в бою"
+L["Top Arrow"] = "Стрелка сверху"
+L["Triggers"] = "Триггеры"
+L["Under Health Threshold"] = "Менее значения здоровья"
+L["Unit Type"] = "Тип юнита"
+L["Use Class Color"] = "Использовать цвет класса"
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = "Используйте перетаскивание для смены приоритета или ПКМ для удаления фильтра."
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = "Используйте Shift+ЛКМ для переключеня между дружественным, враждебным или нормальным ремимами. В нормалльном режиме фильтр будет проверять все юниты. В дружеском долько дружественные, во враждебном только враждебные."
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = "Использовать этот цвет для юнитов, которых держит другой танк."
+L["Use Target Glow"] = "Использовать выделение цели"
+L["Use Target Scale"] = "Масштабирование цели"
+L["Use Threat Color"] = "Использовать цвет угрозы"
+L["You can't remove a default name from the filter, disabling the name."] = "Вы не можете удалить имя по умолчанию из фильтра. Отключаю использование указанного имени."
+
+--Profiles Export/Import
+L["Choose Export Format"] = "Выберите формат экспорта"
+L["Choose What To Export"] = "Выберите что экспортировать"
+L["Decode Text"] = "Декодировать"
+L["Error decoding data. Import string may be corrupted!"] = "Ошибка при кодировании. Импортируемая строка может быть повреждена!"
+L["Error exporting profile!"] = "Ошибка при экспорте профиля!"
+L["Export Now"] = "Экспортировать"
+L["Export Profile"] = "Экспорт профиля"
+L["Exported"] = "Экспортировано"
+L["Filters (All)"] = "Фильтры (Все)"
+L["Filters (NamePlates)"] = "Фильтры (Индикаторы здоровья)"
+L["Filters (UnitFrames)"] = "Фильтры (Рамки юнитов)"
+L["Global (Account Settings)"] = "Глобальные (настройки аккаунта)"
+L["Import Now"] = "Импортировать"
+L["Import Profile"] = "Импорт профиля"
+L["Importing"] = "Импортирую"
+L["Plugin"] = "Плагин"
+L["Private (Character Settings)"] = "Private (Настройки персонажа)"
+L["Profile imported successfully!"] = "Профиль успешно импортирован!"
+L["Profile Name"] = "Имя профиля"
+L["Profile"] = "Профиль"
+L["Table"] = "Таблица"
+
+--Skins
+L["Achievement Frame"] = "Достижения"
+L["Alert Frames"] = "Предупреждения"
+L["Arena Frame"] = "Арена"
+L["Arena Registrar"] = "Регистрация арены"
+L["Auction Frame"] = "Аукцион"
+L["Barbershop Frame"] = "Парикмахерская"
+L["BG Map"] = "Карта ПБ"
+L["BG Score"] = "Таблица ПБ"
+L["Calendar Frame"] = "Календарь"
+L["Character Frame"] = "Окно персонажа"
+L["Debug Tools"] = "Инструменты отладки"
+L["Dressing Room"] = "Примерочная"
+L["GM Chat"] = "ГМ чат"
+L["Gossip Frame"] = "Диалоги"
+L["Greeting Frame"] = "Приветствия"
+L["Guild Bank"] = "Банк гильдии"
+L["Guild Registrar"] = "Регистратор гильдий"
+L["Help Frame"] = "Помощь"
+L["Inspect Frame"] = "Осмотр"
+L["KeyBinding Frame"] = "Назначение клавиш"
+L["LFD Frame"] = "Поиск подземелий"
+L["LFR Frame"] = "Список рейдов"
+L["Loot Frames"] = "Добыча"
+L["Macro Frame"] = "Макросы"
+L["Mail Frame"] = "Почта"
+L["Merchant Frame"] = "Торговец"
+L["Mirror Timers"] = "Таймеры"
+L["Misc Frames"] = "Прочие фреймы"
+L["Petition Frame"] = "Хартия гильдии"
+L["PvP Frames"] = "ПвП фреймы"
+L["Quest Frames"] = "Задания"
+L["Raid Frame"] = "Рейд"
+L["Skins"] = "Скины"
+L["Socket Frame"] = "Инкрустирование"
+L["Spellbook"] = "Книга заклинаний"
+L["Stable"] = "Стойла"
+L["Tabard Frame"] = "Создание накидки"
+L["Talent Frame"] = "Таланты"
+L["Taxi Frame"] = "Такси"
+L["Time Manager"] = "Секундомер"
+L["Trade Frame"] = "Обмен"
+L["TradeSkill Frame"] = "Профессия"
+L["Trainer Frame"] = "Тренер"
+L["Tutorial Frame"] = "Обучение"
+L["World Map"] = "Карта мира"
+
+--Tooltip
+L["Always Hide"] = "Всегда скрывать"
+L["Bags Only"] = "Только в сумках"
+L["Bags/Bank"] = "Сумки/Банк"
+L["Bank Only"] = "Только в банке"
+L["Both"] = "Оба"
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = "Выберите, когда Вы хотите видеть подсказку. Если выбран модификатор, то подсказка будет показана только, если он зажат."
+L["Comparison Font Size"] = "Размер шрифта сравнения"
+L["Cursor Anchor"] = "Около курсора"
+L["Custom Faction Colors"] = "Свои цвета отношения"
+L["Display guild ranks if a unit is guilded."] = "Отображать ранг в гильдии."
+L["Display how many of a certain item you have in your possession."] = "Отображать количество предметов в сумках"
+L["Display player titles."] = "Отображать звания"
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = "Показывать специализацию и уровень предметов в подсказке. Может обновиться не сразу после наведения курсора."
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "Отображать ID заклинания или предмета в подсказке при наведении мыши."
+L["Guild Ranks"] = "Ранги гильдии"
+L["Header Font Size"] = "Размер шрифта заголовка"
+L["Health Bar"] = "Полоса здоровья"
+L["Hide tooltip while in combat."] = "Скрывать подсказку в бою"
+L["Inspect Info"] = "Информация осмотра"
+L["Item Count"] = "Кол-во предметов"
+L["Never Hide"] = "Никогда не скрывать"
+L["Player Titles"] = "Звания игроков"
+L["Should tooltip be anchored to mouse cursor"] = "Привязывает подсказку к курсору мыши."
+L["Spell/Item IDs"] = "ID заклинаний/предметов"
+L["Target Info"] = "Информация о цели"
+L["Text Font Size"] = "Размер шрифта текста"
+L["This setting controls the size of text in item comparison tooltips."] = "Эта опция контролирует размер текста подсказок сравнения предметов."
+L["Tooltip Font Settings"] = "Шрифты подсказок"
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "В рейдовой группе отображать выбравших в цель юнит, для которого показана подсказка"
+
+--UnitFrames
+L["%s and then %s"] = "%s, а затем %s"
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "Сверху"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = "Добавить заклинание в фильтр. Используйте ID, если вы не хотите фильтровать все заклинания с одинаковым именем."
+L["Add a spell to the filter."] = "Добавить заклинание в фильтр"
+L["Add Spell ID or Name"] = "Добавить ID или имя заклинания"
+L["Add SpellID"] = "Добавить ID заклинания"
+L["Additional Filter Override"] = "Принудительный доп. фильтр."
+L["Additional Filter"] = "Дополнительный фильтр"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = "Пропускает не личные ауры из дополнительного фильтра, когда включено блокирование не персональных аур."
+L["Allow Whitelisted Auras"] = "Разрешиь ауры из белого списка"
+L["An X offset (in pixels) to be used when anchoring new frames."] = "Отступ по оси X (в пикселях) при фиксации новой рамки."
+L["An Y offset (in pixels) to be used when anchoring new frames."] = "Отступ по оси Y (в пикселях) при фиксации новой рамки."
+L["Animation Speed"] = "Скорость анимации"
+L["Ascending or Descending order."] = "Восходящий или нисходящий порядок."
+L["Assist Frames"] = "Помощники"
+L["Assist Target"] = "Цели помощников"
+L["At what point should the text be displayed. Set to -1 to disable."] = "При каком значении должен показываться текст. Установите -1 для отключения."
+L["Attach Text To"] = "Привязать текст к"
+L["Attach To"] = "Прикрепить к"
+L["Aura Bars"] = "Полосы аур"
+L["Auto-Hide"] = "Автоматически скрывать"
+L["Bad"] = "Плохое"
+L["Bars will transition smoothly."] = "Полосы будут изменяться плавно"
+L["Below"] = "Снизу"
+L["Blacklist Modifier"] = "Модификатор черного писка"
+L["Blacklist"] = "Черный список"
+L["Block Auras Without Duration"] = "Блокировать ауры без длительности"
+L["Block Blacklisted Auras"] = "Блокировать ауры из черного списка"
+L["Block Non-Dispellable Auras"] = "Блокировать не развеиваемые ауры"
+L["Block Non-Personal Auras"] = "Блокировать чужие ауры"
+L["Block Raid Buffs"] = "Блокировать рейдовые баффы"
+L["Blood"] = "Кровь"
+L["Borders"] = "Границы"
+L["Buff Indicator"] = "Индикатор баффов"
+L["Buffs"] = "Баффы"
+L["By Type"] = "По типу"
+L["Castbar"] = "Полоса заклинаний"
+L["Center"] = "Центр"
+L["Check if you are in range to cast spells on this specific unit."] = "Проверять находится ли конкретный юнит в радиюсе действия Ваших заклинаний."
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = "Выберите UIPARENT, чтобы не дать полосе скрываться вместе с рамкой."
+L["Class Backdrop"] = "Фон по классу"
+L["Class Castbars"] = "Полоса заклинаний по классу"
+L["Class Color Override"] = "Принудительный цвет класса"
+L["Class Health"] = "Здоровье по классу"
+L["Class Power"] = "Ресурс по классу"
+L["Class Resources"] = "Ресурсы класса"
+L["Click Through"] = "Клик насквозь"
+L["Color all buffs that reduce the unit's incoming damage."] = "Окрашивать все баффы, уменьшающие входящий урон по цели."
+L["Color aurabar debuffs by type."] = "Окрашивать полосы аур-дебаффов по типу"
+L["Color castbars by the class of player units."] = "Окрашивать полосу заклинаний по цвету класса игроков."
+L["Color castbars by the reaction type of non-player units."] = "Окрашивать полосу заклинаний по цвету реакции НИП."
+L["Color health by amount remaining."] = "Окрашивает полосу здоровья в зависимости от оставшегося его количества."
+L["Color health by classcolor or reaction."] = "Окрашивает полосу здоровья по цвету класса или отношению."
+L["Color power by classcolor or reaction."] = "Окрашивает полосу ресурсов по цвету класса или реакции."
+L["Color the health backdrop by class or reaction."] = "Окрасить фон полосы здоровья по цвету класса или реакции."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "Изменять цвет полосы здоровья, если на юните есть дебафф, который Вы можете снять."
+L["Color Turtle Buffs"] = "Окрашивать Turtle Buffs"
+L["Color"] = "Цвет"
+L["Colored Icon"] = "Окрашенная иконка"
+L["Coloring (Specific)"] = "Окрашивание конкретных"
+L["Coloring"] = "Окрашивание"
+L["Combat Fade"] = "Скрытие"
+L["Combat Icon"] = "Иконка боя"
+L["Combo Point"] = "Очко серии"
+L["Combobar"] = "Полоса серии"
+L["Configure Auras"] = "Настроить Ауры"
+L["Copy From"] = "Скопировать из"
+L["Count Font Size"] = "Размер шрифта стаков"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "Создать свою текстовую строку. После ввода имени вы сможете выбрать её в выпадающем списке"
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "Создает фильтр. После создания он может быть установлен в секции баффов/дебаффов любого юнита."
+L["Create Custom Text"] = "Создать свой текст"
+L["Create Filter"] = "Создать фильтр"
+L["Current - Max | Percent"] = "Текущее - Макс. | Процент"
+L["Current - Max"] = "Текущее - Максимальное"
+L["Current - Percent"] = "Текущее - Процент"
+L["Current / Max"] = "Текущее / Максимальное"
+L["Current"] = "Текущее"
+L["Custom Dead Backdrop"] = "Свой фон мертвого"
+L["Custom Health Backdrop"] = "Свой фон полосы здоровья"
+L["Custom Texts"] = "Свой текст"
+L["Death"] = "Смерть"
+L["Debuff Highlighting"] = "Подсветка дебаффов"
+L["Debuffs"] = "Дебаффы"
+L["Decimal Threshold"] = "Десятые доли после..."
+L["Deficit"] = "Дефицит"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "Удалить созданный фильтр. Вы не можете удалять фильтры по умолчанию, только созданные вручную."
+L["Delete Filter"] = "Удалить фильтр"
+L["Detach From Frame"] = "Открепить от рамки"
+L["Detached Width"] = "Ширина при откреплении"
+L["Direction the health bar moves when gaining/losing health."] = "Направление, в котором заполняется полоса при потере/восполнении здоровья."
+L["Disable Debuff Highlight"] = "Отключить подсветку дебаффов"
+L["Disabled Blizzard Frames"] = "Отключить фреймы Blizzard"
+L["Disabled"] = "Отключено"
+L["Disables the focus and target of focus unitframes."] = "Отключает фреймы фокуса и цели фокуса."
+L["Disables the player and pet unitframes."] = "Отклчает фреймы игрока и питомца."
+L["Disables the target and target of target unitframes."] = "Отключает фреймы цели и цели цели."
+L["Disconnected"] = "Не в сети"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "Отображать свечение на краю полосы заклинаний для более четкого отделения ее от фона."
+L["Display Frames"] = "Показать рамки"
+L["Display Player"] = "Показывать себя"
+L["Display Target"] = "Показывать цель"
+L["Display Text"] = "Показывать текст"
+L["Display the castbar icon inside the castbar."] = "Отображать иконку на полосе заклинаний."
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = "Отображать полосу заклинаний на информационной панели, иконка будет отображатсья рядом с рамкой."
+L["Display the combat icon on the unitframe."] = "Отображать иконку боя на рамке игрока."
+L["Display the rested icon on the unitframe."] = "Отображать иконку отдыха на рамке игрока"
+L["Display the target of your current cast. Useful for mouseover casts."] = "Отображать имя цели заклинания на полосе."
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "Отображать метки тиков на полосе заклинаний для поддерживаемых заклинаний. Они будут автоматически масштабироваться для заклинаний вроде Похищения души и добавлять новые тики, основываясь на показателе скорости."
+L["Don't display any auras found on the 'Blacklist' filter."] = "Не отображать ауры, обнаруженные в фильтре 'Blacklist'."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = "Не отображать ауры длительностью более этого значения (в секундах). Установите на 0 для отключения."
+L["Don't display auras that are not yours."] = "Не отображать ауры, наложенные не вами."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = "Не отображать ауры длительностью менее этого значения (в секундах). Установите на 0 для отключения."
+L["Don't display auras that cannot be purged or dispelled by your class."] = "Не отображать ауры, которые не могут быть развеяны вашим классом."
+L["Don't display auras that have no duration."] = "Не отображать ауры без длительности"
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = "Не отображать рейдовые баффы, такие как Каска или Лапа."
+L["Down"] = "Вниз"
+L["Dungeon & Raid Filter"] = "Фильтр подземелий и рейдов"
+L["Duration Reverse"] = "Длительность, обратное"
+L["Duration Text"] = "Текст длительности"
+L["Duration"] = "Длительность"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = "Включение опции позволит Вам проводить сортировку в пределах всего рейда, но взамен Вы не сможете понять кто в какой группе."
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = "Включение опции инвертирует порядок группировки в неполном рейде, она изменит направление роста и точку его начала."
+L["Enemy Aura Type"] = "Тип аур врага"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "Скрывать фрейм, когда Вы вне боя, не произносите заклинаний или отсутствует цель."
+L["Fill"] = "Заполнение"
+L["Filled"] = "По ширине рамки"
+L["Filter Type"] = "Тип фильтра"
+L["Fluid Position Buffs on Debuffs"] = "Переменная позиция баффов над дебаффами"
+L["Fluid Position Debuffs on Buffs"] = "Переменная позиция дебаффов над баффами"
+L["Force Off"] = "Постоянно выключен"
+L["Force On"] = "Постоянно включен"
+L["Force Reaction Color"] = "Принудительная реакция"
+L["Force the frames to show, they will act as if they are the player frame."] = "Принудительно показать рамки, они будут вести себя как рамка игрока."
+L["Forces Debuff Highlight to be disabled for these frames"] = "Принудительно не отображает подсветку дебаффов на этих рамках."
+L["Forces reaction color instead of class color on units controlled by players."] = "Принудительно окрашивает полосу здоровья по цвету реакции для рамок игроков."
+L["Format"] = "Формат"
+L["Frame Level"] = "Уровень рамки"
+L["Frame Orientation"] = "Направление рамки"
+L["Frame Strata"] = "Слой рамки"
+L["Frame"] = "Рамка"
+L["Frequent Updates"] = "Частое обновление"
+L["Friendly Aura Type"] = "Тип аур друга"
+L["Friendly"] = "Дружественный"
+L["Frost"] = "Лед"
+L["Glow"] = "Свечение"
+L["Good"] = "Хорошее"
+L["GPS Arrow"] = "Стрелка направления"
+L["Group By"] = "Группировать по"
+L["Grouping & Sorting"] = "Группировка и сортировка"
+L["Groups Per Row/Column"] = "Групп на ряд/столбец"
+L["Growth direction from the first unitframe."] = "Направление роста от первого фрейма."
+L["Growth Direction"] = "Направление роста"
+L["Heal Prediction"] = "Входящее исцеление"
+L["Health Backdrop"] = "Фон полосы здоровья"
+L["Health Border"] = "Граница здоровья"
+L["Health By Value"] = "Здоровье по значению"
+L["Health"] = "Здоровье"
+L["Height"] = "Высота"
+L["Horizontal Spacing"] = "Отступ по горизонтали"
+L["Horizontal"] = "Горизонтально" --Also used in bags module
+L["Icon Inside Castbar"] = "Иконка на полосе"
+L["Icon Size"] = "Размер иконки"
+L["Icon"] = "Иконка"
+L["Icon: BOTTOM"] = "Иконка: внизу"
+L["Icon: BOTTOMLEFT"] = "Иконка: внизу слева"
+L["Icon: BOTTOMRIGHT"] = "Иконка: внизу справа"
+L["Icon: LEFT"] = "Иконка: слева"
+L["Icon: RIGHT"] = "Иконка: справа"
+L["Icon: TOP"] = "Иконка: вверху"
+L["Icon: TOPLEFT"] = "Иконка: вверху слева"
+L["Icon: TOPRIGHT"] = "Иконка: вверху справа"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Если не используется никакой другой фильтр, то будут блокироваться ауры вне фильтра 'Whitelist'. В противном случае будет просто добавлять ауры в белый список в дополнение к другим опциям фильтрации."
+L["If not set to 0 then override the size of the aura icon to this."] = "Если установлено не на 0, то устанавливать размер иконок аур на заданное число."
+L["If the unit is an enemy to you."] = "Если юнит враждебен вам."
+L["If the unit is friendly to you."] = "Если юнит дружественен к вам."
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = "Если у вас активно много 3D портретов, то это может сказаться на производительности. Отключите их на каких-нибудь фреймах, если заметите проблемы."
+L["Ignore mouse events."] = "Игнорировать мышь"
+L["InfoPanel Border"] = "Граница инфо панели"
+L["Information Panel"] = "Информационная панель"
+L["Inset"] = "Внутри"
+L["Inside Information Panel"] = "На инфо панели"
+L["Interruptable"] = "Прерываемые"
+L["Invert Grouping Order"] = "Инвертировать порядок группировки"
+L["JustifyH"] = "Выравнивание"
+L["Latency"] = "Задержка"
+L["Left to Right"] = "Слева направо"
+L["Main statusbar texture."] = "Основная текстура полос состояния (здоровье, ресурс и тд)."
+L["Main Tanks / Main Assist"] = "Танки/помощники"
+L["Make textures transparent."] = "Сделать текстуры прозрачными"
+L["Match Frame Width"] = "По ширине рамки"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = "Максимальное значение переполнения, которое может отображаться за пределами полосы здровья."
+L["Max Bars"] = "Максимум полос"
+L["Max Overflow"] = "Макс. переполнение"
+L["Maximum Duration"] = "Максимальная длительность"
+L["Method to sort by."] = "Метод сортировки."
+L["Middle Click - Set Focus"] = "Средний клик - фокус"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "Нажатие средней кнопкой мыши на фрейм юнита запомнит его в фокус."
+L["Middle"] = "Центр"
+L["Minimum Duration"] = "Минимальная длительность"
+L["Mouseover"] = "При наведении"
+L["Name"] = "Имя" --Also used in Buffs and Debuffs
+L["Neutral"] = "Нейтральный"
+L["Non-Interruptable"] = "Непрерываемые"
+L["None"] = "Нет" --Also used in chat
+L["Not valid spell id"] = "Неверный ID заклинания"
+L["Num Rows"] = "Рядов"
+L["Number of Groups"] = "Количество групп"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "Смещение полосы ресурсов относительно полосы здоровья. Установите на 0 для отключения."
+L["Offset position for text."] = "Отступ для текста."
+L["Offset"] = "Смещение"
+L["Only Match SpellID"] = "Сопостовлять только ID заклинаний"
+L["Only show when the unit is not in range."] = "Отображать только когда юнит вне радиуса."
+L["Only show when you are mousing over a frame."] = "Отображать только при наведении курсора на фрейм."
+L["OOR Alpha"] = "Прозрачность вне радиуса"
+L["Other Filter"] = "Другой фильтр"
+L["Others"] = "Чужое"
+L["Overlay the healthbar"] = "Отображение портрета на полосе здоровья."
+L["Overlay"] = "Наложение"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "Игнорировать пользовательские настройки отображения в определенных ситуациях. Пример: показывать только группы 1 и 2 в подземелье на 10 человек."
+L["Override the default class color setting."] = "Перекрывает установки цвета класса по умолчанию."
+L["Owners Name"] = "Имя хозяина"
+L["Parent"] = "Родитель"
+L["Party Pets"] = "Питомцы группы"
+L["Party Targets"] = "Цели группы"
+L["Per Row"] = "Кол-во в ряду"
+L["Percent"] = "Процент"
+L["Personal"] = "Свое"
+L["Pet Name"] = "Имя питомца"
+L["Player Frame Aura Bars"] = "Полосы аур рамки игрока"
+L["Portrait"] = "Портрет"
+L["Position Buffs on Debuffs"] = "Баффы на месте дебаффов"
+L["Position Debuffs on Buffs"] = "Дебаффы на месте баффов"
+L["Position"] = "Позиция"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "Текст ресурса будет спрятан для НИП. Также текст имени будет смещен в точку расположения текста ресурса."
+L["Power"] = "Ресурс"
+L["Powers"] = "Ресурсы"
+L["Priority"] = "Приоритет"
+L["Profile Specific"] = "По профилю"
+L["PvP Icon"] = "Иконка PvP"
+L["PvP Text"] = "Текст PvP"
+L["PVP Trinket"] = "ПвП Аксессуар"
+L["Raid Icon"] = "Рейдовая иконка"
+L["Raid-Wide Sorting"] = "Общерейдовая сортировка"
+L["Raid40 Frames"] = "Рейд 40"
+L["RaidDebuff Indicator"] = "Индикатор рейдовых дебаффов"
+L["Range Check"] = "Проверка дистанции"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "Более частое обновление состояния здоровья, использует больше памяти и ресурсов процессора. Рекомендуется только для целителей."
+L["Reaction Castbars"] = "Полоса заклинаний по реакции"
+L["Reactions"] = "Отношение"
+L["Ready Check Icon"] = "Иконка готовности"
+L["Remaining"] = "Оставшееся"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = "Удалить заклинание из фильтра. Используйте ID, если в фильтре имя удаляемого заклинания содержит ID."
+L["Remove a spell from the filter."] = "Удалить заклинание из фильтра."
+L["Remove Spell ID or Name"] = "Удалить ID или имя заклинания"
+L["Remove SpellID"] = "Удалить ID заклинания"
+L["Rest Icon"] = "Иконка отдыха"
+L["Restore Defaults"] = "Восстановить умолчания" --Also used in Media and ActionBars sections
+L["Right to Left"] = "Справа налево"
+L["RL / ML Icons"] = "Иконки лидера/ответственного"
+L["Role Icon"] = "Иконка роли"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = "Полоса начнет убывать, когда оставшееся время ауры упадет ниже этого значения в секундах. Установите на 0 для отключения."
+L["Select a unit to copy settings from."] = "Выберите юнит, установки которого Вы хотите скопировать."
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Выберите дополнительный фильтр для использования. Если выбраный фильтр имеет тип 'белый список' и не используется никакой другой фильтр (за исключением блокиования чужих аур), то будут блокироваться ауры вне белого списка. В противном случае будет просто добавлять ауры в белый список в дополнение к другим опциям фильтрации."
+L["Select Filter"] = "Выбрать фильтр"
+L["Select Spell"] = "Выбрать заклинание"
+L["Select the display method of the portrait."] = "Выбирите метод отображения портрета"
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = "Выберите тип фильтра. Черный список будет скрывать содержащиеся заклинания и отображать остальные. Белый список будет показывать включенные заклинания и скрывать все остальные."
+L["Set the font size for unitframes."] = "Устанавливает шрифт для рамок юнитов."
+L["Set the order that the group will sort."] = "Устанавливает метод сортировки в группе."
+L["Set the orientation of the UnitFrame."] = "Устанавливает ориентацию рамки."
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "Устанавливает порядок заклинания. Заметьте, что приоритеты используются только для модуля рейдовых дебаффов, а не для стандартных баффов/дебаффов. Для отключения приоритетности установите на 0."
+L["Set the type of auras to show when a unit is a foe."] = "Устанавливает тип аур для отображения, когда юнит враг."
+L["Set the type of auras to show when a unit is friendly."] = "Устанавливает тип аур для отображения, когда юнит друг."
+L["Sets the font instance's horizontal text alignment style."] = "Устанавливает выравнивание текста по горизонтали"
+L["Show"] = "Показать"
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "Отображать объем входящего исцеления на рамках. Также отображает немного иначе окрашенную полосу для избыточного исцеления."
+L["Show Aura From Other Players"] = "Отображать чужие"
+L["Show Auras"] = "Показать ауры"
+L["Show Dispellable Debuffs"] = "Показывать развеиваемые дебаффы"
+L["Show When Not Active"] = "Показывать при отсутствии"
+L["Size and Positions"] = "Размер и позиция"
+L["Size of the indicator icon."] = "Размер иконки индикатора"
+L["Size Override"] = "Свой размер"
+L["Size"] = "Размер"
+L["Smart Aura Position"] = "Умная позиция аур"
+L["Smart Raid Filter"] = "Умный фильтр рейда"
+L["Smooth Bars"] = "Плавные полосы"
+L["Sort By"] = "Сортировать по"
+L["Spaced"] = "Раздельно"
+L["Spacing"] = "Отступ"
+L["Spark"] = "Искра"
+L["Speed in seconds"] = "Скорость в секундах"
+L["Stack Counter"] = "Количество стаков"
+L["Stack Threshold"] = "Стаки"
+L["Start Near Center"] = "Начинать от центра"
+L["Statusbar Fill Orientation"] = "Направление заполнения полосы"
+L["StatusBar Texture"] = "Текстура полос состояния"
+L["Strata and Level"] = "Слой и уровень"
+L["Style"] = "Стиль"
+L["Tank Frames"] = "Танки"
+L["Tank Target"] = "Цели танков"
+L["Tapped"] = "Чужой"
+L["Target Glow"] = "Подсветка цели"
+L["Target On Mouse-Down"] = "Выделение при нажати"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "Выделять при нажатии кнопки мыши, а не при ее отпускании.\n\n|cffFF0000Внимание: Если Вы используете аддон 'Clique', то Вы также должны изменить его настройки при изменении этой."
+L["Text Color"] = "Цвет текста"
+L["Text Format"] = "Формат текста"
+L["Text Position"] = "Позиция текста"
+L["Text Threshold"] = "Значение текста"
+L["Text Toggle On NPC"] = "Переключение текста для НИП"
+L["Text xOffset"] = "Отсуп текста по Х"
+L["Text yOffset"] = "Отсуп текста по Y"
+L["Text"] = "Текст"
+L["Textured Icon"] = "Иконка с текстурой"
+L["The alpha to set units that are out of range to."] = "Прозрачность рамок юнитов, находящихся вне дальности действия заклинаний."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = "Для показа этого дебаффа, он должен надрать указанное количество стаков. Пи установке на 0, показывается всегда."
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "Следующий фильтр должен быть верен для отображения группы в дополнение к любому другому уже установленному фильтру."
+L["The font that the unitframes will use."] = "Шрифт рамок юнитов"
+L["The initial group will start near the center and grow out."] = "Первая группа появится в центре и будет расти наружу."
+L["The name you have selected is already in use by another element."] = "Выбранное вами имя уже используется другим элементом"
+L["The object you want to attach to."] = "Объект, к которому Вы хотите прикрепить полосы"
+L["Thin Borders"] = "Тонкие границы"
+L["This dictates the size of the icon when it is not attached to the castbar."] = "Определяет размер иконки, когда она не привязана к инфо панели."
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = "Открывает опции окрашивания рамок юнитов. Эти настройки влияют на все рамки."
+L["Threat Display Mode"] = "Режим отображения угрозы"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = "Граница, после которых текст будет показывать десятые доли. Установите на -1 для отключения."
+L["Ticks"] = "Тики"
+L["Time Remaining Reverse"] = "Оставшееся время, обратное"
+L["Time Remaining"] = "Оставшееся время"
+L["Transparent"] = "Прозрачный"
+L["Turtle Color"] = "Цвет Turtle Buffs"
+L["Unholy"] = "Нечистивость"
+L["Uniform Threshold"] = "Граница убывания"
+L["UnitFrames"] = "Рамки юнитов"
+L["Up"] = "Вверх"
+L["Use Custom Level"] = "Свой уровень"
+L["Use Custom Strata"] = "Свой слой"
+L["Use Dead Backdrop"] = "Фон мертвого"
+L["Use Default"] = "Использовать умолчания"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "Использовать свой фоновый цвет вместо основного цвета полосы здоровья."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = "Использовать фильтр \"Buff Indicator (Profile)\", привязанный к профилю вместо глобального."
+L["Use thin borders on certain unitframe elements."] = "Использовать тонкие границы на некоторых элементах рамок юнитов."
+L["Use this backdrop color for units that are dead or ghosts."] = "Использовать этот цвет фона для юнитов, которые мертвы или бегут с кладбища."
+L["Value must be a number"] = "Значение должно быть числом"
+L["Vertical Orientation"] = "Заполнение по вертикали"
+L["Vertical Spacing"] = "Отступ по вертикали"
+L["Vertical"] = "Вертикально" --Also used in bags section
+L["Visibility"] = "Видимость"
+L["What point to anchor to the frame you set to attach to."] = "К какой точке выбранного фиксатора прикрепить ауры."
+L["What to attach the buff anchor frame to."] = "К чему прикреплять баффы."
+L["What to attach the debuff anchor frame to."] = "К чему прикреплять дебаффы."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = "Если включено, то будет отображать только заклинания, добавленные в фильтр по ID."
+L["When true, the header includes the player when not in a raid."] = "Отображать игрока в группе."
+L["Whitelist"] = "Белый список"
+L["Width"] = "Ширина" --Also used in NamePlates module
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = "При отсутствии дебаффов, будет показывать баффы на их месте или наоборот."
+L["xOffset"] = "Отступ по Х"
+L["yOffset"] = "Отступ по Y"
+L["You can't remove a pre-existing filter."] = "Вы не можете удалить фильтр по умолчанию."
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "Вы не можете удалить заклинание из фильтра по умолчанию, которое не было добавлено в него вручную. Отключаю использование в фильтре этого заклинания."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = "Вам нужно будет удерживать этот модификатор для занесения ауры в черный список при нажатии ПКМ. Установите на \"Нет\" для отключения возможности заносить их туда."
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Spanish_Config.lua b/ElvUI_Config/Locales/Spanish_Config.lua
new file mode 100644
index 0000000..9ff819a
--- /dev/null
+++ b/ElvUI_Config/Locales/Spanish_Config.lua
@@ -0,0 +1,1130 @@
+-- Spanish localization file for esES and esMX.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "esES") or AceLocale:NewLocale("ElvUI", "esMX")
+if not L then return end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "Configura los iconos de las auras que aparecen cerca del minimapa."
+L["BAGS_DESC"] = "Ajusta las opciones de las bolsas para ElvUI."
+L["CHAT_DESC"] = "Configura los ajustes del chat para ElvUI."
+L["DATATEXT_DESC"] = "Configura el despliegue en pantalla de los textos de datos."
+L["ELVUI_DESC"] = "ElvUI es un addon que reemplaza la interfaz completa de World of Warcraft."
+L["NAMEPLATE_DESC"] = "Modifica las opciones de la placa de nombre"
+L["PANEL_DESC"] = "Ajusta el tamaño de los paneles izquierdo y derecho. Esto afectará las ventanas de chat y las bolsas."
+L["SKINS_DESC"] = "Configura los Ajustes de Cubiertas."
+L["TOGGLESKIN_DESC"] = "Activa/Desactiva esta cubierta."
+L["TOOLTIP_DESC"] = "Configuración para las Descripciones Emergentes."
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[With the new addition of LibItemSearch, you now have access to much more advanced item searches. The following is a documentation of the search syntax. See the full explanation at: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+Specific Searching:
+ • q:[quality] or quality:[quality]. For instance, q:epic will find all epic items.
+ • l:[level], lvl:[level] or level:[level]. For example, l:30 will find all items with level 30.
+ • t:[search], type:[search] or slot:[search]. For instance, t:weapon will find all weapons.
+ • n:[name] or name:[name]. For instance, typing n:muffins will find all items with names containing "muffins".
+ • s:[set] or set:[set]. For example, s:fire will find all items in equipment sets you have with names that start with fire.
+ • tt:[search], tip:[search] or tooltip:[search]. For instance, tt:binds will find all items that can be bound to account, on equip, or on pickup.
+
+
+Search Operators:
+ • ! : Negates a search. For example, !q:epic will find all items that are NOT epic.
+ • | : Joins two searches. Typing q:epic | t:weapon will find all items that are either epic OR weapons.
+ • & : Intersects two searches. For instance, q:epic & t:weapon will find all items that are epic AND weapons
+ • >, <, <=, => : Performs comparisons on numerical searches. For example, typing lvl: >30 will find all items with level HIGHER than 30.
+
+
+The following search keywords can also be used:
+ • soulbound, bound, bop : Bind on pickup items.
+ • bou : Bind on use items.
+ • boe : Bind on equip items.
+ • boa : Bind on account items.
+ • quest : Quest bound items.]];
+L["TEXT_FORMAT_DESC"] = [[Proporciona una cadena para cambiar el formato de texto.
+
+Ejemplos:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+Formatos de Salud / Poder:
+"current" - cantidad actual
+"percent" - cantidad porcentual
+"current-max" - cantidad actual seguido de cantidad máxima, sólo se mostrará la máxima si la actual es igual a la máxima
+"current-percent" - cantidad actual seguido de porcentaje
+"current-max-percent" - cantidad actual, cantidad máxima y porcentaje, sólo se mostrará la máxima si la actual es igual a la máxima
+"deficit" - muestra el valor de déficit, no muestra nada si no hay déficit
+
+Formatos de Nombre:
+"name:short" - Nombre restringido a 10 caracteres
+"name:medium" - Nombre restringido a 15 caracteres
+"name:long" - Nombre restringido a 20 caracteres
+
+Para desactivarlo dejar el campo en blanco, si necesitas más información visita http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "Paginación"
+L["ActionBars"] = "Barras de Acción"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = true;
+L["Alpha"] = "Transparencia"
+L["Anchor Point"] = "Punto de Fijación"
+L["Backdrop Spacing"] = true;
+L["Backdrop"] = "Fondo"
+L["Button Size"] = "Tamaño del Botón"
+L["Button Spacing"] = "Separación de Botones"
+L["Buttons Per Row"] = "Botones por Fila"
+L["Buttons"] = "Botones"
+L["Change the alpha level of the frame."] = "Cambia el nivel de transparencia del marco"
+L["Color of the actionbutton when not usable."] = true;
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "Color del botón cuando no tengas poder (Mana, Ira)"
+L["Color of the actionbutton when out of range."] = "Color del botón cuando el objetivo esté fuera de rango"
+L["Color of the actionbutton when usable."] = true;
+L["Color when the text is about to expire"] = "Color del texto cuando esté a punto de expirar."
+L["Color when the text is in the days format."] = "Color del texto cuando tenga formato de días."
+L["Color when the text is in the hours format."] = "Color del texto cuando tenga formato de horas."
+L["Color when the text is in the minutes format."] = "Color del texto cuando tenga formato de minutos."
+L["Color when the text is in the seconds format."] = "Color del texto cuando tenga formato de segundos."
+L["Cooldown Text"] = "Texto de Reutilización"
+L["Darken Inactive"] = true;
+L["Days"] = "Días"
+L["Display bind names on action buttons."] = "Muestra las teclas asignadas en los botones."
+L["Display cooldown text on anything with the cooldown spiral."] = "Muestra el texto de reutilización sobre todo lo que tenga la espiral de reutilización."
+L["Display macro names on action buttons."] = "Muestra el nombre de las macros en los botones."
+L["Expiring"] = "Expiración"
+L["Global Fade Transparency"] = true;
+L["Height Multiplier"] = "Multiplicador de Altura"
+L["Hours"] = "Horas"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = true;
+L["Inherit Global Fade"] = true;
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = true;
+L["Key Down"] = "Tecla Pulsada"
+L["Keybind Mode"] = "Asignar Teclas"
+L["Keybind Text"] = "Mostrar Atajos"
+L["LBF Support"] = true;
+L["Low Threshold"] = "Umbral Bajo"
+L["Macro Text"] = "Texto de Macro"
+L["Minutes"] = "Minutos"
+L["Mouse Over"] = "Pasar el ratón sobre"
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "Multiplica el ancho o alto de los fondos por este valor. Es útil si deseas tener más de una barra con fondo."
+L["Not Usable"] = true;
+L["Out of Power"] = "Sin Poder"
+L["Out of Range"] = "Fuera de Rango"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "Restaurar Barra"
+L["Restore the actionbars default settings"] = "Restaura las barras de acción a los ajustes predeterminados."
+L["Seconds"] = "Segundos"
+L["Show Empty Buttons"] = true;
+L["The amount of buttons to display per row."] = "Número de botones a mostrar por fila"
+L["The amount of buttons to display."] = "Número de botones a mostrar"
+L["The button you must hold down in order to drag an ability to another action button."] = "Tecla que debes mantener presionado para mover una habilidad a otro botón de acción."
+L["The first button anchors itself to this point on the bar."] = "El primer botón se fija a este punto de la barra."
+L["The size of the action buttons."] = "El tamaño de los botones de acción."
+L["The spacing between the backdrop and the buttons."] = true;
+L["This setting will be updated upon changing stances."] = true;
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "Umbral para que el texto se ponga rojo y esté en forma decimal. Establécelo en -1 para que nunca se ponga rojo"
+L["Toggles the display of the actionbars backdrop."] = "Muestra/Oculta el fondo de las barras de acción."
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = true;
+L["Usable"] = true;
+L["Visibility State"] = "Estado de Visibilidad"
+L["Width Multiplier"] = "Multiplicador de Anchura"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[Esto funciona como una macro. Puedes ejecutar diferentes situaciones para paginar la barra de acción de forma diferente.
+ Ejemplo: [combat] 2;]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[Esto funciona como una macro. Puede ejecutar diferentes situaciones para mostrar u ocultar la barra de acción de forma diferente.
+ Ejemplo: [combat] show;hide]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = true;
+L["Add Item or Search Syntax"] = true;
+L["Adjust the width of the bag frame."] = "Ajustar el ancho del marco de las bolsas."
+L["Adjust the width of the bank frame."] = "Ajustar el ancho del marco del banco."
+L["Ascending"] = "Ascendente"
+L["Bag Sorting"] = true;
+L["Bag-Bar"] = "Barra de las Bolsas"
+L["Bar Direction"] = "Dirección de la Barra"
+L["Blizzard Style"] = true;
+L["Bottom to Top"] = "De Abajo hacia Arriba"
+L["Button Size (Bag)"] = "Tamaño de los Botones (Bolsas)"
+L["Button Size (Bank)"] = "Tamaño de los Botones (Banco)"
+L["Clear Search On Close"] = true;
+L["Condensed"] = true;
+L["Descending"] = "Descendente"
+L["Direction the bag sorting will use to allocate the items."] = "Dirección de ordenado que se usará para distribuir los objetos."
+L["Disable Bag Sort"] = true;
+L["Disable Bank Sort"] = true;
+L["Display Item Level"] = true;
+L["Displays item level on equippable items."] = true;
+L["Enable/Disable the all-in-one bag."] = "Habilitar/Deshabilitar la bolsa todo en uno."
+L["Enable/Disable the Bag-Bar."] = "Activa/Desactiva la barra de las bolsas."
+L["Full"] = true;
+L["Global"] = true;
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = true;
+L["Ignored Items and Search Syntax (Global)"] = true;
+L["Ignored Items and Search Syntax (Profile)"] = true;
+L["Item Count Font"] = true;
+L["Item Level Threshold"] = true;
+L["Item Level"] = true;
+L["Money Format"] = true;
+L["Panel Width (Bags)"] = "Ancho del Panel (Bolsas)"
+L["Panel Width (Bank)"] = "Ancho del Panel (Banco)"
+L["Search Syntax"] = true;
+L["Set the size of your bag buttons."] = "Establece el tamaño de tus botones de la bolsa."
+L["Short (Whole Numbers)"] = true;
+L["Short"] = true;
+L["Smart"] = true;
+L["Sort Direction"] = "Dirección de Ordenado"
+L["Sort Inverted"] = "Ordenado Invertido"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "La dirección que los marcos de bolsas tienen (Horizontal o Vertical)."
+L["The direction that the bag frames will grow from the anchor."] = "La dirección que los marcos de bolsas crecerán desde el punto de fijación."
+L["The display format of the money text that is shown at the top of the main bag."] = true;
+L["The frame is not shown unless you mouse over the frame."] = "El marco no se muestra a menos que pases el ratón sobre él."
+L["The minimum item level required for it to be shown."] = true;
+L["The size of the individual buttons on the bag frame."] = "El tamaño de los botones individuales en el marco de las bolsas"
+L["The size of the individual buttons on the bank frame."] = "El tamaño de los botones individuales en el marco del banco"
+L["The spacing between buttons."] = "Separación entre los botones."
+L["Top to Bottom"] = "De Arriba hacia Abajo"
+L["Use coin icons instead of colored text."] = true;
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "Buffs y Debuffs";
+L["Begin a new row or column after this many auras."] = "Empieza una nueva fila o columna después de estas auras."
+L["Count xOffset"] = true;
+L["Count yOffset"] = true;
+L["Defines how the group is sorted."] = "Define como se ordena el grupo."
+L["Defines the sort order of the selected sort method."] = "Define el orden para el método de organización seleccionado."
+L["Disabled Blizzard"] = true;
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "Umbral de Transparencia"
+L["Index"] = "Índice"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "Indica si los beneficios lanzados por ti deberían estar separados antes o después."
+L["Limit the number of rows or columns."] = "Limita el número de filas o de columnas."
+L["Max Wraps"] = "Filas/Columnas Máximas"
+L["No Sorting"] = "No Ordenar"
+L["Other's First"] = "Los de Otros Primero"
+L["Remaining Time"] = "Tiempo Restante"
+L["Reminder"] = true
+L["Reverse Style"] = true;
+L["Seperate"] = "Separar"
+L["Set the size of the individual auras."] = "Establece el tamaño de las auras individuales."
+L["Sort Method"] = "Método de Organización"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = true;
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "Umbral antes de que el texto cambie a rojo, entre en forma decimal, y el icono se desvanezca. Establecer a -1 para desactivar."
+L["Time xOffset"] = true;
+L["Time yOffset"] = true;
+L["Time"] = "Tiempo"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = true;
+L["Wrap After"] = "Auras por Fila/Columna"
+L["Your Auras First"] = "Tus Auras Primero"
+
+--Chat
+L["Above Chat"] = "Arriba del Chat"
+L["Adjust the height of your right chat panel."] = true;
+L["Adjust the width of your right chat panel."] = true;
+L["Alerts"] = true;
+L["Allowed Combat Repeat"] = true;
+L["Attempt to create URL links inside the chat."] = "Trata de crear enlaces URL dentro del chat."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "Intenta bloquear las posiciones de los marcos de chat. Si lo deseas, puedes desactivar esta opción para tener completa mobilidad de la ventana de chat. Esto te dará la oportunidad de ubicarla donde desées."
+L["Below Chat"] = "Debajo del Chat"
+L["Chat EditBox Position"] = "Posición del Cuadro de Edición del Chat"
+L["Chat History"] = "Historial de Chat"
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = true;
+L["Custom Timestamp Color"] = true;
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "Muestra la descripción emergente del enlace cuando pasas el cursor sobre él."
+L["Enable the use of separate size options for the right chat panel."] = true;
+L["Exclude Name"] = true;
+L["Excluded names will not be class colored."] = true;
+L["Excluded Names"] = true;
+L["Fade Chat"] = "Desvanecer Chat"
+L["Fade Tabs No Backdrop"] = true;
+L["Fade the chat text when there is no activity."] = "Desvanecer el texto del chat cuando no hay actividad"
+L["Fade Undocked Tabs"] = true;
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = true;
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = true;
+L["Font Outline"] = "Contorno de Fuente"
+L["Font"] = "Fuente"
+L["Hide Both"] = "Ocultar Ambos"
+L["Hyperlink Hover"] = "Cursor Sobre Hipervínculo"
+L["Keyword Alert"] = "Alerta por Palabra Clave"
+L["Keywords"] = "Palabras Claves"
+L["Left Only"] = "Sólo el Izquierdo"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "Lista de palabras a colorear si son encontradas en un mensaje del chat. Si quieres agregar varias palabras debes separarlas con comas. Para buscar tu nombre actual puedes usar %MYNAME%.\n\nEjemplo:\n%MYNAME%, ElvUI, Tanque"
+L["Lock Positions"] = "Bloquear Posiciones"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "Guardar el historial de los marcos de chat principales. Así cuando recargues la interfaz o reconectes verás el historial de chat de tu última sesión."
+L["No Alert In Combat"] = true;
+L["Number of messages you scroll for each step."] = true;
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = true;
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "Tiempo en segundos para desplazarse al final de la ventana de chat si no se ha desplazado completamente hasta el final."
+L["Panel Backdrop"] = "Fondo del Panel"
+L["Panel Height"] = "Altura del Panel"
+L["Panel Texture (Left)"] = "Textura del Panel Izquierdo"
+L["Panel Texture (Right)"] = "Textura del Panel Derecho"
+L["Panel Width"] = "Anchura del Panel"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "Posición del Cuadro de Edición del Chat. Si los textos de datos se deshabilitan éste se colocará arriba del chat."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "Previene que los mismos mensajes se muestren más de una vez en el chat dentro de un cierto número de segundos. Establécelo a cero para desactivar."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = true;
+L["Right Only"] = "Sólo el Derecho"
+L["Right Panel Height"] = true;
+L["Right Panel Width"] = true;
+L["Scroll Interval"] = "Intervalo de Desplazamiento"
+L["Scroll Messages"] = true;
+L["Separate Panel Sizes"] = true;
+L["Set the font outline."] = "Establece el contorno de fuente."
+L["Short Channels"] = "Recortar Canales"
+L["Shorten the channel names in chat."] = "Recorta los nombre de canal en el chat."
+L["Show Both"] = "Mostrar Ambos"
+L["Spam Interval"] = "Intervalo de Spam"
+L["Sticky Chat"] = "Chat Pegajoso"
+L["Tab Font Outline"] = "Contorno de Fuente de la Pestaña"
+L["Tab Font Size"] = "Tamaño de Fuente de la Pestaña"
+L["Tab Font"] = "Fuente de la Pestaña"
+L["Tab Panel Transparency"] = "Transparencia del Panel de Pestañas"
+L["Tab Panel"] = "Panel de Pestañas"
+L["Timestamp Color"] = true;
+L["Toggle showing of the left and right chat panels."] = "Muestra/Oculta los paneles de chat izquierdo y derecho."
+L["Toggle the chat tab panel backdrop."] = "Muestra/oculta el fondo del panel de pestañas"
+L["URL Links"] = "Enlaces URL"
+L["Use Alt Key"] = true;
+L["Use class color for the names of players when they are mentioned."] = true;
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "Cuando abres el Cuadro de Edición del chat para escribir un mensaje teniendo esta opción activa significa que recordará el último canal en el que habló. Si esta opción esta desactivada siempre hablarás por defecto en el canal DECIR."
+L["Whisper Alert"] = "Alerta de Susurro"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[Especifica un archivo ubicado en el directorio texture de World of Warcraft que deseas tener establecido como fondo de panel.
+
+Nota:
+-El tamaño de imagen recomendada es 256x128
+-Debes reiniciar el juego completamente después de agregar un archivo a la carpeta.
+-El archivo debe ser formato tga.
+
+Ejemplo: Interface\AddOns\ElvUI\media\textures\copy
+
+O también puedes simplemente colocar un archivo tga en la carpeta de WoW, y escribir aquí el nombre del archivo.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "Codificación:"
+L["Credits"] = "Créditos"
+L["Donations:"] = "Donativos:"
+L["ELVUI_CREDITS"] = "Quiero dar un agradecimiento especial a las siguientes personas por ayudar a probar y codificar este addon y también a quienes me ayudaron con donativos. Nota: Para los donativos sólo muestro los nombres de quienes me enviaron un mensaje en el foro. Si tu nombre no aparece y quieres que lo agregue mándame un mensaje."
+L["Testing:"] = "Pruebas:"
+
+--DataBars
+L["Current - Percent (Remaining)"] = true;
+L["Current - Remaining"] = true;
+L["DataBars"] = true;
+L["Hide In Combat"] = true;
+L["Setup on-screen display of information bars."] = true;
+
+--DataTexts
+L["Battleground Texts"] = "Textos de los Campos de Batalla"
+L["Block Combat Click"] = true;
+L["Block Combat Hover"] = true;
+L["Blocks all click events while in combat."] = true;
+L["Blocks datatext tooltip from showing in combat."] = true;
+L["BottomLeftMiniPanel"] = "Minimap BottomLeft (Inside)"
+L["BottomMiniPanel"] = "Minimap Bottom (Inside)"
+L["BottomRightMiniPanel"] = "Minimap BottomRight (Inside)"
+L["Datatext Panel (Left)"] = "Panel Izquierdo de los Datos de texto"
+L["Datatext Panel (Right)"] = "Panel Derecho de los Datos de texto"
+L["DataTexts"] = "Textos de Datos"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "Mostrar los paneles de datos debajo del chat para los datos de texto."
+L["Display minimap panels below the minimap, used for datatexts."] = "Muestra los paneles del minimapa debajo del minimapa, usado para los textos de datos."
+L["Gold Format"] = true;
+L["left"] = "Izquierda"
+L["LeftChatDataPanel"] = "Panel de Chat Izquierdo"
+L["LeftMiniPanel"] = "Panel Izquierdo del Minimapa"
+L["middle"] = "Medio"
+L["Minimap Panels"] = "Paneles del Minimapa"
+L["Panel Transparency"] = "Transparencia del Panel"
+L["Panels"] = "Paneles"
+L["right"] = "Derecha"
+L["RightChatDataPanel"] = "Panel de Chat Derecho"
+L["RightMiniPanel"] = "Panel Derecho del Minimapa"
+L["Small Panels"] = true;
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = true;
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap TopLeft (Inside)"
+L["TopMiniPanel"] = "Minimap Top (Inside)"
+L["TopRightMiniPanel"] = "Minimap TopRight (Inside)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "Cuando estás dentro de un campo de batalla muestra la puntuación personal en las barras de texto principales."
+L["Word Wrap"] = true;
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "Debes estar agrupado con el jugador si no está en tu mismo servidor."
+L["Sends your current profile to your target."] = "Envía tu perfil actual a tu objetivo."
+L["Sends your filter settings to your target."] = "Envía los ajustes de tus filtros a tu objetivo."
+L["Share Current Profile"] = "Compartir Perfil Actual"
+L["Share Filters"] = "Compartir Filtros"
+L["This feature will allow you to transfer settings to other characters."] = "Esta característica te permitirá transferir ciertos ajustes a otros personajes."
+L["You must be targeting a player."] = "Debes enfocar a un jugador."
+
+--Filters
+L["Reset Aura Filters"] = true --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "Aceptar Invitaciones"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "Ajusta la posición de la barra de amenaza a la izquierda o derecha de los paneles de texto de datos."
+L["AFK Mode"] = true;
+L["Announce Interrupts"] = "Anunciar Interrupciones"
+L["Announce when you interrupt a spell to the specified chat channel."] = "Anunciar cuando interrumpas un hechizo en el canal especificado."
+L["Attempt to support eyefinity/nvidia surround."] = true;
+L["Auto Greed/DE"] = "Codicia/Desencantar Automático"
+L["Auto Repair"] = "Reparación Automática"
+L["Auto Scale"] = "Escalado Automático"
+L["Automatically accept invites from guild/friends."] = "Aceptar de forma automática invitaciones de la hermandad/amigos."
+L["Automatically repair using the following method when visiting a merchant."] = "Repara de forma automática usando el siguiente método cuando visites un comerciante."
+L["Automatically scale the User Interface based on your screen resolution"] = "Escala de forma automática la interfaz de usuario dependiendo de la resolución de pantalla"
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "Tira codicia o desencanta (si se puede) automáticamente para los objetos verdes. Esto sólo funciona si ya tienes el nivel máximo."
+L["Automatically vendor gray items when visiting a vendor."] = "Vender automáticamente los objetos grises al visitar al vendedor."
+L["Bottom Panel"] = "Panel Inferior"
+L["Chat Bubbles Style"] = true;
+L["Chat Bubbles"] = true;
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = true;
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "Despliega un panel a través de la parte inferior de la pantalla. Es es sólo algo cosmético."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "Despliega un panel a través de la parte superior de la pantalla. Es es sólo algo cosmético."
+L["Display battleground messages in the middle of the screen."] = true;
+L["Enable/Disable the loot frame."] = "Activa/Desactiva el marco de botín."
+L["Enable/Disable the loot roll frame."] = "Activa/Desactiva el marco de sorteo de botín."
+L["Enables the ElvUI Raid Control panel."] = true;
+L["Enhanced PVP Messages"] = true;
+L["General"] = "General"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = true;
+L["Hide At Max Level"] = true;
+L["Hide Error Text"] = "Ocultar Texto de Error"
+L["Hide In Vehicle"] = true;
+L["Hides the red error text at the top of the screen while in combat."] = "Oculta el texto rojo de error en la parte superior de la pantalla mientras estás en combate."
+L["Log Taints"] = "Registro Exhaustivo"
+L["Login Message"] = "Mensaje de inicio"
+L["Loot Roll"] = "Marco de Botín"
+L["Loot"] = "Botín"
+L["Lowest Allowed UI Scale"] = true;
+L["Multi-Monitor Support"] = true;
+L["Name Font"] = "Fuente para Nombres"
+L["Number Prefix"] = true;
+L["Party / Raid"] = true;
+L["Party Only"] = true;
+L["Raid Only"] = true;
+L["Remove Backdrop"] = "Quitar Fondo"
+L["Reset all frames to their original positions."] = "Coloca todos los marcos en sus posiciones originales"
+L["Reset Anchors"] = "Restaurar Fijadores"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "Envia los errores ADDON_ACTION_BLOCKED al marco de errores de Lua. Esos errores en la mayoría de los casos son poco importantes y no afectan al rendimiento del juego. Muchos de esos errores no pueden ser subsanados. Por favor, reporta sólo esos errores si notas algún defecto que entorpezca el juego"
+L["Skin Backdrop (No Borders)"] = true;
+L["Skin Backdrop"] = "Apariencia del Fondo"
+L["Skin the blizzard chat bubbles."] = "Modificar la apariencia de las Burbujas de Chat de Blizzard"
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "Cambia la fuente del texto que aparece encima de las cabezas de los jugadores. |cffFF0000AVISO: Esto requiere que reinicies el juego o reconectes."
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = true;
+L["Thin Border Theme"] = true;
+L["Toggle Tutorials"] = "Mostrar/Ocultar Tutoriales"
+L["Top Panel"] = "Panel Superior"
+L["Version Check"] = true;
+L["Watch Frame Height"] = true;
+L["When you go AFK display the AFK screen."] = true;
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = true;
+L["Applies the primary texture to all statusbars."] = true;
+L["Apply Font To All"] = true;
+L["Apply Texture To All"] = true;
+L["Backdrop color of transparent frames"] = "Color de fondo de los marcos transparentes."
+L["Backdrop Color"] = "Color de Fondo"
+L["Backdrop Faded Color"] = "Color Atenuado de Fondo"
+L["Border Color"] = "Color de Borde"
+L["Color some texts use."] = "Color que usan algunos textos."
+L["Colors"] = "Colores"
+L["CombatText Font"] = "Fuente del Texto de Combate"
+L["Default Font"] = "Fuente Predeterminada"
+L["Font Size"] = "Tamaño de la Fuente"
+L["Fonts"] = "Fuentes"
+L["Main backdrop color of the UI."] = "Color principal de fondo para la interfaz."
+L["Main border color of the UI."] = true;
+L["Media"] = "Medios"
+L["Primary Texture"] = "Textura Primaria"
+L["Replace Blizzard Fonts"] = true;
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = true;
+L["Secondary Texture"] = "Textura Secundaria"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "Establece el tamaño de la fuente para la interfaz. Nota: Esto no afecta elementos que tengan sus propias opciones (Marcos de Unidad, Textos de Datos, etc.)"
+L["Textures"] = "Texturas"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "La fuente que usará el texto de combate. |cffFF0000ADVERTENCIA: Esto requiere un reinicio del juego o salir y entrar nuevamente para que este cambio surta efecto.|r"
+L["The font that the core of the UI will use."] = "La fuente que usará el núcleo de la interfaz."
+L["The texture that will be used mainly for statusbars."] = "La textura que se usará principalmente para las barras de estado."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "Esta textura se usará en objetos como las ventanas de chat y menús desplegables."
+L["Value Color"] = "Color de Dato"
+
+--Maps
+L["Adjust the size of the minimap."] = "Ajusta el tamaño del minimapa."
+L["Always Display"] = "Mostrar Siempre"
+L["Bottom Left"] = true;
+L["Bottom Right"] = true;
+L["Bottom"] = true;
+L["Change settings for the display of the location text that is on the minimap."] = "Cambia la configuración para mostrar el texto de ubicación que está en el minimapa."
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = true;
+L["Instance Difficulty"] = true;
+L["Left"] = "Izquierda"
+L["LFG Queue"] = true;
+L["Location Text"] = "Texto de Ubicación"
+L["Make the world map smaller."] = true;
+L["Maps"] = "Mapas"
+L["Minimap Buttons"] = true;
+L["Minimap Mouseover"] = "Ratón por encima del Minimapa"
+L["Puts coordinates on the world map."] = true;
+L["PvP Queue"] = true
+L["Reset Zoom"] = true;
+L["Right"] = "Derecha"
+L["Scale"] = true;
+L["Smaller World Map"] = true;
+L["Top Left"] = true;
+L["Top Right"] = true;
+L["Top"] = true;
+L["World Map Coordinates"] = true;
+L["X-Offset"] = true;
+L["Y-Offset"] = true;
+
+--Misc
+L["Install"] = "Instalar"
+L["Run the installation process."] = "Ejecutar el proceso de instalación"
+L["Toggle Anchors"] = "Mostrar/Ocultar Fijadores"
+L["Unlock various elements of the UI to be repositioned."] = "Desbloquea varios elementos de la interfaz para ser reubicados."
+L["Version"] = "Versión"
+
+--NamePlates
+L["# Displayed Auras"] = true;
+L["Actions"] = true
+L["Add Name"] = "Añadir Nombre"
+L["Add Nameplate Filter"] = true
+L["Add Regular Filter"] = true
+L["Add Special Filter"] = true
+L["Always Show Target Health"] = true
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = true
+L["Background Glow"] = true
+L["Bad Color"] = true;
+L["Bad Scale"] = true;
+L["Bad Transition Color"] = true;
+L["Base Height for the Aura Icon"] = true;
+L["Border Glow"] = true
+L["Border"] = true
+L["Cast Bar"] = true;
+L["Cast Color"] = true;
+L["Cast No Interrupt Color"] = true;
+L["Cast Time Format"] = true;
+L["Casting"] = true
+L["Channel Time Format"] = true;
+L["Clear Filter"] = true
+L["Color Tanked"] = true;
+L["Control enemy nameplates toggling on or off when in combat."] = true;
+L["Control friendly nameplates toggling on or off when in combat."] = true;
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = true;
+L["Cooldowns"] = true
+L["Copy settings from another unit."] = true;
+L["Copy Settings From"] = true;
+L["Current Level"] = true
+L["Default Settings"] = true;
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "Muestra un icono de sanados sobre los sanadores conocidos en los campos de batalla o arenas."
+L["Elite Icon"] = true
+L["Enable/Disable the scaling of targetted nameplates."] = true;
+L["Enabling this will check your health amount."] = true
+L["Enemy Combat Toggle"] = true;
+L["Enemy NPC Frames"] = true;
+L["Enemy Player Frames"] = true;
+L["Enemy"] = "Enemigo" --Also used in UnitFrames
+L["ENEMY_NPC"] = "Enemy NPC"
+L["ENEMY_PLAYER"] = "Enemy Player"
+L["Filter already exists!"] = "¡El filtro ya existe!"
+L["Filter Priority"] = true;
+L["Filters Page"] = true;
+L["Friendly Combat Toggle"] = true;
+L["Friendly NPC Frames"] = true;
+L["Friendly Player Frames"] = true;
+L["FRIENDLY_NPC"] = "PNJ Amistoso"
+L["FRIENDLY_PLAYER"] = "Jugador Amistoso"
+L["General Options"] = true;
+L["Good Color"] = true;
+L["Good Scale"] = true;
+L["Good Transition Color"] = true;
+L["Healer Icon"] = "Icono de Sanador"
+L["Health Color"] = true
+L["Health Threshold"] = true
+L["Hide Frame"] = true
+L["Hide Spell Name"] = true;
+L["Hide Time"] = true;
+L["Hide"] = "Ocultar" --Also used in DataTexts
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = true
+L["Icon Base Height"] = true;
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = true
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = true
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = true
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = true
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = true
+L["If enabled then the filter will only activate when you are in combat."] = true
+L["If enabled then the filter will only activate when you are out of combat."] = true
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = true
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = true
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = true
+L["Instance Type"] = true
+L["Interruptible"] = true
+L["Is Targeted"] = true
+L["LEVEL_BOSS"] = "Set level to -1 for boss units or set to 0 to disable."
+L["Low Health Threshold"] = "Umbral de Salud Baja"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = true
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = true;
+L["Match Player Level"] = true
+L["Maximum Level"] = true
+L["Maximum Time Left"] = true
+L["Minimum Level"] = true
+L["Minimum Time Left"] = true
+L["Missing"] = true
+L["Name Color"] = true
+L["Name Only"] = true
+L["NamePlates"] = "Placas de Nombre"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = true;
+L["Not Targeted"] = true
+L["Off Cooldown"] = true
+L["On Cooldown"] = true
+L["Over Health Threshold"] = true
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = true;
+L["Player Health"] = true
+L["Player in Combat"] = true
+L["Player Out of Combat"] = true
+L["Reaction Colors"] = true;
+L["Reaction Type"] = true
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "Eliminar Nombre"
+L["Remove Nameplate Filter"] = true
+L["Require All"] = true
+L["Reset filter priority to the default state."] = true;
+L["Reset Priority"] = true;
+L["Return filter to its default state."] = true
+L["Scale of the nameplate that is targetted."] = true;
+L["Select Nameplate Filter"] = true
+L["Set Settings to Default"] = true;
+L["Set the transparency level of nameplates that are not the target nameplate."] = true;
+L["Set to either stack nameplates vertically or allow them to overlap."] = true;
+L["Shortcut to 'Filters' section of the config."] = true;
+L["Shortcut to global filters."] = true
+L["Shortcuts"] = true;
+L["Side Arrows"] = true
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = true
+L["Tagged NPC"] = true;
+L["Tanked Color"] = true;
+L["Target Indicator Color"] = true
+L["Target Indicator"] = true
+L["Target Scale"] = true;
+L["Targeted Nameplate"] = true
+L["Texture"] = true
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = true;
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = true;
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = true
+L["Threat"] = "Amenaza"
+L["Time To Hold"] = true
+L["Toggle Off While In Combat"] = true;
+L["Toggle On While In Combat"] = true;
+L["Top Arrow"] = true
+L["Triggers"] = true
+L["Under Health Threshold"] = true
+L["Unit Type"] = true
+L["Use Class Color"] = true;
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = true;
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = true;
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = true;
+L["Use Target Glow"] = true;
+L["Use Target Scale"] = true;
+L["Use Threat Color"] = true;
+L["You can't remove a default name from the filter, disabling the name."] = "No puedes eliminar un nombre por defecto del filtro, desactivando el nombre."
+
+--Profiles Export/Import
+L["Choose Export Format"] = true;
+L["Choose What To Export"] = true;
+L["Decode Text"] = true;
+L["Error decoding data. Import string may be corrupted!"] = true;
+L["Error exporting profile!"] = true;
+L["Export Now"] = true;
+L["Export Profile"] = true;
+L["Exported"] = true;
+L["Filters (All)"] = true;
+L["Filters (NamePlates)"] = true;
+L["Filters (UnitFrames)"] = true;
+L["Global (Account Settings)"] = true;
+L["Import Now"] = true;
+L["Import Profile"] = true;
+L["Importing"] = true;
+L["Plugin"] = true;
+L["Private (Character Settings)"] = true;
+L["Profile imported successfully!"] = true;
+L["Profile Name"] = true;
+L["Profile"] = true;
+L["Table"] = true;
+
+--Skins
+L["Achievement Frame"] = "Logros"
+L["Alert Frames"] = "Alertas"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "Subastas"
+L["Barbershop Frame"] = "Barbería"
+L["BG Map"] = "Mapa de CB"
+L["BG Score"] = "Puntuación de CB"
+L["Calendar Frame"] = "Calendario"
+L["Character Frame"] = "Personaje"
+L["Debug Tools"] = "Herramientas de Depuración"
+L["Dressing Room"] = "Probador"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "Actualidad"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "Banco de Hermandad"
+L["Guild Registrar"] = "Registrar Hermandad"
+L["Help Frame"] = "Ayuda"
+L["Inspect Frame"] = "Inspección"
+L["KeyBinding Frame"] = "Asignación de Teclas"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "Despojo"
+L["Macro Frame"] = "Macros"
+L["Mail Frame"] = "Correo"
+L["Merchant Frame"] = "Mercader"
+L["Mirror Timers"] = true;
+L["Misc Frames"] = "Misceláneos"
+L["Petition Frame"] = "Petición"
+L["PvP Frames"] = "JcJ"
+L["Quest Frames"] = "Misión"
+L["Raid Frame"] = "Banda"
+L["Skins"] = "Cubiertas"
+L["Socket Frame"] = "Incrustación"
+L["Spellbook"] = "Libro de Hechizos"
+L["Stable"] = "Establo"
+L["Tabard Frame"] = "Tabardos"
+L["Talent Frame"] = "Talentos"
+L["Taxi Frame"] = "Viaje"
+L["Time Manager"] = "Administrador de Tiempo"
+L["Trade Frame"] = "Comercio"
+L["TradeSkill Frame"] = "Comercio de Habilidades"
+L["Trainer Frame"] = "Entrenador"
+L["Tutorial Frame"] = true;
+L["World Map"] = "Mapa Mundial"
+
+--Tooltip
+L["Always Hide"] = "Ocultar Siempre"
+L["Bags Only"] = true;
+L["Bags/Bank"] = true;
+L["Bank Only"] = true;
+L["Both"] = true;
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = true;
+L["Comparison Font Size"] = true;
+L["Cursor Anchor"] = true;
+L["Custom Faction Colors"] = true;
+L["Display guild ranks if a unit is guilded."] = "Mostrar rangos de hermandad si el jugador pertenece a una."
+L["Display how many of a certain item you have in your possession."] = "Despliega la cantidad de un determinado objeto que posees."
+L["Display player titles."] = "Mostrar los títulos de los jugadores"
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = true;
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "Despliega el ID de hechizo u objeto cuando pasas el ratón sobre un hechizo o un ojbeto."
+L["Guild Ranks"] = "Rangos de Hermandad"
+L["Header Font Size"] = true;
+L["Health Bar"] = true;
+L["Hide tooltip while in combat."] = "Oculta la descripción emergente mientras estás en combate."
+L["Inspect Info"] = true;
+L["Item Count"] = "Conteo de Objetos"
+L["Never Hide"] = "Nunca Ocultar"
+L["Player Titles"] = "Títulos de Jugador"
+L["Should tooltip be anchored to mouse cursor"] = true;
+L["Spell/Item IDs"] = "IDs de Hechizo/Objeto"
+L["Target Info"] = true;
+L["Text Font Size"] = true;
+L["This setting controls the size of text in item comparison tooltips."] = true;
+L["Tooltip Font Settings"] = true;
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "Cuando estás en una banda muestra si alguien en tu banda tiene marcado como objetivo a la unidad actual de la descripción emergente."
+
+--UnitFrames
+L["%s and then %s"] = "%s y entonces %s"
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "Encima"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = true;
+L["Add a spell to the filter."] = "Añade un hechizo al filtro."
+L["Add Spell ID or Name"] = true;
+L["Add SpellID"] = "Añadir ID de Hechizo"
+L["Additional Filter Override"] = true;
+L["Additional Filter"] = "Filtro Adicional"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = true;
+L["Allow Whitelisted Auras"] = "Permitir Auras de la Lista Blanca"
+L["An X offset (in pixels) to be used when anchoring new frames."] = true;
+L["An Y offset (in pixels) to be used when anchoring new frames."] = true;
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = true;
+L["Assist Frames"] = "Marcos de Asistencia"
+L["Assist Target"] = "Asistir a Objetivo"
+L["At what point should the text be displayed. Set to -1 to disable."] = "En qué punto debe mostrarse el texto. Establécelo en -1 para desactivar."
+L["Attach Text To"] = true;
+L["Attach To"] = "Adjuntar a"
+L["Aura Bars"] = "Barra de Auras"
+L["Auto-Hide"] = "Ocultar Automáticamente"
+L["Bad"] = "Hostil"
+L["Bars will transition smoothly."] = "Las barras harán las transiciones suavemente."
+L["Below"] = "Debajo"
+L["Blacklist Modifier"] = true;
+L["Blacklist"] = "Lista Negra"
+L["Block Auras Without Duration"] = "Bloquear Auras Sin Duración"
+L["Block Blacklisted Auras"] = "Bloquear Auras de Lista Negra"
+L["Block Non-Dispellable Auras"] = "Bloquear Auras No Disipables"
+L["Block Non-Personal Auras"] = "Bloquear Auras No Personales"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "Sangre"
+L["Borders"] = "Bordes"
+L["Buff Indicator"] = "Indicador de Beneficio"
+L["Buffs"] = "Beneficios"
+L["By Type"] = "Por tipo"
+L["Castbar"] = "Barra de Lanzamiento"
+L["Center"] = "Centro"
+L["Check if you are in range to cast spells on this specific unit."] = "Verifica si estás a distancia de lanzamiento de hechizos de esta unidad en específico"
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = true;
+L["Class Backdrop"] = "Fondo de Clase"
+L["Class Castbars"] = "Barras de Lanzamiento de Clase"
+L["Class Color Override"] = "Ignorar Color de Clase"
+L["Class Health"] = "Salud de Clase"
+L["Class Power"] = "Poder de Clase"
+L["Class Resources"] = "Recursos de Clase"
+L["Click Through"] = "Clic A través"
+L["Color all buffs that reduce the unit's incoming damage."] = "Colorea todos los beneficios que reduzcan el daño recibido por la unidad."
+L["Color aurabar debuffs by type."] = "Color de los perjuicios de la barra de aura por tipo"
+L["Color castbars by the class of player units."] = true;
+L["Color castbars by the reaction type of non-player units."] = true;
+L["Color health by amount remaining."] = "Color de salud por la cantidad restante."
+L["Color health by classcolor or reaction."] = "Color de salud por el color de clase o reacción."
+L["Color power by classcolor or reaction."] = "Color de poder por el color de clase o reacción."
+L["Color the health backdrop by class or reaction."] = "Color de fondo de salud por el color de clase o reacción."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "Color de la barra de salud si hay un perjuicio que puede ser disipado por ti."
+L["Color Turtle Buffs"] = "Colorear Beneficios de Tortuga"
+L["Color"] = "Color"
+L["Colored Icon"] = "Icono Coloreado"
+L["Coloring (Specific)"] = "Coloreado (Específico)"
+L["Coloring"] = "Coloreado"
+L["Combat Fade"] = "Desvanecer en Combate"
+L["Combat Icon"] = true;
+L["Combo Point"] = true;
+L["Combobar"] = true;
+L["Configure Auras"] = "Configurar Auras"
+L["Copy From"] = "Copiar Desde"
+L["Count Font Size"] = "Tamaño de Fuente del Contador"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "Crear una formato de texto personalizado. Una vez que introduzcas un nombre podrás seleccionarlo en la lista despleglable."
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "Crea un filtro, una vez creado podrás establecerlo dentro de la sección beneficios/perjuicios de cada unidad."
+L["Create Custom Text"] = true
+L["Create Filter"] = "Crear Filtro"
+L["Current - Max | Percent"] = "Actual - Máximo | Porcentaje"
+L["Current - Max"] = "Actual - Máximo"
+L["Current - Percent"] = "Actual - Porcentaje"
+L["Current / Max"] = "Actual / Máximo"
+L["Current"] = "Actual"
+L["Custom Dead Backdrop"] = true;
+L["Custom Health Backdrop"] = "Fondo de Salud Personalizado"
+L["Custom Texts"] = "Texto Personalizado"
+L["Death"] = "Muerte"
+L["Debuff Highlighting"] = "Resaltado de Perjuicio"
+L["Debuffs"] = "Perjuicios"
+L["Decimal Threshold"] = true;
+L["Deficit"] = "Déficit"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "Borra el filtro creado, no puedes borrar filtro pre-existentes, sólo los personalizados."
+L["Delete Filter"] = "Borrar Filtro"
+L["Detach From Frame"] = "Separar Del Marco"
+L["Detached Width"] = "Ancho de Separación"
+L["Direction the health bar moves when gaining/losing health."] = "La dirección de la barra de salud se mueve cuando ganas/pierdes salud."
+L["Disable Debuff Highlight"] = true;
+L["Disabled Blizzard Frames"] = true;
+L["Disabled"] = "Desactivado"
+L["Disables the focus and target of focus unitframes."] = true;
+L["Disables the player and pet unitframes."] = true;
+L["Disables the target and target of target unitframes."] = true;
+L["Disconnected"] = "Desconectado"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "Muestra una textura al final de la barra de lanzamiento/estado para ayudar a diferenciar entre la barra de lanzamiento y el fondo."
+L["Display Frames"] = "Mostrar Marcos"
+L["Display Player"] = "Mostrar Jugador"
+L["Display Target"] = "Mostrar Objetivo"
+L["Display Text"] = "Mostrar Texto"
+L["Display the castbar icon inside the castbar."] = true;
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = true;
+L["Display the combat icon on the unitframe."] = true;
+L["Display the rested icon on the unitframe."] = "Muestra el icono de descansado en el marco de unidad."
+L["Display the target of your current cast. Useful for mouseover casts."] = "Muestra el objetivo de tu hechizo actual. Es útil para hechizos por ratón."
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "Muestra las marcas de cada tick en la barra de lanzamiento para los hechizos canalizados. Esto se ajustará automáticamente con base en el hechizo y la celeridad."
+L["Don't display any auras found on the 'Blacklist' filter."] = "No mostrar auras encontradas en el filtro 'Lista Negra'."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that are not yours."] = "No mostrar auras que no sean tuyas."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = true;
+L["Don't display auras that cannot be purged or dispelled by your class."] = "No mostrar auras que no puedan ser purgadas o disipadas por tu clase."
+L["Don't display auras that have no duration."] = "No mostrar auras sin duración."
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "Abajo"
+L["Dungeon & Raid Filter"] = true;
+L["Duration Reverse"] = "Revertir Duración"
+L["Duration Text"] = true;
+L["Duration"] = "Duración"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = true;
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = true;
+L["Enemy Aura Type"] = "Tipo de Aura Enemiga"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "Desvanecer el marco de unidad cuando está fuera de combate, sin lanzar, o sin objetivo."
+L["Fill"] = "Llenar"
+L["Filled"] = "Lleno"
+L["Filter Type"] = "Tipo de Filtro"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "Fuerza Apagada"
+L["Force On"] = "Fuerza Encendida"
+L["Force Reaction Color"] = true;
+L["Force the frames to show, they will act as if they are the player frame."] = "Forzar a mostrar los marcos, esto funcionará si es el marco del jugador."
+L["Forces Debuff Highlight to be disabled for these frames"] = true;
+L["Forces reaction color instead of class color on units controlled by players."] = true;
+L["Format"] = "Formato"
+L["Frame Level"] = true;
+L["Frame Orientation"] = true;
+L["Frame Strata"] = true;
+L["Frame"] = "Marco"
+L["Frequent Updates"] = "Actualizaciones Frecuentes"
+L["Friendly Aura Type"] = "Tipo de Aura Amistosa"
+L["Friendly"] = "Amistoso"
+L["Frost"] = "Escarcha"
+L["Glow"] = "Brillo"
+L["Good"] = "Amistoso"
+L["GPS Arrow"] = true;
+L["Group By"] = "Agrupar Por"
+L["Grouping & Sorting"] = true;
+L["Groups Per Row/Column"] = true;
+L["Growth direction from the first unitframe."] = "Dirección de crecimiento desde el primer marco de unidad."
+L["Growth Direction"] = "Dirección de Crecimiento"
+L["Heal Prediction"] = "Predicción de Sanación"
+L["Health Backdrop"] = "Fondo de Salud"
+L["Health Border"] = "Borde de Salud"
+L["Health By Value"] = "Salud por Valor"
+L["Health"] = "Salud"
+L["Height"] = "Altura"
+L["Horizontal Spacing"] = "Espaciado Horizontal"
+L["Horizontal"] = "Horizontal"
+L["Icon Inside Castbar"] = true;
+L["Icon Size"] = true;
+L["Icon"] = "Icono"
+L["Icon: BOTTOM"] = "Icono: ABAJO"
+L["Icon: BOTTOMLEFT"] = "Icono: ABAJO-IZQUIERDA"
+L["Icon: BOTTOMRIGHT"] = "Icono: ABAJO-DERECHA"
+L["Icon: LEFT"] = "Icono: IZQUIERDA"
+L["Icon: RIGHT"] = "Icono: DERECHA"
+L["Icon: TOP"] = "Icono: ARRIBA"
+L["Icon: TOPLEFT"] = "Icono: ARRIBA-IZQUIERDA"
+L["Icon: TOPRIGHT"] = "Icono: ARRIBA-DERECHA"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Si no utiliza ningún filtro entonces bloqueará todo lo que no esté en la lista blanca, de otra forma simplemente agregará auras en la lista blanca además de cualesquiera otros ajustes de filtro."
+L["If not set to 0 then override the size of the aura icon to this."] = "Si no está a 0 entonces sobrescribe el tamaño del icono del aura con este."
+L["If the unit is an enemy to you."] = "Si la unidad es tu enemiga."
+L["If the unit is friendly to you."] = "Si la unidad es tu amiga."
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = true;
+L["Ignore mouse events."] = "Ignorar los eventos del ratón"
+L["InfoPanel Border"] = true;
+L["Information Panel"] = true;
+L["Inset"] = "Hundido"
+L["Inside Information Panel"] = true;
+L["Interruptable"] = "Interrumpible"
+L["Invert Grouping Order"] = "Invertir orden de agrupamiento"
+L["JustifyH"] = "Justificado Horizontal"
+L["Latency"] = "Latencia"
+L["Left to Right"] = true;
+L["Main statusbar texture."] = "Textura de la barra de estado principal."
+L["Main Tanks / Main Assist"] = "Tanques Principales/Ayudante Principal"
+L["Make textures transparent."] = "Hacer las texturas transparentes."
+L["Match Frame Width"] = "Coincidir con la Anchura del Marco"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = true;
+L["Max Overflow"] = true
+L["Maximum Duration"] = true;
+L["Method to sort by."] = true;
+L["Middle Click - Set Focus"] = "Clic Intermedio - Establecer Foco"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "Hacer clic intermedio en el marco de unidad causará que tu foco sea la unidad."
+L["Middle"] = true;
+L["Minimum Duration"] = true;
+L["Mouseover"] = "Pasar el ratón por encima"
+L["Name"] = "Nombre"
+L["Neutral"] = "Neutral"
+L["Non-Interruptable"] = "No-Interrumpible"
+L["None"] = "Ninguno"
+L["Not valid spell id"] = "No es un id de hechizo válido"
+L["Num Rows"] = "Número de Filas"
+L["Number of Groups"] = "Número de Grupos"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "Desplazamiento de la barra de poder sobre la barra de salud, 0 para desactivar."
+L["Offset position for text."] = "Posición de desplazamiento para el texto."
+L["Offset"] = "Desplazamiento"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "Mostrar sólo cuando la unidad no esté dentro del rango."
+L["Only show when you are mousing over a frame."] = "Mostrar sólo cuando pasas el ratón por encima de un marco."
+L["OOR Alpha"] = "Transparencia FDA"
+L["Other Filter"] = true;
+L["Others"] = "Otros"
+L["Overlay the healthbar"] = "Recubrir la barra de salud"
+L["Overlay"] = "Recubrir"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "Sobrescribir cualquier opción de visibilidad en ciertas situaciones, Ej: Sólo mostrar grupos 1 y 2 dentro de una mazmorra de banda de 10 personas."
+L["Override the default class color setting."] = "Ignorar el ajuste predeterminado del color de clase."
+L["Owners Name"] = true;
+L["Parent"] = true;
+L["Party Pets"] = "Mascotas de Grupo"
+L["Party Targets"] = "Objetivos del Grupo"
+L["Per Row"] = "Por Fila"
+L["Percent"] = "Porcentaje"
+L["Personal"] = true;
+L["Pet Name"] = true;
+L["Player Frame Aura Bars"] = true;
+L["Portrait"] = "Retrato"
+L["Position Buffs on Debuffs"] = true;
+L["Position Debuffs on Buffs"] = true;
+L["Position"] = "Posición"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "El texto de poder estará oculto en los objetivos PNJ, además el texto del nombre será fijado donde el texto de poder."
+L["Power"] = "Poder"
+L["Powers"] = "Poderes"
+L["Priority"] = "Prioridad"
+L["Profile Specific"] = true;
+L["PvP Icon"] = true;
+L["PvP Text"] = true;
+L["PVP Trinket"] = "Abalorio JcJ"
+L["Raid Icon"] = "Icono de Banda"
+L["Raid-Wide Sorting"] = true;
+L["Raid40 Frames"] = true;
+L["RaidDebuff Indicator"] = "Indicador de Perjuicios de Banda"
+L["Range Check"] = "Verificación de Rango"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "Actualizar la salud rápidamente, consume más memoria y cpu. Recomendado sólo para sanadores."
+L["Reaction Castbars"] = true;
+L["Reactions"] = "Reacciones"
+L["Ready Check Icon"] = true;
+L["Remaining"] = "Restante"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = true;
+L["Remove a spell from the filter."] = "Elimina un hechizo del filtro."
+L["Remove Spell ID or Name"] = true;
+L["Remove SpellID"] = "Eliminar ID de Hechizo"
+L["Rest Icon"] = "Icono de Descanso"
+L["Restore Defaults"] = "Restaurar por Defecto"
+L["Right to Left"] = true;
+L["RL / ML Icons"] = "Iconos LB / MD"
+L["Role Icon"] = "Icono de Rol"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = true;
+L["Select a unit to copy settings from."] = "Selecciona una unidad desde la que copiar la configuración."
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "Elige un filtro adicional a usar. Si el filtro seleccionado es una lista blanca y no se usan otros filtros (con la excepción de Bloquear Auras No Personales) entonces bloqueará todo lo que no esté en la lista blanca, de otra forma simplemente agregará auras a la lista blanca además de cualesquiera otro ajuste de filtros."
+L["Select Filter"] = "Seleccionar Filtro"
+L["Select Spell"] = "Seleccionar Hechizo"
+L["Select the display method of the portrait."] = "Selecciona el método de despliegue del retrato."
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = true;
+L["Set the font size for unitframes."] = "Establece el tamaño de la fuente para los marcos de unidad."
+L["Set the order that the group will sort."] = "Establece el orden en que el grupo será organizado."
+L["Set the orientation of the UnitFrame."] = true;
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "Establece el orden de prioridad del hechizo, ten en cuenta que la prioridad sólo se usa para el módulo de perjuicios de banda, no para el módulo estandar de beneficios/perjuicios. 0 para desactivar."
+L["Set the type of auras to show when a unit is a foe."] = "Establece el tipo de auras a mostrar cuando la unidad es enemiga."
+L["Set the type of auras to show when a unit is friendly."] = "Establece el tipo de auras a mostrar cuando la unidad es amistosa."
+L["Sets the font instance's horizontal text alignment style."] = "Establece la alineación horizontal del texto."
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "Muestra una barra de predicción de sanación en el marco de unidad. También muestra una barra ligeramente coloreada para sobresanaciones recibidas."
+L["Show Aura From Other Players"] = "Mostrar Auras de Otros Jugadores"
+L["Show Auras"] = "Mostrar Auras"
+L["Show Dispellable Debuffs"] = true;
+L["Show When Not Active"] = "Mostrar Cuando No Esté Activo"
+L["Size and Positions"] = true;
+L["Size of the indicator icon."] = "Tamaño del icono indicador."
+L["Size Override"] = "Sobrescribir Tamaño"
+L["Size"] = "Tamaño"
+L["Smart Aura Position"] = true;
+L["Smart Raid Filter"] = "Filtro de Banda Inteligente"
+L["Smooth Bars"] = "Barras Suavizadas"
+L["Sort By"] = true;
+L["Spaced"] = "Separadas"
+L["Spacing"] = true;
+L["Spark"] = "Desatar"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = true;
+L["Stack Threshold"] = true;
+L["Start Near Center"] = "Comenzar Cerca del Centro"
+L["Statusbar Fill Orientation"] = true;
+L["StatusBar Texture"] = "Textura de la Barra de Estado"
+L["Strata and Level"] = true;
+L["Style"] = "Estilo"
+L["Tank Frames"] = "Marco de Tanques"
+L["Tank Target"] = "Objetivo del Tanque"
+L["Tapped"] = "Golpear"
+L["Target Glow"] = true;
+L["Target On Mouse-Down"] = "Apuntar al Presionar el Botón del Ratón"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "Apuntar unidades al presionar el botón en lugar de soltarlo. \n\n|cffFF0000Advertencia: Si estás usando Clique es probable que tengas que modificar tus ajustes de Clique cuando cambies esta opción.|r"
+L["Text Color"] = "Color de Texto"
+L["Text Format"] = "Formato de Texto"
+L["Text Position"] = "Posición del Texto"
+L["Text Threshold"] = "Límite del Texto"
+L["Text Toggle On NPC"] = "Alternar Texto en PNJ"
+L["Text xOffset"] = "Desplazamiento X del Texto"
+L["Text yOffset"] = "Desplazamiento Y del Texto"
+L["Text"] = "Texto"
+L["Textured Icon"] = "Icono Texturizado"
+L["The alpha to set units that are out of range to."] = "Establece la transparencia para las unidades fuera de alcance."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = true;
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "La siguiente macro debe ser verdadera para que el grupo se muestre, además de cualquier filtro que ya exista."
+L["The font that the unitframes will use."] = "La fuente que usa el marco de unidad."
+L["The initial group will start near the center and grow out."] = "El grupo inicial comenzará cerca del centro y crecer."
+L["The name you have selected is already in use by another element."] = "El nombre que has seleccionado ya está en uso por otro elemento."
+L["The object you want to attach to."] = "El objeto que quieres adjuntar a."
+L["Thin Borders"] = true;
+L["This dictates the size of the icon when it is not attached to the castbar."] = true;
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = true;
+L["Threat Display Mode"] = "Modo de Despliegue de Amenaza"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = true;
+L["Ticks"] = "Ticks"
+L["Time Remaining Reverse"] = "Revertir Tiempo Restante"
+L["Time Remaining"] = "Tiempo Restante"
+L["Transparent"] = "Transparente"
+L["Turtle Color"] = "Color de Tortuga"
+L["Unholy"] = "Profano"
+L["Uniform Threshold"] = true;
+L["UnitFrames"] = "Marco de Unidad"
+L["Up"] = "Arriba"
+L["Use Custom Level"] = true;
+L["Use Custom Strata"] = true;
+L["Use Dead Backdrop"] = true;
+L["Use Default"] = "Usar Predeterminado"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "Usar el color de fondo personalizado para la salud en vez de un múltiplo del color principal."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = true;
+L["Use thin borders on certain unitframe elements."] = true;
+L["Use this backdrop color for units that are dead or ghosts."] = true;
+L["Value must be a number"] = "El valor debe ser un número"
+L["Vertical Orientation"] = true;
+L["Vertical Spacing"] = "Espaciado Vertical"
+L["Vertical"] = "Vertical"
+L["Visibility"] = "Visibilidad"
+L["What point to anchor to the frame you set to attach to."] = "Punto de fijación a utilizar del marco que se va a sujetar."
+L["What to attach the buff anchor frame to."] = "Dónde sujetar el fijador del marco de beneficios."
+L["What to attach the debuff anchor frame to."] = "Dónde sujetar el fijador del marco de perjuicios."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "Cuando está activo, la cabecera incluye al jugador cuando no está en una banda."
+L["Whitelist"] = "Lista Blanca"
+L["Width"] = "Anchura"
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = true;
+L["xOffset"] = "DesplazamientoX"
+L["yOffset"] = "DesplazamientoY"
+L["You can't remove a pre-existing filter."] = "No puedes eliminar un filtro pre-existente."
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "No puedes eliminar un hechizo de un filtro por defecto que no ha sido personalizado. Establece el hechizo a falso."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = true;
\ No newline at end of file
diff --git a/ElvUI_Config/Locales/Taiwanese_Config.lua b/ElvUI_Config/Locales/Taiwanese_Config.lua
new file mode 100644
index 0000000..f6bffaa
--- /dev/null
+++ b/ElvUI_Config/Locales/Taiwanese_Config.lua
@@ -0,0 +1,1130 @@
+-- Taiwanese localization file for zhTW.
+local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
+local L = AceLocale:NewLocale("ElvUI", "zhTW")
+if not L then return end
+
+-- *_DESC locales
+L["ACTIONBARS_DESC"] = "Modify the actionbar settings."
+L["AURAS_DESC"] = "小地圖旁的光環圖示設定."
+L["BAGS_DESC"] = "調整 ElvUI 背包設定."
+L["CHAT_DESC"] = "對話框架設定."
+L["DATATEXT_DESC"] = "螢幕資訊文字顯示設定."
+L["ELVUI_DESC"] = "ElvUI 為一套功能完整,可用來替換 WOW 原始介面的 UI 套件"
+L["NAMEPLATE_DESC"] = "修改血條設定."
+L["PANEL_DESC"] = "調整左、右對話框的尺寸,此設定將會影響對話與背包框架的尺寸."
+L["SKINS_DESC"] = "調整外觀設定."
+L["TOGGLESKIN_DESC"] = "啟用/停用此外觀."
+L["TOOLTIP_DESC"] = "浮動提示資訊設定選項."
+L["UNITFRAME_DESC"] = "Modify the unitframe settings."
+L["SEARCH_SYNTAX_DESC"] = [[因為新增加的 LibItemSearch,你現在可以使用更進階的物品搜尋. 下面是一份搜尋語法的文件. 想要看更完整的解釋請到: https://github.com/Jaliborc/LibItemSearch-1.2/wiki/Search-Syntax.
+
+條件搜尋:
+ • q:[品質] 或 quality:[品質]. 舉例,q:史詩 會搜尋所有史詩物品.
+ • l:[裝等],lvl:[裝等] 或 level:[裝等]. 舉例,l:30 會搜尋所有裝等30的物品.
+ • t:[類型],type:[類型] 或 slot:[類型]. 舉例,t:武器 會搜尋所有武器.
+ • n:[名稱] 或 name:[名稱]. 舉例,輸入 n:muffins 會搜尋所有物品名稱中含有 "muffins".
+ • s:[套裝] 或 set:[套裝]. 舉例,s:火 會在你定義的套裝名稱起始為 火 的套裝中搜尋所有裝備.
+ • tt:[關鍵字],tip:[關鍵字] 或 tooltip:[關鍵字]. 舉例,tt:綁定 會搜尋所有物品提示中含有綁定兩字的物品 如 帳號綁定,裝備綁定 或 拾取綁定.
+
+
+搜尋運算子:
+ • ! : 反向搜尋. 舉例,!q:史詩 會搜尋所有不是史詩的物品
+ • | : 聯集搜尋. 輸入 q:史詩 | t:武器 會搜尋所有史詩物品 或是 武器.
+ • & : 交集搜尋. 舉例,q:史詩 & t:武器 會搜尋所有既是史詩 也是 武器的物品
+ • >, <, <=, => : 在數值搜尋時進行比較. 舉例,輸入 lvl: >30 會搜尋所有裝等大於30的物品.
+
+
+以下的關鍵字也可以被使用:
+ • soulbound, bound, bop : 拾取綁定.
+ • bou : 使用後綁定.
+ • boe : 裝備後綁定.
+ • boa : 帳號綁定.
+ • quest : 任務綁定.]];
+L["TEXT_FORMAT_DESC"] = [[請填入代碼以變更文字格式。
+
+範例:
+[namecolor][name] [difficultycolor][smartlevel] [shortclassification]
+[healthcolor][health:current-max]
+[powercolor][power:current]
+
+生命/能量值格式:
+"current" - 目前數值
+"percent" - 百分比
+"current-max" - 目前數值 - 最大值,當兩者相同時,僅會顯示最大值
+"current-percent" - 目前數值 - 百分比
+"current-max-percent" - 目前數值 - 最大值 - 百分比,當目前數值等同於最大值時,僅會顯示最大值
+"deficit" - 顯示損失數值,若未損失生命/能量值,將不予顯示
+
+名稱格式:
+"name:short" - 名稱上限為 10 個字元
+"name:medium" - 名稱上限為 15 個字元
+"name:long" - 名稱上限為 20 個字元
+
+若要停用此功能,此欄位請留空。如需更多資訊,請至 http://www.tukui.org]];
+
+--ActionBars
+L["Action Paging"] = "快捷列翻頁"
+L["ActionBars"] = "快捷列"
+L["Action button keybinds will respond on key down, rather than on key up"] = true;
+L["Allow LBF to handle the skinning of this element."] = "允許 LBF 來處理此元件的皮膚"
+L["Alpha"] = "透明度"
+L["Anchor Point"] = "定位方向"
+L["Backdrop Spacing"] = "背景間距"
+L["Backdrop"] = "背景"
+L["Button Size"] = "按鈕尺寸"
+L["Button Spacing"] = "按鈕間距"
+L["Buttons Per Row"] = "每行按鈕數"
+L["Buttons"] = "按鈕數"
+L["Change the alpha level of the frame."] = "改變框架透明度."
+L["Color of the actionbutton when not usable."] = "無法使用的技能快捷鍵顏色."
+L["Color of the actionbutton when out of power (Mana, Rage)."] = "施放能量 (法力、怒氣) 不足的技能快捷鍵顏色."
+L["Color of the actionbutton when out of range."] = "超出施放範圍的技能快捷鍵顏色."
+L["Color of the actionbutton when usable."] = "可使用的技能快捷鍵顏色."
+L["Color when the text is about to expire"] = "即將冷卻完畢的數字顏色."
+L["Color when the text is in the days format."] = "以天顯示的文字顏色."
+L["Color when the text is in the hours format."] = "以小時顯示的文字顏色."
+L["Color when the text is in the minutes format."] = "以分顯示的文字顏色."
+L["Color when the text is in the seconds format."] = "以秒顯示的文字顏色."
+L["Cooldown Text"] = "冷卻文字"
+L["Darken Inactive"] = "非啟用者變暗"
+L["Days"] = "天"
+L["Display bind names on action buttons."] = "在快捷列按鈕上顯示快捷鍵名稱."
+L["Display cooldown text on anything with the cooldown spiral."] = "在任何冷卻動畫上顯示技能冷卻時間."
+L["Display macro names on action buttons."] = "在快捷列按鈕上顯示巨集名稱."
+L["Expiring"] = "即將冷卻完畢"
+L["Global Fade Transparency"] = "全局漸隱透明度"
+L["Height Multiplier"] = "高度倍數"
+L["Hours"] = "時"
+L["If you unlock actionbars then trying to move a spell might instantly cast it if you cast spells on key press instead of key release."] = "如果你將快捷列解鎖後嘗試移動技能, 技能可能會馬上施放因為你使用按下施法而非釋放施法"
+L["Inherit Global Fade"] = "繼承全局漸隱"
+L["Inherit the global fade, mousing over, targetting, setting focus, losing health, entering combat will set the remove transparency. Otherwise it will use the transparency level in the general actionbar settings for global fade alpha."] = "繼承全局漸隱, 當滑鼠滑過, 設為目標, 設為焦點, 損失血量, 進入戰鬥時都會變為不透明, 除此之外將會使用在全局快捷列中的所設定的全局漸隱透明度"
+L["Key Down"] = "按下施法"
+L["Keybind Mode"] = "快捷鍵綁定模式"
+L["Keybind Text"] = "快捷鍵文字"
+L["LBF Support"] = true;
+L["Low Threshold"] = "冷卻時間低閥值"
+L["Macro Text"] = "巨集名稱"
+L["Minutes"] = "分"
+L["Mouse Over"] = "滑鼠滑過顯示"
+L["Multiply the backdrops height or width by this value. This is usefull if you wish to have more than one bar behind a backdrop."] = "根據此值增加背景的高度或寬度. 一般用來設定在一個背景框裡放置多條快捷列."
+L["Not Usable"] = "無法使用"
+L["Out of Power"] = "施放能量不足"
+L["Out of Range"] = "超出施放範圍"
+L["Pick Up Action Key"] = true;
+L["Restore Bar"] = "還原快捷列"
+L["Restore the actionbars default settings"] = "恢復此快捷列的預設設定"
+L["Seconds"] = "秒"
+L["Show Empty Buttons"] = "顯示空白按鈕"
+L["The amount of buttons to display per row."] = "每行所顯示的按鈕數量."
+L["The amount of buttons to display."] = "快捷列按鈕顯示數量."
+L["The button you must hold down in order to drag an ability to another action button."] = "需按住此按鈕,才可將技能拖曳至另一快捷鈕中."
+L["The first button anchors itself to this point on the bar."] = "快捷列第一個按鈕的所在位置."
+L["The size of the action buttons."] = "快捷列按鈕尺寸."
+L["The spacing between the backdrop and the buttons."] = "背景與按鈕之間的間隙"
+L["This setting will be updated upon changing stances."] = "此設定將在切換姿態時更新"
+L["Threshold before text turns red and is in decimal form. Set to -1 for it to never turn red"] = "冷卻時間低於此秒數後將變為紅色數字, 並以小數顯示, 設為- 1 冷卻時間將不會變為紅色."
+L["Toggles the display of the actionbars backdrop."] = "顯示/隱藏快捷列背景框."
+L["Transparency level when not in combat, no target exists, full health, not casting, and no focus target exists."] = "當非戰鬥, 沒有目標, 滿血, 未施法且沒有焦點目標存在時的透明度"
+L["Usable"] = "可以使用"
+L["Visibility State"] = "顯示狀態"
+L["Width Multiplier"] = "寬度倍數"
+L[ [[This works like a macro, you can run different situations to get the actionbar to page differently.
+ Example: [combat] 2;]] ] = [[此功能與巨集概念類似, 可根據不同情況切換至不同的快捷列設定。
+例如:[combat] 2;]]
+L[ [[This works like a macro, you can run different situations to get the actionbar to show/hide differently.
+ Example: [combat] show;hide]] ] = [[此功能與巨集概念類似, 可根據不同情境, 切換顯示/隱藏快捷列。
+例如:[combat] show;hide]]
+
+--Bags
+L["Add an item or search syntax to the ignored list. Items matching the search syntax will be ignored."] = "增加一個物品或是搜尋語法到忽略清單. 符合搜尋語法的物品將會被忽略"
+L["Add Item or Search Syntax"] = "增加物品或是搜尋語法"
+L["Adjust the width of the bag frame."] = "調整背包框架寬度."
+L["Adjust the width of the bank frame."] = "調整銀行框架寬度."
+L["Ascending"] = "升序"
+L["Bag Sorting"] = "背包排序"
+L["Bag-Bar"] = "背包條"
+L["Bar Direction"] = "背包條排序方向"
+L["Blizzard Style"] = "暴雪風格"
+L["Bottom to Top"] = "底部至頂部"
+L["Button Size (Bag)"] = "單個格子尺寸 (背包)"
+L["Button Size (Bank)"] = "單個格子尺寸 (銀行)"
+L["Clear Search On Close"] = "關閉時清空搜尋"
+L["Condensed"] = "濃縮"
+L["Descending"] = "降序"
+L["Direction the bag sorting will use to allocate the items."] = "整理背包物品時,將依此排序方向排放物品."
+L["Disable Bag Sort"] = "停用背包排序"
+L["Disable Bank Sort"] = "停用銀行排序"
+L["Display Item Level"] = "顯示物品等級"
+L["Displays item level on equippable items."] = "在可裝備物品上顯示裝備等級"
+L["Enable/Disable the all-in-one bag."] = "啟用/停用整合背包."
+L["Enable/Disable the Bag-Bar."] = "啟用/停用背包條."
+L["Full"] = "滿"
+L["Global"] = "全局"
+L["Here you can add items or search terms that you want to be excluded from sorting. To remove an item just click on its name in the list."] = "在此你可以新增物品或是搜尋語法來排除排序某些物品. 要移除物品請點選列表中的物品名稱"
+L["Ignored Items and Search Syntax (Global)"] = "忽略的物品與搜尋語法 (全局)"
+L["Ignored Items and Search Syntax (Profile)"] = "忽略的物品與搜尋語法 (個人)"
+L["Item Count Font"] = "物品記數字型"
+L["Item Level Threshold"] = "物品等級閥值"
+L["Item Level"] = "物品等級"
+L["Money Format"] = "金幣格式"
+L["Panel Width (Bags)"] = "框架寬度 (背包)"
+L["Panel Width (Bank)"] = "框架寬度 (銀行)"
+L["Search Syntax"] = "搜尋語法"
+L["Set the size of your bag buttons."] = "設定你的背包格子大小."
+L["Short (Whole Numbers)"] = "短 (完整數字)"
+L["Short"] = "短"
+L["Smart"] = "智慧"
+L["Sort Direction"] = "排序方向"
+L["Sort Inverted"] = "倒序排列"
+L["The direction that the bag frames be (Horizontal or Vertical)."] = "背包框架排序方向 (水平或垂直)."
+L["The direction that the bag frames will grow from the anchor."] = "新增的背包框架將從錨點依此方向增加."
+L["The display format of the money text that is shown at the top of the main bag."] = "在背包主框架上方的金幣顯示格式"
+L["The frame is not shown unless you mouse over the frame."] = "僅於滑鼠移經快捷列時顯示框架."
+L["The minimum item level required for it to be shown."] = "顯示的最低物品等級"
+L["The size of the individual buttons on the bag frame."] = "背包框架單個格子的大小."
+L["The size of the individual buttons on the bank frame."] = "銀行框架單個格子的大小."
+L["The spacing between buttons."] = "兩個按鈕間的距離."
+L["Top to Bottom"] = "頂部至底部"
+L["Use coin icons instead of colored text."] = "使用硬幣圖示取代上色文字"
+
+--Buffs and Debuffs
+L["Buffs and Debuffs"] = "愛好者和減";
+L["Begin a new row or column after this many auras."] = "在這些光環旁開始新的行或列."
+L["Count xOffset"] = "層數X偏移"
+L["Count yOffset"] = "層數Y偏移"
+L["Defines how the group is sorted."] = "定義群組的排序方式."
+L["Defines the sort order of the selected sort method."] = "定義所選排序方式的排序方向."
+L["Disabled Blizzard"] = "停用暴雪框架"
+L["Display reminder bar on the minimap."] = true
+L["Fade Threshold"] = "漸隱時間閥值"
+L["Index"] = "索引"
+L["Indicate whether buffs you cast yourself should be separated before or after."] = "將你自身施放的增益放於整體增益最前方或或最後方."
+L["Limit the number of rows or columns."] = "最大行數或列數."
+L["Max Wraps"] = "每行最大數"
+L["No Sorting"] = "不分類"
+L["Other's First"] = "他人光環優先"
+L["Remaining Time"] = "剩餘時間"
+L["Reminder"] = true
+L["Reverse Style"] = true;
+L["Seperate"] = "光環分離"
+L["Set the size of the individual auras."] = "設定每個光環的尺寸."
+L["Sort Method"] = "分類方式"
+L["The direction the auras will grow and then the direction they will grow after they reach the wrap after limit."] = "光環增加的方向與到達每行最大數後換行增加的方向"
+L["Threshold before text changes red, goes into decimal form, and the icon will fade. Set to -1 to disable."] = "冷卻時間低於此秒數後將變為紅色數字且以小數顯示, 並且圖示會漸隱. 設定為-1 禁用此功能."
+L["Time xOffset"] = "時間X偏移"
+L["Time yOffset"] = "時間Y偏移"
+L["Time"] = "時間"
+L["When enabled active buff icons will light up instead of becoming darker, while inactive buff icons will become darker instead of being lit up."] = true;
+L["Wrap After"] = "每行光環數"
+L["Your Auras First"] = "自身光環優先"
+
+--Chat
+L["Above Chat"] = "對話框上方"
+L["Adjust the height of your right chat panel."] = "調整右側聊天框的高度"
+L["Adjust the width of your right chat panel."] = "調整右側聊天框的寬度"
+L["Alerts"] = "警示"
+L["Allowed Combat Repeat"] = "戰鬥連續按鍵修復"
+L["Attempt to create URL links inside the chat."] = "對話視窗出現網址時建立連結."
+L["Attempt to lock the left and right chat frame positions. Disabling this option will allow you to move the main chat frame anywhere you wish."] = "鎖定左右對話框架的位置.禁用此選項將允許你移動對話框架到任意位置."
+L["Below Chat"] = "對話框下方"
+L["Chat EditBox Position"] = "對話輸入框位置"
+L["Chat History"] = "對話記錄"
+L["Chat Timestamps"] = true;
+L["Class Color Mentions"] = "使用職業上色"
+L["Custom Timestamp Color"] = "自訂時間戳記顏色"
+L["Display the hyperlink tooltip while hovering over a hyperlink."] = "滑鼠懸停在超鏈接上時顯示鏈接提示框."
+L["Enable the use of separate size options for the right chat panel."] = "啟用獨立的右聊天框大小選項"
+L["Exclude Name"] = true;
+L["Excluded names will not be class colored."] = true;
+L["Excluded Names"] = true;
+L["Fade Chat"] = "對話內容漸隱"
+L["Fade Tabs No Backdrop"] = "隱藏拖出的聊天框"
+L["Fade the chat text when there is no activity."] = "未出現新訊息時,隱藏對話框的文字."
+L["Fade Undocked Tabs"] = "隱藏分離的聊天框"
+L["Fades the text on chat tabs that are docked in a panel where the backdrop is disabled."] = "當你把一個聊天框拖出聊天背景框的時候會自動隱藏掉,注意這個聊天框並沒有被刪除,關閉該選項你可以重新找到它"
+L["Fades the text on chat tabs that are not docked at the left or right chat panel."] = "當你把一個聊天框設置為分離狀態時會自動隱藏掉,注意這個聊天框並沒有被刪除,關閉該選項你可以重新找到它"
+L["Font Outline"] = "字體描邊"
+L["Font"] = "字體"
+L["Hide Both"] = "全部隱藏"
+L["Hyperlink Hover"] = "超連結提示資訊"
+L["Keyword Alert"] = "關鍵字警報"
+L["Keywords"] = "關鍵字"
+L["Left Only"] = "僅顯示左框背景"
+L["List of words to color in chat if found in a message. If you wish to add multiple words you must seperate the word with a comma. To search for your current name you can use %MYNAME%.\n\nExample:\n%MYNAME%, ElvUI, RBGs, Tank"] = "如果在對話信息中發現如下文字會自動上色該文字. 如果你需要添加多個詞必須用逗號分開. 如要搜尋角色名稱可使用%MYNAME %.\n\n例如:\n%MYNAME%, ElvUI, RBGs, Tank"
+L["Lock Positions"] = "鎖定位置"
+L["Log the main chat frames history. So when you reloadui or log in and out you see the history from your last session."] = "記錄對話歷史,當你重載,登錄和退出時會恢復你最後一次會話"
+L["No Alert In Combat"] = "戰鬥中不警報"
+L["Number of messages you scroll for each step."] = true;
+L["Number of repeat characters while in combat before the chat editbox is automatically closed."] = "當你在戰鬥中按下技能鍵時,有可能你的輸入框還處於打開狀態,這個功能可以在你按下技能鍵並且在輸入框中輸入下列個數字符串卻沒有放出技能時幫你自動關閉輸入框"
+L["Number of time in seconds to scroll down to the bottom of the chat window if you are not scrolled down completely."] = "對話框滾動到底部所需要的滾動時間(秒)."
+L["Panel Backdrop"] = "對話框背景"
+L["Panel Height"] = "對話框高度"
+L["Panel Texture (Left)"] = "對話框材質(左)"
+L["Panel Texture (Right)"] = "對話框材質(右)"
+L["Panel Width"] = "對話框寛度"
+L["Position of the Chat EditBox, if datatexts are disabled this will be forced to be above chat."] = "對話編輯框位置,如果底部的信息文字被禁用的話,將會強制顯示在對話框頂部."
+L["Prevent the same messages from displaying in chat more than once within this set amount of seconds, set to zero to disable."] = "單位時間(秒) 內屏蔽重複對話信息, 設定為0 禁用此功能."
+L["Require holding the Alt key down to move cursor or cycle through messages in the editbox."] = "開啟該選項使你在查看聊天歷史記錄時需要按住Alt+上下鍵,如果關閉則直接按上下鍵即可"
+L["Right Only"] = "僅顯示右框背景"
+L["Right Panel Height"] = "右面板高度"
+L["Right Panel Width"] = "右面板寬度"
+L["Scroll Interval"] = "滾動間隔"
+L["Scroll Messages"] = true;
+L["Separate Panel Sizes"] = "分離框體大小"
+L["Set the font outline."] = "字體描邊設定."
+L["Short Channels"] = "隱藏頻道名稱"
+L["Shorten the channel names in chat."] = "在對話視窗中隱藏頻道名稱."
+L["Show Both"] = "全部顯示"
+L["Spam Interval"] = "洗頻訊息間隔"
+L["Sticky Chat"] = "記憶對話頻道"
+L["Tab Font Outline"] = "分頁字體描邊"
+L["Tab Font Size"] = "分頁字體尺寸"
+L["Tab Font"] = "分頁字體"
+L["Tab Panel Transparency"] = "標籤面板透明"
+L["Tab Panel"] = "標籤面板"
+L["Timestamp Color"] = "時間戳顏色"
+L["Toggle showing of the left and right chat panels."] = "顯示/隱藏左、右對話框背景."
+L["Toggle the chat tab panel backdrop."] = "顯示/隱藏對話框架標籤面板背景."
+L["URL Links"] = "網址連結"
+L["Use Alt Key"] = "對話歷史Alt鍵"
+L["Use class color for the names of players when they are mentioned."] = "當玩家名字被提及時使用職業顏色"
+L["When opening the Chat Editbox to type a message having this option set means it will retain the last channel you spoke in. If this option is turned off opening the Chat Editbox should always default to the SAY channel."] = "打開此選項將會保存你的輸入框為上一次輸入的頻道, 關閉此選項輸入框將始終保持在說的頻道."
+L["Whisper Alert"] = "密語警報"
+L[ [[Specify a filename located inside the World of Warcraft directory. Textures folder that you wish to have set as a panel background.
+
+Please Note:
+-The image size recommended is 256x128
+-You must do a complete game restart after adding a file to the folder.
+-The file type must be tga format.
+
+Example: Interface\AddOns\ElvUI\media\textures\copy
+
+Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = [[若要設定對話框背景, 請將你希望設定為背景的檔案置放於WoW 目錄底下的「Textures」資料夾中, 並指定該檔名.
+
+請注意:
+- 影像尺寸建議為 256 x 128
+- 在此資料夾新增檔案後, 請務必重新啟動遊戲.
+- 檔案必須為 tga 格式.
+
+範例:Interface\AddOns\ElvUI\media\textures\copy
+
+對多數玩家來說, 較簡易的方式是將 tga 檔放入 WoW 資料夾中, 然後在此處輸入檔案名稱.]]
+
+--Class Cache
+L["Class Cache"] = true;
+L["Enable class caching to colorize names in chat and nameplates."] = true;
+L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
+L["Request info for class cache"] = true;
+L["Store cache in DB"] = true;
+L["Use LibWho to cache class info"] = true;
+L["Wipe DB Cache"] = true;
+L["Wipe Session Cache"] = true;
+
+--Credits
+L["Coding:"] = "編碼:"
+L["Credits"] = "嗚謝"
+L["Donations:"] = "捐款: "
+L["ELVUI_CREDITS"] = "我想透過這個特別方式, 向那些協助測試、編碼及透過捐款協助過我的人表達感謝, 請曾提供協助的朋友至論壇傳私訊給我, 我會將你的名字添加至此處."
+L["Testing:"] = "測試:"
+
+--DataBars
+L["Current - Percent (Remaining)"] = true;
+L["Current - Remaining"] = "當前值 - 剩餘值"
+L["DataBars"] = "數據條"
+L["Hide In Combat"] = "戰鬥中隱藏"
+L["Setup on-screen display of information bars."] = "設置各種數據條"
+
+--DataTexts
+L["Battleground Texts"] = "戰場資訊"
+L["Block Combat Click"] = "戰鬥中屏蔽點擊"
+L["Block Combat Hover"] = "戰鬥中屏蔽提示"
+L["Blocks all click events while in combat."] = "戰鬥中禁用點擊事件"
+L["Blocks datatext tooltip from showing in combat."] = "戰鬥中禁用浮動提示"
+L["BottomLeftMiniPanel"] = "小地圖左下內側"
+L["BottomMiniPanel"] = "小地圖底部內側"
+L["BottomRightMiniPanel"] = "小地圖右下內側"
+L["Datatext Panel (Left)"] = "左側資訊框"
+L["Datatext Panel (Right)"] = "右側資訊框"
+L["DataTexts"] = "資訊文字"
+L["Date Format"] = true;
+L["Display data panels below the chat, used for datatexts."] = "在對話框下顯示用於資訊的框架."
+L["Display minimap panels below the minimap, used for datatexts."] = "顯示小地圖下方的資訊框."
+L["Gold Format"] = "金幣格式"
+L["left"] = "左"
+L["LeftChatDataPanel"] = "左對話框"
+L["LeftMiniPanel"] = "小地圖左側"
+L["middle"] = "中"
+L["Minimap Panels"] = "小地圖欄"
+L["Panel Transparency"] = "面板透明"
+L["Panels"] = "對話框"
+L["right"] = "右"
+L["RightChatDataPanel"] = "右對話框"
+L["RightMiniPanel"] = "小地圖右側"
+L["Small Panels"] = "迷你面板"
+L["The display format of the money text that is shown in the gold datatext and its tooltip."] = "在信息文字中顯示的金錢格式"
+L["Time Format"] = true;
+L["TopLeftMiniPanel"] = "Minimap TopLeft (Inside)"
+L["TopMiniPanel"] = "Minimap Top (Inside)"
+L["TopRightMiniPanel"] = "Minimap TopRight (Inside)"
+L["When inside a battleground display personal scoreboard information on the main datatext bars."] = "處於戰場時, 在主資訊文字條顯示你的戰場得分訊息."
+L["Word Wrap"] = "自動換行"
+
+--Distributor
+L["Must be in group with the player if he isn't on the same server as you."] = "如果不是同一服務器, 那他必需和你在同一隊伍中."
+L["Sends your current profile to your target."] = "發送你的配置文件到當前目標."
+L["Sends your filter settings to your target."] = "發送你的過濾器配置到當前目標."
+L["Share Current Profile"] = "分享當前的配置文件"
+L["Share Filters"] = "分享過濾器配置"
+L["This feature will allow you to transfer settings to other characters."] = "此功能將使你設置轉移給其他角色."
+L["You must be targeting a player."] = "你必須以一名玩家為目標."
+
+--Filters
+L["Reset Aura Filters"] = true --Used in Nameplates/UnitFrames general options
+
+--General
+L["Accept Invites"] = "接受組隊邀請"
+L["Adjust the position of the threat bar to either the left or right datatext panels."] = "調整仇恨條的位置於左側或右側資訊面板"
+L["AFK Mode"] = "離開模式"
+L["Announce Interrupts"] = "斷法通告"
+L["Announce when you interrupt a spell to the specified chat channel."] = "在指定對話頻道通知斷法信息."
+L["Attempt to support eyefinity/nvidia surround."] = true;
+L["Auto Greed/DE"] = "自動貪婪/分解"
+L["Auto Repair"] = "自動修裝"
+L["Auto Scale"] = "自動縮放"
+L["Automatically accept invites from guild/friends."] = "自動接受公會成員/朋友的組隊邀請."
+L["Automatically repair using the following method when visiting a merchant."] = "與商人對話時,透過下列方式自動修復裝備."
+L["Automatically scale the User Interface based on your screen resolution"] = "依螢幕解析度自動縮放 UI 介面."
+L["Automatically select greed or disenchant (when available) on green quality items. This will only work if you are the max level."] = "當你的等級達到滿級時, 自動選擇貪婪或分解綠色物品."
+L["Automatically vendor gray items when visiting a vendor."] = "當訪問商人時自動出售灰色物品."
+L["Bottom Panel"] = "底部面板"
+L["Chat Bubbles Style"] = "聊天氣泡樣式"
+L["Chat Bubbles"] = "聊天氣泡"
+L["Controls the amount of decimals used in values displayed on elements like NamePlates and UnitFrames."] = true
+L["Decimal Length"] = true
+L["Direction the bar moves on gains/losses"] = true;
+L["Display a panel across the bottom of the screen. This is for cosmetic only."] = "顯示跨越螢幕底部的面板,僅僅是用于裝飾."
+L["Display a panel across the top of the screen. This is for cosmetic only."] = "顯示跨越螢幕頂部的面板,僅僅是用于裝飾."
+L["Display battleground messages in the middle of the screen."] = "屏幕中間顯示戰場信息"
+L["Enable/Disable the loot frame."] = "啟用/停用拾取框架."
+L["Enable/Disable the loot roll frame."] = "啟用/停用擲骰框架."
+L["Enables the ElvUI Raid Control panel."] = true;
+L["Enhanced PVP Messages"] = "PVP增強信息"
+L["General"] = "一般設定"
+L["Height of the watch tracker. Increase size to be able to see more objectives."] = "任務框體的高度.增加大小以看到更多目標"
+L["Hide At Max Level"] = "在最高等級時隱藏"
+L["Hide Error Text"] = "隱藏錯誤文字"
+L["Hide In Vehicle"] = "騎乘時隱藏"
+L["Hides the red error text at the top of the screen while in combat."] = "戰鬥中隱藏螢幕頂部紅字錯誤信息."
+L["Log Taints"] = "錯誤記錄"
+L["Login Message"] = "登入資訊"
+L["Loot Roll"] = "擲骰"
+L["Loot"] = "拾取"
+L["Lowest Allowed UI Scale"] = "最低允許UI縮放"
+L["Multi-Monitor Support"] = "多顯示器支持"
+L["Name Font"] = "名稱字體"
+L["Number Prefix"] = "數值縮寫"
+L["Party / Raid"] = "小隊/團隊"
+L["Party Only"] = "僅小隊"
+L["Raid Only"] = "僅團隊"
+L["Remove Backdrop"] = "移除背景"
+L["Reset all frames to their original positions."] = "重設所有框架至預設位置."
+L["Reset Anchors"] = "重置位置"
+L["Send ADDON_ACTION_BLOCKED errors to the Lua Error frame. These errors are less important in most cases and will not effect your game performance. Also a lot of these errors cannot be fixed. Please only report these errors if you notice a Defect in gameplay."] = "發送ADDON_ACTION_BLOCKED錯誤至Lua錯誤框, 這些錯誤並不重要, 不會影響你的遊戲體驗. 並且很多這類錯誤無法被修復. 請只將影響遊戲體驗的錯誤發送給我們."
+L["Skin Backdrop (No Borders)"] = "美化背景(無邊界)"
+L["Skin Backdrop"] = "美化背景"
+L["Skin the blizzard chat bubbles."] = "美化暴雪對話泡泡."
+L["The font that appears on the text above players heads. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "玩家頭頂姓名的字體. |cffFF0000警告: 你需要重新開啟遊戲或重新登錄才能使用此功能.|r"
+L["The Thin Border Theme option will change the overall apperance of your UI. Using Thin Border Theme is a slight performance increase over the traditional layout."] = "細邊框主題會改變所有的外觀,使用細邊框主題會略微提升性能"
+L["Thin Border Theme"] = "細邊框主題"
+L["Toggle Tutorials"] = "教學開關"
+L["Top Panel"] = "頂部面板"
+L["Version Check"] = true;
+L["Watch Frame Height"] = true;
+L["When you go AFK display the AFK screen."] = "當你離開時顯示AFK界面"
+
+--Media
+L["Applies the font and font size settings throughout the entire user interface. Note: Some font size settings will be skipped due to them having a smaller font size by default."] = "把該字體設置應用到所有ElvUI設置中去,但是某些設置並不會被改變."
+L["Applies the primary texture to all statusbars."] = "將主要材質應用到所有狀態條"
+L["Apply Font To All"] = "應用字體到所有"
+L["Apply Texture To All"] = "應用材質到所有"
+L["Backdrop color of transparent frames"] = "透明框架的背景顏色"
+L["Backdrop Color"] = "背景顏色"
+L["Backdrop Faded Color"] = "背景透明色"
+L["Border Color"] = "邊框顏色"
+L["Color some texts use."] = "數值(非文字)使用的顏色"
+L["Colors"] = "顏色"
+L["CombatText Font"] = "戰鬥文字字體"
+L["Default Font"] = "預設字體"
+L["Font Size"] = "字體尺寸"
+L["Fonts"] = "字體"
+L["Main backdrop color of the UI."] = "介面背景主色"
+L["Main border color of the UI."] = "UI的主要邊框顏色."
+L["Media"] = "材質"
+L["Primary Texture"] = "主要材質"
+L["Replace Blizzard Fonts"] = "替代暴雪字體"
+L["Replaces the default Blizzard fonts on various panels and frames with the fonts chosen in the Media section of the ElvUI config. NOTE: Any font that inherits from the fonts ElvUI usually replaces will be affected as well if you disable this. Enabled by default."] = "用ElvUI字體設置代替暴雪原有字體設置,如果禁用有可能導致你的UI出問題,默認開啟開選項."
+L["Secondary Texture"] = "次要材質"
+L["Set the font size for everything in UI. Note: This doesn't effect somethings that have their own seperate options (UnitFrame Font, Datatext Font, ect..)"] = "設定介面上所有字體的尺寸, 但不包含本身有獨立設定的字體(如單位框架字體、資訊文字字體等...)"
+L["Textures"] = "材質"
+L["The font that combat text will use. |cffFF0000WARNING: This requires a game restart or re-log for this change to take effect.|r"] = "戰鬥資訊將使用此字體, |cffFF0000警告:需重啟遊戲或重新登入才可使此變更生效.|r"
+L["The font that the core of the UI will use."] = "核心UI 所使用的字體."
+L["The texture that will be used mainly for statusbars."] = "此材質主用於狀態列上."
+L["This texture will get used on objects like chat windows and dropdown menus."] = "主要用於對話視窗及下拉選單等物件的材質."
+L["Value Color"] = "數值顏色"
+
+--Maps
+L["Adjust the size of the minimap."] = "調整小地圖尺寸."
+L["Always Display"] = "總是顯示"
+L["Bottom Left"] = "左下"
+L["Bottom Right"] = "右下"
+L["Bottom"] = "下"
+L["Change settings for the display of the location text that is on the minimap."] = "改變小地圖所在位置文字的顯示設定."
+L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"] = "是否啟用小地圖. |cffFF0000警告: 關掉後你將看不到小地圖周圍的資訊文字.|r"
+L["Instance Difficulty"] = "副本難度"
+L["Left"] = "左"
+L["LFG Queue"] = "隨機隊列"
+L["Location Text"] = "所在位置文字"
+L["Make the world map smaller."] = "讓世界地圖更小."
+L["Maps"] = "地圖"
+L["Minimap Buttons"] = "小地圖按鈕"
+L["Minimap Mouseover"] = "小地圖滑鼠滑過"
+L["Puts coordinates on the world map."] = "在世界地圖上放置坐標"
+L["PvP Queue"] = true
+L["Reset Zoom"] = "重置縮放"
+L["Right"] = "右"
+L["Scale"] = "縮放"
+L["Smaller World Map"] = "更小的世界地圖"
+L["Top Left"] = "左上"
+L["Top Right"] = "右上"
+L["Top"] = "上"
+L["World Map Coordinates"] = "世界地圖坐標"
+L["X-Offset"] = "X偏移"
+L["Y-Offset"] = "Y偏移"
+
+--Misc
+L["Install"] = "安裝"
+L["Run the installation process."] = "執行安裝程序"
+L["Toggle Anchors"] = "解鎖元件定位"
+L["Unlock various elements of the UI to be repositioned."] = "解鎖介面上的各種元件, 以便更改位置."
+L["Version"] = "版本"
+
+--NamePlates
+L["# Displayed Auras"] = "顯示光環的數量"
+L["Actions"] = "動作"
+L["Add Name"] = "添加名稱"
+L["Add Nameplate Filter"] = "添加姓名版過濾器"
+L["Add Regular Filter"] = "添加常規過濾器"
+L["Add Special Filter"] = "添加特殊過濾器"
+L["Always Show Target Health"] = "始終顯示目標血量"
+L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."] = true
+L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."] = true
+L["Background Glow"] = "背景發光"
+L["Bad Color"] = "危險顏色"
+L["Bad Scale"] = "危險縮放"
+L["Bad Transition Color"] = "危險過渡顏色"
+L["Base Height for the Aura Icon"] = "光環圖標基礎高度"
+L["Border Glow"] = "邊框發光"
+L["Border"] = "邊框"
+L["Cast Bar"] = "施法條"
+L["Cast Color"] = "施法條顏色"
+L["Cast No Interrupt Color"] = "無法打斷的顏色"
+L["Cast Time Format"] = "施法時間格式"
+L["Casting"] = "施法"
+L["Channel Time Format"] = "通道法術時間格式"
+L["Clear Filter"] = "清空過濾器"
+L["Color Tanked"] = "被坦住的顏色"
+L["Control enemy nameplates toggling on or off when in combat."] = "控制戰鬥中敵對姓名板的開啟和關閉"
+L["Control friendly nameplates toggling on or off when in combat."] = "控制戰鬥中友方姓名板的開啟和關閉"
+L["Controls how many auras are displayed, this will also affect the size of the auras."] = "控制顯示多少光環,這也會影響光環大小"
+L["Cooldowns"] = true
+L["Copy settings from another unit."] = "從其他框架中複製設置"
+L["Copy Settings From"] = "複製設置"
+L["Current Level"] = "當前等級"
+L["Default Settings"] = "默認設置"
+L["Display a healer icon over known healers inside battlegrounds or arenas."] = "戰場或競技場中,為已確認為補職的玩家標上補職圖示."
+L["Elite Icon"] = "精英標誌"
+L["Enable/Disable the scaling of targetted nameplates."] = "啟用/禁用目標姓名板的縮放"
+L["Enabling this will check your health amount."] = true
+L["Enemy Combat Toggle"] = "敵對戰鬥開關"
+L["Enemy NPC Frames"] = "敵對NPC框架"
+L["Enemy Player Frames"] = "敵對玩家框架"
+L["Enemy"] = "敵對"
+L["ENEMY_NPC"] = "Enemy NPC"
+L["ENEMY_PLAYER"] = "Enemy Player"
+L["Filter already exists!"] = "過濾器已存在!"
+L["Filter Priority"] = "過濾器優先順序"
+L["Filters Page"] = "過濾器介面"
+L["Friendly Combat Toggle"] = "友方戰鬥開關"
+L["Friendly NPC Frames"] = "友方NPC框架"
+L["Friendly Player Frames"] = "友方玩家框架"
+L["FRIENDLY_NPC"] = "Friendly NPC"
+L["FRIENDLY_PLAYER"] = "Friendly Player"
+L["General Options"] = "常規選項"
+L["Good Color"] = "正常顏色"
+L["Good Scale"] = "正常縮放"
+L["Good Transition Color"] = "正常過渡顏色"
+L["Healer Icon"] = "補職圖示"
+L["Health Color"] = "血量顏色"
+L["Health Threshold"] = "血量閾值"
+L["Hide Frame"] = "隱藏框架"
+L["Hide Spell Name"] = "隱藏法術名字"
+L["Hide Time"] = "隱藏時間"
+L["Hide"] = "隱藏"
+L["How many seconds the castbar should stay visible after the cast failed or was interrupted."] = "在施法失敗或被打斷時施法條保持可見的秒數"
+L["Icon Base Height"] = "圖標基礎高度"
+L["Icon Position"] = true
+L["If enabled then it checks if auras are missing instead of being present on the unit."] = "如果選中則將會檢查光環是否缺失而不是光環是否存在"
+L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."] = "如果選中則要求滿足所有光環. 不啟用則只要求任一光環存在即可啟動."
+L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."] = true
+L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."] = "如果選中則過濾器僅僅在單位等級大於等於該值的時候啟動"
+L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."] = "如果選中則過濾器僅僅在單位等級小於等於該值的時候啟動"
+L["If enabled then the filter will only activate if the level of the unit matches this value."] = "如果選中則過濾器僅僅在單位等級符合該值的時候啟動"
+L["If enabled then the filter will only activate if the level of the unit matches your own."] = "如果選中則過濾器僅僅在單位等級符合你的等級的時候啟動"
+L["If enabled then the filter will only activate if the unit is casting interruptible spells."] = "如果選中則過濾器僅僅在單位施放可打斷技能的時候啟動"
+L["If enabled then the filter will only activate when you are in combat."] = "如果選中則過濾器僅僅在你在戰鬥中的時候啟動"
+L["If enabled then the filter will only activate when you are out of combat."] = "如果選中則過濾器僅僅在你不在戰鬥中的時候啟動"
+L["If the aura is listed with a number then you need to use that to remove it from the list."] = "如果光環和一個數一起列出你需要用它來將其移出列表"
+L["If this list is empty, and if 'Interruptible' is checked, then the filter will activate on any type of cast that can be interrupted."] = "如果列表為空, 並且'可打斷'被選中, 那麼過濾器會在任何可被打斷的施法時啟動"
+L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."] = "如果這個閾值被設置則單位的血量需要比設定值更高才會將過濾器啟動. 設為0以禁用."
+L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."] = "如果這個閾值被設置則單位的血量需要比設定值更低才會將過濾器啟動. 設為0以禁用."
+L["Instance Type"] = true
+L["Interruptible"] = "可打斷"
+L["Is Targeted"] = "目標"
+L["LEVEL_BOSS"] = "Set level to -1 for boss units or set to 0 to disable."
+L["Low Health Threshold"] = "低生命值閥值"
+L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."] = "更低的數值意味著更高的優先順序. 過濾器將按照1至100的順序進行."
+L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."] = "姓名板在此設定值下會變黃色,在設定值一半以下會變紅色."
+L["Match Player Level"] = "符合玩家等級"
+L["Maximum Level"] = "最高等級"
+L["Maximum Time Left"] = true
+L["Minimum Level"] = "最低等級"
+L["Minimum Time Left"] = true
+L["Missing"] = "缺失"
+L["Name Color"] = "姓名顏色"
+L["Name Only"] = true
+L["NamePlates"] = "姓名面板(血條)"
+L["Nameplate Motion Type"] = true;
+L["Non-Target Transparency"] = "非目標透明度"
+L["Not Targeted"] = "非目標"
+L["Off Cooldown"] = true
+L["On Cooldown"] = true
+L["Over Health Threshold"] = "高於血量閾值"
+L["Overlapping Nameplates"] = true;
+L["Personal Auras"] = "個人光環"
+L["Player Health"] = true
+L["Player in Combat"] = "玩家戰鬥中"
+L["Player Out of Combat"] = "玩家戰鬥外"
+L["Reaction Colors"] = "聲望顏色"
+L["Reaction Type"] = "聲望類型"
+L["Remove a Name from the list."] = true
+L["Remove Name"] = "刪除篩選名"
+L["Remove Nameplate Filter"] = "移除姓名版過濾器"
+L["Require All"] = "要求全部"
+L["Reset filter priority to the default state."] = "重置過濾器優先順序到預設狀態"
+L["Reset Priority"] = "重置優先順序"
+L["Return filter to its default state."] = "返回過濾器至預設狀態"
+L["Scale of the nameplate that is targetted."] = "縮放選定目標的姓名板"
+L["Select Nameplate Filter"] = "選擇姓名版過濾器"
+L["Set Settings to Default"] = "恢復默認設置"
+L["Set the transparency level of nameplates that are not the target nameplate."] = "設定未被選中目標的姓名板的透明度"
+L["Set to either stack nameplates vertically or allow them to overlap."] = "設置將姓名板垂直排列或者允許重疊"
+L["Shortcut to 'Filters' section of the config."] = "一個到'過濾器'功能表的快速鍵"
+L["Shortcut to global filters."] = true
+L["Shortcuts"] = "快捷鍵"
+L["Side Arrows"] = "側面箭頭"
+L["Stacking Nameplates"] = true;
+L["Style Filter"] = "樣式過濾器"
+L["Tagged NPC"] = "標記的NPC"
+L["Tanked Color"] = "坦克顏色"
+L["Target Indicator Color"] = true
+L["Target Indicator"] = "目標指示器"
+L["Target Scale"] = "目標縮放"
+L["Targeted Nameplate"] = "目標姓名板"
+L["Texture"] = "材質"
+L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."] = "這些過濾器不像常規過濾器那樣使用一個法術列表, 而是使用魔獸API和部分代碼邏輯來決定光環顯示與否."
+L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."] = "這些過濾器使用一個法術清單來決定光環顯示與否. 這些過濾器的內容可以在設置中的'過濾器'選項中更改."
+L["This will reset the contents of this filter back to default. Any spell you have added to this filter will be removed."] = true
+L["Threat"] = "仇恨"
+L["Time To Hold"] = "停留時間"
+L["Toggle Off While In Combat"] = "戰鬥時關閉"
+L["Toggle On While In Combat"] = "戰鬥時啟用"
+L["Top Arrow"] = "頂部箭頭"
+L["Triggers"] = "觸發器"
+L["Under Health Threshold"] = "低於血量閾值"
+L["Unit Type"] = "單位類型"
+L["Use Class Color"] = "使用職業顏色"
+L["Use drag and drop to rearrange filter priority or right click to remove a filter."] = "使用拖拽的方式調整過濾器優先順序, 或者右鍵移除一個過濾器"
+L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."] = true
+L["Use Tanked Color when a nameplate is being effectively tanked by another tank."] = "當另一個坦克更有效的坦住時姓名板使用被坦住的顏色"
+L["Use Target Glow"] = "目標外框高亮"
+L["Use Target Scale"] = "使用目標縮放"
+L["Use Threat Color"] = "使用仇恨顏色"
+L["You can't remove a default name from the filter, disabling the name."] = "你無法自篩選器移除,請停用預設名稱."
+
+--Profiles Export/Import
+L["Choose Export Format"] = "選擇導出格式"
+L["Choose What To Export"] = "選擇導出內容"
+L["Decode Text"] = "解碼文字"
+L["Error decoding data. Import string may be corrupted!"] = "解碼錯誤.導出字符串可能已損壞!"
+L["Error exporting profile!"] = "導出配置文件失敗"
+L["Export Now"] = "現在導出"
+L["Export Profile"] = "導出配置文件"
+L["Exported"] = "已導出"
+L["Filters (All)"] = "過濾器(全部)"
+L["Filters (NamePlates)"] = "過濾器(姓名板)"
+L["Filters (UnitFrames)"] = "過濾器(框架)"
+L["Global (Account Settings)"] = "全域(賬號設置)"
+L["Import Now"] = "現在導入"
+L["Import Profile"] = "導入配置文件"
+L["Importing"] = "正在導入"
+L["Plugin"] = "插件"
+L["Private (Character Settings)"] = "個人(角色配置)"
+L["Profile imported successfully!"] = "配置文件導入成功"
+L["Profile Name"] = "配置文件名稱"
+L["Profile"] = "配置文件"
+L["Table"] = "表"
+
+--Skins
+L["Achievement Frame"] = "成就"
+L["Alert Frames"] = "警報"
+L["Arena Frame"] = true;
+L["Arena Registrar"] = true;
+L["Auction Frame"] = "拍賣"
+L["Barbershop Frame"] = "美容院"
+L["BG Map"] = "戰場地圖"
+L["BG Score"] = "戰場積分"
+L["Calendar Frame"] = "行事曆"
+L["Character Frame"] = "角色"
+L["Debug Tools"] = "除錯工具"
+L["Dressing Room"] = "試衣間"
+L["GM Chat"] = true;
+L["Gossip Frame"] = "對話"
+L["Greeting Frame"] = true;
+L["Guild Bank"] = "公會銀行"
+L["Guild Registrar"] = "公會註冊"
+L["Help Frame"] = "幫助"
+L["Inspect Frame"] = "觀察"
+L["KeyBinding Frame"] = "快捷鍵"
+L["LFD Frame"] = true;
+L["LFR Frame"] = true;
+L["Loot Frames"] = "拾取框架"
+L["Macro Frame"] = "巨集"
+L["Mail Frame"] = "信箱"
+L["Merchant Frame"] = "商人"
+L["Mirror Timers"] = true;
+L["Misc Frames"] = "其他"
+L["Petition Frame"] = "回報GM"
+L["PvP Frames"] = "PvP框架"
+L["Quest Frames"] = "任務"
+L["Raid Frame"] = "團隊框架"
+L["Skins"] = "美化外觀"
+L["Socket Frame"] = "珠寶插槽"
+L["Spellbook"] = "技能書"
+L["Stable"] = "獸欄"
+L["Tabard Frame"] = "外袍"
+L["Talent Frame"] = "天賦"
+L["Taxi Frame"] = "載具"
+L["Time Manager"] = "時間管理"
+L["Trade Frame"] = "交易"
+L["TradeSkill Frame"] = "專業技能"
+L["Trainer Frame"] = "訓練師"
+L["Tutorial Frame"] = true;
+L["World Map"] = "世界地圖"
+
+--Tooltip
+L["Always Hide"] = "總是隱藏"
+L["Bags Only"] = "僅背包"
+L["Bags/Bank"] = "背包/銀行"
+L["Bank Only"] = "僅銀行"
+L["Both"] = "兩者"
+L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."] = "選擇何時顯示提示.如果選擇了設置鍵,你需要按住它來顯示提示"
+L["Comparison Font Size"] = "比較字體大小"
+L["Cursor Anchor"] = "指針錨點"
+L["Custom Faction Colors"] = "自定義聲望顏色"
+L["Display guild ranks if a unit is guilded."] = "當目標有公會時顯示其位階."
+L["Display how many of a certain item you have in your possession."] = "顯示當前物品在你身上的數量"
+L["Display player titles."] = "顯示玩家稱號."
+L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."] = "當按住shift時展示該玩家的專精和裝等,由於需要讀取所以不會在指向某玩家時立即更新."
+L["Display the spell or item ID when mousing over a spell or item tooltip."] = "滑鼠提示中顯示技能或物品的ID"
+L["Guild Ranks"] = "公會會階"
+L["Header Font Size"] = "標題名字大小"
+L["Health Bar"] = "生命條"
+L["Hide tooltip while in combat."] = "戰鬥時不顯示提示."
+L["Inspect Info"] = "更多信息"
+L["Item Count"] = "物品數量"
+L["Never Hide"] = "從不隱藏"
+L["Player Titles"] = "玩家稱號"
+L["Should tooltip be anchored to mouse cursor"] = "提示錨定在滑鼠"
+L["Spell/Item IDs"] = "技能/物品ID"
+L["Target Info"] = "目標信息"
+L["Text Font Size"] = "字體大小"
+L["This setting controls the size of text in item comparison tooltips."] = "設置對比框中的文字大小"
+L["Tooltip Font Settings"] = "提示文字設置"
+L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."] = "顯示團隊中目標與你目前浮動提示目標相同的隊友."
+
+--UnitFrames
+L["%s and then %s"] = "%s 與 %s"
+L["2D"] = "2D"
+L["3D"] = "3D"
+L["Above"] = "向上"
+L["Add a spell to the filter. Use spell ID if you don't want to match all auras which share the same name."] = "添加一個技能到過濾器.使用法術ID以避免匹配到同名的光環"
+L["Add a spell to the filter."] = "添加一個技能到過濾器"
+L["Add Spell ID or Name"] = "添加技能ID或者名字"
+L["Add SpellID"] = "添加技能ID"
+L["Additional Filter Override"] = true;
+L["Additional Filter"] = "額外的過濾器"
+L["Allow non-personal auras from additional filter when 'Block Non-Personal Auras' is enabled."] = true;
+L["Allow Whitelisted Auras"] = "允許白名單中的光環"
+L["An X offset (in pixels) to be used when anchoring new frames."] = "錨定新框架時的X偏移(單位:像素)"
+L["An Y offset (in pixels) to be used when anchoring new frames."] = "錨定新框架時的Y偏移(單位:像素)"
+L["Animation Speed"] = true;
+L["Ascending or Descending order."] = "升序或降序"
+L["Assist Frames"] = "助理框架"
+L["Assist Target"] = "助理目標"
+L["At what point should the text be displayed. Set to -1 to disable."] = "在何時顯示文本. 設定為-1 禁用此功能."
+L["Attach Text To"] = "文字附著於"
+L["Attach To"] = "附加到"
+L["Aura Bars"] = "光環條"
+L["Auto-Hide"] = "自動隱藏"
+L["Bad"] = "危險"
+L["Bars will transition smoothly."] = "狀態條平滑增減"
+L["Below"] = "向下"
+L["Blacklist Modifier"] = "黑名單功能鍵"
+L["Blacklist"] = "黑名單"
+L["Block Auras Without Duration"] = "不顯示沒有持續時間的光環"
+L["Block Blacklisted Auras"] = "不顯示黑名單中的光環"
+L["Block Non-Dispellable Auras"] = "顯示可以驅散的光環"
+L["Block Non-Personal Auras"] = "顯示個人光環"
+L["Block Raid Buffs"] = true;
+L["Blood"] = "血魄符文"
+L["Borders"] = "邊框"
+L["Buff Indicator"] = "Buff 提示器"
+L["Buffs"] = "增益光環"
+L["By Type"] = "類型"
+L["Castbar"] = "施法條"
+L["Center"] = "置中"
+L["Check if you are in range to cast spells on this specific unit."] = "檢查你是否在技能有效範圍內."
+L["Choose UIPARENT to prevent it from hiding with the unitframe."] = "使用UIPARENT來防止它隨框體隱藏"
+L["Class Backdrop"] = "生命條背景職業色"
+L["Class Castbars"] = "施法條職業色"
+L["Class Color Override"] = "職業色覆蓋"
+L["Class Health"] = "生命條職業色"
+L["Class Power"] = "能量條職業色"
+L["Class Resources"] = "職業能量"
+L["Click Through"] = "點擊穿透"
+L["Color all buffs that reduce the unit's incoming damage."] = "減少目標受到的傷害的所有 Buff 的顏色."
+L["Color aurabar debuffs by type."] = "按類型顯示光環條顔色."
+L["Color castbars by the class of player units."] = "按職業顯示施法條顏色"
+L["Color castbars by the reaction type of non-player units."] = "按非玩家單位的聲望顯示施法條顏色"
+L["Color health by amount remaining."] = "按數值變化血量顏色."
+L["Color health by classcolor or reaction."] = "以職業色顯示生命."
+L["Color power by classcolor or reaction."] = "以職業色顯示能量."
+L["Color the health backdrop by class or reaction."] = "生命條背景色以職業色顯示."
+L["Color the unit healthbar if there is a debuff that can be dispelled by you."] = "如果單位目標的減益光環可被驅散, 加亮顯示其生命值."
+L["Color Turtle Buffs"] = "減傷類 Buff 的顏色"
+L["Color"] = "顏色"
+L["Colored Icon"] = "圖示色彩"
+L["Coloring (Specific)"] = "著色(具體)"
+L["Coloring"] = "著色"
+L["Combat Fade"] = "戰鬥隱藏"
+L["Combat Icon"] = "戰鬥按鈕"
+L["Combo Point"] = "連擊點"
+L["Combobar"] = true;
+L["Configure Auras"] = "設置光環"
+L["Copy From"] = "複製自"
+L["Count Font Size"] = "計數字體尺寸"
+L["Create a custom fontstring. Once you enter a name you will be able to select it from the elements dropdown list."] = "輸入一個名稱創建自定義字體樣式之後, 你可以在組件的下拉菜單中選擇使用."
+L["Create a filter, once created a filter can be set inside the buffs/debuffs section of each unit."] = "創造一個過濾器, 一旦創造, 每個單位的buff/debuff 都能使用."
+L["Create Custom Text"] = true
+L["Create Filter"] = "創造過濾器"
+L["Current - Max | Percent"] = "目前值- 最大值| 百分比"
+L["Current - Max"] = "目前值 - 最大值"
+L["Current - Percent"] = "目前值 - 百分比"
+L["Current / Max"] = "目前/最大值"
+L["Current"] = "目前值"
+L["Custom Dead Backdrop"] = "自定義死亡背景"
+L["Custom Health Backdrop"] = "自訂生命條背景"
+L["Custom Texts"] = "自定義字體"
+L["Death"] = "死亡符文"
+L["Debuff Highlighting"] = "減益光環加亮顯示"
+L["Debuffs"] = "減益光環"
+L["Decimal Threshold"] = "小數閾值"
+L["Deficit"] = "虧損值"
+L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."] = "刪除一個創造的過濾器, 你不能刪除內建的過濾器, 只能刪除你自已添加的."
+L["Delete Filter"] = "刪除過濾器"
+L["Detach From Frame"] = "從框架分離"
+L["Detached Width"] = "分離寬度"
+L["Direction the health bar moves when gaining/losing health."] = "生命條的增減方向."
+L["Disable Debuff Highlight"] = "禁用debuff高亮"
+L["Disabled Blizzard Frames"] = "禁用暴雪框架"
+L["Disabled"] = "禁用"
+L["Disables the focus and target of focus unitframes."] = "禁用焦點和目標的焦點框架"
+L["Disables the player and pet unitframes."] = "禁用玩家和寵物框架"
+L["Disables the target and target of target unitframes."] = "禁用目標和目標的目標框架"
+L["Disconnected"] = "離線"
+L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."] = "在施法狀態條的末端顯示一個火花材質來區分施法條和背景條."
+L["Display Frames"] = "顯示框架"
+L["Display Player"] = "顯示玩家"
+L["Display Target"] = "顯示目標"
+L["Display Text"] = "顯示文本"
+L["Display the castbar icon inside the castbar."] = "在施法條內顯示圖標"
+L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."] = "如果關閉施法條內顯示圖標,你可以自定義施法條外圖標的大小和位置"
+L["Display the combat icon on the unitframe."] = "在單位框架內顯示戰鬥圖標"
+L["Display the rested icon on the unitframe."] = "在單位框架上顯示充分休息圖示."
+L["Display the target of your current cast. Useful for mouseover casts."] = "顯示你當前的施法目標. 可以轉換成鼠标滑過類型."
+L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."] = "若為需引導的法術, 在施法條上顯示每跳週期傷害. 啟動此功能後, 針對吸取靈魂這類的法術, 將自動調整顯示每跳週期傷害, 並視加速等級增加額外的周期傷害."
+L["Don't display any auras found on the 'Blacklist' filter."] = "不顯示任何'黑名單'過濾器中的光環."
+L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."] = "不顯示高於此時間(單位:秒)的光環.設置為0以禁用"
+L["Don't display auras that are not yours."] = "不顯示不是你施放的光環."
+L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."] = true
+L["Don't display auras that cannot be purged or dispelled by your class."] = "不顯示你不能驅散的光環."
+L["Don't display auras that have no duration."] = "不限時沒有持續時間的光環."
+L["Don't display raid buffs such as Blessing of Kings or Mark of the Wild."] = true;
+L["Down"] = "下"
+L["Dungeon & Raid Filter"] = true
+L["Duration Reverse"] = "持續時間反轉"
+L["Duration Text"] = "持續時間文字"
+L["Duration"] = "持續時間"
+L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."] = "啟用後將可以在整個團隊內排序,但你不再可以區分不同小隊"
+L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."] = "啟用後翻轉未滿團隊的隊伍順序(起始方向)"
+L["Enemy Aura Type"] = "敵對光環類型"
+L["Fade the unitframe when out of combat, not casting, no target exists."] = "非戰鬥/施法/目標不存在時隱藏單位框架"
+L["Fill"] = "填充"
+L["Filled"] = "全長"
+L["Filter Type"] = "過濾器類型"
+L["Fluid Position Buffs on Debuffs"] = true
+L["Fluid Position Debuffs on Buffs"] = true
+L["Force Off"] = "強制關閉"
+L["Force On"] = "強制開啓"
+L["Force Reaction Color"] = "強制聲望顏色"
+L["Force the frames to show, they will act as if they are the player frame."] = "強制框架顯示."
+L["Forces Debuff Highlight to be disabled for these frames"] = "為這些框架強制禁用debuff高亮"
+L["Forces reaction color instead of class color on units controlled by players."] = "對於玩家控制的角色強制使用聲望顏色而不是職業顏色"
+L["Format"] = "格式"
+L["Frame Level"] = "框架層次"
+L["Frame Orientation"] = "框架方向"
+L["Frame Strata"] = "框架層級"
+L["Frame"] = "框架"
+L["Frequent Updates"] = "立即更新生命值"
+L["Friendly Aura Type"] = "友好目標光環類型"
+L["Friendly"] = "友好"
+L["Frost"] = "冰霜符文"
+L["Glow"] = "閃爍"
+L["Good"] = "安全"
+L["GPS Arrow"] = true;
+L["Group By"] = "隊伍排列方式"
+L["Grouping & Sorting"] = "分組與排序"
+L["Groups Per Row/Column"] = "每行/列的組數"
+L["Growth direction from the first unitframe."] = "增長方向從第一個頭像框架開始."
+L["Growth Direction"] = "增長方向"
+L["Heal Prediction"] = "治療量預測"
+L["Health Backdrop"] = "生命條背景"
+L["Health Border"] = "生命條邊框"
+L["Health By Value"] = "生命條顏色依數值變化"
+L["Health"] = "生命條"
+L["Height"] = "高"
+L["Horizontal Spacing"] = "水平間隔"
+L["Horizontal"] = "水平"
+L["Icon Inside Castbar"] = "施法條內的圖標"
+L["Icon Size"] = "圖標尺寸"
+L["Icon"] = "圖示"
+L["Icon: BOTTOM"] = "圖示: 底部"
+L["Icon: BOTTOMLEFT"] = "圖示: 底部左側"
+L["Icon: BOTTOMRIGHT"] = "圖示: 底部右側"
+L["Icon: LEFT"] = "圖示: 左側"
+L["Icon: RIGHT"] = "圖示: 右側"
+L["Icon: TOP"] = "圖示: 頂部"
+L["Icon: TOPLEFT"] = "圖示: 頂部左側"
+L["Icon: TOPRIGHT"] = "圖示: 頂部右側"
+L["If no other filter options are being used then it will block anything not on the 'Whitelist' filter, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "若沒有啓用其他過濾器,那只會顯示'白名單'裡面的光環."
+L["If not set to 0 then override the size of the aura icon to this."] = "若設為 0,光環圖示大小將不會變更為此值."
+L["If the unit is an enemy to you."] = "如果是你的敵對目標"
+L["If the unit is friendly to you."] = "如果是你的友好目標"
+L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."] = "如果你同時激活了很多3D頭像你很可能有FPS的影響.如果你有這方面的問題請禁用一部分頭像"
+L["Ignore mouse events."] = "忽略滑鼠事件."
+L["InfoPanel Border"] = "信息面板邊框"
+L["Information Panel"] = "信息面板"
+L["Inset"] = "插入"
+L["Inside Information Panel"] = "插入信息面板"
+L["Interruptable"] = "可斷法的施法顏色"
+L["Invert Grouping Order"] = "反轉隊伍排序"
+L["JustifyH"] = "橫向字體對齊"
+L["Latency"] = "延遲"
+L["Left to Right"] = "左到右"
+L["Main statusbar texture."] = "主狀態條材質"
+L["Main Tanks / Main Assist"] = "主坦克 / 主助理"
+L["Make textures transparent."] = "材質透明"
+L["Match Frame Width"] = "匹配視窗寬度"
+L["Max amount of overflow allowed to extend past the end of the health bar."] = true
+L["Max Bars"] = "最多"
+L["Max Overflow"] = true
+L["Maximum Duration"] = "最大持續時間"
+L["Method to sort by."] = "排序方式"
+L["Middle Click - Set Focus"] = "滑鼠中鍵 - 設置焦點"
+L["Middle clicking the unit frame will cause your focus to match the unit."] = "滑鼠中鍵點擊單位框架設置焦點."
+L["Middle"] = "中間"
+L["Minimum Duration"] = "最低持續時間"
+L["Mouseover"] = "滑鼠滑過顯示"
+L["Name"] = "姓名"
+L["Neutral"] = "中立"
+L["Non-Interruptable"] = "不可斷法的施法條色"
+L["None"] = "無"
+L["Not valid spell id"] = "無效的技能ID"
+L["Num Rows"] = "行數"
+L["Number of Groups"] = "每隊單位數量"
+L["Offset of the powerbar to the healthbar, set to 0 to disable."] = "偏移能量條與生命條的位置, 設定為0 禁用此功能."
+L["Offset position for text."] = "偏移文本的位置."
+L["Offset"] = "偏移"
+L["Only Match SpellID"] = true
+L["Only show when the unit is not in range."] = "不在範圍內時顯示."
+L["Only show when you are mousing over a frame."] = "鼠標滑過時顯示."
+L["OOR Alpha"] = "超出距離透明度"
+L["Other Filter"] = true
+L["Others"] = "他人的"
+L["Overlay the healthbar"] = "頭像重疊顯示於生命條上"
+L["Overlay"] = "重疊顯示"
+L["Override any custom visibility setting in certain situations, EX: Only show groups 1 and 2 inside a 10 man instance."] = "複寫可見性的設定, 例如: 在10人副本里只顯示1隊和2隊."
+L["Override the default class color setting."] = "覆蓋默認職業色設置."
+L["Owners Name"] = "所有者姓名"
+L["Parent"] = true;
+L["Party Pets"] = "隊伍寵物"
+L["Party Targets"] = "隊伍目標"
+L["Per Row"] = "每行"
+L["Percent"] = "百分比"
+L["Personal"] = "個人的"
+L["Pet Name"] = "寵物名字"
+L["Player Frame Aura Bars"] = "玩家框架光環條"
+L["Portrait"] = "頭像"
+L["Position Buffs on Debuffs"] = "增益在減益上"
+L["Position Debuffs on Buffs"] = "減益在減益上"
+L["Position"] = "位置"
+L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."] = "NPC 目標將隱藏能量值文字."
+L["Power"] = "能量"
+L["Powers"] = "能量"
+L["Priority"] = "優先級"
+L["Profile Specific"] = "角色專用"
+L["PvP Icon"] = "PvP圖標"
+L["PvP Text"] = "PvP文字"
+L["PVP Trinket"] = "PVP 飾品"
+L["Raid Icon"] = "團隊圖示"
+L["Raid-Wide Sorting"] = "全團隊排序"
+L["Raid40 Frames"] = "40人團隊框架"
+L["RaidDebuff Indicator"] = "團隊副本減益光環標示"
+L["Range Check"] = "距離檢查"
+L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."] = "實時更新生命值會佔用更多的內存的和CPU, 只推薦治療角色開啟."
+L["Reaction Castbars"] = "聲望施法條"
+L["Reactions"] = "陣營聲望"
+L["Ready Check Icon"] = true;
+L["Remaining"] = "剩餘數值"
+L["Remove a spell from the filter. Use the spell ID if you see the ID as part of the spell name in the filter."] = "從過濾器中移除一個技能. 當你看見有ID在過濾器中的技能名字時使用技能ID"
+L["Remove a spell from the filter."] = "從過濾器中移除一個技能."
+L["Remove Spell ID or Name"] = "移除技能ID或者名稱"
+L["Remove SpellID"] = "移除技能ID"
+L["Rest Icon"] = "充分休息圖示"
+L["Restore Defaults"] = "恢復預設"
+L["Right to Left"] = "右到左"
+L["RL / ML Icons"] = "團隊隊長/裝備分配圖示"
+L["Role Icon"] = "角色定位圖示"
+L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."] = true;
+L["Select a unit to copy settings from."] = "選擇從哪單位複制."
+L["Select an additional filter to use. If the selected filter is a whitelist and no other filters are being used (with the exception of Block Non-Personal Auras) then it will block anything not on the whitelist, otherwise it will simply add auras on the whitelist in addition to any other filter settings."] = "請選擇一個過濾器, 若你啓用的是'白名單', 則只顯示'白名單'裡的光環."
+L["Select Filter"] = "選擇過濾器"
+L["Select Spell"] = "選擇技能"
+L["Select the display method of the portrait."] = "選擇頭像的顯示方式"
+L["Set the filter type. Blacklist will hide any auras in the list and show all others. Whitelist will show any auras in the filter and hide all others."] = "設置過濾器類型. 黑名單將隱藏列表內的任何光環而顯示其他. 白名單將顯示過濾器內的任何光環而隱藏其他所有光環."
+L["Set the font size for unitframes."] = "設定單位框架字體尺寸."
+L["Set the order that the group will sort."] = "設定組排序的順序."
+L["Set the orientation of the UnitFrame."] = "設置框架的方向"
+L["Set the priority order of the spell, please note that prioritys are only used for the raid debuff module, not the standard buff/debuff module. If you want to disable set to zero."] = "設定該法術的優先順序. 請注意, 優先級只用於Raid Debuff模塊, 而不是標準的Buff/Debuff模塊. 設定為0 禁用此功能."
+L["Set the type of auras to show when a unit is a foe."] = "當單位是敵對時設定光環顯示的類型."
+L["Set the type of auras to show when a unit is friendly."] = "當單位是友好時設定光環顯示的類型."
+L["Sets the font instance's horizontal text alignment style."] = "設定橫向字體的對齊方式."
+L["Show"] = true;
+L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."] = "在單位框架中顯示即將回复的的預測治療量, 過量治療則以不同顏色顯示. "
+L["Show Aura From Other Players"] = "顯示其他玩家的光環"
+L["Show Auras"] = "顯示光環"
+L["Show Dispellable Debuffs"] = "顯示無法驅散的debuff"
+L["Show When Not Active"] = "顯示當前無效的光環"
+L["Size and Positions"] = "大小和位置"
+L["Size of the indicator icon."] = "提示圖示尺寸"
+L["Size Override"] = "尺寸覆蓋"
+L["Size"] = "尺寸"
+L["Smart Aura Position"] = "智能光環位置"
+L["Smart Raid Filter"] = "智能團隊過濾"
+L["Smooth Bars"] = "平滑化"
+L["Sort By"] = "排序"
+L["Spaced"] = "留空"
+L["Spacing"] = "間隙"
+L["Spark"] = "火花"
+L["Speed in seconds"] = true;
+L["Stack Counter"] = "層數計數"
+L["Stack Threshold"] = "層數閾值"
+L["Start Near Center"] = "由中心開始"
+L["Statusbar Fill Orientation"] = "狀態條填充方向"
+L["StatusBar Texture"] = "狀態條材質"
+L["Strata and Level"] = true;
+L["Style"] = "風格"
+L["Tank Frames"] = "坦克框架"
+L["Tank Target"] = "坦克目標"
+L["Tapped"] = "被攻擊"
+L["Target Glow"] = "選中高亮"
+L["Target On Mouse-Down"] = "滑鼠按下設為目標"
+L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."] = "按下滑鼠時設為目標,而不是鬆開滑鼠按鍵時. \n\n|cffFF0000警告: 如果使用'Clique'等點擊施法插件, 你可能需要調整這些插件的設置."
+L["Text Color"] = "文字顔色"
+L["Text Format"] = "文字格式"
+L["Text Position"] = "文字位置"
+L["Text Threshold"] = "文本閥值"
+L["Text Toggle On NPC"] = "NPC 文字顯示開關"
+L["Text xOffset"] = "文字X軸偏移"
+L["Text yOffset"] = "文字Y軸偏移"
+L["Text"] = "文本"
+L["Textured Icon"] = "圖示紋理"
+L["The alpha to set units that are out of range to."] = "單位框架超出距離的透明度."
+L["The debuff needs to reach this amount of stacks before it is shown. Set to 0 to always show the debuff."] = "減益需要達到這個數量的層數才會顯示. 設為0來一直顯示它."
+L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."] = "為了顯示設定過的過濾器下面的巨集必須啟用."
+L["The font that the unitframes will use."] = "單位框架字體."
+L["The initial group will start near the center and grow out."] = "最初的隊伍由中心開始增長."
+L["The name you have selected is already in use by another element."] = "你所選的名稱已經被另一組件佔用."
+L["The object you want to attach to."] = "你想依附的目標."
+L["Thin Borders"] = "細邊框"
+L["This dictates the size of the icon when it is not attached to the castbar."] = true;
+L["This opens the UnitFrames Color settings. These settings affect all unitframes."] = "這將開啟單位框體顏色設置.這些設置會影響所有單位框體"
+L["Threat Display Mode"] = "仇恨顯示模式"
+L["Threshold before text goes into decimal form. Set to -1 to disable decimals."] = "文字變為小數時的閾值.設為-1以禁用小數"
+L["Ticks"] = "週期傷害"
+L["Time Remaining Reverse"] = "剩餘時間反轉"
+L["Time Remaining"] = "剩餘時間"
+L["Transparent"] = "透明"
+L["Turtle Color"] = "減傷類的顏色"
+L["Unholy"] = "穢邪符文"
+L["Uniform Threshold"] = "統一閾值"
+L["UnitFrames"] = "單位框架"
+L["Up"] = "上"
+L["Use Custom Level"] = true;
+L["Use Custom Strata"] = true;
+L["Use Dead Backdrop"] = "死亡背景"
+L["Use Default"] = "自定義默認值"
+L["Use the custom health backdrop color instead of a multiple of the main health color."] = "自定義生命條背景色."
+L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."] = "使用配置文件內的增益指示器而不是全域的"
+L["Use thin borders on certain unitframe elements."] = "使用細邊框"
+L["Use this backdrop color for units that are dead or ghosts."] = "死亡或靈魂狀態背景"
+L["Value must be a number"] = "數值必須為一個數字"
+L["Vertical Orientation"] = "垂直方向"
+L["Vertical Spacing"] = "垂直間隔"
+L["Vertical"] = "垂直"
+L["Visibility"] = "可見性"
+L["What point to anchor to the frame you set to attach to."] = "增益光環框架於其依附框架的依附位置."
+L["What to attach the buff anchor frame to."] = "Buff 定位附加到的框架."
+L["What to attach the debuff anchor frame to."] = "Debuff 定位附加到的框架."
+L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."] = true
+L["When true, the header includes the player when not in a raid."] = "若啟用, 隊伍中將顯示玩家."
+L["Whitelist"] = "白名單"
+L["Width"] = "寬"
+L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."] = "如果沒有debuff則把buff顯示在debuff位置"
+L["xOffset"] = "X軸偏移"
+L["yOffset"] = "Y軸偏移"
+L["You can't remove a pre-existing filter."] = "你不能刪除一個內建的過濾器"
+L["You may not remove a spell from a default filter that is not customly added. Setting spell to false instead."] = "你不能移除一個內建技能, 僅能停用此技能."
+L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."] = "按住設置按鍵+右鍵單擊會把該玩家加入黑名單, 設為無以關閉該功能"
\ No newline at end of file
diff --git a/ElvUI_Config/Maps.lua b/ElvUI_Config/Maps.lua
new file mode 100644
index 0000000..c1a3956
--- /dev/null
+++ b/ElvUI_Config/Maps.lua
@@ -0,0 +1,501 @@
+local E, L, V, P, G, _ = unpack(ElvUI);
+local WM = E:GetModule("WorldMap");
+local MM = E:GetModule("Minimap");
+
+E.Options.args.maps = {
+ type = "group",
+ name = L["Maps"],
+ childGroups = "tab",
+ args = {
+ worldMap = {
+ order = 1,
+ type = "group",
+ name = WORLD_MAP,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = WORLD_MAP
+ },
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ guiInline = true,
+ args = {
+ smallerWorldMap = {
+ order = 1,
+ type = "toggle",
+ name = L["Smaller World Map"],
+ desc = L["Make the world map smaller."],
+ get = function(info) return E.global.general.smallerWorldMap end,
+ set = function(info, value) E.global.general.smallerWorldMap = value; E:StaticPopup_Show("GLOBAL_RL") end,
+ }
+ },
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = "\n"
+ },
+ coordinatesGroup = {
+ order = 3,
+ type = "group",
+ name = L["World Map Coordinates"],
+ guiInline = true,
+ args = {
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ desc = L["Puts coordinates on the world map."],
+ get = function(info) return E.global.general.WorldMapCoordinates.enable; end,
+ set = function(info, value) E.global.general.WorldMapCoordinates.enable = value; E:StaticPopup_Show("GLOBAL_RL"); end
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = " "
+ },
+ position = {
+ order = 3,
+ type = "select",
+ name = L["Position"],
+ get = function(info) return E.global.general.WorldMapCoordinates.position; end,
+ set = function(info, value) E.global.general.WorldMapCoordinates.position = value; WM:PositionCoords(); end,
+ disabled = function() return not E.global.general.WorldMapCoordinates.enable; end,
+ values = {
+ ["TOP"] = "TOP",
+ ["TOPLEFT"] = "TOPLEFT",
+ ["TOPRIGHT"] = "TOPRIGHT",
+ ["BOTTOM"] = "BOTTOM",
+ ["BOTTOMLEFT"] = "BOTTOMLEFT",
+ ["BOTTOMRIGHT"] = "BOTTOMRIGHT"
+ }
+ },
+ xOffset = {
+ order = 4,
+ type = "range",
+ name = L["X-Offset"],
+ get = function(info) return E.global.general.WorldMapCoordinates.xOffset; end,
+ set = function(info, value) E.global.general.WorldMapCoordinates.xOffset = value; WM:PositionCoords(); end,
+ disabled = function() return not E.global.general.WorldMapCoordinates.enable end,
+ min = -200, max = 200, step = 1
+ },
+ yOffset = {
+ order = 5,
+ type = "range",
+ name = L["Y-Offset"],
+ get = function(info) return E.global.general.WorldMapCoordinates.yOffset; end,
+ set = function(info, value) E.global.general.WorldMapCoordinates.yOffset = value; WM:PositionCoords(); end,
+ disabled = function() return not E.global.general.WorldMapCoordinates.enable end,
+ min = -200, max = 200, step = 1
+ }
+ }
+ }
+ }
+ },
+ minimap = {
+ order = 2,
+ type = "group",
+ name = MINIMAP_LABEL,
+ get = function(info) return E.db.general.minimap[ info[getn(info)] ]; end,
+ childGroups = "tab",
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = MINIMAP_LABEL
+ },
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ guiInline = true,
+ args = {
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ desc = L["Enable/Disable the minimap. |cffFF0000Warning: This will prevent you from seeing the minimap datatexts.|r"],
+ get = function(info) return E.private.general.minimap[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.general.minimap[ info[getn(info)] ] = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ },
+ size = {
+ order = 2,
+ type = "range",
+ name = L["Size"],
+ desc = L["Adjust the size of the minimap."],
+ min = 120, max = 250, step = 1,
+ get = function(info) return E.db.general.minimap[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap[ info[getn(info)] ] = value; MM:UpdateSettings(); end,
+ disabled = function() return not E.private.general.minimap.enable; end
+ }
+ }
+ },
+ locationTextGroup = {
+ order = 2,
+ type = "group",
+ name = L["Location Text"],
+ args = {
+ locationText = {
+ order = 1,
+ type = "select",
+ name = L["Location Text"],
+ desc = L["Change settings for the display of the location text that is on the minimap."],
+ get = function(info) return E.db.general.minimap.locationText; end,
+ set = function(info, value) E.db.general.minimap.locationText = value; MM:UpdateSettings(); MM:Update_ZoneText(); end,
+ values = {
+ ["MOUSEOVER"] = L["Minimap Mouseover"],
+ ["SHOW"] = L["Always Display"],
+ ["HIDE"] = L["Hide"]
+ },
+ disabled = function() return not E.private.general.minimap.enable; end
+ },
+ locationFont = {
+ order = 2,
+ type = "select",
+ dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ set = function(info, value) E.db.general.minimap.locationFont = value; MM:Update_ZoneText(); end,
+ disabled = function() return not E.private.general.minimap.enable; end,
+ },
+ locationFontSize = {
+ order = 3,
+ type = "range",
+ name = L["Font Size"],
+ min = 6, max = 36, step = 1,
+ set = function(info, value) E.db.general.minimap.locationFontSize = value; MM:Update_ZoneText(); end,
+ disabled = function() return not E.private.general.minimap.enable end,
+ },
+ locationFontOutline = {
+ order = 4,
+ type = "select",
+ name = L["Font Outline"],
+ set = function(info, value) E.db.general.minimap.locationFontOutline = value; MM:Update_ZoneText(); end,
+ disabled = function() return not E.private.general.minimap.enable; end,
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ }
+ }
+ },
+ zoomResetGroup = {
+ order = 3,
+ type = "group",
+ name = L["Reset Zoom"],
+ args = {
+ enableZoomReset = {
+ order = 1,
+ type = "toggle",
+ name = L["Reset Zoom"],
+ get = function(info) return E.db.general.minimap.resetZoom.enable; end,
+ set = function(info, value) E.db.general.minimap.resetZoom.enable = value; MM:UpdateSettings(); end,
+ disabled = function() return not E.private.general.minimap.enable; end
+ },
+ zoomResetTime = {
+ order = 2,
+ type = "range",
+ name = L["Seconds"],
+ min = 1, max = 15, step = 1,
+ get = function(info) return E.db.general.minimap.resetZoom.time; end,
+ set = function(info, value) E.db.general.minimap.resetZoom.time = value; MM:UpdateSettings(); end,
+ disabled = function() return (not E.db.general.minimap.resetZoom.enable or not E.private.general.minimap.enable); end
+ }
+ }
+ },
+ icons = {
+ order = 4,
+ type = "group",
+ name = L["Minimap Buttons"],
+ args = {
+ calendar = {
+ order = 1,
+ type = "group",
+ name = L["Calendar"],
+ get = function(info) return E.db.general.minimap.icons.calendar[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap.icons.calendar[ info[getn(info)] ] = value; MM:UpdateSettings(); end,
+ args = {
+ hideCalendar = {
+ order = 1,
+ type = "toggle",
+ name = L["Hide"],
+ get = function(info) return E.private.general.minimap.hideCalendar; end,
+ set = function(info, value) E.private.general.minimap.hideCalendar = value; MM:UpdateSettings(); end,
+ width = "full"
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full"
+ },
+ position = {
+ order = 3,
+ type = "select",
+ name = L["Position"],
+ disabled = function() return E.private.general.minimap.hideCalendar; end,
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["TOPLEFT"] = L["Top Left"],
+ ["TOPRIGHT"] = L["Top Right"],
+ ["BOTTOMLEFT"] = L["Bottom Left"],
+ ["BOTTOMRIGHT"] = L["Bottom Right"]
+ }
+ },
+ scale = {
+ order = 4,
+ type = "range",
+ name = L["Scale"],
+ min = 0.5, max = 2, step = 0.05
+ },
+ xOffset = {
+ order = 5,
+ type = "range",
+ name = L["xOffset"],
+ min = -50, max = 50, step = 1,
+ disabled = function() return E.private.general.minimap.hideCalendar; end
+ },
+ yOffset = {
+ order = 6,
+ type = "range",
+ name = L["yOffset"],
+ min = -50, max = 50, step = 1,
+ disabled = function() return E.private.general.minimap.hideCalendar; end
+ }
+ }
+ },
+ mail = {
+ order = 2,
+ type = "group",
+ name = "MAIL_LABEL",
+ get = function(info) return E.db.general.minimap.icons.mail[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap.icons.mail[ info[getn(info)] ] = value; MM:UpdateSettings(); end,
+ args = {
+ position = {
+ order = 1,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["TOPLEFT"] = L["Top Left"],
+ ["TOPRIGHT"] = L["Top Right"],
+ ["BOTTOMLEFT"] = L["Bottom Left"],
+ ["BOTTOMRIGHT"] = L["Bottom Right"]
+ }
+ },
+ scale = {
+ order = 2,
+ type = "range",
+ name = L["Scale"],
+ min = 0.5, max = 2, step = 0.05
+ },
+ xOffset = {
+ order = 3,
+ type = "range",
+ name = L["xOffset"],
+ min = -50, max = 50, step = 1
+ },
+ yOffset = {
+ order = 4,
+ type = "range",
+ name = L["yOffset"],
+ min = -50, max = 50, step = 1
+ }
+ }
+ },
+ lfgEye = {
+ order = 3,
+ type = "group",
+ name = L["LFG Queue"],
+ get = function(info) return E.db.general.minimap.icons.lfgEye[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap.icons.lfgEye[ info[getn(info)] ] = value; MM:UpdateSettings(); end,
+ args = {
+ position = {
+ order = 1,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["TOPLEFT"] = L["Top Left"],
+ ["TOPRIGHT"] = L["Top Right"],
+ ["BOTTOMLEFT"] = L["Bottom Left"],
+ ["BOTTOMRIGHT"] = L["Bottom Right"]
+ }
+ },
+ scale = {
+ order = 2,
+ type = "range",
+ name = L["Scale"],
+ min = 0.5, max = 2, step = 0.05
+ },
+ xOffset = {
+ order = 3,
+ type = "range",
+ name = L["xOffset"],
+ min = -50, max = 50, step = 1
+ },
+ yOffset = {
+ order = 4,
+ type = "range",
+ name = L["yOffset"],
+ min = -50, max = 50, step = 1
+ }
+ }
+ },
+ battlefield = {
+ order = 4,
+ type = "group",
+ name = L["PvP Queue"],
+ get = function(info) return E.db.general.minimap.icons.battlefield[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap.icons.battlefield[ info[getn(info)] ] = value; MM:UpdateSettings(); end,
+ args = {
+ position = {
+ order = 1,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["TOPLEFT"] = L["Top Left"],
+ ["TOPRIGHT"] = L["Top Right"],
+ ["BOTTOMLEFT"] = L["Bottom Left"],
+ ["BOTTOMRIGHT"] = L["Bottom Right"]
+ }
+ },
+ scale = {
+ order = 2,
+ type = "range",
+ name = L["Scale"],
+ min = 0.5, max = 2, step = 0.05
+ },
+ xOffset = {
+ order = 3,
+ type = "range",
+ name = L["xOffset"],
+ min = -50, max = 50, step = 1
+ },
+ yOffset = {
+ order = 4,
+ type = "range",
+ name = L["yOffset"],
+ min = -50, max = 50, step = 1
+ }
+ }
+ },
+ difficulty = {
+ order = 5,
+ type = "group",
+ name = L["Instance Difficulty"],
+ get = function(info) return E.db.general.minimap.icons.difficulty[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap.icons.difficulty[ info[getn(info)] ] = value; MM:UpdateSettings(); end,
+ args = {
+ position = {
+ order = 1,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["TOPLEFT"] = L["Top Left"],
+ ["TOPRIGHT"] = L["Top Right"],
+ ["BOTTOMLEFT"] = L["Bottom Left"],
+ ["BOTTOMRIGHT"] = L["Bottom Right"]
+ }
+ },
+ scale = {
+ order = 2,
+ type = "range",
+ name = L["Scale"],
+ min = 0.5, max = 2, step = 0.05
+ },
+ xOffset = {
+ order = 3,
+ type = "range",
+ name = L["xOffset"],
+ min = -50, max = 50, step = 1
+ },
+ yOffset = {
+ order = 4,
+ type = "range",
+ name = L["yOffset"],
+ min = -50, max = 50, step = 1
+ }
+ }
+ },
+ vehicleLeave = {
+ order = 6,
+ type = "group",
+ name = "LEAVE_VEHICLE",
+ get = function(info) return E.db.general.minimap.icons.vehicleLeave[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.general.minimap.icons.vehicleLeave[ info[getn(info)] ] = value; E:GetModule("ActionBars"):UpdateVehicleLeave(); end,
+ args = {
+ hide = {
+ order = 1,
+ type = "toggle",
+ name = L["Hide"]
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full"
+ },
+ position = {
+ order = 3,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["TOPLEFT"] = L["Top Left"],
+ ["TOPRIGHT"] = L["Top Right"],
+ ["BOTTOMLEFT"] = L["Bottom Left"],
+ ["BOTTOMRIGHT"] = L["Bottom Right"]
+ }
+ },
+ scale = {
+ order = 4,
+ type = "range",
+ name = L["Scale"],
+ min = 0.5, max = 2, step = 0.05,
+ },
+ xOffset = {
+ order = 5,
+ type = "range",
+ name = L["xOffset"],
+ min = -50, max = 50, step = 1
+ },
+ yOffset = {
+ order = 6,
+ type = "range",
+ name = L["yOffset"],
+ min = -50, max = 50, step = 1
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Nameplates.lua b/ElvUI_Config/Nameplates.lua
new file mode 100644
index 0000000..04bc4ae
--- /dev/null
+++ b/ElvUI_Config/Nameplates.lua
@@ -0,0 +1,878 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local NP = E:GetModule("NamePlates");
+
+local selectedFilter
+local filters
+
+local ACD = LibStub("AceConfigDialog-3.0")
+
+local positionValues = {
+ TOPLEFT = "TOPLEFT",
+ LEFT = "LEFT",
+ BOTTOMLEFT = "BOTTOMLEFT",
+ RIGHT = "RIGHT",
+ TOPRIGHT = "TOPRIGHT",
+ BOTTOMRIGHT = "BOTTOMRIGHT",
+ CENTER = "CENTER",
+ TOP = "TOP",
+ BOTTOM = "BOTTOM"
+};
+
+local function UpdateFilterGroup()
+ if not selectedFilter or not E.global["nameplates"]["filter"][selectedFilter] then
+ E.Options.args.nameplate.args.generalGroup.args.filters.args.filterGroup = nil
+ return
+ end
+
+ E.Options.args.nameplate.args.generalGroup.args.filters.args.filterGroup = {
+ type = "group",
+ name = selectedFilter,
+ guiInline = true,
+ order = -10,
+ get = function(info) return E.global["nameplates"]["filter"][selectedFilter][ info[getn(info)] ] end,
+ set = function(info, value) E.global["nameplates"]["filter"][selectedFilter][ info[getn(info)] ] = value; NP:ForEachPlate("CheckFilter"); NP:ConfigureAll(); UpdateFilterGroup() end,
+ args = {
+ enable = {
+ type = "toggle",
+ order = 1,
+ name = L["Enable"],
+ desc = L["Use this filter."],
+ },
+ hide = {
+ type = "toggle",
+ order = 2,
+ name = L["Hide"],
+ desc = L["Prevent any nameplate with this unit name from showing."],
+ },
+ customColor = {
+ type = "toggle",
+ order = 3,
+ name = L["Custom Color"],
+ desc = L["Disable threat coloring for this plate and use the custom color."],
+ },
+ color = {
+ type = "color",
+ order = 4,
+ name = L["Color"],
+ get = function(info)
+ local t = E.global["nameplates"]["filter"][selectedFilter][ info[getn(info)] ]
+ if t then
+ return t.r, t.g, t.b, t.a
+ end
+ end,
+ set = function(info, r, g, b)
+ E.global["nameplates"]["filter"][selectedFilter][ info[getn(info)] ] = {}
+ local t = E.global["nameplates"]["filter"][selectedFilter][ info[getn(info)] ]
+ if t then
+ t.r, t.g, t.b = r, g, b
+ UpdateFilterGroup()
+ NP:ForEachPlate("CheckFilter")
+ NP:ConfigureAll()
+ end
+ end
+ },
+ customScale = {
+ type = "range",
+ name = L["Custom Scale"],
+ desc = L["Set the scale of the nameplate."],
+ min = 0.67, max = 2, step = 0.01
+ }
+ }
+ }
+end
+
+local ORDER = 100;
+local function GetUnitSettings(unit, name)
+ local copyValues = {};
+ for x, y in pairs(NP.db.units) do
+ if(type(y) == "table" and x ~= unit) then
+ copyValues[x] = L[x];
+ end
+ end
+ local group = {
+ order = ORDER,
+ type = "group",
+ name = name,
+ childGroups = "tab",
+ get = function(info) return E.db.nameplates.units[unit][ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit][ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ copySettings = {
+ order = -10,
+ type = "select",
+ name = L["Copy Settings From"],
+ desc = L["Copy settings from another unit."],
+ values = copyValues,
+ get = function() return ""; end,
+ set = function(info, value)
+ NP:CopySettings(value, unit);
+ NP:ConfigureAll();
+ end
+ },
+ defaultSettings = {
+ order = -9,
+ type = "execute",
+ name = L["Default Settings"],
+ desc = L["Set Settings to Default"],
+ func = function(info, value)
+ NP:ResetSettings(unit);
+ NP:ConfigureAll();
+ end
+ },
+ healthGroup = {
+ order = 1,
+ name = L["Health"],
+ type = "group",
+ get = function(info) return E.db.nameplates.units[unit].healthbar[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].healthbar[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Health"]
+ },
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"]
+ },
+ height = {
+ order = 2,
+ type = "range",
+ name = L["Height"],
+ min = 4, max = 20, step = 1
+ },
+ width = {
+ order = 3,
+ type = "range",
+ name = L["Width"],
+ min = 50, max = 200, step = 1
+ },
+ textGroup = {
+ order = 100,
+ type = "group",
+ name = L["Text"],
+ guiInline = true,
+ get = function(info) return E.db.nameplates.units[unit].healthbar.text[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].healthbar.text[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"]
+ },
+ format = {
+ order = 2,
+ name = L["Format"],
+ type = "select",
+ values = {
+ ["CURRENT"] = L["Current"],
+ ["CURRENT_MAX"] = L["Current / Max"],
+ ["CURRENT_PERCENT"] = L["Current - Percent"],
+ ["CURRENT_MAX_PERCENT"] = L["Current - Max | Percent"],
+ ["PERCENT"] = L["Percent"],
+ ["DEFICIT"] = L["Deficit"]
+ }
+ }
+ }
+ }
+ }
+ },
+ castGroup = {
+ order = 3,
+ name = L["Cast Bar"],
+ type = "group",
+ get = function(info) return E.db.nameplates.units[unit].castbar[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].castbar[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Cast Bar"]
+ },
+ enable = {
+ order = 1,
+ name = L["Enable"],
+ type = "toggle",
+ },
+ hideSpellName = {
+ order = 2,
+ type = "toggle",
+ name = L["Hide Spell Name"]
+ },
+ hideTime = {
+ order = 3,
+ type = "toggle",
+ name = L["Hide Time"]
+ },
+ height = {
+ order = 4,
+ type = "range",
+ name = L["Height"],
+ min = 4, max = 20, step = 1
+ },
+ offset = {
+ order = 5,
+ type = "range",
+ name = L["Offset"],
+ min = 0, max = 30, step = 1
+ },
+ castTimeFormat = {
+ order = 6,
+ type = "select",
+ name = L["Cast Time Format"],
+ values = {
+ ["CURRENT"] = L["Current"],
+ ["CURRENT_MAX"] = L["Current / Max"],
+ ["REMAINING"] = L["Remaining"]
+ }
+ },
+ channelTimeFormat = {
+ order = 7,
+ type = "select",
+ name = L["Channel Time Format"],
+ values = {
+ ["CURRENT"] = L["Current"],
+ ["CURRENT_MAX"] = L["Current / Max"],
+ ["REMAINING"] = L["Remaining"]
+ }
+ },
+ timeToHold = {
+ order = 8,
+ type = "range",
+ name = L["Time To Hold"],
+ desc = L["How many seconds the castbar should stay visible after the cast failed or was interrupted."],
+ min = 0, max = 4, step = 0.1
+ }
+ }
+ },
+ buffsGroup = {
+ order = 4,
+ name = L["Buffs"],
+ type = "group",
+ get = function(info) return E.db.nameplates.units[unit].buffs.filters[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].buffs.filters[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ disabled = function() return not E.db.nameplates.units[unit].healthbar.enable; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Buffs"]
+ },
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.db.nameplates.units[unit].buffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].buffs[ info[getn(info)] ] = value; NP:ConfigureAll(); end
+ },
+ numAuras = {
+ order = 2,
+ type = "range",
+ name = L["# Displayed Auras"],
+ desc = L["Controls how many auras are displayed, this will also affect the size of the auras."],
+ min = 1, max = 8, step = 1,
+ get = function(info) return E.db.nameplates.units[unit].buffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].buffs[ info[getn(info)] ] = value; NP:ConfigureAll(); end
+ },
+ baseHeight = {
+ order = 3,
+ type = "range",
+ name = L["Icon Base Height"],
+ desc = L["Base Height for the Aura Icon"],
+ min = 6, max = 60, step = 1,
+ get = function(info) return E.db.nameplates.units[unit].buffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].buffs[ info[getn(info)] ] = value; NP:ConfigureAll(); end
+ },
+ filtersGroup = {
+ name = L["Filters"],
+ order = 4,
+ type = "group",
+ guiInline = true,
+ args = {
+ personal = {
+ order = 1,
+ type = "toggle",
+ name = L["Personal Auras"]
+ },
+ maxDuration = {
+ order = 2,
+ type = "range",
+ name = L["Maximum Duration"],
+ min = 5, max = 3000, step = 1
+ },
+ filter = {
+ order = 3,
+ type = "select",
+ name = FILTER,
+ values = function()
+ local filters = {}
+ filters[""] = NONE
+ for filter in pairs(E.global.unitframe["aurafilters"]) do
+ filters[filter] = filter
+ end
+ return filters
+ end
+ }
+ }
+ }
+ }
+ },
+ debuffsGroup = {
+ order = 5,
+ name = L["Debuffs"],
+ type = "group",
+ get = function(info) return E.db.nameplates.units[unit].debuffs.filters[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].debuffs.filters[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ disabled = function() return not E.db.nameplates.units[unit].healthbar.enable; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Debuffs"]
+ },
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.db.nameplates.units[unit].debuffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].debuffs[ info[getn(info)] ] = value; NP:ConfigureAll(); end
+ },
+ numAuras = {
+ order = 2,
+ type = "range",
+ name = L["# Displayed Auras"],
+ desc = L["Controls how many auras are displayed, this will also affect the size of the auras."],
+ min = 1, max = 8, step = 1,
+ get = function(info) return E.db.nameplates.units[unit].debuffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].debuffs[ info[getn(info)] ] = value; NP:ConfigureAll(); end
+ },
+ baseHeight = {
+ order = 3,
+ type = "range",
+ name = L["Icon Base Height"],
+ desc = L["Base Height for the Aura Icon"],
+ min = 6, max = 60, step = 1,
+ get = function(info) return E.db.nameplates.units[unit].debuffs[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].debuffs[ info[getn(info)] ] = value; NP:ConfigureAll(); end
+ },
+ filtersGroup = {
+ name = L["Filters"],
+ order = 4,
+ type = "group",
+ guiInline = true,
+ args = {
+ personal = {
+ order = 1,
+ type = "toggle",
+ name = L["Personal Auras"]
+ },
+ maxDuration = {
+ order = 2,
+ type = "range",
+ name = L["Maximum Duration"],
+ min = 5, max = 3000, step = 1
+ },
+ filter = {
+ order = 3,
+ type = "select",
+ name = FILTER,
+ values = function()
+ local filters = {}
+ filters[""] = NONE
+ for filter in pairs(E.global.unitframe["aurafilters"]) do
+ filters[filter] = filter
+ end
+ return filters
+ end
+ }
+ }
+ }
+ }
+ },
+ levelGroup = {
+ order = 6,
+ name = LEVEL,
+ type = "group",
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = LEVEL
+ },
+ enable = {
+ order = 1,
+ name = L["Enable"],
+ type = "toggle",
+ get = function(info) return E.db.nameplates.units[unit].showLevel; end,
+ set = function(info, value) E.db.nameplates.units[unit].showLevel = value; NP:ConfigureAll(); end
+ }
+ }
+ },
+ nameGroup = {
+ order = 7,
+ name = L["Name"],
+ type = "group",
+ get = function(info) return E.db.nameplates.units[unit].name[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].name[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Name"]
+ },
+ enable = {
+ order = 1,
+ name = L["Enable"],
+ type = "toggle",
+ get = function(info) return E.db.nameplates.units[unit].showName; end,
+ set = function(info, value) E.db.nameplates.units[unit].showName = value; NP:ConfigureAll(); end
+ }
+ }
+ }
+ }
+ };
+
+ if(unit == "FRIENDLY_PLAYER" or unit == "ENEMY_PLAYER") then
+ group.args.healthGroup.args.useClassColor = {
+ order = 4,
+ type = "toggle",
+ name = L["Use Class Color"],
+ desc = L["Depends on Class Caching module!"],
+ disabled = function() return not E.private.general.classCache end
+ };
+ group.args.nameGroup.args.useClassColor = {
+ order = 3,
+ type = "toggle",
+ name = L["Use Class Color"],
+ desc = L["Depends on Class Caching module!"],
+ disabled = function() return not E.private.general.classCache end
+ };
+ elseif(unit == "ENEMY_NPC" or unit == "FRIENDLY_NPC") then
+ group.args.eliteIcon = {
+ order = 10,
+ name = L["Elite Icon"],
+ type = "group",
+ get = function(info) return E.db.nameplates.units[unit].eliteIcon[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.units[unit].eliteIcon[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Elite Icon"]
+ },
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"]
+ },
+ position = {
+ order = 2,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ ["TOP"] = L["Top"],
+ ["BOTTOM"] = L["Bottom"],
+ ["CENTER"] = L["Center"]
+ }
+ },
+ size = {
+ order = 3,
+ type = "range",
+ name = L["Size"],
+ min = 12, max = 42, step = 1
+ },
+ xOffset = {
+ order = 4,
+ type = "range",
+ name = L["X-Offset"],
+ min = -100, max = 100, step = 1
+ },
+ yOffset = {
+ order = 5,
+ type = "range",
+ name = L["Y-Offset"],
+ min = -100, max = 100, step = 1
+ }
+ }
+ };
+ end
+
+ ORDER = ORDER + 100;
+ return group;
+end
+
+E.Options.args.nameplate = {
+ type = "group",
+ name = L["NamePlates"],
+ childGroups = "tab",
+ get = function(info) return E.db.nameplates[ info[getn(info)] ] end,
+ set = function(info, value) E.db.nameplates[ info[getn(info)] ] = value; NP:ConfigureAll(); end,
+ args = {
+ enable = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.private.nameplates[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.nameplates[ info[getn(info)] ] = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ intro = {
+ order = 2,
+ type = "description",
+ name = L["NAMEPLATE_DESC"]
+ },
+ header = {
+ order = 3,
+ type = "header",
+ name = L["Shortcuts"]
+ },
+ generalGroup = {
+ order = 20,
+ type = "group",
+ name = L["General Options"],
+ childGroups = "tab",
+ disabled = function() return not E.NamePlates; end,
+ args = {
+ general = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ statusbar = {
+ order = 0,
+ type = "select",
+ dialogControl = "LSM30_Statusbar",
+ name = L["StatusBar Texture"],
+ values = AceGUIWidgetLSMlists.statusbar,
+ },
+ useTargetGlow = {
+ order = 2,
+ type = "toggle",
+ name = L["Use Target Glow"],
+ },
+ useTargetScale = {
+ order = 3,
+ type = "toggle",
+ name = L["Use Target Scale"],
+ desc = L["Enable/Disable the scaling of targetted nameplates."],
+ },
+ targetScale = {
+ order = 4,
+ type = "range",
+ name = L["Target Scale"],
+ desc = L["Scale of the nameplate that is targetted."],
+ min = 0.3, max = 2, step = 0.01,
+ isPercent = true,
+ disabled = function() return E.db.nameplates.useTargetScale ~= true end,
+ },
+ nonTargetTransparency = {
+ name = L["Non-Target Transparency"],
+ desc = L["Set the transparency level of nameplates that are not the target nameplate."],
+ type = "range",
+ min = 0, max = 1, step = 0.01,
+ isPercent = true,
+ order = 8,
+ },
+ lowHealthThreshold = {
+ order = 9,
+ name = L["Low Health Threshold"],
+ desc = L["Make the unitframe glow yellow when it is below this percent of health, it will glow red when the health value is half of this value."],
+ type = "range",
+ isPercent = true,
+ min = 0, max = 1, step = 0.01,
+ },
+ showEnemyCombat = {
+ order = 10,
+ type = "select",
+ name = L["Enemy Combat Toggle"],
+ desc = L["Control enemy nameplates toggling on or off when in combat."],
+ values = {
+ ["DISABLED"] = L["Disabled"],
+ ["TOGGLE_ON"] = L["Toggle On While In Combat"],
+ ["TOGGLE_OFF"] = L["Toggle Off While In Combat"],
+ },
+ set = function(info, value)
+ E.db.nameplates[ info[getn(info)] ] = value;
+ NP:PLAYER_REGEN_ENABLED();
+ end,
+ },
+ showFriendlyCombat = {
+ order = 11,
+ type = "select",
+ name = L["Friendly Combat Toggle"],
+ desc = L["Control friendly nameplates toggling on or off when in combat."],
+ values = {
+ ["DISABLED"] = L["Disabled"],
+ ["TOGGLE_ON"] = L["Toggle On While In Combat"],
+ ["TOGGLE_OFF"] = L["Toggle Off While In Combat"],
+ },
+ set = function(info, value)
+ E.db.nameplates[ info[getn(info)] ] = value;
+ NP:PLAYER_REGEN_ENABLED();
+ end
+ },
+ comboPoints = {
+ order = 12,
+ type = "toggle",
+ name = L["Combobar"]
+ }
+ }
+ },
+ fontGroup = {
+ order = 100,
+ type = "group",
+ name = L["Fonts"],
+ args = {
+ font = {
+ order = 4,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font
+ },
+ fontSize = {
+ order = 5,
+ type = "range",
+ name = L["Font Size"],
+ min = 4, max = 34, step = 1,
+ },
+ fontOutline = {
+ order = 6,
+ type = "select",
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ }
+ }
+ }
+ },
+ threatGroup = {
+ order = 150,
+ type = "group",
+ name = L["Threat"],
+ -- TODO
+ hidden = true,
+ get = function(info)
+ local t = E.db.nameplates.threat[ info[getn(info)] ];
+ local d = P.nameplates.threat[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.nameplates.threat[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ end,
+ args = {
+ useThreatColor = {
+ order = 1,
+ type = "toggle",
+ name = L["Use Threat Color"],
+ get = function(info) return E.db.nameplates.threat.useThreatColor; end,
+ set = function(info, value) E.db.nameplates.threat.useThreatColor = value; end
+ },
+ goodColor = {
+ order = 2,
+ type = "color",
+ name = L["Good Color"],
+ hasAlpha = false,
+ disabled = function() return not E.db.nameplates.threat.useThreatColor; end
+ },
+ badColor = {
+ order = 3,
+ type = "color",
+ name = L["Bad Color"],
+ hasAlpha = false,
+ disabled = function() return not E.db.nameplates.threat.useThreatColor; end
+ },
+ goodTransition = {
+ order = 4,
+ type = "color",
+ name = L["Good Transition Color"],
+ hasAlpha = false,
+ disabled = function() return not E.db.nameplates.threat.useThreatColor; end
+ },
+ badTransition = {
+ order = 5,
+ type = "color",
+ name = L["Bad Transition Color"],
+ hasAlpha = false,
+ disabled = function() return not E.db.nameplates.threat.useThreatColor; end
+ },
+ beingTankedByTank = {
+ order = 6,
+ type = "toggle",
+ name = L["Color Tanked"],
+ desc = L["Use Tanked Color when a nameplate is being effectively tanked by another tank."],
+ get = function(info) return E.db.nameplates.threat[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.threat[ info[getn(info)] ] = value; end,
+ disabled = function() return not E.db.nameplates.threat.useThreatColor; end
+ },
+ beingTankedByTankColor = {
+ order = 7,
+ type = "color",
+ name = L["Tanked Color"],
+ hasAlpha = false,
+ disabled = function() return (not E.db.nameplates.threat.beingTankedByTank or not E.db.nameplates.threat.useThreatColor); end
+ },
+ goodScale = {
+ order = 8,
+ type = "range",
+ name = L["Good Scale"],
+ get = function(info) return E.db.nameplates.threat[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.threat[ info[getn(info)] ] = value; end,
+ min = 0.3, max = 2, step = 0.01,
+ isPercent = true
+ },
+ badScale = {
+ order = 9,
+ type = "range",
+ name = L["Bad Scale"],
+ get = function(info) return E.db.nameplates.threat[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.nameplates.threat[ info[getn(info)] ] = value; end,
+ min = 0.3, max = 2, step = 0.01,
+ isPercent = true
+ }
+ }
+ },
+ castGroup = {
+ order = 175,
+ type = "group",
+ name = L["Cast Bar"],
+ get = function(info)
+ local t = E.db.nameplates[ info[getn(info)] ];
+ local d = P.nameplates[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.nameplates[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ NP:ForEachPlate("ConfigureElement_CastBar");
+ end,
+ args = {
+ castColor = {
+ order = 1,
+ type = "color",
+ name = L["Cast Color"],
+ hasAlpha = false
+ }
+ }
+ },
+ reactions = {
+ order = 200,
+ type = "group",
+ name = L["Reaction Colors"],
+ get = function(info)
+ local t = E.db.nameplates.reactions[ info[getn(info)] ];
+ local d = P.nameplates.reactions[info[getn(info)]];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.nameplates.reactions[ info[getn(info)] ];
+ t.r, t.g, t.b = r, g, b;
+ NP:ConfigureAll();
+ end,
+ args = {
+ bad = {
+ order = 1,
+ type = "color",
+ name = L["Enemy"],
+ hasAlpha = false
+ },
+ neutral = {
+ order = 2,
+ type = "color",
+ name = L["Neutral"],
+ hasAlpha = false
+ },
+ good = {
+ order = 3,
+ type = "color",
+ name = L["Friendly NPC"],
+ hasAlpha = false
+ },
+ tapped = {
+ order = 4,
+ type = "color",
+ name = L["Tagged NPC"],
+ hasAlpha = false
+ },
+ friendlyPlayer = {
+ order = 5,
+ type = "color",
+ name = L["Friendly Player"],
+ hasAlpha = false
+ }
+ }
+ },
+ filters = {
+ order = 300,
+ type = "group",
+ name = L["Filters"],
+ args = {
+ addname = {
+ order = 2,
+ type = "input",
+ name = L["Add Name"],
+ get = function(info) return "" end,
+ set = function(info, value)
+ if E.global["nameplates"]["filter"][value] then
+ E:Print(L["Filter already exists!"])
+ return
+ end
+
+ E.global["nameplates"]["filter"][value] = {
+ ["enable"] = true,
+ ["hide"] = false,
+ ["customColor"] = false,
+ ["customScale"] = 1,
+ ["color"] = {r = 104/255, g = 138/255, b = 217/255}
+ }
+ UpdateFilterGroup()
+ NP:ConfigureAll()
+ end
+ },
+ deletename = {
+ order = 3,
+ type = "input",
+ name = L["Remove Name"],
+ get = function(info) return "" end,
+ set = function(info, value)
+ if G["nameplates"]["filter"][value] then
+ E.global["nameplates"]["filter"][value].enable = false;
+ E:Print(L["You can't remove a default name from the filter, disabling the name."])
+ else
+ E.global["nameplates"]["filter"][value] = nil;
+ E.Options.args.nameplates.args.filters.args.filterGroup = nil;
+ end
+ UpdateFilterGroup()
+ NP:ConfigureAll();
+ end
+ },
+ selectFilter = {
+ order = 3,
+ type = "select",
+ name = L["Select Filter"],
+ get = function(info) return selectedFilter end,
+ set = function(info, value) selectedFilter = value; UpdateFilterGroup() end,
+ values = function()
+ filters = {}
+ for filter in pairs(E.global["nameplates"]["filter"]) do
+ filters[filter] = filter
+ end
+ return filters
+ end
+ }
+ }
+ }
+ }
+ },
+ friendlyPlayerGroup = GetUnitSettings("FRIENDLY_PLAYER", L["Friendly Player Frames"]),
+ enemyPlayerGroup = GetUnitSettings("ENEMY_PLAYER", L["Enemy Player Frames"]),
+ friendlyNPCGroup = GetUnitSettings("FRIENDLY_NPC", L["Friendly NPC Frames"]),
+ enemyNPCGroup = GetUnitSettings("ENEMY_NPC", L["Enemy NPC Frames"])
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Skins.lua b/ElvUI_Config/Skins.lua
new file mode 100644
index 0000000..ed96679
--- /dev/null
+++ b/ElvUI_Config/Skins.lua
@@ -0,0 +1,228 @@
+local E, L, V, P, G = unpack(ElvUI);
+local S = E:GetModule("Skins");
+
+E.Options.args.skins = {
+ type = "group",
+ name = L["Skins"],
+ childGroups = "tree",
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["SKINS_DESC"]
+ },
+ blizzardEnable = {
+ order = 2,
+ type = "toggle",
+ name = "Blizzard",
+ get = function(info) return E.private.skins.blizzard.enable; end,
+ set = function(info, value) E.private.skins.blizzard.enable = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ },
+ ace3 = {
+ order = 3,
+ type = "toggle",
+ name = "Ace3",
+ get = function(info) return E.private.skins.ace3.enable; end,
+ set = function(info, value) E.private.skins.ace3.enable = value; E:StaticPopup_Show("PRIVATE_RL"); end,
+ },
+ blizzard = {
+ order = 100,
+ type = "group",
+ name = "Blizzard",
+ get = function(info) return E.private.skins.blizzard[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.skins.blizzard[ info[getn(info)] ] = value; E:StaticPopup_Show("CONFIG_RL"); end,
+ disabled = function() return not E.private.skins.blizzard.enable end,
+ guiInline = true,
+ args = {
+ alertframes = {
+ type = "toggle",
+ name = L["Alert Frames"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ auctionhouse = {
+ type = "toggle",
+ name = L["Auction Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ bags = {
+ type = "toggle",
+ name = L["Bags"],
+ desc = L["TOGGLESKIN_DESC"],
+ disabled = function() return E.private.bags.enable end
+ },
+ battlefield = {
+ type = "toggle",
+ name = L["Battlefield Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ bgscore = {
+ type = "toggle",
+ name = L["BG Score"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ binding = {
+ type = "toggle",
+ name = L["KeyBinding Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ character = {
+ type = "toggle",
+ name = L["Character Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ debug = {
+ type = "toggle",
+ name = L["Debug Tools"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ dressingroom = {
+ type = "toggle",
+ name = L["Dressing Room"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ friends = {
+ type = "toggle",
+ name = L["Friends"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ gossip = {
+ type = "toggle",
+ name = L["Gossip Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ greeting = {
+ type = "toggle",
+ name = L["Greeting Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ guildregistrar = {
+ type = "toggle",
+ name = L["Guild Registrar"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ help = {
+ type = "toggle",
+ name = L["Help Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ inspect = {
+ type = "toggle",
+ name = L["Inspect Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ loot = {
+ type = "toggle",
+ name = L["Loot Frames"],
+ desc = L["TOGGLESKIN_DESC"],
+ disabled = function() return E.private.general.loot end
+ },
+ lootRoll = {
+ type = "toggle",
+ name = L["Loot Roll"],
+ desc = L["TOGGLESKIN_DESC"],
+ disabled = function() return E.private.general.lootRoll end
+ },
+ macro = {
+ type = "toggle",
+ name = L["Macro Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ mail = {
+ type = "toggle",
+ name = L["Mail Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ merchant = {
+ type = "toggle",
+ name = L["Merchant Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ misc = {
+ type = "toggle",
+ name = L["Misc Frames"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ petition = {
+ type = "toggle",
+ name = L["Petition Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ quest = {
+ type = "toggle",
+ name = L["Quest Frames"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ questtimers = {
+ type = "toggle",
+ name = QUEST_TIMERS,
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ raid = {
+ type = "toggle",
+ name = L["Raid Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ spellbook = {
+ type = "toggle",
+ name = L["Spellbook"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ stable = {
+ type = "toggle",
+ name = L["Stable"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ tabard = {
+ type = "toggle",
+ name = L["Tabard Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ talent = {
+ type = "toggle",
+ name = L["Talent Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ taxi = {
+ type = "toggle",
+ name = L["Taxi Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ tooltip = {
+ type = "toggle",
+ name = L["Tooltip"],
+ desc = L["TOGGLESKIN_DESC"],
+ },
+ trade = {
+ type = "toggle",
+ name = L["Trade Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ tradeskill = {
+ type = "toggle",
+ name = L["TradeSkill Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ trainer = {
+ type = "toggle",
+ name = L["Trainer Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ tutorial = {
+ type = "toggle",
+ name = L["Tutorial Frame"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ worldmap = {
+ type = "toggle",
+ name = L["World Map"],
+ desc = L["TOGGLESKIN_DESC"]
+ },
+ mirrorTimers = {
+ type = "toggle",
+ name = L["Mirror Timers"],
+ desc = L["TOGGLESKIN_DESC"]
+ }
+ }
+ }
+ }
+};
\ No newline at end of file
diff --git a/ElvUI_Config/Tooltip.lua b/ElvUI_Config/Tooltip.lua
new file mode 100644
index 0000000..7895e6b
--- /dev/null
+++ b/ElvUI_Config/Tooltip.lua
@@ -0,0 +1,316 @@
+local E, L, V, P, G = unpack(ElvUI);
+local TT = E:GetModule("Tooltip");
+
+local tonumber, tostring = tonumber, tostring
+
+E.Options.args.tooltip = {
+ type = "group",
+ name = L["Tooltip"],
+ childGroups = "tab",
+ get = function(info) return E.db.tooltip[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.tooltip[ info[getn(info)] ] = value; end,
+ args = {
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["TOOLTIP_DESC"]
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.private.tooltip[ info[getn(info)] ]; end,
+ set = function(info, value) E.private.tooltip[ info[getn(info)] ] = value; E:StaticPopup_Show("PRIVATE_RL"); end
+ },
+ general = {
+ order = 3,
+ type = "group",
+ name = L["General"],
+ disabled = function() return not E.Tooltip; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["General"]
+ },
+ cursorAnchor = {
+ order = 1,
+ type = "toggle",
+ name = L["Cursor Anchor"],
+ desc = L["Should tooltip be anchored to mouse cursor"]
+ },
+ targetInfo = {
+ order = 2,
+ type = "toggle",
+ name = L["Target Info"],
+ desc = L["When in a raid group display if anyone in your raid is targeting the current tooltip unit."]
+ },
+ playerTitles = {
+ order = 3,
+ type = "toggle",
+ name = L["Player Titles"],
+ desc = L["Display player titles."]
+ },
+ guildRanks = {
+ order = 4,
+ type = "toggle",
+ name = L["Guild Ranks"],
+ desc = L["Display guild ranks if a unit is guilded."]
+ },
+ inspectInfo = {
+ order = 5,
+ type = "toggle",
+ name = L["Inspect Info"],
+ desc = L["Display the players talent spec and item level in the tooltip, this may not immediately update when mousing over a unit."],
+ },
+ spellID = {
+ order = 6,
+ type = "toggle",
+ name = L["Spell/Item IDs"],
+ desc = L["Display the spell or item ID when mousing over a spell or item tooltip."]
+ },
+ itemCount = {
+ order = 7,
+ type = "select",
+ name = L["Item Count"],
+ desc = L["Display how many of a certain item you have in your possession."],
+ values = {
+ ["BAGS_ONLY"] = L["Bags Only"],
+ ["BANK_ONLY"] = L["Bank Only"],
+ ["BOTH"] = L["Both"],
+ ["NONE"] = L["None"]
+ }
+ },
+ colorAlpha = {
+ order = 8,
+ type = "range",
+ name = OPACITY,
+ isPercent = true,
+ min = 0, max = 1, step = 0.01
+ },
+ fontGroup = {
+ order = 8,
+ type = "group",
+ guiInline = true,
+ name = L["Tooltip Font Settings"],
+ args = {
+ font = {
+ order = 1,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ get = function(info) return E.db.tooltip.font; end,
+ set = function(info, value) E.db.tooltip.font = value; TT:SetTooltipFonts(); end
+ },
+ fontOutline = {
+ order = 2,
+ name = L["Font Outline"],
+ type = "select",
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ },
+ get = function(info) return E.db.tooltip.fontOutline; end,
+ set = function(info, value) E.db.tooltip.fontOutline = value; TT:SetTooltipFonts(); end,
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = ""
+ },
+ headerFontSize = {
+ order = 4,
+ type = "range",
+ name = L["Header Font Size"],
+ min = 4, max = 33, step = 1,
+ get = function(info) return E.db.tooltip.headerFontSize; end,
+ set = function(info, value) E.db.tooltip.headerFontSize = value; TT:SetTooltipFonts(); end
+ },
+ textFontSize = {
+ order = 5,
+ type = "range",
+ name = L["Text Font Size"],
+ min = 4, max = 33, step = 1,
+ get = function(info) return E.db.tooltip.textFontSize end,
+ set = function(info, value) E.db.tooltip.textFontSize = value; TT:SetTooltipFonts() end
+ },
+ smallTextFontSize = {
+ order = 6,
+ type = "range",
+ name = L["Comparison Font Size"],
+ desc = L["This setting controls the size of text in item comparison tooltips."],
+ min = 4, max = 33, step = 1,
+ get = function(info) return E.db.tooltip.smallTextFontSize; end,
+ set = function(info, value) E.db.tooltip.smallTextFontSize = value; TT:SetTooltipFonts(); end
+ }
+ }
+ },
+ factionColors = {
+ order = 9,
+ type = "group",
+ name = L["Custom Faction Colors"],
+ guiInline = true,
+ args = {
+ useCustomFactionColors = {
+ order = 0,
+ type = "toggle",
+ name = L["Custom Faction Colors"],
+ get = function(info) return E.db.tooltip.useCustomFactionColors; end,
+ set = function(info, value) E.db.tooltip.useCustomFactionColors = value; end
+ }
+ },
+ get = function(info)
+ local t = E.db.tooltip.factionColors[ tonumber(info[getn(info)]) ];
+ local d = P.tooltip.factionColors[ tonumber(info[getn(info)]) ];
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b;
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.tooltip.factionColors[ tonumber(info[getn(info)]) ];
+ t.r, t.g, t.b = r, g, b;
+ end
+ }
+ }
+ },
+ visibility = {
+ order = 4,
+ type = "group",
+ name = L["Visibility"],
+ get = function(info) return E.db.tooltip.visibility[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.tooltip.visibility[ info[getn(info)] ] = value; end,
+ disabled = function() return not E.Tooltip; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Visibility"]
+ },
+ actionbars = {
+ order = 1,
+ type = "select",
+ name = L["ActionBars"],
+ desc = L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."],
+ values = {
+ ["ALL"] = L["Always Hide"],
+ ["NONE"] = L["Never Hide"],
+ --["SHIFT"] = SHIFT_KEY,
+ --["ALT"] = ALT_KEY,
+ --["CTRL"] = CTRL_KEY
+ }
+ },
+ bags = {
+ order = 2,
+ type = "select",
+ name = L["Bags/Bank"],
+ desc = L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."],
+ values = {
+ ["ALL"] = L["Always Hide"],
+ ["NONE"] = L["Never Hide"],
+ --["SHIFT"] = SHIFT_KEY,
+ --["ALT"] = ALT_KEY,
+ --["CTRL"] = CTRL_KEY
+ }
+ },
+ unitFrames = {
+ order = 3,
+ type = "select",
+ name = L["UnitFrames"],
+ desc = L["Choose when you want the tooltip to show. If a modifer is chosen, then you need to hold that down to show the tooltip."],
+ values = {
+ ["ALL"] = L["Always Hide"],
+ ["NONE"] = L["Never Hide"],
+ --["SHIFT"] = SHIFT_KEY,
+ --["ALT"] = ALT_KEY,
+ --["CTRL"] = CTRL_KEY
+ }
+ }
+ }
+ },
+ healthBar = {
+ order = 5,
+ type = "group",
+ name = L["Health Bar"],
+ get = function(info) return E.db.tooltip.healthBar[ info[getn(info)] ]; end,
+ set = function(info, value) E.db.tooltip.healthBar[ info[getn(info)] ] = value; end,
+ disabled = function() return not E.Tooltip; end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Health Bar"]
+ },
+ height = {
+ order = 1,
+ type = "range",
+ name = L["Height"],
+ min = 1, max = 15, step = 1,
+ set = function(info, value) E.db.tooltip.healthBar.height = value; GameTooltipStatusBar:Height(value); end
+ },
+ statusPosition = {
+ order = 2,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["BOTTOM"] = L["Bottom"],
+ ["TOP"] = L["Top"]
+ }
+ },
+ text = {
+ order = 3,
+ type = "toggle",
+ name = L["Text"],
+ set = function(info, value) E.db.tooltip.healthBar.text = value; if(value) then GameTooltipStatusBar.text:Show(); else GameTooltipStatusBar.text:Hide() end end
+ },
+ font = {
+ order = 4,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ set = function(info, value)
+ E.db.tooltip.healthBar.font = value;
+ E:FontTemplate(GameTooltipStatusBar.text, E.LSM:Fetch("font", E.db.tooltip.healthBar.font), E.db.tooltip.healthBar.fontSize, E.db.tooltip.healthBar.fontOutline);
+ end,
+ disabled = function() return not E.db.tooltip.healthBar.text end
+ },
+ fontSize = {
+ order = 5,
+ type = "range",
+ name = L["Font Size"],
+ min = 6, max = 500, step = 1,
+ set = function(info, value)
+ E.db.tooltip.healthBar.fontSize = value;
+ E:FontTemplate(GameTooltipStatusBar.text, E.LSM:Fetch("font", E.db.tooltip.healthBar.font), E.db.tooltip.healthBar.fontSize, E.db.tooltip.healthBar.fontOutline);
+ end,
+ disabled = function() return not E.db.tooltip.healthBar.text end
+ },
+ fontOutline = {
+ order = 6,
+ type = "select",
+ name = L["Font Outline"],
+ values = {
+ ["NONE"] = L["None"],
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE"
+ },
+ set = function(info, value)
+ E.db.tooltip.healthBar.fontOutline = value;
+ E:FontTemplate(GameTooltipStatusBar.text, E.LSM:Fetch("font", E.db.tooltip.healthBar.font), E.db.tooltip.healthBar.fontSize, E.db.tooltip.healthBar.fontOutline);
+ end,
+ disabled = function() return not E.db.tooltip.healthBar.text end
+ }
+ }
+ }
+ }
+};
+
+for i = 1, 8 do
+ E.Options.args.tooltip.args.general.args.factionColors.args[tostring(i)] = {
+ order = i,
+ type = "color",
+ hasAlpha = false,
+ name = _G["FACTION_STANDING_LABEL" .. i],
+ disabled = function() return not E.Tooltip or not E.db.tooltip.useCustomFactionColors; end,
+ };
+end
\ No newline at end of file
diff --git a/ElvUI_Config/UnitFrames.lua b/ElvUI_Config/UnitFrames.lua
new file mode 100644
index 0000000..b3713a6
--- /dev/null
+++ b/ElvUI_Config/UnitFrames.lua
@@ -0,0 +1,4878 @@
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local UF = E:GetModule("UnitFrames");
+
+local ns = oUF
+local ElvUF = ns.oUF
+
+local _G = _G
+local next = next
+local select = select
+local pairs = pairs
+local ipairs = ipairs
+local format = string.format
+local tremove = table.remove
+local tconcat = table.concat
+local tinsert = table.insert
+local twipe = table.wipe
+local strsplit = strsplit
+local match = string.match
+local gsub = string.gsub
+local IsAddOnLoaded = IsAddOnLoaded
+local GetScreenWidth = GetScreenWidth
+local RAID_CLASS_COLORS = RAID_CLASS_COLORS
+local HIDE, DELETE, NONE, FILTERS, FONT_SIZE, COLOR = HIDE, DELETE, NONE, FILTERS, FONT_SIZE, COLOR
+
+local SHIFT_KEY, ALT_KEY, CTRL_KEY = "SHIFT_KEY", "ALT_KEY", "CTRL_KEY"
+local HEALTH, MANA, NAME, PLAYER, CLASS, GROUP = HEALTH, MANA, NAME, PLAYER, CLASS, GROUP
+local RAGE, FOCUS, ENERGY = RAGE, FOCUS, ENERGY
+------------------------------
+
+local ACD = LibStub("AceConfigDialog-3.0")
+local fillValues = {
+ ["fill"] = L["Filled"],
+ ["spaced"] = L["Spaced"],
+ ["inset"] = L["Inset"]
+};
+
+local positionValues = {
+ TOPLEFT = "TOPLEFT",
+ LEFT = "LEFT",
+ BOTTOMLEFT = "BOTTOMLEFT",
+ RIGHT = "RIGHT",
+ TOPRIGHT = "TOPRIGHT",
+ BOTTOMRIGHT = "BOTTOMRIGHT",
+ CENTER = "CENTER",
+ TOP = "TOP",
+ BOTTOM = "BOTTOM",
+};
+
+local threatValues = {
+ ["GLOW"] = L["Glow"],
+ ["BORDERS"] = L["Borders"],
+ ["HEALTHBORDER"] = L["Health Border"],
+ ["INFOPANELBORDER"] = L["InfoPanel Border"],
+ ["ICONTOPLEFT"] = L["Icon: TOPLEFT"],
+ ["ICONTOPRIGHT"] = L["Icon: TOPRIGHT"],
+ ["ICONBOTTOMLEFT"] = L["Icon: BOTTOMLEFT"],
+ ["ICONBOTTOMRIGHT"] = L["Icon: BOTTOMRIGHT"],
+ ["ICONLEFT"] = L["Icon: LEFT"],
+ ["ICONRIGHT"] = L["Icon: RIGHT"],
+ ["ICONTOP"] = L["Icon: TOP"],
+ ["ICONBOTTOM"] = L["Icon: BOTTOM"],
+ ["NONE"] = "NONE"
+}
+
+local petAnchors = {
+ TOPLEFT = "TOPLEFT",
+ LEFT = "LEFT",
+ BOTTOMLEFT = "BOTTOMLEFT",
+ RIGHT = "RIGHT",
+ TOPRIGHT = "TOPRIGHT",
+ BOTTOMRIGHT = "BOTTOMRIGHT",
+ TOP = "TOP",
+ BOTTOM = "BOTTOM",
+};
+
+local auraBarsSortValues = {
+ ["TIME_REMAINING"] = L["Time Remaining"],
+ ["TIME_REMAINING_REVERSE"] = L["Time Remaining Reverse"],
+ ["TIME_DURATION"] = L["Duration"],
+ ["TIME_DURATION_REVERSE"] = L["Duration Reverse"],
+ ["NAME"] = "NAME",
+ ["NONE"] = "NONE",
+}
+
+local auraSortValues = {
+ ["TIME_REMAINING"] = L["Time Remaining"],
+ ["DURATION"] = L["Duration"],
+ ["NAME"] = "NAME",
+ ["INDEX"] = L["Index"],
+ ["PLAYER"] = "PLAYER",
+}
+
+local auraSortMethodValues = {
+ ["ASCENDING"] = L["Ascending"],
+ ["DESCENDING"] = L["Descending"]
+}
+
+local CUSTOMTEXT_CONFIGS = {}
+
+local carryFilterFrom, carryFilterTo
+local function filterValue(value)
+ return gsub(value,"([%(%)%.%%%+%-%*%?%[%^%$])","%%%1")
+end
+
+local function filterMatch(s,v)
+ local m1, m2, m3, m4 = "^"..v.."$", "^"..v..",", ","..v.."$", ","..v..","
+ return (match(s, m1) and m1) or (match(s, m2) and m2) or (match(s, m3) and m3) or (match(s, m4) and v..",")
+end
+
+local function filterPriority(auraType, groupName, value, remove, movehere, friendState)
+ if not auraType or not value then return end
+ local filter = E.db.unitframe.units[groupName] and E.db.unitframe.units[groupName][auraType] and E.db.unitframe.units[groupName][auraType].priority
+ if not filter then return end
+ local found = filterMatch(filter, filterValue(value))
+ if found and movehere then
+ local tbl, sv, sm = {strsplit(",",filter)}
+ for i in ipairs(tbl) do
+ if tbl[i] == value then sv = i elseif tbl[i] == movehere then sm = i end
+ if sv and sm then break end
+ end
+ tremove(tbl, sm);tinsert(tbl, sv, movehere);
+ E.db.unitframe.units[groupName][auraType].priority = tconcat(tbl,",")
+ elseif found and friendState then
+ local realValue = match(value, "^Friendly:([^,]*)") or match(value, "^Enemy:([^,]*)") or value
+ local friend = filterMatch(filter, filterValue("Friendly:"..realValue))
+ local enemy = filterMatch(filter, filterValue("Enemy:"..realValue))
+ local default = filterMatch(filter, filterValue(realValue))
+
+ local state =
+ (friend and (not enemy) and format("%s%s","Enemy:",realValue)) --[x] friend [ ] enemy: > enemy
+ or ((not enemy and not friend) and format("%s%s","Friendly:",realValue)) --[ ] friend [ ] enemy: > friendly
+ or (enemy and (not friend) and default and format("%s%s","Friendly:",realValue)) --[ ] friend [x] enemy: (default exists) > friendly
+ or (enemy and (not friend) and match(value, "^Enemy:") and realValue) --[ ] friend [x] enemy: (no default) > realvalue
+ or (friend and enemy and realValue) --[x] friend [x] enemy: > default
+
+ if state then
+ local stateFound = filterMatch(filter, filterValue(state))
+ if not stateFound then
+ local tbl, sv, sm = {strsplit(",",filter)}
+ for i in ipairs(tbl) do
+ if tbl[i] == value then sv = i;break end
+ end
+ tinsert(tbl, sv, state);tremove(tbl, sv+1)
+ E.db.unitframe.units[groupName][auraType].priority = tconcat(tbl,",")
+ end
+ end
+ elseif found and remove then
+ E.db.unitframe.units[groupName][auraType].priority = gsub(filter, found, "")
+ elseif not found and not remove then
+ E.db.unitframe.units[groupName][auraType].priority = (filter == "" and value) or (filter..","..value)
+ end
+end
+
+-----------------------------------------------------------------------
+-- OPTIONS TABLES
+-----------------------------------------------------------------------
+local function GetOptionsTable_AuraBars(friendlyOnly, updateFunc, groupName)
+ local config = {
+ order = 1100,
+ type = "group",
+ name = L["Aura Bars"],
+ get = function(info) return E.db.unitframe.units[groupName]["aurabar"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["aurabar"][ info[getn(info)] ] = value; updateFunc(UF, groupName) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Aura Bars"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ configureButton1 = {
+ order = 3,
+ name = L["Coloring"],
+ desc = L["This opens the UnitFrames Color settings. These settings affect all unitframes."],
+ type = "execute",
+ func = function() ACD:SelectGroup("ElvUI", "unitframe", "generalOptionsGroup", "allColorsGroup", "auraBars") end,
+ },
+ configureButton2 = {
+ order = 4,
+ name = L["Coloring (Specific)"],
+ type = "execute",
+ func = function() E:SetToFilterConfig("AuraBar Colors") end,
+ },
+ anchorPoint = {
+ type = "select",
+ order = 5,
+ name = L["Anchor Point"],
+ desc = L["What point to anchor to the frame you set to attach to."],
+ values = {
+ ["ABOVE"] = L["Above"],
+ ["BELOW"] = L["Below"],
+ },
+ },
+ attachTo = {
+ type = "select",
+ order = 6,
+ name = L["Attach To"],
+ desc = L["The object you want to attach to."],
+ values = {
+ ["FRAME"] = L["Frame"],
+ ["DEBUFFS"] = L["Debuffs"],
+ ["BUFFS"] = L["Buffs"],
+ },
+ },
+ height = {
+ type = "range",
+ order = 7,
+ name = L["Height"],
+ min = 6, max = 40, step = 1,
+ },
+ maxBars = {
+ type = "range",
+ order = 8,
+ name = L["Max Bars"],
+ min = 1, max = 40, step = 1,
+ },
+ sort = {
+ type = "select",
+ order = 9,
+ name = L["Sort Method"],
+ values = auraBarsSortValues,
+ },
+ filters = {
+ name = FILTERS,
+ guiInline = true,
+ type = "group",
+ order = 500,
+ args = {},
+ },
+ friendlyAuraType = {
+ type = "select",
+ order = 16,
+ name = L["Friendly Aura Type"],
+ desc = L["Set the type of auras to show when a unit is friendly."],
+ values = {
+ ["HARMFUL"] = L["Debuffs"],
+ ["HELPFUL"] = L["Buffs"],
+ },
+ },
+ enemyAuraType = {
+ type = "select",
+ order = 17,
+ name = L["Enemy Aura Type"],
+ desc = L["Set the type of auras to show when a unit is a foe."],
+ values = {
+ ["HARMFUL"] = L["Debuffs"],
+ ["HELPFUL"] = L["Buffs"],
+ },
+ },
+ uniformThreshold = {
+ order = 18,
+ type = "range",
+ name = L["Uniform Threshold"],
+ desc = L["Seconds remaining on the aura duration before the bar starts moving. Set to 0 to disable."],
+ min = 0, max = 3600, step = 1,
+ },
+ yOffset = {
+ order = 19,
+ type = "range",
+ name = L["yOffset"],
+ min = -1000, max = 1000, step = 1,
+ },
+ },
+ }
+
+ if groupName == "target" then
+ config.args.attachTo.values["PLAYER_AURABARS"] = L["Player Frame Aura Bars"]
+ end
+
+ config.args.filters.args.minDuration = {
+ order = 16,
+ type = "range",
+ name = L["Minimum Duration"],
+ desc = L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."],
+ min = 0, max = 10800, step = 1,
+ }
+ config.args.filters.args.maxDuration = {
+ order = 17,
+ type = "range",
+ name = L["Maximum Duration"],
+ desc = L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."],
+ min = 0, max = 10800, step = 1,
+ }
+ config.args.filters.args.jumpToFilter = {
+ order = 18,
+ name = L["Filters Page"],
+ desc = L["Shortcut to 'Filters' section of the config."],
+ type = "execute",
+ func = function() ACD:SelectGroup("ElvUI", "filters") end,
+ }
+ config.args.filters.args.specialPriority = {
+ order = 19,
+ name = L["Add Special Filter"],
+ desc = L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."],
+ type = "select",
+ values = function()
+ local filters = {}
+ local list = E.global.unitframe["specialFilters"]
+ if not list then return end
+ for filter in pairs(list) do
+ filters[filter] = filter
+ end
+ return filters
+ end,
+ set = function(info, value)
+ filterPriority("aurabar", groupName, value)
+ updateFunc(UF, groupName)
+ end
+ }
+ config.args.filters.args.priority = {
+ order = 20,
+ name = L["Add Regular Filter"],
+ desc = L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."],
+ type = "select",
+ values = function()
+ local filters = {}
+ local list = E.global.unitframe["aurafilters"]
+ if not list then return end
+ for filter in pairs(list) do
+ filters[filter] = filter
+ end
+ return filters
+ end,
+ set = function(info, value)
+ filterPriority("aurabar", groupName, value)
+ updateFunc(UF, groupName)
+ end
+ }
+ config.args.filters.args.resetPriority = {
+ order = 21,
+ name = L["Reset Priority"],
+ desc = L["Reset filter priority to the default state."],
+ type = "execute",
+ func = function()
+ E.db.unitframe.units[groupName].aurabar.priority = P.unitframe.units[groupName].aurabar.priority
+ updateFunc(UF, groupName)
+ end,
+ }
+ config.args.filters.args.filterPriority = {
+ order = 22,
+ dragdrop = true,
+ type = "multiselect",
+ name = L["Filter Priority"],
+ dragOnLeave = function() end, --keep this here
+ dragOnEnter = function(info, value)
+ carryFilterTo = info.obj.value
+ end,
+ dragOnMouseDown = function(info, value)
+ carryFilterFrom, carryFilterTo = info.obj.value, nil
+ end,
+ dragOnMouseUp = function(info, value)
+ filterPriority("aurabar", groupName, carryFilterTo, nil, carryFilterFrom) --add it in the new spot
+ carryFilterFrom, carryFilterTo = nil, nil
+ end,
+ dragOnClick = function(info, value)
+ filterPriority("aurabar", groupName, carryFilterFrom, true)
+ end,
+ stateSwitchGetText = function(button, text, value)
+ local friend, enemy = match(text, "^Friendly:([^,]*)"), match(text, "^Enemy:([^,]*)")
+ return (friend and format("|cFF33FF33%s|r %s", L["Friend"], friend)) or (enemy and format("|cFFFF3333%s|r %s", L["Enemy"], enemy))
+ end,
+ stateSwitchOnClick = function(info, value)
+ filterPriority("aurabar", groupName, carryFilterFrom, nil, nil, true)
+ end,
+ values = function()
+ local str = E.db.unitframe.units[groupName].aurabar.priority
+ if str == "" then return nil end
+ return {strsplit(",",str)}
+ end,
+ get = function(info, value)
+ local str = E.db.unitframe.units[groupName].aurabar.priority
+ if str == "" then return nil end
+ local tbl = {strsplit(",",str)}
+ return tbl[value]
+ end,
+ set = function(info, value)
+ E.db.unitframe.units[groupName].aurabar[ info[getn(info)] ] = nil -- this was being set when drag and drop was first added, setting it to nil to clear tester profiles of this variable
+ updateFunc(UF, groupName)
+ end
+ }
+ config.args.filters.args.spacer1 = {
+ order = 23,
+ type = "description",
+ name = L["Use drag and drop to rearrange filter priority or right click to remove a filter."].."\n"..L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."],
+ }
+
+ return config
+end
+
+local function GetOptionsTable_Auras(friendlyUnitOnly, auraType, isGroupFrame, updateFunc, groupName, numUnits)
+ local config = {
+ order = auraType == "buffs" and 600 or 700,
+ type = "group",
+ name = auraType == "buffs" and L["Buffs"] or L["Debuffs"],
+ get = function(info) return E.db.unitframe.units[groupName][auraType][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName][auraType][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ type = "header",
+ order = 1,
+ name = auraType == "buffs" and L["Buffs"] or L["Debuffs"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ perrow = {
+ type = "range",
+ order = 3,
+ name = L["Per Row"],
+ min = 1, max = 20, step = 1,
+ },
+ numrows = {
+ type = "range",
+ order = 4,
+ name = L["Num Rows"],
+ min = 1, max = 10, step = 1,
+ },
+ sizeOverride = {
+ type = "range",
+ order = 5,
+ name = L["Size Override"],
+ desc = L["If not set to 0 then override the size of the aura icon to this."],
+ min = 0, max = 60, step = 1,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ min = -1000, max = 1000, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ min = -1000, max = 1000, step = 1,
+ },
+ anchorPoint = {
+ type = "select",
+ order = 8,
+ name = L["Anchor Point"],
+ desc = L["What point to anchor to the frame you set to attach to."],
+ values = positionValues,
+ },
+ fontSize = {
+ order = 9,
+ name = FONT_SIZE,
+ type = "range",
+ min = 6, max = 212, step = 1,
+ },
+ clickThrough = {
+ order = 15,
+ name = L["Click Through"],
+ desc = L["Ignore mouse events."],
+ type = "toggle",
+ },
+ sortMethod = {
+ order = 16,
+ name = L["Sort By"],
+ desc = L["Method to sort by."],
+ type = "select",
+ values = auraSortValues,
+ },
+ sortDirection = {
+ order = 16,
+ name = L["Sort Direction"],
+ desc = L["Ascending or Descending order."],
+ type = "select",
+ values = auraSortMethodValues,
+ },
+ filters = {
+ name = FILTERS,
+ guiInline = true,
+ type = "group",
+ order = 500,
+ args = {},
+ },
+ },
+ }
+
+ if auraType == "buffs" then
+ config.args.attachTo = {
+ type = "select",
+ order = 7,
+ name = L["Attach To"],
+ desc = L["What to attach the buff anchor frame to."],
+ values = {
+ ["FRAME"] = L["Frame"],
+ ["DEBUFFS"] = L["Debuffs"],
+ ["HEALTH"] = L["Health"],
+ ["POWER"] = L["Power"],
+ },
+ }
+ else
+ config.args.attachTo = {
+ type = "select",
+ order = 7,
+ name = L["Attach To"],
+ desc = L["What to attach the debuff anchor frame to."],
+ values = {
+ ["FRAME"] = L["Frame"],
+ ["BUFFS"] = L["Buffs"],
+ ["HEALTH"] = L["Health"],
+ ["POWER"] = L["Power"],
+ },
+ }
+ end
+
+ if isGroupFrame then
+ config.args.countFontSize = {
+ order = 10,
+ name = L["Count Font Size"],
+ type = "range",
+ min = 6, max = 212, step = 1,
+ }
+ end
+
+ config.args.filters.args.minDuration = {
+ order = 16,
+ type = "range",
+ name = L["Minimum Duration"],
+ desc = L["Don't display auras that are shorter than this duration (in seconds). Set to zero to disable."],
+ min = 0, max = 10800, step = 1,
+ }
+ config.args.filters.args.maxDuration = {
+ order = 17,
+ type = "range",
+ name = L["Maximum Duration"],
+ desc = L["Don't display auras that are longer than this duration (in seconds). Set to zero to disable."],
+ min = 0, max = 10800, step = 1,
+ }
+ config.args.filters.args.jumpToFilter = {
+ order = 18,
+ name = L["Filters Page"],
+ desc = L["Shortcut to 'Filters' section of the config."],
+ type = "execute",
+ func = function() ACD:SelectGroup("ElvUI", "filters") end,
+ }
+ config.args.filters.args.specialPriority = {
+ order = 19,
+ name = L["Add Special Filter"],
+ desc = L["These filters don't use a list of spells like the regular filters. Instead they use the WoW API and some code logic to determine if an aura should be allowed or blocked."],
+ type = "select",
+ values = function()
+ local filters = {}
+ local list = E.global.unitframe["specialFilters"]
+ if not list then return end
+ for filter in pairs(list) do
+ filters[filter] = filter
+ end
+ return filters
+ end,
+ set = function(info, value)
+ filterPriority(auraType, groupName, value)
+ updateFunc(UF, groupName, numUnits)
+ end
+ }
+ config.args.filters.args.priority = {
+ order = 20,
+ name = L["Add Regular Filter"],
+ desc = L["These filters use a list of spells to determine if an aura should be allowed or blocked. The content of these filters can be modified in the 'Filters' section of the config."],
+ type = "select",
+ values = function()
+ local filters = {}
+ local list = E.global.unitframe["aurafilters"]
+ if not list then return end
+ for filter in pairs(list) do
+ filters[filter] = filter
+ end
+ return filters
+ end,
+ set = function(info, value)
+ filterPriority(auraType, groupName, value)
+ updateFunc(UF, groupName, numUnits)
+ end
+ }
+ config.args.filters.args.resetPriority = {
+ order = 21,
+ name = L["Reset Priority"],
+ desc = L["Reset filter priority to the default state."],
+ type = "execute",
+ func = function()
+ E.db.unitframe.units[groupName][auraType].priority = P.unitframe.units[groupName][auraType].priority
+ updateFunc(UF, groupName, numUnits)
+ end,
+ }
+ config.args.filters.args.filterPriority = {
+ order = 22,
+ dragdrop = true,
+ type = "multiselect",
+ name = L["Filter Priority"],
+ dragOnLeave = function() end, --keep this here
+ dragOnEnter = function(info, value)
+ carryFilterTo = info.obj.value
+ end,
+ dragOnMouseDown = function(info, value)
+ carryFilterFrom, carryFilterTo = info.obj.value, nil
+ end,
+ dragOnMouseUp = function(info, value)
+ filterPriority(auraType, groupName, carryFilterTo, nil, carryFilterFrom) --add it in the new spot
+ carryFilterFrom, carryFilterTo = nil, nil
+ end,
+ dragOnClick = function(info, value)
+ filterPriority(auraType, groupName, carryFilterFrom, true)
+ end,
+ stateSwitchGetText = function(button, text, value)
+ local friend, enemy = match(text, "^Friendly:([^,]*)"), match(text, "^Enemy:([^,]*)")
+ return (friend and format("|cFF33FF33%s|r %s", L["Friend"], friend)) or (enemy and format("|cFFFF3333%s|r %s", L["Enemy"], enemy))
+ end,
+ stateSwitchOnClick = function(info, value)
+ filterPriority(auraType, groupName, carryFilterFrom, nil, nil, true)
+ end,
+ values = function()
+ local str = E.db.unitframe.units[groupName][auraType].priority
+ if str == "" then return nil end
+ return {strsplit(",",str)}
+ end,
+ get = function(info, value)
+ local str = E.db.unitframe.units[groupName][auraType].priority
+ if str == "" then return nil end
+ local tbl = {strsplit(",",str)}
+ return tbl[value]
+ end,
+ set = function(info, value)
+ E.db.unitframe.units[groupName][auraType][ info[getn(info)] ] = nil -- this was being set when drag and drop was first added, setting it to nil to clear tester profiles of this variable
+ updateFunc(UF, groupName, numUnits)
+ end
+ }
+ config.args.filters.args.spacer1 = {
+ order = 23,
+ type = "description",
+ name = L["Use drag and drop to rearrange filter priority or right click to remove a filter."].."\n"..L["Use Shift+LeftClick to toggle between friendly or enemy or normal state. Normal state will allow the filter to be checked on all units. Friendly state is for friendly units only and enemy state is for enemy units."],
+ }
+
+ return config
+end
+
+local function GetOptionsTable_Castbar(hasTicks, updateFunc, groupName, numUnits)
+ local config = {
+ order = 800,
+ type = "group",
+ name = L["Castbar"],
+ get = function(info) return E.db.unitframe.units[groupName]["castbar"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["castbar"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Castbar"],
+ },
+ matchsize = {
+ order = 2,
+ type = "execute",
+ name = L["Match Frame Width"],
+ func = function() E.db.unitframe.units[groupName]["castbar"]["width"] = E.db.unitframe.units[groupName]["width"]; updateFunc(UF, groupName, numUnits) end,
+ },
+ forceshow = {
+ order = 3,
+ name = L["Show"].." / "..HIDE,
+ func = function()
+ local frameName = E:StringTitle(groupName)
+ frameName = "ElvUF_"..frameName
+ frameName = gsub(frameName, "t(arget)", "T%1")
+
+ if numUnits then
+ for i=1, numUnits do
+ local castbar = _G[frameName..i].Castbar
+ if not castbar.oldHide then
+ castbar.oldHide = castbar.Hide
+ castbar.Hide = castbar.Show
+ castbar:Show()
+ else
+ castbar.Hide = castbar.oldHide
+ castbar.oldHide = nil
+ castbar:Hide()
+ end
+ end
+ else
+ local castbar = _G[frameName].Castbar
+ if not castbar.oldHide then
+ castbar.oldHide = castbar.Hide
+ castbar.Hide = castbar.Show
+ castbar:Show()
+ else
+ castbar.Hide = castbar.oldHide
+ castbar.oldHide = nil
+ castbar:Hide()
+ end
+ end
+ end,
+ type = "execute",
+ },
+ configureButton = {
+ order = 4,
+ name = L["Coloring"],
+ desc = L["This opens the UnitFrames Color settings. These settings affect all unitframes."],
+ type = "execute",
+ func = function() ACD:SelectGroup("ElvUI", "unitframe", "generalOptionsGroup", "allColorsGroup", "castBars") end,
+ },
+ enable = {
+ type = "toggle",
+ order = 5,
+ name = L["Enable"],
+ },
+ width = {
+ order = 6,
+ name = L["Width"],
+ type = "range",
+ softMax = 600,
+ min = 50, max = GetScreenWidth(), step = 1,
+ },
+ height = {
+ order = 7,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 85, step = 1,
+ },
+ latency = {
+ order = 8,
+ name = L["Latency"],
+ type = "toggle",
+ },
+ format = {
+ order = 9,
+ type = "select",
+ name = L["Format"],
+ values = {
+ ["CURRENTMAX"] = L["Current / Max"],
+ ["CURRENT"] = L["Current"],
+ ["REMAINING"] = L["Remaining"],
+ },
+ },
+ spark = {
+ order = 10,
+ type = "toggle",
+ name = L["Spark"],
+ desc = L["Display a spark texture at the end of the castbar statusbar to help show the differance between castbar and backdrop."],
+ },
+ insideInfoPanel = {
+ order = 11,
+ name = L["Inside Information Panel"],
+ desc = L["Display the castbar inside the information panel, the icon will be displayed outside the main unitframe."],
+ type = "toggle",
+ disabled = function() return not E.db.unitframe.units[groupName].infoPanel or not E.db.unitframe.units[groupName].infoPanel.enable end,
+ },
+ iconSettings = {
+ order = 13,
+ type = "group",
+ name = L["Icon"],
+ guiInline = true,
+ get = function(info) return E.db.unitframe.units[groupName]["castbar"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["castbar"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ icon = {
+ order = 1,
+ name = L["Enable"],
+ type = "toggle",
+ },
+ iconAttached = {
+ order = 2,
+ name = L["Icon Inside Castbar"],
+ desc = L["Display the castbar icon inside the castbar."],
+ type = "toggle",
+ },
+ iconSize = {
+ order = 3,
+ name = L["Icon Size"],
+ desc = L["This dictates the size of the icon when it is not attached to the castbar."],
+ type = "range",
+ disabled = function() return E.db.unitframe.units[groupName].castbar.iconAttached end,
+ min = 8, max = 150, step = 1,
+ },
+ iconAttachedTo = {
+ order = 4,
+ type = "select",
+ name = L["Attach To"],
+ disabled = function() return E.db.unitframe.units[groupName].castbar.iconAttached end,
+ values = {
+ ["Frame"] = L["Frame"],
+ ["Castbar"] = L["Castbar"],
+ },
+ },
+ iconPosition = {
+ type = "select",
+ order = 5,
+ name = L["Position"],
+ values = positionValues,
+ disabled = function() return E.db.unitframe.units[groupName].castbar.iconAttached end,
+ },
+ iconXOffset = {
+ order = 5,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ disabled = function() return E.db.unitframe.units[groupName].castbar.iconAttached end,
+ },
+ iconYOffset = {
+ order = 6,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ disabled = function() return E.db.unitframe.units[groupName].castbar.iconAttached end,
+ },
+ },
+ },
+ },
+ }
+
+
+ if hasTicks then
+ config.args.displayTarget = {
+ order = 11,
+ type = "toggle",
+ name = L["Display Target"],
+ desc = L["Display the target of your current cast. Useful for mouseover casts."],
+ }
+
+ config.args.ticks = {
+ order = 12,
+ type = "group",
+ guiInline = true,
+ name = L["Ticks"],
+ args = {
+ ticks = {
+ order = 1,
+ type = 'toggle',
+ name = L["Ticks"],
+ desc = L["Display tick marks on the castbar for channelled spells. This will adjust automatically for spells like Drain Soul and add additional ticks based on haste."],
+ },
+ tickColor = {
+ order = 2,
+ type = "color",
+ name = COLOR,
+ hasAlpha = true,
+ get = function(info)
+ local c = E.db.unitframe.units[groupName].castbar.tickColor
+ local d = P.unitframe.units[groupName].castbar.tickColor
+ return c.r, c.g, c.b, c.a, d.r, d.g, d.b, d.a
+ end,
+ set = function(info, r, g, b, a)
+ local c = E.db.unitframe.units[groupName].castbar.tickColor
+ c.r, c.g, c.b, c.a = r, g, b, a
+ updateFunc(UF, groupName, numUnits)
+ end,
+ },
+ tickWidth = {
+ order = 3,
+ type = "range",
+ name = L["Width"],
+ min = 1, max = 20, step = 1,
+ },
+ },
+ }
+ end
+
+ return config
+end
+
+
+local function GetOptionsTable_InformationPanel(updateFunc, groupName, numUnits)
+
+ local config = {
+ order = 4000,
+ type = "group",
+ name = L["Information Panel"],
+ get = function(info) return E.db.unitframe.units[groupName]["infoPanel"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["infoPanel"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Information Panel"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ transparent = {
+ type = "toggle",
+ order = 3,
+ name = L["Transparent"],
+ },
+ height = {
+ type = "range",
+ order = 4,
+ name = L["Height"],
+ min = 4, max = 30, step = 1,
+ },
+ }
+ }
+
+ return config
+end
+
+local function GetOptionsTable_Health(isGroupFrame, updateFunc, groupName, numUnits)
+ local config = {
+ order = 100,
+ type = "group",
+ name = L["Health"],
+ get = function(info) return E.db.unitframe.units[groupName]["health"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["health"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Health"],
+ },
+ position = {
+ type = "select",
+ order = 2,
+ name = L["Text Position"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 3,
+ type = "range",
+ name = L["Text xOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 4,
+ type = "range",
+ name = L["Text yOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ attachTextTo = {
+ type = "select",
+ order = 5,
+ name = L["Attach Text To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ configureButton = {
+ order = 6,
+ name = L["Coloring"],
+ desc = L["This opens the UnitFrames Color settings. These settings affect all unitframes."],
+ type = "execute",
+ func = function() ACD:SelectGroup("ElvUI", "unitframe", "generalOptionsGroup", "allColorsGroup", "healthGroup") end,
+ },
+ },
+ }
+
+ if isGroupFrame then
+ config.args.frequentUpdates = {
+ type = "toggle",
+ order = 2,
+ name = L["Frequent Updates"],
+ desc = L["Rapidly update the health, uses more memory and cpu. Only recommended for healing."],
+ }
+
+ config.args.orientation = {
+ type = "select",
+ order = 3,
+ name = L["Statusbar Fill Orientation"],
+ desc = L["Direction the health bar moves when gaining/losing health."],
+ values = {
+ ["HORIZONTAL"] = L["Horizontal"],
+ ["VERTICAL"] = L["Vertical"],
+ },
+ }
+ end
+
+ return config
+end
+
+local function CreateCustomTextGroup(unit, objectName)
+ if not E.Options.args.unitframe.args[unit] then
+ return
+ elseif E.Options.args.unitframe.args[unit].args.customText.args[objectName] then
+ E.Options.args.unitframe.args[unit].args.customText.args[objectName].hidden = false -- Re-show existing custom texts which belong to current profile and were previously hidden
+ tinsert(CUSTOMTEXT_CONFIGS, E.Options.args.unitframe.args[unit].args.customText.args[objectName]) --Register this custom text config to be hidden again on profile change
+ return
+ end
+
+ E.Options.args.unitframe.args[unit].args.customText.args[objectName] = {
+ order = -1,
+ type = "group",
+ name = objectName,
+ get = function(info) return E.db.unitframe.units[unit].customTexts[objectName][ info[getn(info)] ] end,
+ set = function(info, value)
+ E.db.unitframe.units[unit].customTexts[objectName][ info[getn(info)] ] = value;
+
+ if unit == "party" or unit:find("raid") then
+ UF:CreateAndUpdateHeaderGroup(unit)
+ elseif unit == "boss" then
+ UF:CreateAndUpdateUFGroup("boss", MAX_BOSS_FRAMES)
+ elseif unit == "arena" then
+ UF:CreateAndUpdateUFGroup("arena", 5)
+ else
+ UF:CreateAndUpdateUF(unit)
+ end
+ end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = objectName,
+ },
+ delete = {
+ type = "execute",
+ order = 2,
+ name = DELETE,
+ func = function()
+ E.Options.args.unitframe.args[unit].args.customText.args[objectName] = nil;
+ E.db.unitframe.units[unit].customTexts[objectName] = nil;
+
+ if unit == "boss" or unit == "arena" then
+ for i=1, 5 do
+ if UF[unit..i] then
+ UF[unit..i]:Tag(UF[unit..i]["customTexts"][objectName], "");
+ UF[unit..i]["customTexts"][objectName]:Hide();
+ end
+ end
+ elseif unit == "party" or unit:find("raid") then
+ for i=1, UF[unit]:GetNumChildren() do
+ local child = select(i, UF[unit]:GetChildren())
+ if child.Tag then
+ child:Tag(child["customTexts"][objectName], "");
+ child["customTexts"][objectName]:Hide();
+ else
+ for x=1, child:GetNumChildren() do
+ local c2 = select(x, child:GetChildren())
+ if(c2.Tag) then
+ c2:Tag(c2["customTexts"][objectName], "");
+ c2["customTexts"][objectName]:Hide();
+ end
+ end
+ end
+ end
+ elseif UF[unit] then
+ UF[unit]:Tag(UF[unit]["customTexts"][objectName], "");
+ UF[unit]["customTexts"][objectName]:Hide();
+ end
+ end,
+ },
+ font = {
+ type = "select", dialogControl = "LSM30_Font",
+ order = 3,
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ },
+ size = {
+ order = 4,
+ name = FONT_SIZE,
+ type = "range",
+ min = 4, max = 212, step = 1,
+ },
+ fontOutline = {
+ order = 5,
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ type = "select",
+ values = {
+ ["NONE"] = NONE,
+ ["OUTLINE"] = "OUTLINE",
+
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE",
+ },
+ },
+ justifyH = {
+ order = 6,
+ type = "select",
+ name = L["JustifyH"],
+ desc = L["Sets the font instance's horizontal text alignment style."],
+ values = {
+ ["CENTER"] = L["Center"],
+ ["LEFT"] = L["Left"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ xOffset = {
+ order = 7,
+ type = "range",
+ name = L["xOffset"],
+ min = -400, max = 400, step = 1,
+ },
+ yOffset = {
+ order = 8,
+ type = "range",
+ name = L["yOffset"],
+ min = -400, max = 400, step = 1,
+ },
+ attachTextTo = {
+ type = "select",
+ order = 9,
+ name = L["Attach Text To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ },
+ }
+
+ tinsert(CUSTOMTEXT_CONFIGS, E.Options.args.unitframe.args[unit].args.customText.args[objectName]) --Register this custom text config to be hidden on profile change
+end
+
+local function GetOptionsTable_CustomText(updateFunc, groupName, numUnits, orderOverride)
+ local config = {
+ order = 5100,
+ type = "group",
+ name = L["Custom Texts"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Custom Texts"],
+ },
+ createCustomText = {
+ order = 2,
+ type = "input",
+ name = L["Create Custom Text"],
+ width = "full",
+ get = function() return "" end,
+ set = function(info, textName)
+ for object, _ in pairs(E.db.unitframe.units[groupName]) do
+ if object:lower() == textName:lower() then
+ E:Print(L["The name you have selected is already in use by another element."])
+ return
+ end
+ end
+
+ if not E.db.unitframe.units[groupName].customTexts then
+ E.db.unitframe.units[groupName].customTexts = {};
+ end
+
+ local frameName = "ElvUF_"..E:StringTitle(groupName)
+ if E.db.unitframe.units[groupName].customTexts[textName] or (_G[frameName] and _G[frameName]["customTexts"] and _G[frameName]["customTexts"][textName] or _G[frameName.."Group1UnitButton1"] and _G[frameName.."Group1UnitButton1"]["customTexts"] and _G[frameName.."Group1UnitButton1"][textName]) then
+ E:Print(L["The name you have selected is already in use by another element."])
+ return;
+ end
+
+ E.db.unitframe.units[groupName].customTexts[textName] = {
+ ["text_format"] = "",
+ ["size"] = E.db.unitframe.fontSize,
+ ["font"] = E.db.unitframe.font,
+ ["xOffset"] = 0,
+ ["yOffset"] = 0,
+ ["justifyH"] = "CENTER",
+ ["fontOutline"] = E.db.unitframe.fontOutline,
+ ["attachTextTo"] = "Health"
+ };
+
+ CreateCustomTextGroup(groupName, textName)
+ updateFunc(UF, groupName, numUnits)
+ end,
+ },
+ },
+ }
+
+ return config
+end
+
+local function GetOptionsTable_Name(updateFunc, groupName, numUnits)
+ local config = {
+ order = 400,
+ type = "group",
+ name = L["Name"],
+ get = function(info) return E.db.unitframe.units[groupName]["name"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["name"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Name"],
+ },
+ position = {
+ type = "select",
+ order = 2,
+ name = L["Text Position"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 3,
+ type = "range",
+ name = L["Text xOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 4,
+ type = "range",
+ name = L["Text yOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ attachTextTo = {
+ type = "select",
+ order = 5,
+ name = L["Attach Text To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ },
+ }
+
+ return config
+end
+
+local function GetOptionsTable_Portrait(updateFunc, groupName, numUnits)
+ local config = {
+ order = 400,
+ type = "group",
+ name = L["Portrait"],
+ get = function(info) return E.db.unitframe.units[groupName]["portrait"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["portrait"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Portrait"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ desc = L["If you have a lot of 3D Portraits active then it will likely have a big impact on your FPS. Disable some portraits if you experience FPS issues."],
+ },
+ width = {
+ type = "range",
+ order = 3,
+ name = L["Width"],
+ min = 15, max = 150, step = 1,
+ },
+ overlay = {
+ type = "toggle",
+ name = L["Overlay"],
+ desc = L["Overlay the healthbar"],
+ order = 4,
+ },
+ style = {
+ type = "select",
+ name = L["Style"],
+ desc = L["Select the display method of the portrait."],
+ order = 5,
+ values = {
+ ["2D"] = L["2D"],
+ ["3D"] = L["3D"],
+ },
+ },
+ },
+ }
+
+ return config
+end
+
+local function GetOptionsTable_Power(hasDetatchOption, updateFunc, groupName, numUnits, hasStrataLevel)
+ local config = {
+ order = 200,
+ type = "group",
+ name = L["Power"],
+ get = function(info) return E.db.unitframe.units[groupName]["power"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["power"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Power"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ width = {
+ type = "select",
+ order = 3,
+ name = L["Style"],
+ values = fillValues,
+ set = function(info, value)
+ E.db.unitframe.units[groupName]["power"][ info[getn(info)] ] = value;
+
+ local frameName = E:StringTitle(groupName)
+ frameName = "ElvUF_"..frameName
+ frameName = string.gsub(frameName, "t(arget)", "T%1")
+
+ if numUnits then
+ for i=1, numUnits do
+ if _G[frameName..i] then
+ local v = _G[frameName..i].Power:GetValue()
+ local min, max = _G[frameName..i].Power:GetMinMaxValues()
+ _G[frameName..i].Power:SetMinMaxValues(min, max + 500)
+ _G[frameName..i].Power:SetValue(1)
+ _G[frameName..i].Power:SetValue(0)
+ end
+ end
+ else
+ if _G[frameName] and _G[frameName].Power then
+ local v = _G[frameName].Power:GetValue()
+ local min, max = _G[frameName].Power:GetMinMaxValues()
+ _G[frameName].Power:SetMinMaxValues(min, max + 500)
+ _G[frameName].Power:SetValue(1)
+ _G[frameName].Power:SetValue(0)
+ else
+ for i=1, _G[frameName]:GetNumChildren() do
+ local child = select(i, _G[frameName]:GetChildren())
+ if child and child.Power then
+ local v = child.Power:GetValue()
+ local min, max = child.Power:GetMinMaxValues()
+ child.Power:SetMinMaxValues(min, max + 500)
+ child.Power:SetValue(1)
+ child.Power:SetValue(0)
+ end
+ end
+ end
+ end
+
+ updateFunc(UF, groupName, numUnits)
+ end,
+ },
+ height = {
+ type = "range",
+ name = L["Height"],
+ order = 4,
+ min = ((E.db.unitframe.thinBorders or E.PixelMode) and 3 or 7), max = 50, step = 1,
+ },
+ offset = {
+ type = "range",
+ name = L["Offset"],
+ desc = L["Offset of the powerbar to the healthbar, set to 0 to disable."],
+ order = 5,
+ min = 0, max = 20, step = 1,
+ },
+ configureButton = {
+ order = 6,
+ name = L["Coloring"],
+ desc = L["This opens the UnitFrames Color settings. These settings affect all unitframes."],
+ type = "execute",
+ func = function() ACD:SelectGroup("ElvUI", "unitframe", "generalOptionsGroup", "allColorsGroup", "powerGroup") end,
+ },
+ position = {
+ type = "select",
+ order = 7,
+ name = L["Text Position"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 8,
+ type = "range",
+ name = L["Text xOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 9,
+ type = "range",
+ name = L["Text yOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ attachTextTo = {
+ type = "select",
+ order = 10,
+ name = L["Attach Text To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ },
+ }
+
+ if hasDetatchOption then
+ config.args.detachFromFrame = {
+ type = "toggle",
+ order = 11,
+ name = L["Detach From Frame"],
+ }
+ config.args.detachedWidth = {
+ type = "range",
+ order = 12,
+ name = L["Detached Width"],
+ disabled = function() return not E.db.unitframe.units[groupName].power.detachFromFrame end,
+ min = 15, max = 450, step = 1,
+ }
+ config.args.parent = {
+ type = "select",
+ order = 13,
+ name = L["Parent"],
+ desc = L["Choose UIPARENT to prevent it from hiding with the unitframe."],
+ disabled = function() return not E.db.unitframe.units[groupName].power.detachFromFrame end,
+ values = {
+ ["FRAME"] = "FRAME",
+ ["UIPARENT"] = "UIPARENT",
+ },
+ }
+ end
+
+ if hasStrataLevel then
+ config.args.strataAndLevel = {
+ order = 101,
+ type = "group",
+ name = L["Strata and Level"],
+ get = function(info) return E.db.unitframe.units[groupName]["power"]["strataAndLevel"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["power"]["strataAndLevel"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ guiInline = true,
+ args = {
+ useCustomStrata = {
+ order = 1,
+ type = "toggle",
+ name = L["Use Custom Strata"],
+ },
+ frameStrata = {
+ order = 2,
+ type = "select",
+ name = L["Frame Strata"],
+ values = {
+ ["BACKGROUND"] = "BACKGROUND",
+ ["LOW"] = "LOW",
+ ["MEDIUM"] = "MEDIUM",
+ ["HIGH"] = "HIGH",
+ ["DIALOG"] = "DIALOG",
+ ["TOOLTIP"] = "TOOLTIP",
+ },
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = "",
+ },
+ useCustomLevel = {
+ order = 4,
+ type = "toggle",
+ name = L["Use Custom Level"],
+ },
+ frameLevel = {
+ order = 5,
+ type = "range",
+ name = L["Frame Level"],
+ min = 2, max = 128, step = 1,
+ },
+ },
+ }
+ end
+
+ return config
+end
+
+local function GetOptionsTable_RaidIcon(updateFunc, groupName, numUnits)
+ local config = {
+ order = 5000,
+ type = "group",
+ name = L["Raid Icon"],
+ get = function(info) return E.db.unitframe.units[groupName]["raidicon"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["raidicon"][ info[getn(info)] ] = value; updateFunc(UF, groupName, numUnits) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Raid Icon"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ attachTo = {
+ type = "select",
+ order = 3,
+ name = L["Position"],
+ values = positionValues,
+ },
+ attachToObject = {
+ type = "select",
+ order = 4,
+ name = L["Attach To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ size = {
+ type = "range",
+ name = L["Size"],
+ order = 4,
+ min = 8, max = 60, step = 1,
+ },
+ xOffset = {
+ order = 5,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 6,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ },
+ }
+
+ return config
+end
+
+local function GetOptionsTable_RaidDebuff(updateFunc, groupName)
+ local config = {
+ order = 800,
+ type = "group",
+ name = L["RaidDebuff Indicator"],
+ get = function(info) return E.db.unitframe.units[groupName]["rdebuffs"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["rdebuffs"][ info[getn(info)] ] = value; updateFunc(UF, groupName) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["RaidDebuff Indicator"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ showDispellableDebuff = {
+ order = 3,
+ type = "toggle",
+ name = L["Show Dispellable Debuffs"],
+ },
+ onlyMatchSpellID = {
+ order = 4,
+ type = "toggle",
+ name = L["Only Match SpellID"],
+ desc = L["When enabled it will only show spells that were added to the filter using a spell ID and not a name."],
+ },
+ size = {
+ order = 4,
+ type = "range",
+ name = L["Size"],
+ min = 8, max = 100, step = 1,
+ },
+ font = {
+ order = 5,
+ type = "select", dialogControl = "LSM30_Font",
+ name = L["Font"],
+ values = AceGUIWidgetLSMlists.font,
+ },
+ fontSize = {
+ order = 6,
+ type = "range",
+ name = FONT_SIZE,
+ min = 7, max = 212, step = 1,
+ },
+ fontOutline = {
+ order = 7,
+ type = "select",
+ name = L["Font Outline"],
+ values = {
+ ["NONE"] = NONE,
+ ["OUTLINE"] = "OUTLINE",
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE",
+ },
+ },
+ xOffset = {
+ order = 8,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 9,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ configureButton = {
+ order = 10,
+ type = "execute",
+ name = L["Configure Auras"],
+ func = function() E:SetToFilterConfig("RaidDebuffs") end,
+ },
+ duration = {
+ order = 11,
+ type = "group",
+ guiInline = true,
+ name = L["Duration Text"],
+ get = function(info) return E.db.unitframe.units[groupName]["rdebuffs"]["duration"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["rdebuffs"]["duration"][ info[getn(info)] ] = value; updateFunc(UF, groupName) end,
+ args = {
+ position = {
+ order = 1,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["TOP"] = "TOP",
+ ["LEFT"] = "LEFT",
+ ["RIGHT"] = "RIGHT",
+ ["BOTTOM"] = "BOTTOM",
+ ["CENTER"] = "CENTER",
+ ["TOPLEFT"] = "TOPLEFT",
+ ["TOPRIGHT"] = "TOPRIGHT",
+ ["BOTTOMLEFT"] = "BOTTOMLEFT",
+ ["BOTTOMRIGHT"] = "BOTTOMRIGHT",
+ },
+ },
+ xOffset = {
+ order = 2,
+ type = "range",
+ name = L["xOffset"],
+ min = -10, max = 10, step = 1,
+ },
+ yOffset = {
+ order = 3,
+ type = "range",
+ name = L["yOffset"],
+ min = -10, max = 10, step = 1,
+ },
+ color = {
+ order = 4,
+ type = "color",
+ name = COLOR,
+ hasAlpha = true,
+ get = function(info)
+ local c = E.db.unitframe.units.raid.rdebuffs.duration.color
+ local d = P.unitframe.units.raid.rdebuffs.duration.color
+ return c.r, c.g, c.b, c.a, d.r, d.g, d.b, d.a
+ end,
+ set = function(info, r, g, b, a)
+ local c = E.db.unitframe.units.raid.rdebuffs.duration.color
+ c.r, c.g, c.b, c.a = r, g, b, a
+ UF:CreateAndUpdateHeaderGroup("raid")
+ end,
+ },
+ },
+ },
+ stack = {
+ order = 12,
+ type = "group",
+ guiInline = true,
+ name = L["Stack Counter"],
+ get = function(info) return E.db.unitframe.units[groupName]["rdebuffs"]["stack"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["rdebuffs"]["stack"][ info[getn(info)] ] = value; updateFunc(UF, groupName) end,
+ args = {
+ position = {
+ order = 1,
+ type = "select",
+ name = L["Position"],
+ values = {
+ ["TOP"] = "TOP",
+ ["LEFT"] = "LEFT",
+ ["RIGHT"] = "RIGHT",
+ ["BOTTOM"] = "BOTTOM",
+ ["CENTER"] = "CENTER",
+ ["TOPLEFT"] = "TOPLEFT",
+ ["TOPRIGHT"] = "TOPRIGHT",
+ ["BOTTOMLEFT"] = "BOTTOMLEFT",
+ ["BOTTOMRIGHT"] = "BOTTOMRIGHT",
+ },
+ },
+ xOffset = {
+ order = 2,
+ type = "range",
+ name = L["xOffset"],
+ min = -10, max = 10, step = 1,
+ },
+ yOffset = {
+ order = 3,
+ type = "range",
+ name = L["yOffset"],
+ min = -10, max = 10, step = 1,
+ },
+ color = {
+ order = 4,
+ type = "color",
+ name = COLOR,
+ hasAlpha = true,
+ get = function(info)
+ local c = E.db.unitframe.units[groupName].rdebuffs.stack.color
+ local d = P.unitframe.units[groupName].rdebuffs.stack.color
+ return c.r, c.g, c.b, c.a, d.r, d.g, d.b, d.a
+ end,
+ set = function(info, r, g, b, a)
+ local c = E.db.unitframe.units[groupName].rdebuffs.stack.color
+ c.r, c.g, c.b, c.a = r, g, b, a
+ updateFunc(UF, groupName)
+ end,
+ },
+ },
+ },
+ },
+ }
+
+ return config
+end
+
+local function GetOptionsTable_ReadyCheckIcon(updateFunc, groupName)
+ local config = {
+ order = 900,
+ type = "group",
+ name = L["Ready Check Icon"],
+ get = function(info) return E.db.unitframe.units[groupName]["readycheckIcon"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["readycheckIcon"][ info[getn(info)] ] = value; updateFunc(UF, groupName) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Ready Check Icon"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ size = {
+ order = 3,
+ type = "range",
+ name = L["Size"],
+ min = 8, max = 60, step = 1,
+ },
+ attachTo = {
+ order = 4,
+ type = "select",
+ name = L["Attach To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ position = {
+ order = 5,
+ type = "select",
+ name = L["Position"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ },
+ }
+
+ return config
+end
+
+local function GetOptionsTable_GPS(groupName)
+ local config = {
+ order = 1000,
+ type = "group",
+ name = L["GPS Arrow"],
+ get = function(info) return E.db.unitframe.units[groupName]["GPSArrow"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[groupName]["GPSArrow"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup(groupName) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["GPS Arrow"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ onMouseOver = {
+ order = 3,
+ type = "toggle",
+ name = L["Mouseover"],
+ desc = L["Only show when you are mousing over a frame."],
+ },
+ outOfRange = {
+ order = 4,
+ type = "toggle",
+ name = L["Out of Range"],
+ desc = L["Only show when the unit is not in range."],
+ },
+ size = {
+ order = 5,
+ type = "range",
+ name = L["Size"],
+ min = 8, max = 60, step = 1,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ }
+ }
+ }
+
+ return config
+end
+
+local function GetOptionsTableForNonGroup_GPS(unit)
+ local config = {
+ order = 1000,
+ type = "group",
+ name = L["GPS Arrow"],
+ get = function(info) return E.db.unitframe.units[unit]["GPSArrow"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units[unit]["GPSArrow"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF(unit) end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["GPS Arrow"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ onMouseOver = {
+ order = 3,
+ type = "toggle",
+ name = L["Mouseover"],
+ desc = L["Only show when you are mousing over a frame."],
+ },
+ outOfRange = {
+ order = 4,
+ type = "toggle",
+ name = L["Out of Range"],
+ desc = L["Only show when the unit is not in range."],
+ },
+ size = {
+ order = 5,
+ type = "range",
+ name = L["Size"],
+ min = 8, max = 60, step = 1,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ }
+ }
+ }
+
+ return config
+end
+
+E.Options.args.unitframe = {
+ type = "group",
+ name = L["UnitFrames"],
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value end,
+ args = {
+ enable = {
+ order = 0,
+ type = "toggle",
+ name = L["Enable"],
+ get = function(info) return E.private.unitframe.enable end,
+ set = function(info, value) E.private.unitframe.enable = value; E:StaticPopup_Show("PRIVATE_RL") end
+ },
+ intro = {
+ order = 1,
+ type = "description",
+ name = L["UNITFRAME_DESC"],
+ },
+ header = {
+ order = 2,
+ type = "header",
+ name = L["Shortcuts"],
+ },
+ spacer1 = {
+ order = 3,
+ type = "description",
+ name = " ",
+ },
+ generalOptionsGroup = {
+ order = 19,
+ type = "group",
+ name = L["General Options"],
+ childGroups = "tab",
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["General"],
+ },
+ thinBorders = {
+ order = 1,
+ name = L["Thin Borders"],
+ desc = L["Use thin borders on certain unitframe elements."],
+ type = "toggle",
+ disabled = function() return E.private.general.pixelPerfect end,
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; E:StaticPopup_Show("CONFIG_RL") end,
+ },
+ OORAlpha = {
+ order = 2,
+ name = L["OOR Alpha"],
+ desc = L["The alpha to set units that are out of range to."],
+ type = "range",
+ min = 0, max = 1, step = 0.01,
+ },
+ debuffHighlighting = {
+ order = 3,
+ name = L["Debuff Highlighting"],
+ desc = L["Color the unit healthbar if there is a debuff that can be dispelled by you."],
+ type = "select",
+ values = {
+ ["NONE"] = NONE,
+ ["GLOW"] = L["Glow"],
+ ["FILL"] = L["Fill"]
+ },
+ },
+ targetOnMouseDown = {
+ order = 4,
+ name = L["Target On Mouse-Down"],
+ desc = L["Target units on mouse down rather than mouse up. \n\n|cffFF0000Warning: If you are using the addon 'Clique' you may have to adjust your clique settings when changing this."],
+ type = "toggle",
+ },
+ auraBlacklistModifier = {
+ order = 5,
+ type = "select",
+ name = L["Blacklist Modifier"],
+ desc = L["You need to hold this modifier down in order to blacklist an aura by right-clicking the icon. Set to None to disable the blacklist functionality."],
+ values = {
+ ["NONE"] = NONE,
+ ["SHIFT"] = SHIFT_KEY,
+ ["ALT"] = ALT_KEY,
+ ["CTRL"] = CTRL_KEY,
+ },
+ },
+ resetFilters = {
+ order = 6,
+ name = L["Reset Aura Filters"],
+ type = "execute",
+ func = function(info, value)
+ E:StaticPopup_Show("RESET_UF_AF") --reset unitframe aurafilters
+ end,
+ },
+ barGroup = {
+ order = 20,
+ type = "group",
+ guiInline = true,
+ name = L["Bars"],
+ args = {
+ smoothbars = {
+ type = "toggle",
+ order = 1,
+ name = L["Smooth Bars"],
+ desc = L["Bars will transition smoothly."],
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; UF:Update_AllFrames(); end,
+ },
+ smoothSpeed = {
+ type = "range",
+ order = 2,
+ name = L["Animation Speed"],
+ desc = L["Speed in seconds"],
+ min = 0.1, max = 3, step = 0.01,
+ disabled = function() return not E.db.unitframe.smoothbars; end,
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; UF:Update_AllFrames(); end
+ },
+ statusbar = {
+ type = "select", dialogControl = "LSM30_Statusbar",
+ order = 3,
+ name = L["StatusBar Texture"],
+ desc = L["Main statusbar texture."],
+ values = AceGUIWidgetLSMlists.statusbar,
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; UF:Update_StatusBars() end,
+ },
+ },
+ },
+ fontGroup = {
+ order = 30,
+ type = "group",
+ guiInline = true,
+ name = L["Fonts"],
+ args = {
+ font = {
+ type = "select", dialogControl = "LSM30_Font",
+ order = 4,
+ name = L["Default Font"],
+ desc = L["The font that the unitframes will use."],
+ values = AceGUIWidgetLSMlists.font,
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; UF:Update_FontStrings() end,
+ },
+ fontSize = {
+ order = 5,
+ name = FONT_SIZE,
+ desc = L["Set the font size for unitframes."],
+ type = "range",
+ min = 4, max = 212, step = 1,
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; UF:Update_FontStrings() end,
+ },
+ fontOutline = {
+ order = 6,
+ name = L["Font Outline"],
+ desc = L["Set the font outline."],
+ type = "select",
+ values = {
+ ["NONE"] = NONE,
+ ["OUTLINE"] = "OUTLINE",
+
+ ["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
+ ["THICKOUTLINE"] = "THICKOUTLINE",
+ },
+ set = function(info, value) E.db.unitframe[ info[getn(info)] ] = value; UF:Update_FontStrings() end,
+ },
+ },
+ },
+ },
+ },
+ allColorsGroup = {
+ order = 2,
+ type = "group",
+ childGroups = "tree",
+ name = L["Colors"],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Colors"],
+ },
+ borderColor = {
+ order = 1,
+ type = "color",
+ name = L["Border Color"],
+ get = function(info)
+ local t = E.db.unitframe.colors.borderColor
+ local d = P.unitframe.colors.borderColor
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.borderColor
+ t.r, t.g, t.b = r, g, b
+ E:UpdateMedia()
+ E:UpdateBorderColors()
+ end,
+ },
+ healthGroup = {
+ order = 2,
+ type = "group",
+ name = HEALTH,
+ get = function(info)
+ local t = E.db.unitframe.colors[ info[getn(info)] ]
+ local d = P.unitframe.colors[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ args = {
+ healthclass = {
+ order = 1,
+ type = "toggle",
+ name = L["Class Health"],
+ desc = L["Color health by classcolor or reaction."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ forcehealthreaction = {
+ order = 2,
+ type = "toggle",
+ name = L["Force Reaction Color"],
+ desc = L["Forces reaction color instead of class color on units controlled by players."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ disabled = function() return not E.db.unitframe.colors.healthclass end,
+ },
+ colorhealthbyvalue = {
+ order = 3,
+ type = "toggle",
+ name = L["Health By Value"],
+ desc = L["Color health by amount remaining."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ customhealthbackdrop = {
+ order = 4,
+ type = "toggle",
+ name = L["Custom Health Backdrop"],
+ desc = L["Use the custom health backdrop color instead of a multiple of the main health color."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ classbackdrop = {
+ order = 5,
+ type = "toggle",
+ name = L["Class Backdrop"],
+ desc = L["Color the health backdrop by class or reaction."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ transparentHealth = {
+ order = 6,
+ type = "toggle",
+ name = L["Transparent"],
+ desc = L["Make textures transparent."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ useDeadBackdrop = {
+ order = 7,
+ type = "toggle",
+ name = L["Use Dead Backdrop"],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ health = {
+ order = 10,
+ type = "color",
+ name = L["Health"],
+ },
+ health_backdrop = {
+ order = 11,
+ type = "color",
+ name = L["Health Backdrop"],
+ },
+ tapped = {
+ order = 12,
+ type = "color",
+ name = L["Tapped"],
+ },
+ disconnected = {
+ order = 13,
+ type = "color",
+ name = L["Disconnected"],
+ },
+ health_backdrop_dead = {
+ order = 14,
+ type = "color",
+ name = L["Custom Dead Backdrop"],
+ desc = L["Use this backdrop color for units that are dead or ghosts."],
+ },
+ },
+ },
+ powerGroup = {
+ order = 3,
+ type = "group",
+ name = L["Powers"],
+ get = function(info)
+ local t = E.db.unitframe.colors.power[ info[getn(info)] ]
+ local d = P.unitframe.colors.power[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.power[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ args = {
+ powerclass = {
+ order = 0,
+ type = "toggle",
+ name = L["Class Power"],
+ desc = L["Color power by classcolor or reaction."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ transparentPower = {
+ order = 1,
+ type = "toggle",
+ name = L["Transparent"],
+ desc = L["Make textures transparent."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ MANA = {
+ order = 2,
+ name = MANA,
+ type = "color",
+ },
+ RAGE = {
+ order = 3,
+ name = RAGE,
+ type = "color",
+ },
+ FOCUS = {
+ order = 4,
+ name = FOCUS,
+ type = "color",
+ },
+ ENERGY = {
+ order = 5,
+ name = ENERGY,
+ type = "color",
+ },
+ },
+ },
+ reactionGroup = {
+ order = 4,
+ type = "group",
+ name = L["Reactions"],
+ get = function(info)
+ local t = E.db.unitframe.colors.reaction[ info[getn(info)] ]
+ local d = P.unitframe.colors.reaction[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.reaction[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ args = {
+ BAD = {
+ order = 1,
+ name = L["Bad"],
+ type = "color",
+ },
+ NEUTRAL = {
+ order = 2,
+ name = L["Neutral"],
+ type = "color",
+ },
+ GOOD = {
+ order = 3,
+ name = L["Good"],
+ type = "color",
+ },
+ },
+ },
+ castBars = {
+ order = 5,
+ type = "group",
+ name = L["Castbar"],
+ get = function(info)
+ local t = E.db.unitframe.colors[ info[getn(info)] ]
+ local d = P.unitframe.colors[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ args = {
+ castClassColor = {
+ order = 0,
+ type = "toggle",
+ name = L["Class Castbars"],
+ desc = L["Color castbars by the class of player units."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ castReactionColor = {
+ order = 1,
+ type = "toggle",
+ name = L["Reaction Castbars"],
+ desc = L["Color castbars by the reaction type of non-player units."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ transparentCastbar = {
+ order = 2,
+ type = "toggle",
+ name = L["Transparent"],
+ desc = L["Make textures transparent."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ castColor = {
+ order = 3,
+ name = L["Interruptable"],
+ type = "color",
+ },
+ castNoInterrupt = {
+ order = 4,
+ name = L["Non-Interruptable"],
+ type = "color",
+ },
+ },
+ },
+ auraBars = {
+ order = 6,
+ type = "group",
+ name = L["Aura Bars"],
+ args = {
+ transparentAurabars = {
+ order = 0,
+ type = "toggle",
+ name = L["Transparent"],
+ desc = L["Make textures transparent."],
+ get = function(info) return E.db.unitframe.colors[ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.colors[ info[getn(info)] ] = value; UF:Update_AllFrames() end,
+ },
+ auraBarByType = {
+ order = 1,
+ name = L["By Type"],
+ desc = L["Color aurabar debuffs by type."],
+ type = "toggle",
+ },
+ auraBarTurtle = {
+ order = 2,
+ name = L["Color Turtle Buffs"],
+ desc = L["Color all buffs that reduce the unit's incoming damage."],
+ type = "toggle",
+ },
+ BUFFS = {
+ order = 10,
+ name = L["Buffs"],
+ type = "color",
+ get = function(info)
+ local t = E.db.unitframe.colors.auraBarBuff
+ local d = P.unitframe.colors.auraBarBuff
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ if E:CheckClassColor(r, g, b) then
+ local classColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
+ r = classColor.r
+ g = classColor.g
+ b = classColor.b
+ end
+
+ local t = E.db.unitframe.colors.auraBarBuff
+ t.r, t.g, t.b = r, g, b
+
+ UF:Update_AllFrames()
+ end,
+ },
+ DEBUFFS = {
+ order = 11,
+ name = L["Debuffs"],
+ type = "color",
+ get = function(info)
+ local t = E.db.unitframe.colors.auraBarDebuff
+ local d = P.unitframe.colors.auraBarDebuff
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.auraBarDebuff
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ },
+ auraBarTurtleColor = {
+ order = 12,
+ name = L["Turtle Color"],
+ type = "color",
+ get = function(info)
+ local t = E.db.unitframe.colors.auraBarTurtleColor
+ local d = P.unitframe.colors.auraBarTurtleColor
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.auraBarTurtleColor
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ },
+ },
+ },
+ healPrediction = {
+ order = 7,
+ name = L["Heal Prediction"],
+ type = "group",
+ get = function(info)
+ local t = E.db.unitframe.colors.healPrediction[ info[getn(info)] ]
+ local d = P.unitframe.colors.healPrediction[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b, d.a
+ end,
+ set = function(info, r, g, b, a)
+ local t = E.db.unitframe.colors.healPrediction[ info[getn(info)] ]
+ t.r, t.g, t.b, t.a = r, g, b, a
+ UF:Update_AllFrames()
+ end,
+ args = {
+ personal = {
+ order = 1,
+ name = L["Personal"],
+ type = "color",
+ hasAlpha = true,
+ },
+ others = {
+ order = 2,
+ name = L["Others"],
+ type = "color",
+ hasAlpha = true,
+ },
+ maxOverflow = {
+ order = 3,
+ type = "range",
+ name = L["Max Overflow"],
+ desc = L["Max amount of overflow allowed to extend past the end of the health bar."],
+ isPercent = true,
+ min = 0, max = 1, step = 0.01,
+ get = function(info) return E.db.unitframe.colors.healPrediction.maxOverflow end,
+ set = function(info, value) E.db.unitframe.colors.healPrediction.maxOverflow = value; UF:Update_AllFrames() end,
+ },
+ },
+ },
+ },
+ },
+ disabledBlizzardFrames = {
+ order = 3,
+ type = "group",
+ name = L["Disabled Blizzard Frames"],
+ get = function(info) return E.private.unitframe.disabledBlizzardFrames[ info[getn(info)] ] end,
+ set = function(info, value) E.private["unitframe"].disabledBlizzardFrames[ info[getn(info)] ] = value; E:StaticPopup_Show("PRIVATE_RL") end,
+ args = {
+ header = {
+ order = 0,
+ type = "header",
+ name = L["Disabled Blizzard Frames"],
+ },
+ player = {
+ order = 1,
+ type = "toggle",
+ name = L["Player Frame"],
+ desc = L["Disables the player and pet unitframes."],
+ },
+ target = {
+ order = 2,
+ type = "toggle",
+ name = L["Target Frame"],
+ desc = L["Disables the target and target of target unitframes."],
+ },
+ focus = {
+ order = 3,
+ type = "toggle",
+ name = L["Focus Frame"],
+ desc = L["Disables the focus and target of focus unitframes."],
+ },
+ boss = {
+ order = 4,
+ type = "toggle",
+ name = L["Boss Frames"],
+ },
+ arena = {
+ order = 5,
+ type = "toggle",
+ name = L["Arena Frames"],
+ },
+ party = {
+ order = 6,
+ type = "toggle",
+ name = L["Party Frames"],
+ },
+ raid = {
+ order = 7,
+ type = "toggle",
+ name = L["Raid Frames"],
+ },
+ },
+ },
+ --[[raidDebuffIndicator = {
+ order = 4,
+ type = "group",
+ name = L["RaidDebuff Indicator"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["RaidDebuff Indicator"],
+ },
+ instanceFilter = {
+ order = 2,
+ type = "select",
+ name = L["Dungeon & Raid Filter"],
+ values = function()
+ local filters = {}
+ local list = E.global.unitframe["aurafilters"]
+ if not list then return end
+ for filter in pairs(list) do
+ filters[filter] = filter
+ end
+
+ return filters
+ end,
+ get = function(info) return E.global.unitframe.raidDebuffIndicator.instanceFilter end,
+ set = function(info, value) E.global.unitframe.raidDebuffIndicator.instanceFilter = value; UF:UpdateAllHeaders() end,
+ },
+ otherFilter = {
+ order = 3,
+ type = "select",
+ name = L["Other Filter"],
+ values = function()
+ local filters = {}
+ local list = E.global.unitframe["aurafilters"]
+ if not list then return end
+ for filter in pairs(list) do
+ filters[filter] = filter
+ end
+
+ return filters
+ end,
+ get = function(info) return E.global.unitframe.raidDebuffIndicator.otherFilter end,
+ set = function(info, value) E.global.unitframe.raidDebuffIndicator.otherFilter = value; UF:UpdateAllHeaders() end,
+ },
+ },
+ },--]]
+ },
+ },
+ },
+}
+
+--Player
+E.Options.args.unitframe.args.player = {
+ name = L["Player Frame"],
+ type = "group",
+ order = 300,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["player"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["player"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("player") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ width = "full",
+ set = function(info, value)
+ E.db.unitframe.units["player"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateUF("player");
+ if value == true and E.db.unitframe.units.player.combatfade then
+ ElvUF_Pet:SetParent(ElvUF_Player)
+ else
+ ElvUF_Pet:SetParent(ElvUF_Parent)
+ end
+ end,
+ },
+ copyFrom = {
+ type = "select",
+ order = 2,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = UF["units"],
+ set = function(info, value) UF:MergeUnitSettings(value, "player"); end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 3,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("player"); E:ResetMovers(L["Player Frame"]) end,
+ },
+ showAuras = {
+ order = 4,
+ type = "execute",
+ name = L["Show Auras"],
+ func = function()
+ local frame = ElvUF_Player
+ if frame.forceShowAuras then
+ frame.forceShowAuras = nil;
+ else
+ frame.forceShowAuras = true;
+ end
+
+ UF:CreateAndUpdateUF("player")
+ end,
+ },
+ width = {
+ order = 5,
+ name = L["Width"],
+ type = "range",
+ min = 50, max = 500, step = 1,
+ set = function(info, value)
+ if E.db.unitframe.units["player"].castbar.width == E.db.unitframe.units["player"][ info[getn(info)] ] then
+ E.db.unitframe.units["player"].castbar.width = value;
+ end
+
+ E.db.unitframe.units["player"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateUF("player");
+ end,
+ },
+ height = {
+ order = 6,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ combatfade = {
+ order = 7,
+ name = L["Combat Fade"],
+ desc = L["Fade the unitframe when out of combat, not casting, no target exists."],
+ type = "toggle",
+ set = function(info, value)
+ E.db.unitframe.units["player"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateUF("player");
+ if value == true and E.db.unitframe.units.player.enable then
+ ElvUF_Pet:SetParent(ElvUF_Player)
+ else
+ ElvUF_Pet:SetParent(ElvUF_Parent)
+ end
+ end,
+ },
+ healPrediction = {
+ order = 8,
+ name = L["Heal Prediction"],
+ desc = L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."],
+ type = "toggle",
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 9,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["player"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["player"]["power"].hideonnpc = value; UF:CreateAndUpdateUF("player") end,
+ },
+ restIcon = {
+ order = 10,
+ name = L["Rest Icon"],
+ desc = L["Display the rested icon on the unitframe."],
+ type = "toggle",
+ },
+ combatIcon = {
+ order = 11,
+ name = L["Combat Icon"],
+ desc = L["Display the combat icon on the unitframe."],
+ type = "toggle",
+ },
+ threatStyle = {
+ type = "select",
+ order = 12,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ smartAuraPosition = {
+ order = 13,
+ type = "select",
+ name = L["Smart Aura Position"],
+ desc = L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."],
+ values = {
+ ["DISABLED"] = DISABLE,
+ ["BUFFS_ON_DEBUFFS"] = L["Position Buffs on Debuffs"],
+ ["DEBUFFS_ON_BUFFS"] = L["Position Debuffs on Buffs"],
+ ["FLUID_BUFFS_ON_DEBUFFS"] = L["Fluid Position Buffs on Debuffs"],
+ ["FLUID_DEBUFFS_ON_BUFFS"] = L["Fluid Position Debuffs on Buffs"],
+ },
+ },
+ orientation = {
+ order = 14,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ colorOverride = {
+ order = 15,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ },
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateUF, "player"),
+ health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "player"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "player"),
+ power = GetOptionsTable_Power(true, UF.CreateAndUpdateUF, "player", nil, true),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "player"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "player"),
+ --buffs = GetOptionsTable_Auras(true, "buffs", false, UF.CreateAndUpdateUF, "player"),
+ --debuffs = GetOptionsTable_Auras(true, "debuffs", false, UF.CreateAndUpdateUF, "player"),
+ castbar = GetOptionsTable_Castbar(true, UF.CreateAndUpdateUF, "player"),
+ --aurabar = GetOptionsTable_AuraBars(true, UF.CreateAndUpdateUF, "player"),
+ raidicon = GetOptionsTable_RaidIcon(UF.CreateAndUpdateUF, "player"),
+ classbar = {
+ order = 1000,
+ type = "group",
+ name = L["Classbar"],
+ get = function(info) return E.db.unitframe.units["player"]["classbar"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["player"]["classbar"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("player") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Classbar"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ height = {
+ type = "range",
+ order = 3,
+ name = L["Height"],
+ min = ((E.db.unitframe.thinBorders or E.PixelMode) and 3 or 7),
+ max = (E.db.unitframe.units["player"]["classbar"].detachFromFrame and 300 or 30),
+ step = 1,
+ },
+ fill = {
+ type = "select",
+ order = 4,
+ name = L["Fill"],
+ values = {
+ ["fill"] = L["Filled"],
+ ["spaced"] = L["Spaced"],
+ },
+ },
+ autoHide = {
+ order = 5,
+ type = "toggle",
+ name = L["Auto-Hide"],
+ },
+ detachFromFrame = {
+ type = "toggle",
+ order = 6,
+ name = L["Detach From Frame"],
+ set = function(info, value)
+ if value == true then
+ E.Options.args.unitframe.args.player.args.classbar.args.height.max = 300
+ else
+ E.Options.args.unitframe.args.player.args.classbar.args.height.max = 30
+ end
+ E.db.unitframe.units["player"]["classbar"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateUF("player")
+ end,
+ },
+ verticalOrientation = {
+ order = 7,
+ type = "toggle",
+ name = L["Vertical Orientation"],
+ disabled = function() return not E.db.unitframe.units["player"]["classbar"].detachFromFrame end,
+ },
+ detachedWidth = {
+ type = "range",
+ order = 8,
+ name = L["Detached Width"],
+ disabled = function() return not E.db.unitframe.units["player"]["classbar"].detachFromFrame end,
+ min = ((E.db.unitframe.thinBorders or E.PixelMode) and 3 or 7), max = 800, step = 1,
+ },
+ parent = {
+ type = "select",
+ order = 9,
+ name = L["Parent"],
+ desc = L["Choose UIPARENT to prevent it from hiding with the unitframe."],
+ disabled = function() return not E.db.unitframe.units["player"]["classbar"].detachFromFrame end,
+ values = {
+ ["FRAME"] = "FRAME",
+ ["UIPARENT"] = "UIPARENT",
+ },
+ },
+ strataAndLevel = {
+ order = 20,
+ type = "group",
+ name = L["Strata and Level"],
+ get = function(info) return E.db.unitframe.units["player"]["classbar"]["strataAndLevel"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["player"]["classbar"]["strataAndLevel"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("player") end,
+ guiInline = true,
+ disabled = function() return not E.db.unitframe.units["player"]["classbar"].detachFromFrame end,
+ hidden = function() return not E.db.unitframe.units["player"]["classbar"].detachFromFrame end,
+ args = {
+ useCustomStrata = {
+ order = 1,
+ type = "toggle",
+ name = L["Use Custom Strata"],
+ },
+ frameStrata = {
+ order = 2,
+ type = "select",
+ name = L["Frame Strata"],
+ values = {
+ ["BACKGROUND"] = "BACKGROUND",
+ ["LOW"] = "LOW",
+ ["MEDIUM"] = "MEDIUM",
+ ["HIGH"] = "HIGH",
+ ["DIALOG"] = "DIALOG",
+ ["TOOLTIP"] = "TOOLTIP",
+ },
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ name = "",
+ },
+ useCustomLevel = {
+ order = 4,
+ type = "toggle",
+ name = L["Use Custom Level"],
+ },
+ frameLevel = {
+ order = 5,
+ type = "range",
+ name = L["Frame Level"],
+ min = 2, max = 128, step = 1,
+ },
+ },
+ },
+ },
+ },
+ pvpIcon = {
+ order = 449,
+ type = "group",
+ name = L["PvP Icon"],
+ get = function(info) return E.db.unitframe.units["player"]["pvpIcon"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["player"]["pvpIcon"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("player") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["PvP Icon"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ scale = {
+ order = 3,
+ type = "range",
+ name = L["Scale"],
+ isPercent = true,
+ min = 0.1, max = 2, step = 0.01,
+ },
+ spacer = {
+ order = 4,
+ type = "description",
+ name = " ",
+ },
+ anchorPoint = {
+ order = 5,
+ type = "select",
+ name = L["Anchor Point"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["X-Offset"],
+ min = -100, max = 100, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["Y-Offset"],
+ min = -100, max = 100, step = 1,
+ },
+ },
+ },
+ pvpText = {
+ order = 450,
+ type = "group",
+ name = L["PvP Text"],
+ get = function(info) return E.db.unitframe.units["player"]["pvp"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["player"]["pvp"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("player") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name =L["PvP Text"],
+ },
+ position = {
+ type = "select",
+ order = 2,
+ name = L["Position"],
+ values = positionValues,
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ },
+ },
+ },
+}
+
+--Target
+E.Options.args.unitframe.args.target = {
+ name = L["Target Frame"],
+ type = "group",
+ order = 400,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["target"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["target"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("target") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ width = "full",
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = UF["units"],
+ set = function(info, value) UF:MergeUnitSettings(value, "target"); end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 4,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("target"); E:ResetMovers(L["Target Frame"]) end,
+ },
+ showAuras = {
+ order = 5,
+ type = "execute",
+ name = L["Show Auras"],
+ func = function()
+ local frame = ElvUF_Target
+ if frame.forceShowAuras then
+ frame.forceShowAuras = nil;
+ else
+ frame.forceShowAuras = true;
+ end
+
+ UF:CreateAndUpdateUF("target")
+ end,
+ },
+ width = {
+ order = 6,
+ name = L["Width"],
+ type = "range",
+ min = 50, max = 500, step = 1,
+ set = function(info, value)
+ if E.db.unitframe.units["target"].castbar.width == E.db.unitframe.units["target"][ info[getn(info)] ] then
+ E.db.unitframe.units["target"].castbar.width = value;
+ end
+
+ E.db.unitframe.units["target"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateUF("target");
+ end,
+ },
+ height = {
+ order = 7,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ rangeCheck = {
+ order = 8,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ healPrediction = {
+ order = 9,
+ name = L["Heal Prediction"],
+ desc = L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."],
+ type = "toggle",
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 10,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["target"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["target"]["power"].hideonnpc = value; UF:CreateAndUpdateUF("target") end,
+ },
+ middleClickFocus = {
+ order = 11,
+ name = L["Middle Click - Set Focus"],
+ desc = L["Middle clicking the unit frame will cause your focus to match the unit."],
+ type = "toggle",
+ disabled = function() return IsAddOnLoaded("Clique") end,
+ },
+ threatStyle = {
+ type = "select",
+ order = 12,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ smartAuraPosition = {
+ order = 13,
+ type = "select",
+ name = L["Smart Aura Position"],
+ desc = L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."],
+ values = {
+ ["DISABLED"] = DISABLE,
+ ["BUFFS_ON_DEBUFFS"] = L["Position Buffs on Debuffs"],
+ ["DEBUFFS_ON_BUFFS"] = L["Position Debuffs on Buffs"],
+ ["FLUID_BUFFS_ON_DEBUFFS"] = L["Fluid Position Buffs on Debuffs"],
+ ["FLUID_DEBUFFS_ON_BUFFS"] = L["Fluid Position Debuffs on Buffs"],
+ },
+ },
+ orientation = {
+ order = 14,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ colorOverride = {
+ order = 15,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ },
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateUF, "target"),
+ health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "target"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "target"),
+ power = GetOptionsTable_Power(true, UF.CreateAndUpdateUF, "target", nil, true),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "target"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "target"),
+ --buffs = GetOptionsTable_Auras(false, "buffs", false, UF.CreateAndUpdateUF, "target"),
+ --debuffs = GetOptionsTable_Auras(false, "debuffs", false, UF.CreateAndUpdateUF, "target"),
+ castbar = GetOptionsTable_Castbar(false, UF.CreateAndUpdateUF, "target"),
+ --aurabar = GetOptionsTable_AuraBars(false, UF.CreateAndUpdateUF, "target"),
+ raidicon = GetOptionsTable_RaidIcon(UF.CreateAndUpdateUF, "target"),
+ GPSArrow = GetOptionsTableForNonGroup_GPS("target"),
+ combobar = {
+ order = 850,
+ type = "group",
+ name = L["Combobar"],
+ get = function(info) return E.db.unitframe.units["target"]["combobar"][ info[getn(info)] ]; end,
+ set = function(info, value) E.db.unitframe.units["target"]["combobar"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("target"); end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Combobar"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ height = {
+ order = 3,
+ type = "range",
+ name = L["Height"],
+ min = ((E.db.unitframe.thinBorders or E.PixelMode) and 3 or 7), max = 15, step = 1,
+ },
+ fill = {
+ order = 4,
+ type = "select",
+ name = L["Fill"],
+ values = {
+ ["fill"] = L["Filled"],
+ ["spaced"] = L["Spaced"],
+ },
+ },
+ autoHide = {
+ order = 5,
+ type = "toggle",
+ name = L["Auto-Hide"],
+ },
+ detachFromFrame = {
+ order = 6,
+ type = "toggle",
+ name = L["Detach From Frame"],
+ },
+ detachedWidth = {
+ order = 7,
+ type = "range",
+ name = L["Detached Width"],
+ disabled = function() return not E.db.unitframe.units["target"]["combobar"].detachFromFrame; end,
+ min = 15, max = 450, step = 1,
+ },
+ },
+ },
+ pvpIcon = {
+ order = 449,
+ type = "group",
+ name = L["PvP Icon"],
+ get = function(info) return E.db.unitframe.units["target"]["pvpIcon"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["target"]["pvpIcon"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("target") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["PvP Icon"],
+ },
+ enable = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable"],
+ },
+ scale = {
+ order = 3,
+ type = "range",
+ name = L["Scale"],
+ isPercent = true,
+ min = 0.1, max = 2, step = 0.01,
+ },
+ spacer = {
+ order = 4,
+ type = "description",
+ name = " ",
+ },
+ anchorPoint = {
+ order = 5,
+ type = "select",
+ name = L["Anchor Point"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["X-Offset"],
+ min = -100, max = 100, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["Y-Offset"],
+ min = -100, max = 100, step = 1,
+ },
+ },
+ },
+ },
+}
+
+--TargetTarget
+E.Options.args.unitframe.args.targettarget = {
+ name = L["TargetTarget Frame"],
+ type = "group",
+ order = 500,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["targettarget"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["targettarget"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("targettarget") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ width = "full",
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = UF["units"],
+ set = function(info, value) UF:MergeUnitSettings(value, "targettarget"); end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 4,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("targettarget"); E:ResetMovers(L["TargetTarget Frame"]) end,
+ },
+ showAuras = {
+ order = 5,
+ type = "execute",
+ name = L["Show Auras"],
+ func = function()
+ local frame = ElvUF_TargetTarget
+ if frame.forceShowAuras then
+ frame.forceShowAuras = nil;
+ else
+ frame.forceShowAuras = true;
+ end
+
+ UF:CreateAndUpdateUF("targettarget")
+ end,
+ },
+ width = {
+ order = 6,
+ name = L["Width"],
+ type = "range",
+ min = 50, max = 500, step = 1,
+ },
+ height = {
+ order = 7,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ rangeCheck = {
+ order = 8,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 9,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["targettarget"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["targettarget"]["power"].hideonnpc = value; UF:CreateAndUpdateUF("targettarget") end,
+ },
+ threatStyle = {
+ type = "select",
+ order = 10,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ smartAuraPosition = {
+ order = 11,
+ type = "select",
+ name = L["Smart Aura Position"],
+ desc = L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."],
+ values = {
+ ["DISABLED"] = DISABLE,
+ ["BUFFS_ON_DEBUFFS"] = L["Position Buffs on Debuffs"],
+ ["DEBUFFS_ON_BUFFS"] = L["Position Debuffs on Buffs"],
+ },
+ },
+ orientation = {
+ order = 12,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ colorOverride = {
+ order = 13,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ },
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateUF, "targettarget"),
+ health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "targettarget"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "targettarget"),
+ power = GetOptionsTable_Power(nil, UF.CreateAndUpdateUF, "targettarget"),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "targettarget"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "targettarget"),
+ --buffs = GetOptionsTable_Auras(false, "buffs", false, UF.CreateAndUpdateUF, "targettarget"),
+ --debuffs = GetOptionsTable_Auras(false, "debuffs", false, UF.CreateAndUpdateUF, "targettarget"),
+ raidicon = GetOptionsTable_RaidIcon(UF.CreateAndUpdateUF, "targettarget"),
+ },
+}
+
+--TargetTargetTarget
+E.Options.args.unitframe.args.targettargettarget = {
+ name = L["TargetTargetTarget Frame"],
+ type = "group",
+ order = 500,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["targettargettarget"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["targettargettarget"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("targettargettarget") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ width = "full",
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = UF["units"],
+ set = function(info, value) UF:MergeUnitSettings(value, "targettargettarget"); end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 4,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("targettargettarget"); E:ResetMovers(L["TargetTargetTarget Frame"]) end,
+ },
+ showAuras = {
+ order = 5,
+ type = "execute",
+ name = L["Show Auras"],
+ func = function()
+ local frame = ElvUF_TargetTargetTarget
+ if frame.forceShowAuras then
+ frame.forceShowAuras = nil;
+ else
+ frame.forceShowAuras = true;
+ end
+
+ UF:CreateAndUpdateUF("targettargettarget")
+ end,
+ },
+ width = {
+ order = 6,
+ name = L["Width"],
+ type = "range",
+ min = 50, max = 500, step = 1,
+ },
+ height = {
+ order = 7,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ rangeCheck = {
+ order = 8,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 9,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["targettargettarget"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["targettargettarget"]["power"].hideonnpc = value; UF:CreateAndUpdateUF("targettargettarget") end,
+ },
+ threatStyle = {
+ type = "select",
+ order = 10,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ smartAuraPosition = {
+ order = 11,
+ type = "select",
+ name = L["Smart Aura Position"],
+ desc = L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."],
+ values = {
+ ["DISABLED"] = DISABLE,
+ ["BUFFS_ON_DEBUFFS"] = L["Position Buffs on Debuffs"],
+ ["DEBUFFS_ON_BUFFS"] = L["Position Debuffs on Buffs"],
+ ["FLUID_BUFFS_ON_DEBUFFS"] = L["Fluid Position Buffs on Debuffs"],
+ ["FLUID_DEBUFFS_ON_BUFFS"] = L["Fluid Position Debuffs on Buffs"],
+ },
+ },
+ orientation = {
+ order = 12,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ colorOverride = {
+ order = 13,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ },
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateUF, "targettargettarget"),
+ health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "targettargettarget"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "targettargettarget"),
+ power = GetOptionsTable_Power(nil, UF.CreateAndUpdateUF, "targettargettarget"),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "targettargettarget"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "targettargettarget"),
+ --buffs = GetOptionsTable_Auras(false, "buffs", false, UF.CreateAndUpdateUF, "targettargettarget"),
+ --debuffs = GetOptionsTable_Auras(false, "debuffs", false, UF.CreateAndUpdateUF, "targettargettarget"),
+ raidicon = GetOptionsTable_RaidIcon(UF.CreateAndUpdateUF, "targettargettarget"),
+ },
+}
+
+--Pet
+E.Options.args.unitframe.args.pet = {
+ name = L["Pet Frame"],
+ type = "group",
+ order = 800,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["pet"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["pet"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("pet") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ width = "full",
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = UF["units"],
+ set = function(info, value) UF:MergeUnitSettings(value, "pet"); end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 4,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("pet"); E:ResetMovers(L["Pet Frame"]) end,
+ },
+ showAuras = {
+ order = 5,
+ type = "execute",
+ name = L["Show Auras"],
+ func = function()
+ local frame = ElvUF_Pet
+ if frame.forceShowAuras then
+ frame.forceShowAuras = nil;
+ else
+ frame.forceShowAuras = true;
+ end
+
+ UF:CreateAndUpdateUF("pet")
+ end,
+ },
+ width = {
+ order = 6,
+ name = L["Width"],
+ type = "range",
+ min = 50, max = 500, step = 1,
+ },
+ height = {
+ order = 7,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ rangeCheck = {
+ order = 8,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ healPrediction = {
+ order = 9,
+ name = L["Heal Prediction"],
+ desc = L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."],
+ type = "toggle",
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 10,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["pet"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["pet"]["power"].hideonnpc = value; UF:CreateAndUpdateUF("pet") end,
+ },
+ threatStyle = {
+ type = "select",
+ order = 11,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ smartAuraPosition = {
+ order = 12,
+ type = "select",
+ name = L["Smart Aura Position"],
+ desc = L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."],
+ values = {
+ ["DISABLED"] = DISABLE,
+ ["BUFFS_ON_DEBUFFS"] = L["Position Buffs on Debuffs"],
+ ["DEBUFFS_ON_BUFFS"] = L["Position Debuffs on Buffs"],
+ ["FLUID_BUFFS_ON_DEBUFFS"] = L["Fluid Position Buffs on Debuffs"],
+ ["FLUID_DEBUFFS_ON_BUFFS"] = L["Fluid Position Debuffs on Buffs"],
+ },
+ },
+ orientation = {
+ order = 13,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ colorOverride = {
+ order = 14,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ },
+ },
+ buffIndicator = {
+ order = 600,
+ type = "group",
+ name = L["Buff Indicator"],
+ get = function(info) return E.db.unitframe.units["pet"]["buffIndicator"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["pet"]["buffIndicator"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("pet") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Buff Indicator"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ size = {
+ type = "range",
+ name = L["Size"],
+ desc = L["Size of the indicator icon."],
+ order = 3,
+ min = 4, max = 50, step = 1,
+ },
+ fontSize = {
+ type = "range",
+ name = FONT_SIZE,
+ order = 4,
+ min = 7, max = 22, step = 1,
+ },
+ },
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateUF, "pet"),
+ health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "pet"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "pet"),
+ power = GetOptionsTable_Power(false, UF.CreateAndUpdateUF, "pet"),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "pet"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "pet"),
+ --buffs = GetOptionsTable_Auras(true, "buffs", false, UF.CreateAndUpdateUF, "pet"),
+ --debuffs = GetOptionsTable_Auras(true, "debuffs", false, UF.CreateAndUpdateUF, "pet"),
+ castbar = GetOptionsTable_Castbar(false, UF.CreateAndUpdateUF, "pet"),
+ },
+}
+
+--Pet Target
+E.Options.args.unitframe.args.pettarget = {
+ name = L["PetTarget Frame"],
+ type = "group",
+ order = 900,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["pettarget"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["pettarget"][ info[getn(info)] ] = value; UF:CreateAndUpdateUF("pettarget") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ generalGroup = {
+ order = 1,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ width = "full",
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = UF["units"],
+ set = function(info, value) UF:MergeUnitSettings(value, "pettarget"); end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 4,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("pettarget"); E:ResetMovers(L["PetTarget Frame"]) end,
+ },
+ showAuras = {
+ order = 5,
+ type = "execute",
+ name = L["Show Auras"],
+ func = function()
+ local frame = ElvUF_PetTarget
+ if frame.forceShowAuras then
+ frame.forceShowAuras = nil;
+ else
+ frame.forceShowAuras = true;
+ end
+
+ UF:CreateAndUpdateUF("pettarget")
+ end,
+ },
+ width = {
+ order = 6,
+ name = L["Width"],
+ type = "range",
+ min = 50, max = 500, step = 1,
+ },
+ height = {
+ order = 7,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ rangeCheck = {
+ order = 8,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 9,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["pettarget"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["pettarget"]["power"].hideonnpc = value; UF:CreateAndUpdateUF("pettarget") end,
+ },
+ threatStyle = {
+ type = "select",
+ order = 10,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ smartAuraPosition = {
+ order = 11,
+ type = "select",
+ name = L["Smart Aura Position"],
+ desc = L["Will show Buffs in the Debuff position when there are no Debuffs active, or vice versa."],
+ values = {
+ ["DISABLED"] = DISABLE,
+ ["BUFFS_ON_DEBUFFS"] = L["Position Buffs on Debuffs"],
+ ["DEBUFFS_ON_BUFFS"] = L["Position Debuffs on Buffs"],
+ ["FLUID_BUFFS_ON_DEBUFFS"] = L["Fluid Position Buffs on Debuffs"],
+ ["FLUID_DEBUFFS_ON_BUFFS"] = L["Fluid Position Debuffs on Buffs"],
+ },
+ },
+ orientation = {
+ order = 12,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ colorOverride = {
+ order = 13,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ },
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateUF, "pettarget"),
+ health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "pettarget"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "pettarget"),
+ power = GetOptionsTable_Power(false, UF.CreateAndUpdateUF, "pettarget"),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "pettarget"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "pettarget"),
+ --buffs = GetOptionsTable_Auras(false, "buffs", false, UF.CreateAndUpdateUF, "pettarget"),
+ --debuffs = GetOptionsTable_Auras(false, "debuffs", false, UF.CreateAndUpdateUF, "pettarget"),
+ },
+}
+
+local groupPoints = {
+ ["TOP"] = "TOP",
+ ["BOTTOM"] = "BOTTOM",
+ ["LEFT"] = "LEFT",
+ ["RIGHT"] = "RIGHT",
+}
+
+--Party Frames
+E.Options.args.unitframe.args.party = {
+ name = L["Party Frames"],
+ type = "group",
+ order = 1100,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["party"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ configureToggle = {
+ order = 1,
+ type = "execute",
+ name = L["Display Frames"],
+ func = function()
+ UF:HeaderConfig(ElvUF_Party, ElvUF_Party.forceShow ~= true or nil)
+ end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 2,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("party"); E:ResetMovers(L["Party Frames"]) end,
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = {
+ ["raid"] = L["Raid Frames"],
+ ["raid40"] = L["Raid40 Frames"],
+ },
+ set = function(info, value) UF:MergeUnitSettings(value, "party", true); end,
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateHeaderGroup, "party", nil, 4),
+ generalGroup = {
+ order = 5,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 3,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["party"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["party"]["power"].hideonnpc = value; UF:CreateAndUpdateHeaderGroup("party"); end,
+ },
+ rangeCheck = {
+ order = 4,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ healPrediction = {
+ order = 5,
+ name = L["Heal Prediction"],
+ desc = L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."],
+ type = "toggle",
+ },
+ threatStyle = {
+ type = "select",
+ order = 6,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ colorOverride = {
+ order = 7,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ orientation = {
+ order = 8,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ targetGlow = {
+ order = 9,
+ type = "toggle",
+ name = L["Target Glow"],
+ },
+ positionsGroup = {
+ order = 100,
+ name = L["Size and Positions"],
+ type = "group",
+ guiInline = true,
+ set = function(info, value) E.db.unitframe.units["party"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party", nil, nil, true) end,
+ args = {
+ width = {
+ order = 1,
+ name = L["Width"],
+ type = "range",
+ min = 10, max = 500, step = 1,
+ set = function(info, value) E.db.unitframe.units["party"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ },
+ height = {
+ order = 2,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 500, step = 1,
+ set = function(info, value) E.db.unitframe.units["party"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ },
+ spacer = {
+ order = 3,
+ name = "",
+ type = "description",
+ width = "full",
+ },
+ growthDirection = {
+ order = 4,
+ name = L["Growth Direction"],
+ desc = L["Growth direction from the first unitframe."],
+ type = "select",
+ values = {
+ DOWN_RIGHT = format(L["%s and then %s"], L["Down"], L["Right"]),
+ DOWN_LEFT = format(L["%s and then %s"], L["Down"], L["Left"]),
+ UP_RIGHT = format(L["%s and then %s"], L["Up"], L["Right"]),
+ UP_LEFT = format(L["%s and then %s"], L["Up"], L["Left"]),
+ RIGHT_DOWN = format(L["%s and then %s"], L["Right"], L["Down"]),
+ RIGHT_UP = format(L["%s and then %s"], L["Right"], L["Up"]),
+ LEFT_DOWN = format(L["%s and then %s"], L["Left"], L["Down"]),
+ LEFT_UP = format(L["%s and then %s"], L["Left"], L["Up"]),
+ },
+ },
+ numGroups = {
+ order = 7,
+ type = "range",
+ name = L["Number of Groups"],
+ min = 1, max = 8, step = 1,
+ set = function(info, value)
+ E.db.unitframe.units["party"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateHeaderGroup("party")
+ if ElvUF_Party.isForced then
+ UF:HeaderConfig(ElvUF_Party)
+ UF:HeaderConfig(ElvUF_Party, true)
+ end
+ end,
+ },
+ groupsPerRowCol = {
+ order = 8,
+ type = "range",
+ name = L["Groups Per Row/Column"],
+ min = 1, max = 8, step = 1,
+ set = function(info, value)
+ E.db.unitframe.units["party"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateHeaderGroup("party")
+ if ElvUF_Party.isForced then
+ UF:HeaderConfig(ElvUF_Party)
+ UF:HeaderConfig(ElvUF_Party, true)
+ end
+ end,
+ },
+ horizontalSpacing = {
+ order = 9,
+ type = "range",
+ name = L["Horizontal Spacing"],
+ min = -1, max = 50, step = 1,
+ },
+ verticalSpacing = {
+ order = 10,
+ type = "range",
+ name = L["Vertical Spacing"],
+ min = -1, max = 50, step = 1,
+ },
+ },
+ },
+ visibilityGroup = {
+ order = 200,
+ name = L["Visibility"],
+ type = "group",
+ guiInline = true,
+ set = function(info, value) E.db.unitframe.units["party"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party", nil, nil, true) end,
+ args = {
+ showPlayer = {
+ order = 1,
+ type = "toggle",
+ name = L["Display Player"],
+ desc = L["When true, the header includes the player when not in a raid."],
+ },
+ visibility = {
+ order = 2,
+ type = "input",
+ name = L["Visibility"],
+ desc = L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."],
+ width = "full",
+ },
+ },
+ },
+ sortingGroup = {
+ order = 300,
+ type = "group",
+ guiInline = true,
+ name = L["Grouping & Sorting"],
+ set = function(info, value) E.db.unitframe.units["party"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party", nil, nil, true) end,
+ args = {
+ groupBy = {
+ order = 1,
+ name = L["Group By"],
+ desc = L["Set the order that the group will sort."],
+ type = "select",
+ values = {
+ ["CLASS"] = CLASS,
+ ["NAME"] = NAME,
+ ["MTMA"] = L["Main Tanks / Main Assist"],
+ ["GROUP"] = GROUP,
+ },
+ },
+ sortDir = {
+ order = 2,
+ name = L["Sort Direction"],
+ desc = L["Defines the sort order of the selected sort method."],
+ type = "select",
+ values = {
+ ["ASC"] = L["Ascending"],
+ ["DESC"] = L["Descending"]
+ },
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ width = "full",
+ name = " "
+ },
+ raidWideSorting = {
+ order = 4,
+ name = L["Raid-Wide Sorting"],
+ desc = L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."],
+ type = "toggle",
+ },
+ invertGroupingOrder = {
+ order = 5,
+ name = L["Invert Grouping Order"],
+ desc = L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."],
+ disabled = function() return not E.db.unitframe.units["party"].raidWideSorting end,
+ type = "toggle",
+ },
+ startFromCenter = {
+ order = 6,
+ name = L["Start Near Center"],
+ desc = L["The initial group will start near the center and grow out."],
+ disabled = function() return not E.db.unitframe.units["party"].raidWideSorting end,
+ type = "toggle",
+ },
+ },
+ },
+ },
+ },
+ buffIndicator = {
+ order = 701,
+ type = "group",
+ name = L["Buff Indicator"],
+ get = function(info) return E.db.unitframe.units["party"]["buffIndicator"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["buffIndicator"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Buff Indicator"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ size = {
+ type = "range",
+ name = L["Size"],
+ desc = L["Size of the indicator icon."],
+ order = 3,
+ min = 4, max = 50, step = 1,
+ },
+ fontSize = {
+ type = "range",
+ name = FONT_SIZE,
+ order = 4,
+ min = 7, max = 22, step = 1,
+ },
+ profileSpecific = {
+ type = "toggle",
+ name = L["Profile Specific"],
+ desc = L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."],
+ order = 5,
+ },
+ configureButton = {
+ type = "execute",
+ name = L["Configure Auras"],
+ func = function()
+ if E.db.unitframe.units["party"]["buffIndicator"].profileSpecific then
+ E:SetToFilterConfig("Buff Indicator (Profile)")
+ else
+ E:SetToFilterConfig("Buff Indicator")
+ end
+ end,
+ order = 6
+ },
+ },
+ },
+ roleIcon = {
+ order = 702,
+ type = "group",
+ name = L["Role Icon"],
+ get = function(info) return E.db.unitframe.units["party"]["roleIcon"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["roleIcon"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Role Icon"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ position = {
+ type = "select",
+ order = 3,
+ name = L["Position"],
+ values = positionValues,
+ },
+ attachTo = {
+ type = "select",
+ order = 4,
+ name = L["Attach To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ xOffset = {
+ order = 5,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 6,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ size = {
+ type = "range",
+ order = 7,
+ name = L["Size"],
+ min = 4, max = 100, step = 1,
+ },
+ },
+ },
+ raidRoleIcons = {
+ order = 703,
+ type = "group",
+ name = L["RL / ML Icons"],
+ get = function(info) return E.db.unitframe.units["party"]["raidRoleIcons"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["raidRoleIcons"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["RL / ML Icons"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ position = {
+ type = "select",
+ order = 3,
+ name = L["Position"],
+ values = {
+ ["TOPLEFT"] = "TOPLEFT",
+ ["TOPRIGHT"] = "TOPRIGHT",
+ },
+ },
+ },
+ },
+ health = GetOptionsTable_Health(true, UF.CreateAndUpdateHeaderGroup, "party"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateHeaderGroup, "party"),
+ power = GetOptionsTable_Power(false, UF.CreateAndUpdateHeaderGroup, "party"),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateHeaderGroup, "party"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateHeaderGroup, "party"),
+ --buffs = GetOptionsTable_Auras(true, "buffs", true, UF.CreateAndUpdateHeaderGroup, "party"),
+ --debuffs = GetOptionsTable_Auras(true, "debuffs", true, UF.CreateAndUpdateHeaderGroup, "party"),
+ rdebuffs = GetOptionsTable_RaidDebuff(UF.CreateAndUpdateHeaderGroup, "party"),
+ petsGroup = {
+ order = 850,
+ type = "group",
+ name = L["Party Pets"],
+ get = function(info) return E.db.unitframe.units["party"]["petsGroup"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["petsGroup"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Party Pets"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ width = {
+ order = 3,
+ name = L["Width"],
+ type = "range",
+ min = 10, max = 500, step = 1,
+ },
+ height = {
+ order = 4,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ anchorPoint = {
+ type = "select",
+ order = 5,
+ name = L["Anchor Point"],
+ desc = L["What point to anchor to the frame you set to attach to."],
+ values = petAnchors,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ desc = L["An X offset (in pixels) to be used when anchoring new frames."],
+ min = -500, max = 500, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ desc = L["An Y offset (in pixels) to be used when anchoring new frames."],
+ min = -500, max = 500, step = 1,
+ },
+ name = {
+ order = 8,
+ type = "group",
+ guiInline = true,
+ get = function(info) return E.db.unitframe.units["party"]["petsGroup"]["name"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["petsGroup"]["name"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ name = L["Name"],
+ args = {
+ position = {
+ type = "select",
+ order = 1,
+ name = L["Text Position"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 2,
+ type = "range",
+ name = L["Text xOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 3,
+ type = "range",
+ name = L["Text yOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ },
+ },
+ },
+ },
+ targetsGroup = {
+ order = 900,
+ type = "group",
+ name = L["Party Targets"],
+ get = function(info) return E.db.unitframe.units["party"]["targetsGroup"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["targetsGroup"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Party Targets"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ width = {
+ order = 3,
+ name = L["Width"],
+ type = "range",
+ min = 10, max = 500, step = 1,
+ },
+ height = {
+ order = 4,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 250, step = 1,
+ },
+ anchorPoint = {
+ type = "select",
+ order = 5,
+ name = L["Anchor Point"],
+ desc = L["What point to anchor to the frame you set to attach to."],
+ values = petAnchors,
+ },
+ xOffset = {
+ order = 6,
+ type = "range",
+ name = L["xOffset"],
+ desc = L["An X offset (in pixels) to be used when anchoring new frames."],
+ min = -500, max = 500, step = 1,
+ },
+ yOffset = {
+ order = 7,
+ type = "range",
+ name = L["yOffset"],
+ desc = L["An Y offset (in pixels) to be used when anchoring new frames."],
+ min = -500, max = 500, step = 1,
+ },
+ name = {
+ order = 8,
+ type = "group",
+ guiInline = true,
+ get = function(info) return E.db.unitframe.units["party"]["targetsGroup"]["name"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["party"]["targetsGroup"]["name"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("party") end,
+ name = L["Name"],
+ args = {
+ position = {
+ type = "select",
+ order = 1,
+ name = L["Text Position"],
+ values = positionValues,
+ },
+ xOffset = {
+ order = 2,
+ type = "range",
+ name = L["Text xOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 3,
+ type = "range",
+ name = L["Text yOffset"],
+ desc = L["Offset position for text."],
+ min = -300, max = 300, step = 1,
+ },
+ text_format = {
+ order = 100,
+ name = L["Text Format"],
+ type = "input",
+ width = "full",
+ desc = L["TEXT_FORMAT_DESC"],
+ },
+ },
+ },
+ },
+ },
+ raidicon = GetOptionsTable_RaidIcon(UF.CreateAndUpdateHeaderGroup, "party"),
+ readycheckIcon = GetOptionsTable_ReadyCheckIcon(UF.CreateAndUpdateHeaderGroup, "party"),
+ GPSArrow = GetOptionsTable_GPS("party"),
+ },
+}
+
+--Raid Frames
+E.Options.args.unitframe.args.raid = {
+ name = L["Raid Frames"],
+ type = "group",
+ order = 1100,
+ childGroups = "tab",
+ get = function(info) return E.db.unitframe.units["raid"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["raid"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid") end,
+ disabled = function() return not E.UnitFrames; end,
+ args = {
+ configureToggle = {
+ order = 1,
+ type = "execute",
+ name = L["Display Frames"],
+ func = function()
+ UF:HeaderConfig(_G["ElvUF_Raid"], _G["ElvUF_Raid"].forceShow ~= true or nil)
+ end,
+ },
+ resetSettings = {
+ type = "execute",
+ order = 2,
+ name = L["Restore Defaults"],
+ func = function(info, value) UF:ResetUnitSettings("raid"); E:ResetMovers("Raid Frames") end,
+ },
+ copyFrom = {
+ type = "select",
+ order = 3,
+ name = L["Copy From"],
+ desc = L["Select a unit to copy settings from."],
+ values = {
+ ["party"] = L["Party Frames"],
+ ["raid40"] = L["Raid40 Frames"],
+ },
+ set = function(info, value) UF:MergeUnitSettings(value, "raid", true); end,
+ },
+ customText = GetOptionsTable_CustomText(UF.CreateAndUpdateHeaderGroup, "raid", nil, 4),
+ generalGroup = {
+ order = 5,
+ type = "group",
+ name = L["General"],
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["General"],
+ },
+ enable = {
+ type = "toggle",
+ order = 2,
+ name = L["Enable"],
+ },
+ hideonnpc = {
+ type = "toggle",
+ order = 3,
+ name = L["Text Toggle On NPC"],
+ desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
+ get = function(info) return E.db.unitframe.units["raid"]["power"].hideonnpc end,
+ set = function(info, value) E.db.unitframe.units["raid"]["power"].hideonnpc = value; UF:CreateAndUpdateHeaderGroup("raid"); end,
+ },
+ rangeCheck = {
+ order = 4,
+ name = L["Range Check"],
+ desc = L["Check if you are in range to cast spells on this specific unit."],
+ type = "toggle",
+ },
+ healPrediction = {
+ order = 5,
+ name = L["Heal Prediction"],
+ desc = L["Show an incoming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."],
+ type = "toggle",
+ },
+ threatStyle = {
+ type = "select",
+ order = 6,
+ name = L["Threat Display Mode"],
+ values = threatValues,
+ },
+ colorOverride = {
+ order = 7,
+ name = L["Class Color Override"],
+ desc = L["Override the default class color setting."],
+ type = "select",
+ values = {
+ ["USE_DEFAULT"] = L["Use Default"],
+ ["FORCE_ON"] = L["Force On"],
+ ["FORCE_OFF"] = L["Force Off"],
+ },
+ },
+ orientation = {
+ order = 8,
+ type = "select",
+ name = L["Frame Orientation"],
+ desc = L["Set the orientation of the UnitFrame."],
+ values = {
+ --["AUTOMATIC"] = L["Automatic"], not sure if i will use this yet
+ ["LEFT"] = L["Left"],
+ ["MIDDLE"] = L["Middle"],
+ ["RIGHT"] = L["Right"],
+ },
+ },
+ targetGlow = {
+ order = 9,
+ type = "toggle",
+ name = L["Target Glow"],
+ },
+ positionsGroup = {
+ order = 100,
+ name = L["Size and Positions"],
+ type = "group",
+ guiInline = true,
+ set = function(info, value) E.db.unitframe.units["raid"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid", nil, nil, true) end,
+ args = {
+ width = {
+ order = 1,
+ name = L["Width"],
+ type = "range",
+ min = 10, max = 500, step = 1,
+ set = function(info, value) E.db.unitframe.units["raid"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid") end,
+ },
+ height = {
+ order = 2,
+ name = L["Height"],
+ type = "range",
+ min = 10, max = 500, step = 1,
+ set = function(info, value) E.db.unitframe.units["raid"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid") end,
+ },
+ spacer = {
+ order = 3,
+ name = "",
+ type = "description",
+ width = "full",
+ },
+ growthDirection = {
+ order = 4,
+ name = L["Growth Direction"],
+ desc = L["Growth direction from the first unitframe."],
+ type = "select",
+ values = {
+ DOWN_RIGHT = format(L["%s and then %s"], L["Down"], L["Right"]),
+ DOWN_LEFT = format(L["%s and then %s"], L["Down"], L["Left"]),
+ UP_RIGHT = format(L["%s and then %s"], L["Up"], L["Right"]),
+ UP_LEFT = format(L["%s and then %s"], L["Up"], L["Left"]),
+ RIGHT_DOWN = format(L["%s and then %s"], L["Right"], L["Down"]),
+ RIGHT_UP = format(L["%s and then %s"], L["Right"], L["Up"]),
+ LEFT_DOWN = format(L["%s and then %s"], L["Left"], L["Down"]),
+ LEFT_UP = format(L["%s and then %s"], L["Left"], L["Up"]),
+ },
+ },
+ numGroups = {
+ order = 7,
+ type = "range",
+ name = L["Number of Groups"],
+ min = 1, max = 8, step = 1,
+ set = function(info, value)
+ E.db.unitframe.units["raid"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateHeaderGroup("raid")
+ if _G["ElvUF_Raid"].isForced then
+ UF:HeaderConfig(_G["ElvUF_Raid"])
+ UF:HeaderConfig(_G["ElvUF_Raid"], true)
+ end
+ end,
+ },
+ groupsPerRowCol = {
+ order = 8,
+ type = "range",
+ name = L["Groups Per Row/Column"],
+ min = 1, max = 8, step = 1,
+ set = function(info, value)
+ E.db.unitframe.units["raid"][ info[getn(info)] ] = value;
+ UF:CreateAndUpdateHeaderGroup("raid")
+ if _G["ElvUF_Raid"].isForced then
+ UF:HeaderConfig(_G["ElvUF_Raid"])
+ UF:HeaderConfig(_G["ElvUF_Raid"], true)
+ end
+ end,
+ },
+ horizontalSpacing = {
+ order = 9,
+ type = "range",
+ name = L["Horizontal Spacing"],
+ min = -1, max = 50, step = 1,
+ },
+ verticalSpacing = {
+ order = 10,
+ type = "range",
+ name = L["Vertical Spacing"],
+ min = -1, max = 50, step = 1,
+ },
+ },
+ },
+ visibilityGroup = {
+ order = 200,
+ name = L["Visibility"],
+ type = "group",
+ guiInline = true,
+ set = function(info, value) E.db.unitframe.units["raid"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid", nil, nil, true) end,
+ args = {
+ showPlayer = {
+ order = 1,
+ type = "toggle",
+ name = L["Display Player"],
+ desc = L["When true, the header includes the player when not in a raid."],
+ },
+ visibility = {
+ order = 2,
+ type = "input",
+ name = L["Visibility"],
+ desc = L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."],
+ width = "full",
+ },
+ },
+ },
+ sortingGroup = {
+ order = 300,
+ type = "group",
+ guiInline = true,
+ name = L["Grouping & Sorting"],
+ set = function(info, value) E.db.unitframe.units["raid"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid", nil, nil, true) end,
+ args = {
+ groupBy = {
+ order = 1,
+ name = L["Group By"],
+ desc = L["Set the order that the group will sort."],
+ type = "select",
+ values = {
+ ["CLASS"] = "CLASS",
+ ["NAME"] = "NAME",
+ ["MTMA"] = L["Main Tanks / Main Assist"],
+ ["GROUP"] = "GROUP",
+ },
+ },
+ sortDir = {
+ order = 2,
+ name = L["Sort Direction"],
+ desc = L["Defines the sort order of the selected sort method."],
+ type = "select",
+ values = {
+ ["ASC"] = L["Ascending"],
+ ["DESC"] = L["Descending"]
+ },
+ },
+ spacer = {
+ order = 3,
+ type = "description",
+ width = "full",
+ name = " "
+ },
+ raidWideSorting = {
+ order = 4,
+ name = L["Raid-Wide Sorting"],
+ desc = L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."],
+ type = "toggle",
+ },
+ invertGroupingOrder = {
+ order = 5,
+ name = L["Invert Grouping Order"],
+ desc = L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."],
+ disabled = function() return not E.db.unitframe.units["raid"].raidWideSorting end,
+ type = "toggle",
+ },
+ startFromCenter = {
+ order = 6,
+ name = L["Start Near Center"],
+ desc = L["The initial group will start near the center and grow out."],
+ disabled = function() return not E.db.unitframe.units["raid"].raidWideSorting end,
+ type = "toggle",
+ },
+ },
+ },
+ },
+ },
+ health = GetOptionsTable_Health(true, UF.CreateAndUpdateHeaderGroup, "raid"),
+ infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateHeaderGroup, "raid"),
+ power = GetOptionsTable_Power(false, UF.CreateAndUpdateHeaderGroup, "raid"),
+ name = GetOptionsTable_Name(UF.CreateAndUpdateHeaderGroup, "raid"),
+ portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateHeaderGroup, "raid"),
+ --buffs = GetOptionsTable_Auras(true, "buffs", true, UF.CreateAndUpdateHeaderGroup, "raid"),
+ --debuffs = GetOptionsTable_Auras(true, "debuffs", true, UF.CreateAndUpdateHeaderGroup, "raid"),
+ buffIndicator = {
+ order = 701,
+ type = "group",
+ name = L["Buff Indicator"],
+ get = function(info) return E.db.unitframe.units["raid"]["buffIndicator"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["raid"]["buffIndicator"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Buff Indicator"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ size = {
+ type = "range",
+ name = L["Size"],
+ desc = L["Size of the indicator icon."],
+ order = 3,
+ min = 4, max = 50, step = 1,
+ },
+ fontSize = {
+ type = "range",
+ name = FONT_SIZE,
+ order = 4,
+ min = 7, max = 22, step = 1,
+ },
+ profileSpecific = {
+ type = "toggle",
+ name = L["Profile Specific"],
+ desc = L["Use the profile specific filter 'Buff Indicator (Profile)' instead of the global filter 'Buff Indicator'."],
+ order = 5,
+ },
+ configureButton = {
+ type = "execute",
+ name = L["Configure Auras"],
+ func = function()
+ if E.db.unitframe.units["raid"]["buffIndicator"].profileSpecific then
+ E:SetToFilterConfig("Buff Indicator (Profile)")
+ else
+ E:SetToFilterConfig("Buff Indicator")
+ end
+ end,
+ order = 6
+ },
+ },
+ },
+ roleIcon = {
+ order = 702,
+ type = "group",
+ name = L["Role Icon"],
+ get = function(info) return E.db.unitframe.units["raid"]["roleIcon"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["raid"]["roleIcon"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["Role Icon"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ position = {
+ type = "select",
+ order = 3,
+ name = L["Position"],
+ values = positionValues,
+ },
+ attachTo = {
+ type = "select",
+ order = 4,
+ name = L["Attach To"],
+ values = {
+ ["Health"] = L["Health"],
+ ["Power"] = L["Power"],
+ ["InfoPanel"] = L["Information Panel"],
+ ["Frame"] = L["Frame"],
+ },
+ },
+ xOffset = {
+ order = 5,
+ type = "range",
+ name = L["xOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ yOffset = {
+ order = 6,
+ type = "range",
+ name = L["yOffset"],
+ min = -300, max = 300, step = 1,
+ },
+ size = {
+ type = "range",
+ order = 7,
+ name = L["Size"],
+ min = 4, max = 100, step = 1,
+ },
+ },
+ },
+ raidRoleIcons = {
+ order = 703,
+ type = "group",
+ name = L["RL / ML Icons"],
+ get = function(info) return E.db.unitframe.units["raid"]["raidRoleIcons"][ info[getn(info)] ] end,
+ set = function(info, value) E.db.unitframe.units["raid"]["raidRoleIcons"][ info[getn(info)] ] = value; UF:CreateAndUpdateHeaderGroup("raid") end,
+ args = {
+ header = {
+ order = 1,
+ type = "header",
+ name = L["RL / ML Icons"],
+ },
+ enable = {
+ type = "toggle",
+ name = L["Enable"],
+ order = 2,
+ },
+ position = {
+ type = "select",
+ order = 3,
+ name = L["Position"],
+ values = {
+ ["TOPLEFT"] = "TOPLEFT",
+ ["TOPRIGHT"] = "TOPRIGHT",
+ },
+ },
+ },
+ },
+ --rdebuffs = GetOptionsTable_RaidDebuff(UF.CreateAndUpdateHeaderGroup, "raid"),
+ --raidicon = GetOptionsTable_RaidIcon(UF.CreateAndUpdateHeaderGroup, "raid"),
+ readycheckIcon = GetOptionsTable_ReadyCheckIcon(UF.CreateAndUpdateHeaderGroup, "raid"),
+ GPSArrow = GetOptionsTable_GPS("raid"),
+ },
+}
+
+--MORE COLORING STUFF YAY
+E.Options.args.unitframe.args.generalOptionsGroup.args.allColorsGroup.args.classResourceGroup = {
+ order = -10,
+ type = "group",
+ name = L["Class Resources"],
+ get = function(info)
+ local t = E.db.unitframe.colors.classResources[ info[getn(info)] ]
+ local d = P.unitframe.colors.classResources[ info[getn(info)] ]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.classResources[ info[getn(info)] ]
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ args = {}
+}
+
+E.Options.args.unitframe.args.generalOptionsGroup.args.allColorsGroup.args.classResourceGroup.args.bgColor = {
+ order = 1,
+ type = "color",
+ name = L["Backdrop Color"],
+ hasAlpha = false,
+}
+
+for i = 1, 3 do
+ E.Options.args.unitframe.args.generalOptionsGroup.args.allColorsGroup.args.classResourceGroup.args["combo"..i] = {
+ order = i + 2,
+ type = "color",
+ name = L["Combo Point"].." #"..i,
+ get = function(info)
+ local t = E.db.unitframe.colors.classResources.comboPoints[i]
+ local d = P.unitframe.colors.classResources.comboPoints[i]
+ return t.r, t.g, t.b, t.a, d.r, d.g, d.b
+ end,
+ set = function(info, r, g, b)
+ local t = E.db.unitframe.colors.classResources.comboPoints[i]
+ t.r, t.g, t.b = r, g, b
+ UF:Update_AllFrames()
+ end,
+ }
+end
+
+
+if P.unitframe.colors.classResources[E.myclass] then
+ E.Options.args.unitframe.args.generalOptionsGroup.args.allColorsGroup.args.classResourceGroup.args.spacer2 = {
+ order = 10,
+ name = " ",
+ type = "description",
+ width = "full",
+ }
+end
+
+--Custom Texts
+function E:RefreshCustomTextsConfigs()
+ --Hide any custom texts that don't belong to current profile
+ for _, customText in pairs(CUSTOMTEXT_CONFIGS) do
+ customText.hidden = true
+ end
+ twipe(CUSTOMTEXT_CONFIGS)
+
+ for unit, _ in pairs(E.db.unitframe.units) do
+ if E.db.unitframe.units[unit].customTexts then
+ for objectName, _ in pairs(E.db.unitframe.units[unit].customTexts) do
+ CreateCustomTextGroup(unit, objectName)
+ end
+ end
+ end
+end
+E:RefreshCustomTextsConfigs()