init
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local wipe, date = wipe, date
|
||||
local format, select, type, ipairs, pairs = format, select, type, ipairs, pairs
|
||||
local strmatch, strfind, tonumber, tostring = strmatch, strfind, tonumber, tostring
|
||||
--WoW API / Variables
|
||||
local GetCVarBool = GetCVarBool
|
||||
local GetFunctionCPUUsage = GetFunctionCPUUsage
|
||||
local RequestBattlefieldScoreData = RequestBattlefieldScoreData
|
||||
local UnitGroupRolesAssigned = UnitGroupRolesAssigned
|
||||
local UnitHasVehicleUI = UnitHasVehicleUI
|
||||
local IsInInstance = IsInInstance
|
||||
|
||||
E.Role = "Melee" -- TODO: Load locally, or save per specialization.
|
||||
|
||||
do -- other non-english locales require this
|
||||
E.UnlocalizedClasses = {}
|
||||
for k, v in pairs(_G.LOCALIZED_CLASS_NAMES_MALE) do E.UnlocalizedClasses[v] = k end
|
||||
for k, v in pairs(_G.LOCALIZED_CLASS_NAMES_FEMALE) do E.UnlocalizedClasses[v] = k end
|
||||
|
||||
function E:UnlocalizedClassName(className)
|
||||
return (className and className ~= "") and E.UnlocalizedClasses[className]
|
||||
end
|
||||
end
|
||||
|
||||
function E:ScanTooltipTextures(clean, grabTextures)
|
||||
local textures
|
||||
for i = 1, 10 do
|
||||
local tex = _G["ElvUI_ScanTooltipTexture"..i]
|
||||
local texture = tex and tex:GetTexture()
|
||||
if texture then
|
||||
if grabTextures then
|
||||
if not textures then textures = {} end
|
||||
textures[i] = texture
|
||||
end
|
||||
if clean then
|
||||
tex:SetTexture()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return textures
|
||||
end
|
||||
|
||||
function E:GetPlayerRole()
|
||||
local isTank, isHealer, isDamage = UnitGroupRolesAssigned("player")
|
||||
|
||||
if isTank or isHealer or isDamage then
|
||||
return isTank and "TANK" or isHealer and "HEALER" or isDamage and "DAMAGER"
|
||||
else
|
||||
return "DAMAGER" -- Assume dps role; Nothing better for ascension.
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
--local Masque = E.Libs.Masque
|
||||
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
|
||||
end
|
||||
|
||||
do
|
||||
local CPU_USAGE = {}
|
||||
local function CompareCPUDiff(showall, minCalls)
|
||||
local greatestUsage, greatestCalls, greatestName, newName, newFunc
|
||||
local greatestDiff, lastModule, mod, usage, calls, diff = 0
|
||||
|
||||
for name, oldUsage in pairs(CPU_USAGE) do
|
||||
newName, newFunc = strmatch(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
|
||||
usage, calls = GetFunctionCPUUsage(mod[newFunc], true)
|
||||
diff = usage - oldUsage
|
||||
if showall and (calls > minCalls) then
|
||||
E:Print("Name("..name..") Calls("..calls..") Diff("..(diff > 0 and format("%.3f", diff) or 0)..")")
|
||||
end
|
||||
if (diff > greatestDiff) and calls > minCalls then
|
||||
greatestName, greatestUsage, greatestCalls, greatestDiff = name, usage, calls, diff
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if greatestName then
|
||||
E:Print(greatestName.." had the CPU usage of: "..(greatestUsage > 0 and format("%.3f", greatestUsage) or 0).."ms. And has been called "..greatestCalls.." times.")
|
||||
else
|
||||
E:Print("CPU Usage: No CPU Usage differences found.")
|
||||
end
|
||||
|
||||
wipe(CPU_USAGE)
|
||||
end
|
||||
|
||||
function E:GetTopCPUFunc(msg)
|
||||
if not GetCVarBool("scriptProfile") then
|
||||
E:Print("For `/cpuusage` to work, you need to enable script profiling via: `/console scriptProfile 1` then reload. Disable after testing by setting it back to 0.")
|
||||
return
|
||||
end
|
||||
|
||||
local module, showall, delay, minCalls = strmatch(msg, "^(%S+)%s*(%S*)%s*(%S*)%s*(.*)$")
|
||||
local checkCore, mod = (not module or module == "") and "E"
|
||||
|
||||
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
|
||||
|
||||
wipe(CPU_USAGE)
|
||||
if module == "all" then
|
||||
for moduName, modu in pairs(self.modules) do
|
||||
for funcName, func in pairs(modu) do
|
||||
if (funcName ~= "GetModule") and (type(func) == "function") then
|
||||
CPU_USAGE[moduName..":"..funcName] = GetFunctionCPUUsage(func, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if not checkCore then
|
||||
mod = self:GetModule(module, true)
|
||||
if not mod then
|
||||
self:Print(module.." not found, falling back to checking core.")
|
||||
mod, checkCore = self, "E"
|
||||
end
|
||||
else
|
||||
mod = self
|
||||
end
|
||||
for name, func in pairs(mod) do
|
||||
if (name ~= "GetModule") and type(func) == "function" then
|
||||
CPU_USAGE[(checkCore or module)..":"..name] = GetFunctionCPUUsage(func, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:Delay(delay, CompareCPUDiff, showall, minCalls)
|
||||
self:Print("Calculating CPU Usage differences (module: "..(checkCore or module)..", showall: "..tostring(showall)..", minCalls: "..tostring(minCalls)..", delay: "..tostring(delay)..")")
|
||||
end
|
||||
end
|
||||
|
||||
function E:RegisterObjectForVehicleLock(object, originalParent)
|
||||
if not object or not originalParent then
|
||||
E:Print("Error. Usage: RegisterObjectForVehicleLock(object, originalParent)")
|
||||
return
|
||||
end
|
||||
|
||||
object = _G[object] or object
|
||||
--Entering/Exiting vehicles will often happen in combat.
|
||||
--For this reason we cannot allow protected objects.
|
||||
if object.IsProtected and object:IsProtected() then
|
||||
E:Print("Error. Object is protected and cannot be changed in combat.")
|
||||
return
|
||||
end
|
||||
|
||||
--Check if we are already in a vehicles
|
||||
if UnitHasVehicleUI("player") then
|
||||
object:SetParent(E.HiddenFrame)
|
||||
end
|
||||
|
||||
--Add object to table
|
||||
E.VehicleLocks[object] = originalParent
|
||||
end
|
||||
|
||||
function E:UnregisterObjectForVehicleLock(object)
|
||||
if not object then
|
||||
E:Print("Error. Usage: UnregisterObjectForVehicleLock(object)")
|
||||
return
|
||||
end
|
||||
|
||||
object = _G[object] or object
|
||||
--Check if object was registered to begin with
|
||||
if not E.VehicleLocks[object] then return end
|
||||
|
||||
--Change parent of object back to original parent
|
||||
local originalParent = E.VehicleLocks[object]
|
||||
if originalParent then
|
||||
object:SetParent(originalParent)
|
||||
end
|
||||
|
||||
--Remove object from table
|
||||
E.VehicleLocks[object] = nil
|
||||
end
|
||||
|
||||
function E:EnterVehicleHideFrames(_, unit)
|
||||
if unit ~= "player" then return end
|
||||
|
||||
for object in pairs(E.VehicleLocks) do
|
||||
object:SetParent(E.HiddenFrame)
|
||||
end
|
||||
end
|
||||
|
||||
function E:ExitVehicleShowFrames(_, unit)
|
||||
if unit ~= "player" then return end
|
||||
|
||||
for object, originalParent in pairs(E.VehicleLocks) do
|
||||
object:SetParent(originalParent)
|
||||
end
|
||||
end
|
||||
|
||||
function E:RequestBGInfo()
|
||||
RequestBattlefieldScoreData()
|
||||
end
|
||||
|
||||
function E:PLAYER_ENTERING_WORLD()
|
||||
if not self.MediaUpdated then
|
||||
self:UpdateMedia()
|
||||
self.MediaUpdated = true
|
||||
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:PLAYER_LEVEL_UP(_, level)
|
||||
E.mylevel = level
|
||||
end
|
||||
|
||||
function E:LoadAPI()
|
||||
self:RegisterEvent("PLAYER_LEVEL_UP")
|
||||
self:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
self:RegisterEvent("UNIT_ENTERED_VEHICLE", "EnterVehicleHideFrames")
|
||||
self:RegisterEvent("UNIT_EXITED_VEHICLE", "ExitVehicleShowFrames")
|
||||
self:RegisterEvent("UI_SCALE_CHANGED", "PixelScaleChanged")
|
||||
|
||||
do -- setup cropIcon texCoords
|
||||
local opt = E.db.general.cropIcon
|
||||
local modifier = 0.04 * opt
|
||||
for i, v in ipairs(E.TexCoords) do
|
||||
if i % 2 == 0 then
|
||||
E.TexCoords[i] = v - modifier
|
||||
else
|
||||
E.TexCoords[i] = v + modifier
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,294 @@
|
||||
------------------------------------------------------------------------
|
||||
-- Animation Functions
|
||||
------------------------------------------------------------------------
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
--Lua functions
|
||||
local random, next, unpack, strsub = random, next, unpack, strsub
|
||||
--WoW API / Variables
|
||||
|
||||
E.AnimShake = {{-9,7,-7,12}, {-5,9,-9,5}, {-5,7,-7,5}, {-9,9,-9,9}, {-5,7,-7,5}, {-9,7,-9,5}}
|
||||
E.AnimShakeH = {-5,5,-2,5,-2,5}
|
||||
|
||||
function E:FlashLoopFinished(requested)
|
||||
if not requested then self:Play() end
|
||||
end
|
||||
|
||||
function E:RandomAnimShake(index)
|
||||
local s = E.AnimShake[index]
|
||||
return random(s[1], s[2]), random(s[3], s[4])
|
||||
end
|
||||
|
||||
function E:SetUpAnimGroup(obj, Type, ...)
|
||||
if not Type then Type = "Flash" end
|
||||
|
||||
if strsub(Type, 1, 5) == "Flash" then
|
||||
obj.anim = obj:CreateAnimationGroup("Flash")
|
||||
obj.anim.fadein = obj.anim:CreateAnimation("ALPHA", "FadeIn")
|
||||
obj.anim.fadein:SetChange(1)
|
||||
obj.anim.fadein:SetOrder(2)
|
||||
|
||||
obj.anim.fadeout = obj.anim:CreateAnimation("ALPHA", "FadeOut")
|
||||
obj.anim.fadeout:SetChange(-1)
|
||||
obj.anim.fadeout:SetOrder(1)
|
||||
|
||||
if Type == "FlashLoop" then
|
||||
obj.anim:SetScript("OnFinished", E.FlashLoopFinished)
|
||||
end
|
||||
elseif strsub(Type, 1, 5) == "Shake" then
|
||||
local shake = obj:CreateAnimationGroup(Type)
|
||||
shake:SetLooping("REPEAT")
|
||||
shake.path = shake:CreateAnimation("Path")
|
||||
|
||||
if Type == "Shake" then
|
||||
shake.path:SetDuration(0.7)
|
||||
obj.shake = shake
|
||||
elseif Type == "ShakeH" then
|
||||
shake.path:SetDuration(2)
|
||||
obj.shakeh = shake
|
||||
end
|
||||
|
||||
for i = 1, 6 do
|
||||
shake.path[i] = shake.path:CreateControlPoint()
|
||||
|
||||
if Type == "Shake" then
|
||||
shake.path[i]:SetOffset(E:RandomAnimShake(i))
|
||||
else
|
||||
shake.path[i]:SetOffset(E.AnimShakeH[i], 0)
|
||||
end
|
||||
end
|
||||
shake.path[1]:SetOrder(1)
|
||||
shake.path[2]:SetOrder(2)
|
||||
shake.path[3]:SetOrder(3)
|
||||
shake.path[4]:SetOrder(4)
|
||||
shake.path[5]:SetOrder(5)
|
||||
shake.path[6]:SetOrder(6)
|
||||
else
|
||||
local x, y, duration, customName = ...
|
||||
if not customName then customName = "anim" end
|
||||
|
||||
local anim = obj:CreateAnimationGroup("Move_In")
|
||||
obj[customName] = anim
|
||||
|
||||
anim.in1 = anim:CreateAnimation("Translation")
|
||||
anim.in1:SetDuration(0)
|
||||
anim.in1:SetOrder(1)
|
||||
anim.in1:SetOffset(E:Scale(x), E:Scale(y))
|
||||
|
||||
anim.in2 = anim:CreateAnimation("Translation")
|
||||
anim.in2:SetDuration(duration)
|
||||
anim.in2:SetOrder(2)
|
||||
anim.in2:SetSmoothing("OUT")
|
||||
anim.in2:SetOffset(E:Scale(-x), E:Scale(-y))
|
||||
|
||||
anim.out1 = obj:CreateAnimationGroup("Move_Out")
|
||||
anim.out1:SetScript("OnFinished", function() obj:Hide() end)
|
||||
|
||||
anim.out2 = anim.out1:CreateAnimation("Translation")
|
||||
anim.out2:SetDuration(duration)
|
||||
anim.out2:SetOrder(1)
|
||||
anim.out2:SetSmoothing("IN")
|
||||
anim.out2:SetOffset(E:Scale(x), E:Scale(y))
|
||||
end
|
||||
end
|
||||
|
||||
function E:Shake(obj)
|
||||
if not obj.shake then
|
||||
E:SetUpAnimGroup(obj, "Shake")
|
||||
end
|
||||
|
||||
obj.shake:Play()
|
||||
end
|
||||
|
||||
function E:StopShake(obj)
|
||||
if obj.shake then
|
||||
obj.shake:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
function E:ShakeHorizontal(obj)
|
||||
if not obj.shakeh then
|
||||
E:SetUpAnimGroup(obj, "ShakeH")
|
||||
end
|
||||
|
||||
obj.shakeh:Play()
|
||||
end
|
||||
|
||||
function E:StopShakeHorizontal(obj)
|
||||
if obj.shakeh then
|
||||
obj.shakeh:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
function E:Flash(obj, duration, loop)
|
||||
if not obj.anim then
|
||||
E:SetUpAnimGroup(obj, loop and "FlashLoop" or "Flash")
|
||||
end
|
||||
|
||||
if not obj.anim:IsPlaying() then
|
||||
obj.anim.fadein:SetDuration(duration)
|
||||
obj.anim.fadeout:SetDuration(duration)
|
||||
obj.anim:Play()
|
||||
end
|
||||
end
|
||||
|
||||
function E:StopFlash(obj)
|
||||
if obj.anim and obj.anim:IsPlaying() then
|
||||
obj.anim:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
function E:SlideIn(obj, customName)
|
||||
if not customName then customName = "anim" end
|
||||
if not obj[customName] then return end
|
||||
|
||||
obj[customName].out1:Stop()
|
||||
obj[customName]:Play()
|
||||
obj:Show()
|
||||
end
|
||||
|
||||
function E:SlideOut(obj, customName)
|
||||
if not customName then customName = "anim" end
|
||||
if not obj[customName] then return end
|
||||
|
||||
obj[customName]:Finish()
|
||||
obj[customName]:Stop()
|
||||
obj[customName].out1:Play()
|
||||
end
|
||||
|
||||
local FADEFRAMES, FADEMANAGER = {}, CreateFrame("FRAME")
|
||||
FADEMANAGER.delay = 0.05
|
||||
|
||||
function E:UIFrameFade_OnUpdate(elapsed)
|
||||
FADEMANAGER.timer = (FADEMANAGER.timer or 0) + elapsed
|
||||
|
||||
if FADEMANAGER.timer > FADEMANAGER.delay then
|
||||
FADEMANAGER.timer = 0
|
||||
|
||||
for frame, info in next, FADEFRAMES do
|
||||
-- Reset the timer if there isn't one, this is just an internal counter
|
||||
if frame:IsVisible() then
|
||||
info.fadeTimer = (info.fadeTimer or 0) + (elapsed + FADEMANAGER.delay)
|
||||
else
|
||||
info.fadeTimer = info.timeToFade + 1
|
||||
end
|
||||
|
||||
-- If the fadeTimer is less then the desired fade time then set the alpha otherwise hold the fade state, call the finished function, or just finish the fade
|
||||
if info.fadeTimer < info.timeToFade then
|
||||
if info.mode == "IN" then
|
||||
frame:SetAlpha((info.fadeTimer / info.timeToFade) * info.diffAlpha + info.startAlpha)
|
||||
else
|
||||
frame:SetAlpha(((info.timeToFade - info.fadeTimer) / info.timeToFade) * info.diffAlpha + info.endAlpha)
|
||||
end
|
||||
else
|
||||
frame:SetAlpha(info.endAlpha)
|
||||
|
||||
-- If there is a fadeHoldTime then wait until its passed to continue on
|
||||
if info.fadeHoldTime and info.fadeHoldTime > 0 then
|
||||
info.fadeHoldTime = info.fadeHoldTime - elapsed
|
||||
else
|
||||
-- Complete the fade and call the finished function if there is one
|
||||
E:UIFrameFadeRemoveFrame(frame)
|
||||
|
||||
if info.finishedFunc then
|
||||
if info.finishedArgs then
|
||||
info.finishedFunc(unpack(info.finishedArgs))
|
||||
else -- optional method
|
||||
info.finishedFunc(info.finishedArg1, info.finishedArg2, info.finishedArg3, info.finishedArg4, info.finishedArg5)
|
||||
end
|
||||
|
||||
if not info.finishedFuncKeep then
|
||||
info.finishedFunc = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not next(FADEFRAMES) then
|
||||
FADEMANAGER:SetScript("OnUpdate", nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Generic fade function
|
||||
function E:UIFrameFade(frame, info)
|
||||
if not frame then return end
|
||||
|
||||
frame.fadeInfo = info
|
||||
|
||||
if not info.mode then
|
||||
info.mode = "IN"
|
||||
end
|
||||
|
||||
if info.mode == "IN" then
|
||||
if not info.startAlpha then info.startAlpha = 0 end
|
||||
if not info.endAlpha then info.endAlpha = 1 end
|
||||
if not info.diffAlpha then info.diffAlpha = info.endAlpha - info.startAlpha end
|
||||
else
|
||||
if not info.startAlpha then info.startAlpha = 1 end
|
||||
if not info.endAlpha then info.endAlpha = 0 end
|
||||
if not info.diffAlpha then info.diffAlpha = info.startAlpha - info.endAlpha end
|
||||
end
|
||||
|
||||
frame:SetAlpha(info.startAlpha)
|
||||
|
||||
if not frame:IsProtected() then
|
||||
frame:Show()
|
||||
end
|
||||
|
||||
if not FADEFRAMES[frame] then
|
||||
FADEFRAMES[frame] = info -- read below comment
|
||||
FADEMANAGER:SetScript("OnUpdate", E.UIFrameFade_OnUpdate)
|
||||
else
|
||||
FADEFRAMES[frame] = info -- keep these both, we need this updated in the event its changed to another ref from a plugin or sth, don't move it up!
|
||||
end
|
||||
end
|
||||
|
||||
-- Convenience function to do a simple fade in
|
||||
function E:UIFrameFadeIn(frame, timeToFade, startAlpha, endAlpha)
|
||||
if not frame then return end
|
||||
|
||||
if frame.FadeObject then
|
||||
frame.FadeObject.fadeTimer = nil
|
||||
else
|
||||
frame.FadeObject = {}
|
||||
end
|
||||
|
||||
frame.FadeObject.mode = "IN"
|
||||
frame.FadeObject.timeToFade = timeToFade
|
||||
frame.FadeObject.startAlpha = startAlpha
|
||||
frame.FadeObject.endAlpha = endAlpha
|
||||
frame.FadeObject.diffAlpha = endAlpha - startAlpha
|
||||
|
||||
E:UIFrameFade(frame, frame.FadeObject)
|
||||
end
|
||||
|
||||
-- Convenience function to do a simple fade out
|
||||
function E:UIFrameFadeOut(frame, timeToFade, startAlpha, endAlpha)
|
||||
if not frame then return end
|
||||
|
||||
if frame.FadeObject then
|
||||
frame.FadeObject.fadeTimer = nil
|
||||
else
|
||||
frame.FadeObject = {}
|
||||
end
|
||||
|
||||
frame.FadeObject.mode = "OUT"
|
||||
frame.FadeObject.timeToFade = timeToFade
|
||||
frame.FadeObject.startAlpha = startAlpha
|
||||
frame.FadeObject.endAlpha = endAlpha
|
||||
frame.FadeObject.diffAlpha = startAlpha - endAlpha
|
||||
|
||||
E:UIFrameFade(frame, frame.FadeObject)
|
||||
end
|
||||
|
||||
function E:UIFrameFadeRemoveFrame(frame)
|
||||
if frame and FADEFRAMES[frame] then
|
||||
if frame.FadeObject then
|
||||
frame.FadeObject.fadeTimer = nil
|
||||
end
|
||||
|
||||
FADEFRAMES[frame] = nil
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,369 @@
|
||||
--[[
|
||||
Collection of previous april fools pranks
|
||||
|
||||
Harlem Shake: Try it out with the command /harlemshake
|
||||
Hello Kitty: Try it out with the command /hellokitty (pay attention to the popups, read what it says)
|
||||
]]
|
||||
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local UF = E:GetModule("UnitFrames")
|
||||
local AB = E:GetModule("ActionBars")
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local pairs = pairs
|
||||
local twipe, tinsert = wipe, tinsert
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
local DoEmote = DoEmote
|
||||
local GetCVar, SetCVar = GetCVar, SetCVar
|
||||
local PlayMusic, StopMusic = PlayMusic, StopMusic
|
||||
local SendChatMessage = SendChatMessage
|
||||
local NUM_PET_ACTION_SLOTS = NUM_PET_ACTION_SLOTS
|
||||
|
||||
--Harlem Shake (Activate with command: /harlemshake)
|
||||
--People really seemed to like this one. We got a lot of positive responses.
|
||||
do
|
||||
function E:StopHarlemShake()
|
||||
E.isMassiveShaking = nil
|
||||
StopMusic()
|
||||
SetCVar("Sound_EnableAllSound", self.oldEnableAllSound)
|
||||
SetCVar("Sound_EnableMusic", self.oldEnableMusic)
|
||||
|
||||
self:StopShakeHorizontal(ElvUI_StaticPopup1)
|
||||
for _, object in pairs(self.massiveShakeObjects) do
|
||||
if object then
|
||||
self:StopShake(object)
|
||||
end
|
||||
end
|
||||
|
||||
if E.massiveShakeTimer then
|
||||
E:CancelTimer(E.massiveShakeTimer)
|
||||
end
|
||||
|
||||
E.global.aprilFools = true
|
||||
E:StaticPopup_Hide("HARLEM_SHAKE")
|
||||
twipe(self.massiveShakeObjects)
|
||||
DoEmote("Dance")
|
||||
end
|
||||
|
||||
function E:DoTheHarlemShake()
|
||||
E.isMassiveShaking = true
|
||||
ElvUI_StaticPopup1Button1:Enable()
|
||||
|
||||
for _, object in pairs(self.massiveShakeObjects) do
|
||||
if object and object:IsShown() then
|
||||
self:Shake(object)
|
||||
end
|
||||
end
|
||||
|
||||
E.massiveShakeTimer = E:ScheduleTimer("StopHarlemShake", 42.5)
|
||||
SendChatMessage("DO THE HARLEM SHAKE!", "YELL")
|
||||
end
|
||||
|
||||
function E:BeginHarlemShake()
|
||||
DoEmote("Dance")
|
||||
ElvUI_StaticPopup1Button1:Disable()
|
||||
self:ShakeHorizontal(ElvUI_StaticPopup1)
|
||||
self.oldEnableAllSound = GetCVar("Sound_EnableAllSound")
|
||||
self.oldEnableMusic = GetCVar("Sound_EnableMusic")
|
||||
|
||||
SetCVar("Sound_EnableAllSound", 1)
|
||||
SetCVar("Sound_EnableMusic", 1)
|
||||
PlayMusic(E.Media.Sounds.HarlemShake)
|
||||
E:ScheduleTimer("DoTheHarlemShake", 15.5)
|
||||
|
||||
self.massiveShakeObjects = {}
|
||||
tinsert(self.massiveShakeObjects, GameTooltip)
|
||||
tinsert(self.massiveShakeObjects, Minimap)
|
||||
tinsert(self.massiveShakeObjects, WatchFrame)
|
||||
tinsert(self.massiveShakeObjects, LeftChatPanel)
|
||||
tinsert(self.massiveShakeObjects, RightChatPanel)
|
||||
tinsert(self.massiveShakeObjects, LeftChatToggleButton)
|
||||
tinsert(self.massiveShakeObjects, RightChatToggleButton)
|
||||
|
||||
if ElvUI_ReputationBar then
|
||||
tinsert(self.massiveShakeObjects, ElvUI_ReputationBar)
|
||||
end
|
||||
if ElvUI_ExperienceBar then
|
||||
tinsert(self.massiveShakeObjects, ElvUI_ExperienceBar)
|
||||
end
|
||||
|
||||
for unit in pairs(UF.units) do
|
||||
tinsert(self.massiveShakeObjects, UF[unit])
|
||||
end
|
||||
|
||||
for _, header in pairs(UF.headers) do
|
||||
tinsert(self.massiveShakeObjects, header)
|
||||
end
|
||||
|
||||
for _, bar in pairs(AB.handledBars) do
|
||||
for i = 1, #bar.buttons do
|
||||
tinsert(self.massiveShakeObjects, bar.buttons[i])
|
||||
end
|
||||
end
|
||||
|
||||
if ElvUI_StanceBar then
|
||||
for i = 1, #ElvUI_StanceBar.buttons do
|
||||
tinsert(self.massiveShakeObjects, ElvUI_StanceBar.buttons[i])
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, NUM_PET_ACTION_SLOTS do
|
||||
local button = _G["PetActionButton"..i]
|
||||
if button then
|
||||
tinsert(self.massiveShakeObjects, button)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:HarlemShakeToggle()
|
||||
self:StaticPopup_Show("HARLEM_SHAKE")
|
||||
end
|
||||
end
|
||||
|
||||
--Hello Kitty (Activate with command: /hellokitty)
|
||||
--This is one of those pranks where you either love it or hate it I think
|
||||
--Unfortunately there was a bug which caused some of the hello kitty changes to stick,
|
||||
-- when they should have reverted to the original settings. This bug was fixed later on.
|
||||
do
|
||||
local function OnDragStart(self)
|
||||
self:StartMoving()
|
||||
end
|
||||
|
||||
local function OnDragStop(self)
|
||||
self:StopMovingOrSizing()
|
||||
end
|
||||
|
||||
local function OnUpdate(self, elapsed)
|
||||
if self.elapsed and self.elapsed > 0.1 then
|
||||
self.tex:SetTexCoord((self.curFrame - 1) * 0.1, 0, (self.curFrame - 1) * 0.1, 1, self.curFrame * 0.1, 0, self.curFrame * 0.1, 1)
|
||||
|
||||
if self.countUp then
|
||||
self.curFrame = self.curFrame + 1
|
||||
else
|
||||
self.curFrame = self.curFrame - 1
|
||||
end
|
||||
|
||||
if self.curFrame > 10 then
|
||||
self.countUp = false
|
||||
self.curFrame = 9
|
||||
elseif self.curFrame < 1 then
|
||||
self.countUp = true
|
||||
self.curFrame = 2
|
||||
end
|
||||
self.elapsed = 0
|
||||
else
|
||||
self.elapsed = (self.elapsed or 0) + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
function E:SetupHelloKitty()
|
||||
if not self.db.tempSettings then
|
||||
self.db.tempSettings = {}
|
||||
end
|
||||
|
||||
--Store old settings
|
||||
local t = self.db.tempSettings
|
||||
local c = self.db.general.backdropcolor
|
||||
if self:HelloKittyFixCheck() then
|
||||
E:HelloKittyFix()
|
||||
else
|
||||
self.oldEnableAllSound = GetCVar("Sound_EnableAllSound")
|
||||
self.oldEnableMusic = GetCVar("Sound_EnableMusic")
|
||||
|
||||
t.backdropcolor = {r = c.r, g = c.g, b = c.b}
|
||||
c = self.db.general.backdropfadecolor
|
||||
t.backdropfadecolor = {r = c.r, g = c.g, b = c.b, a = c.a}
|
||||
c = self.db.general.bordercolor
|
||||
t.bordercolor = {r = c.r, g = c.g, b = c.b}
|
||||
c = self.db.general.valuecolor
|
||||
t.valuecolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
t.panelBackdropNameLeft = self.db.chat.panelBackdropNameLeft
|
||||
t.panelBackdropNameRight = self.db.chat.panelBackdropNameRight
|
||||
|
||||
c = self.db.unitframe.colors.health
|
||||
t.health = {r = c.r, g = c.g, b = c.b}
|
||||
t.healthclass = self.db.unitframe.colors.healthclass
|
||||
|
||||
c = self.db.unitframe.colors.castColor
|
||||
t.castColor = {r = c.r, g = c.g, b = c.b}
|
||||
t.transparentCastbar = self.db.unitframe.colors.transparentCastbar
|
||||
|
||||
c = self.db.unitframe.colors.auraBarBuff
|
||||
t.auraBarBuff = {r = c.r, g = c.g, b = c.b}
|
||||
t.transparentAurabars = self.db.unitframe.colors.transparentAurabars
|
||||
|
||||
--Apply new settings
|
||||
self.db.general.backdropfadecolor = {r = 131/255, g = 36/255, b = 130/255, a = 0.36}
|
||||
self.db.general.backdropcolor = {r = 223/255, g = 76/255, b = 188/255}
|
||||
self.db.general.bordercolor = {r = 223/255, g = 217/255, b = 47/255}
|
||||
self.db.general.valuecolor = {r = 223/255, g = 217/255, b = 47/255}
|
||||
|
||||
self.db.chat.panelBackdropNameLeft = E.Media.Textures.HelloKittyChat
|
||||
self.db.chat.panelBackdropNameRight = E.Media.Textures.HelloKittyChat
|
||||
|
||||
self.db.unitframe.colors.castColor = {r = 223/255, g = 76/255, b = 188/255}
|
||||
self.db.unitframe.colors.transparentCastbar = true
|
||||
|
||||
self.db.unitframe.colors.auraBarBuff = {r = 223/255, g = 76/255, b = 188/255}
|
||||
self.db.unitframe.colors.transparentAurabars = true
|
||||
|
||||
self.db.unitframe.colors.health = {r = 223/255, g = 76/255, b = 188/255}
|
||||
self.db.unitframe.colors.healthclass = false
|
||||
|
||||
SetCVar("Sound_EnableAllSound", 1)
|
||||
SetCVar("Sound_EnableMusic", 1)
|
||||
PlayMusic(E.Media.Sounds.HelloKitty)
|
||||
E:StaticPopup_Show("HELLO_KITTY_END")
|
||||
|
||||
self.db.general.kittys = true
|
||||
self:CreateKittys()
|
||||
|
||||
self:UpdateAll()
|
||||
end
|
||||
end
|
||||
|
||||
function E:RestoreHelloKitty()
|
||||
--Store old settings
|
||||
self.db.general.kittys = false
|
||||
if HelloKittyLeft then
|
||||
HelloKittyLeft:Hide()
|
||||
HelloKittyRight:Hide()
|
||||
end
|
||||
|
||||
if not self.db.tempSettings then return end
|
||||
if self:HelloKittyFixCheck() then
|
||||
self:HelloKittyFix()
|
||||
self.db.tempSettings = nil
|
||||
return
|
||||
end
|
||||
local c = self.db.tempSettings.backdropcolor
|
||||
self.db.general.backdropcolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
c = self.db.tempSettings.backdropfadecolor
|
||||
self.db.general.backdropfadecolor = {r = c.r, g = c.g, b = c.b, a = (c.a or 0.8)}
|
||||
|
||||
c = self.db.tempSettings.bordercolor
|
||||
self.db.general.bordercolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
c = self.db.tempSettings.valuecolor
|
||||
self.db.general.valuecolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
self.db.chat.panelBackdropNameLeft = self.db.tempSettings.panelBackdropNameLeft
|
||||
self.db.chat.panelBackdropNameRight = self.db.tempSettings.panelBackdropNameRight
|
||||
|
||||
c = self.db.tempSettings.health
|
||||
self.db.unitframe.colors.health = {r = c.r, g = c.g, b = c.b}
|
||||
self.db.unitframe.colors.healthclass = self.db.tempSettings.healthclass
|
||||
|
||||
c = self.db.tempSettings.castColor
|
||||
self.db.unitframe.colors.castColor = {r = c.r, g = c.g, b = c.b}
|
||||
self.db.unitframe.colors.transparentCastbar = self.db.tempSettings.transparentCastbar
|
||||
|
||||
c = self.db.tempSettings.auraBarBuff
|
||||
self.db.unitframe.colors.auraBarBuff = {r = c.r, g = c.g, b = c.b}
|
||||
self.db.unitframe.colors.transparentAurabars = self.db.tempSettings.transparentAurabars
|
||||
|
||||
self.db.tempSettings = nil
|
||||
|
||||
self:UpdateAll()
|
||||
end
|
||||
|
||||
function E:CreateKittys()
|
||||
if HelloKittyLeft then
|
||||
HelloKittyLeft:Show()
|
||||
HelloKittyRight:Show()
|
||||
return
|
||||
end
|
||||
local helloKittyLeft = CreateFrame("Frame", "HelloKittyLeft", UIParent)
|
||||
helloKittyLeft:SetSize(120, 128)
|
||||
helloKittyLeft:SetMovable(true)
|
||||
helloKittyLeft:EnableMouse(true)
|
||||
helloKittyLeft:RegisterForDrag("LeftButton")
|
||||
helloKittyLeft:Point("BOTTOMLEFT", LeftChatPanel, "BOTTOMRIGHT", 2, -4)
|
||||
helloKittyLeft.tex = helloKittyLeft:CreateTexture(nil, "OVERLAY")
|
||||
helloKittyLeft.tex:SetAllPoints()
|
||||
helloKittyLeft.tex:SetTexture(E.Media.Textures.HelloKitty)
|
||||
helloKittyLeft.tex:SetTexCoord(0, 0, 0, 1, 0, 0, 0, 1)
|
||||
helloKittyLeft.curFrame = 1
|
||||
helloKittyLeft.countUp = true
|
||||
helloKittyLeft:SetClampedToScreen(true)
|
||||
helloKittyLeft:SetScript("OnDragStart", OnDragStart)
|
||||
helloKittyLeft:SetScript("OnDragStop", OnDragStop)
|
||||
helloKittyLeft:SetScript("OnUpdate", OnUpdate)
|
||||
|
||||
local helloKittyRight = CreateFrame("Frame", "HelloKittyRight", UIParent)
|
||||
helloKittyRight:SetSize(120, 128)
|
||||
helloKittyRight:SetMovable(true)
|
||||
helloKittyRight:EnableMouse(true)
|
||||
helloKittyRight:RegisterForDrag("LeftButton")
|
||||
helloKittyRight:Point("BOTTOMRIGHT", RightChatPanel, "BOTTOMLEFT", -2, -4)
|
||||
helloKittyRight.tex = helloKittyRight:CreateTexture(nil, "OVERLAY")
|
||||
helloKittyRight.tex:SetAllPoints()
|
||||
helloKittyRight.tex:SetTexture(E.Media.Textures.HelloKitty)
|
||||
helloKittyRight.tex:SetTexCoord(0, 0, 0, 1, 0, 0, 0, 1)
|
||||
helloKittyRight.curFrame = 10
|
||||
helloKittyRight.countUp = false
|
||||
helloKittyRight:SetClampedToScreen(true)
|
||||
helloKittyRight:SetScript("OnDragStart", OnDragStart)
|
||||
helloKittyRight:SetScript("OnDragStop", OnDragStop)
|
||||
helloKittyRight:SetScript("OnUpdate", OnUpdate)
|
||||
end
|
||||
|
||||
--When it bugged out for a user the command "/hellokittyfix" attempted to restore the changed settings to default
|
||||
function E:HelloKittyFixCheck(secondCheck)
|
||||
local t = self.db.tempSettings
|
||||
if not t and not secondCheck then t = self.db.general end
|
||||
if t and t.backdropcolor then
|
||||
return self:Round(t.backdropcolor.r, 2) == 0.87 and self:Round(t.backdropcolor.g, 2) == 0.3 and self:Round(t.backdropcolor.b, 2) == 0.74
|
||||
end
|
||||
end
|
||||
|
||||
function E:HelloKittyFix()
|
||||
local c = P.general.backdropcolor
|
||||
self.db.general.backdropcolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
c = P.general.backdropfadecolor
|
||||
self.db.general.backdropfadecolor = {r = c.r, g = c.g, b = c.b, a = (c.a or 0.8)}
|
||||
|
||||
c = P.general.bordercolor
|
||||
self.db.general.bordercolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
c = P.general.valuecolor
|
||||
self.db.general.valuecolor = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
self.db.chat.panelBackdropNameLeft = ""
|
||||
self.db.chat.panelBackdropNameRight = ""
|
||||
|
||||
c = P.unitframe.colors.health
|
||||
self.db.unitframe.colors.health = {r = c.r, g = c.g, b = c.b}
|
||||
|
||||
c = P.unitframe.colors.castColor
|
||||
self.db.unitframe.colors.castColor = {r = c.r, g = c.g, b = c.b}
|
||||
self.db.unitframe.colors.transparentCastbar = false
|
||||
|
||||
c = P.unitframe.colors.castColor
|
||||
self.db.unitframe.colors.auraBarBuff = {r = c.r, g = c.g, b = c.b}
|
||||
self.db.unitframe.colors.transparentAurabars = false
|
||||
|
||||
if HelloKittyLeft then
|
||||
HelloKittyLeft:Hide()
|
||||
HelloKittyRight:Hide()
|
||||
self.db.general.kittys = nil
|
||||
return
|
||||
end
|
||||
|
||||
self.db.tempSettings = nil
|
||||
self:UpdateAll()
|
||||
end
|
||||
|
||||
function E:HelloKittyToggle()
|
||||
if HelloKittyLeft and HelloKittyLeft:IsShown() then
|
||||
self:RestoreHelloKitty()
|
||||
else
|
||||
self:StaticPopup_Show("HELLO_KITTY")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,280 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule("DataTexts")
|
||||
local AB = E:GetModule("ActionBars")
|
||||
|
||||
--Lua functions
|
||||
local tonumber, type = tonumber, type
|
||||
local format, lower, match, split = string.format, string.lower, string.match, string.split
|
||||
--WoW API / Variables
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local UIFrameFadeOut, UIFrameFadeIn = UIFrameFadeOut, UIFrameFadeIn
|
||||
local EnableAddOn, DisableAllAddOns = EnableAddOn, DisableAllAddOns
|
||||
local SetCVar = SetCVar
|
||||
local ReloadUI = ReloadUI
|
||||
local debugprofilestop = debugprofilestop
|
||||
local UpdateAddOnCPUUsage, GetAddOnCPUUsage = UpdateAddOnCPUUsage, GetAddOnCPUUsage
|
||||
local ResetCPUUsage = ResetCPUUsage
|
||||
local GetAddOnInfo = GetAddOnInfo
|
||||
local GetCVarBool = GetCVarBool
|
||||
local ERR_NOT_IN_COMBAT = ERR_NOT_IN_COMBAT
|
||||
|
||||
function E:Grid(msg)
|
||||
msg = msg and tonumber(msg)
|
||||
if type(msg) == "number" and (msg <= 256 and msg >= 4) then
|
||||
E.db.gridSize = msg
|
||||
E:Grid_Show()
|
||||
elseif ElvUIGrid and ElvUIGrid:IsShown() then
|
||||
E:Grid_Hide()
|
||||
else
|
||||
E:Grid_Show()
|
||||
end
|
||||
end
|
||||
|
||||
function E:LuaError(msg)
|
||||
msg = lower(msg)
|
||||
if msg == "on" then
|
||||
DisableAllAddOns()
|
||||
EnableAddOn("ElvUI")
|
||||
EnableAddOn("ElvUI_OptionsUI")
|
||||
SetCVar("scriptErrors", 1)
|
||||
ReloadUI()
|
||||
elseif msg == "off" then
|
||||
SetCVar("scriptErrors", 0)
|
||||
E:Print("Lua errors off.")
|
||||
else
|
||||
E:Print("/luaerror on - /luaerror off")
|
||||
end
|
||||
end
|
||||
|
||||
function E:BGStats()
|
||||
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 (#command == 0) then
|
||||
self:Print("usage: /in <seconds> <command>")
|
||||
self:Print("example: /in 1.5 /say hi")
|
||||
else
|
||||
E:Delay(secs, OnCallback, command)
|
||||
end
|
||||
end
|
||||
|
||||
function FarmMode()
|
||||
if InCombatLockdown() then E:Print(ERR_NOT_IN_COMBAT) return end
|
||||
if not E.private.general.minimap.enable then return end
|
||||
|
||||
if Minimap:IsShown() then
|
||||
UIFrameFadeOut(Minimap, 0.3)
|
||||
UIFrameFadeIn(FarmModeMap, 0.3)
|
||||
Minimap.fadeInfo.finishedFunc = function()
|
||||
Minimap:Hide()
|
||||
FarmModeMap:SetAlpha(1)
|
||||
|
||||
local zoomLevel = Minimap:GetZoom()
|
||||
if zoomLevel < 5 then
|
||||
Minimap:SetZoom(zoomLevel + 1)
|
||||
Minimap:SetZoom(zoomLevel)
|
||||
else
|
||||
Minimap:SetZoom(zoomLevel - 1)
|
||||
Minimap:SetZoom(zoomLevel)
|
||||
end
|
||||
end
|
||||
FarmModeMap.enabled = true
|
||||
else
|
||||
UIFrameFadeOut(FarmModeMap, 0.3)
|
||||
UIFrameFadeIn(Minimap, 0.3)
|
||||
FarmModeMap.fadeInfo.finishedFunc = function()
|
||||
FarmModeMap:Hide()
|
||||
Minimap:SetAlpha(1)
|
||||
|
||||
local zoomLevel = Minimap:GetZoom()
|
||||
if zoomLevel < 5 then
|
||||
Minimap:SetZoom(zoomLevel + 1)
|
||||
Minimap:SetZoom(zoomLevel)
|
||||
else
|
||||
Minimap:SetZoom(zoomLevel - 1)
|
||||
Minimap:SetZoom(zoomLevel)
|
||||
end
|
||||
end
|
||||
FarmModeMap.enabled = false
|
||||
end
|
||||
end
|
||||
|
||||
function E:FarmMode(msg)
|
||||
if not E.private.general.minimap.enable then return end
|
||||
|
||||
if msg and type(tonumber(msg)) == "number" and tonumber(msg) <= 500 and tonumber(msg) >= 20 and not InCombatLockdown() then
|
||||
E.db.farmSize = tonumber(msg)
|
||||
FarmModeMap:Size(tonumber(msg))
|
||||
end
|
||||
|
||||
FarmMode()
|
||||
end
|
||||
|
||||
-- make this a locale later?
|
||||
local MassKickMessage = "Guild Cleanup Results: Removed all guild members below rank %s, that have a minimal level of %s, and have not been online for at least: %s days."
|
||||
function E:MassGuildKick(msg)
|
||||
local minLevel, minDays, minRankIndex = split(",", msg)
|
||||
minRankIndex = tonumber(minRankIndex)
|
||||
minLevel = tonumber(minLevel)
|
||||
minDays = tonumber(minDays)
|
||||
|
||||
if not minLevel or not minDays then
|
||||
E:Print("Usage: /cleanguild <minLevel>, <minDays>, [<minRankIndex>]")
|
||||
return
|
||||
end
|
||||
|
||||
if minDays > 31 then
|
||||
E:Print("Maximum days value must be below 32.")
|
||||
return
|
||||
end
|
||||
|
||||
if not minRankIndex then minRankIndex = GuildControlGetNumRanks() - 1 end
|
||||
|
||||
for i = 1, GetNumGuildMembers() do
|
||||
local name, _, rankIndex, level, _, _, note, officerNote, connected, _, classFileName = GetGuildRosterInfo(i)
|
||||
local minLevelx = minLevel
|
||||
|
||||
if classFileName == "DEATHKNIGHT" then
|
||||
minLevelx = minLevelx + 55
|
||||
end
|
||||
|
||||
if not connected then
|
||||
local years, months, days = GetGuildRosterLastOnline(i)
|
||||
if days ~= nil and ((years > 0 or months > 0 or days >= minDays) and rankIndex >= minRankIndex)
|
||||
and note ~= nil and officerNote ~= nil and (level <= minLevelx) then
|
||||
GuildUninvite(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SendChatMessage(format(MassKickMessage, GuildControlGetRankName(minRankIndex), minLevel, minDays), "GUILD")
|
||||
end
|
||||
|
||||
local num_frames = 0
|
||||
local function OnUpdate()
|
||||
num_frames = num_frames + 1
|
||||
end
|
||||
local f = CreateFrame("Frame")
|
||||
f:Hide()
|
||||
f:SetScript("OnUpdate", OnUpdate)
|
||||
|
||||
local toggleMode, debugTimer, cpuImpactMessage = false, 0, "Consumed %sms per frame. Each frame took %sms to render."
|
||||
function E:GetCPUImpact()
|
||||
if not GetCVarBool("scriptProfile") then
|
||||
E:Print("For `/cpuimpact` to work, you need to enable script profiling via: `/console scriptProfile 1` then reload. Disable after testing by setting it back to 0.")
|
||||
return
|
||||
end
|
||||
|
||||
if not toggleMode then
|
||||
ResetCPUUsage()
|
||||
toggleMode, num_frames, debugTimer = true, 0, debugprofilestop()
|
||||
self:Print("CPU Impact being calculated, type /cpuimpact to get results when you are ready.")
|
||||
f:Show()
|
||||
else
|
||||
f:Hide()
|
||||
local ms_passed = debugprofilestop() - debugTimer
|
||||
UpdateAddOnCPUUsage()
|
||||
|
||||
local per, passed =
|
||||
((num_frames == 0 and 0) or (GetAddOnCPUUsage("ElvUI") / num_frames)),
|
||||
((num_frames == 0 and 0) or (ms_passed / num_frames))
|
||||
self:Print(format(cpuImpactMessage, per and per > 0 and format("%.3f", per) or 0, passed and passed > 0 and format("%.3f", passed) or 0))
|
||||
toggleMode = false
|
||||
end
|
||||
end
|
||||
|
||||
local BLIZZARD_ADDONS = {
|
||||
"Blizzard_AchievementUI",
|
||||
"Blizzard_ArenaUI",
|
||||
"Blizzard_AuctionUI",
|
||||
"Blizzard_BarbershopUI",
|
||||
"Blizzard_BattlefieldMinimap",
|
||||
"Blizzard_BindingUI",
|
||||
"Blizzard_Calendar",
|
||||
"Blizzard_CombatLog",
|
||||
"Blizzard_CombatText",
|
||||
"Blizzard_DebugTools",
|
||||
"Blizzard_GlyphUI",
|
||||
"Blizzard_GMChatUI",
|
||||
"Blizzard_GMSurveyUI",
|
||||
"Blizzard_GuildBankUI",
|
||||
"Blizzard_InspectUI",
|
||||
"Blizzard_ItemSocketingUI",
|
||||
"Blizzard_MacroUI",
|
||||
"Blizzard_RaidUI",
|
||||
"Blizzard_TalentUI",
|
||||
"Blizzard_TimeManager",
|
||||
"Blizzard_TokenUI",
|
||||
"Blizzard_TradeSkillUI",
|
||||
"Blizzard_TrainerUI"
|
||||
}
|
||||
|
||||
function E:EnableBlizzardAddOns()
|
||||
for _, addon in pairs(BLIZZARD_ADDONS) do
|
||||
local reason = select(5, GetAddOnInfo(addon))
|
||||
if reason == "DISABLED" then
|
||||
EnableAddOn(addon)
|
||||
E:Print("The following addon was re-enabled:", addon)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:ChangeRole(role)
|
||||
local roles = {
|
||||
["melee"]="Melee",
|
||||
["caster"]="Caster",
|
||||
["ranged"]="Ranged",
|
||||
["tank"]="Tank",
|
||||
}
|
||||
E.Role = roles[lower(role)] or "Melee"
|
||||
print("Role was changed to:", E.Role)
|
||||
end
|
||||
|
||||
function E:LoadCommands()
|
||||
self:RegisterChatCommand("in", "DelayScriptCall")
|
||||
self:RegisterChatCommand("ec", "ToggleOptionsUI")
|
||||
self:RegisterChatCommand("elvui", "ToggleOptionsUI")
|
||||
self:RegisterChatCommand("cpuimpact", "GetCPUImpact")
|
||||
|
||||
self:RegisterChatCommand("cpuusage", "GetTopCPUFunc")
|
||||
-- args: module, showall, delay, minCalls
|
||||
-- Example1: /cpuusage all
|
||||
-- Example2: /cpuusage Bags true
|
||||
-- Example3: /cpuusage UnitFrames nil 50 25
|
||||
-- Note: showall, delay, and minCalls will default if not set
|
||||
-- arg1 can be "all" this will scan all registered modules!
|
||||
|
||||
self:RegisterChatCommand("bgstats", "BGStats")
|
||||
self:RegisterChatCommand("hellokitty", "HelloKittyToggle")
|
||||
self:RegisterChatCommand("hellokittyfix", "HelloKittyFix")
|
||||
self:RegisterChatCommand("harlemshake", "HarlemShakeToggle")
|
||||
self:RegisterChatCommand("luaerror", "LuaError")
|
||||
self:RegisterChatCommand("egrid", "Grid")
|
||||
self:RegisterChatCommand("moveui", "ToggleMoveMode")
|
||||
self:RegisterChatCommand("resetui", "ResetUI")
|
||||
self:RegisterChatCommand("enable", "EnableAddon")
|
||||
self:RegisterChatCommand("disable", "DisableAddon")
|
||||
self:RegisterChatCommand("farmmode", "FarmMode")
|
||||
self:RegisterChatCommand("cleanguild", "MassGuildKick")
|
||||
self:RegisterChatCommand("estatus", "ShowStatusReport")
|
||||
|
||||
self:RegisterChatCommand("role", "ChangeRole")
|
||||
-- This command is added for Ascension. Role checks will be unreliable, but
|
||||
-- this will allow one to set Role manually.
|
||||
-- /role expects one of "melee", "caster", "ranged", "tank"
|
||||
-- and defaults to "melee" if no role is provided.
|
||||
|
||||
if E.private.actionbar.enable then
|
||||
self:RegisterChatCommand("kb", AB.ActivateBindMode)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,509 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); -- Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local S = E:GetModule("Skins")
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local unpack = unpack
|
||||
local type, ipairs, tonumber = type, ipairs, tonumber
|
||||
local floor, select = floor, select
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local EditBox_ClearFocus = EditBox_ClearFocus
|
||||
local RESET = RESET
|
||||
|
||||
local selectedValue, grid = "ALL"
|
||||
|
||||
E.ConfigModeLayouts = {
|
||||
"ALL",
|
||||
"GENERAL",
|
||||
"SOLO",
|
||||
"PARTY",
|
||||
"ARENA",
|
||||
"RAID",
|
||||
"ACTIONBARS"
|
||||
}
|
||||
|
||||
E.ConfigModeLocalizedStrings = {
|
||||
ALL = ALL,
|
||||
GENERAL = GENERAL,
|
||||
SOLO = SOLO,
|
||||
PARTY = PARTY,
|
||||
ARENA = ARENA,
|
||||
RAID = RAID,
|
||||
ACTIONBARS = ACTIONBARS_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:ToggleMoveMode(override, configType)
|
||||
if InCombatLockdown() then return end
|
||||
if override ~= nil and override ~= "" then E.ConfigurationMode = override end
|
||||
|
||||
if E.ConfigurationMode ~= true then
|
||||
E:Grid_Show()
|
||||
|
||||
if not ElvUIMoverPopupWindow then
|
||||
E:CreateMoverPopup()
|
||||
end
|
||||
|
||||
ElvUIMoverPopupWindow:Show()
|
||||
|
||||
if IsAddOnLoaded("ElvUI_OptionsUI") then
|
||||
if E.Libs.AceConfigDialog then
|
||||
E.Libs.AceConfigDialog:Close("ElvUI")
|
||||
end
|
||||
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
E.ConfigurationMode = true
|
||||
else
|
||||
E:Grid_Hide()
|
||||
|
||||
if ElvUIMoverPopupWindow then
|
||||
ElvUIMoverPopupWindow: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_GetRegion()
|
||||
if grid then
|
||||
if grid.regionCount and grid.regionCount > 0 then
|
||||
local line = select(grid.regionCount, grid:GetRegions())
|
||||
grid.regionCount = grid.regionCount - 1
|
||||
line:SetAlpha(1)
|
||||
return line
|
||||
else
|
||||
return grid:CreateTexture()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:Grid_Create()
|
||||
if not grid then
|
||||
grid = CreateFrame("Frame", "ElvUIGrid", E.UIParent)
|
||||
grid:SetFrameStrata("BACKGROUND")
|
||||
else
|
||||
grid.regionCount = 0
|
||||
local numRegions = grid:GetNumRegions()
|
||||
for i = 1, numRegions do
|
||||
local region = select(i, grid:GetRegions())
|
||||
if region and region.IsObjectType and region:IsObjectType("Texture") then
|
||||
grid.regionCount = grid.regionCount + 1
|
||||
region:SetAlpha(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local size = E.mult
|
||||
local width, height = E.UIParent:GetSize()
|
||||
|
||||
local ratio = width / height
|
||||
local hStepheight = height * ratio
|
||||
local wStep = width / E.db.gridSize
|
||||
local hStep = hStepheight / E.db.gridSize
|
||||
|
||||
grid.boxSize = E.db.gridSize
|
||||
grid:SetPoint("CENTER", E.UIParent)
|
||||
grid:SetSize(width, height)
|
||||
grid:Show()
|
||||
|
||||
for i = 0, E.db.gridSize do
|
||||
local tx = E:Grid_GetRegion()
|
||||
if i == E.db.gridSize / 2 then
|
||||
tx:SetTexture(1, 0, 0)
|
||||
tx:SetDrawLayer("BORDER")
|
||||
else
|
||||
tx:SetTexture(0, 0, 0)
|
||||
tx:SetDrawLayer("BACKGROUND")
|
||||
end
|
||||
tx:ClearAllPoints()
|
||||
tx:Point("TOPLEFT", grid, "TOPLEFT", i*wStep - (size/2), 0)
|
||||
tx:Point("BOTTOMRIGHT", grid, "BOTTOMLEFT", i*wStep + (size/2), 0)
|
||||
end
|
||||
|
||||
do
|
||||
local tx = E:Grid_GetRegion()
|
||||
tx:SetTexture(1, 0, 0)
|
||||
tx:SetDrawLayer("BORDER")
|
||||
tx:ClearAllPoints()
|
||||
tx:Point("TOPLEFT", grid, "TOPLEFT", 0, -(height/2) + (size/2))
|
||||
tx:Point("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2 + size/2))
|
||||
end
|
||||
|
||||
for i = 1, floor((height/2)/hStep) do
|
||||
local tx = E:Grid_GetRegion()
|
||||
tx:SetTexture(0, 0, 0)
|
||||
tx:SetDrawLayer("BACKGROUND")
|
||||
tx:ClearAllPoints()
|
||||
tx:Point("TOPLEFT", grid, "TOPLEFT", 0, -(height/2+i*hStep) + (size/2))
|
||||
tx:Point("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2+i*hStep + size/2))
|
||||
|
||||
tx = E:Grid_GetRegion()
|
||||
tx:SetTexture(0, 0, 0)
|
||||
tx:SetDrawLayer("BACKGROUND")
|
||||
tx:ClearAllPoints()
|
||||
tx:Point("TOPLEFT", grid, "TOPLEFT", 0, -(height/2-i*hStep) + (size/2))
|
||||
tx:Point("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2-i*hStep + size/2))
|
||||
end
|
||||
end
|
||||
|
||||
local function ConfigMode_OnClick(self)
|
||||
selectedValue = self.value
|
||||
E:ToggleMoveMode(false, self.value)
|
||||
UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, self.value)
|
||||
end
|
||||
|
||||
local function ConfigMode_Initialize()
|
||||
local info = _G.UIDropDownMenu_CreateInfo()
|
||||
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:Point(mover.positionOverride or point, E.UIParent, mover.positionOverride and "BOTTOMLEFT" or point, x, y)
|
||||
E:SaveMoverPosition(mover.name)
|
||||
|
||||
--Update coordinates in Nudge Window
|
||||
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)
|
||||
|
||||
local ElvUIMoverNudgeWindow = ElvUIMoverNudgeWindow
|
||||
ElvUIMoverNudgeWindow.xOffset:SetText(x)
|
||||
ElvUIMoverNudgeWindow.yOffset:SetText(y)
|
||||
ElvUIMoverNudgeWindow.xOffset.currentValue = x
|
||||
ElvUIMoverNudgeWindow.yOffset.currentValue = y
|
||||
ElvUIMoverNudgeWindow.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:Width(360)
|
||||
f:Height(195)
|
||||
f:SetTemplate("Transparent")
|
||||
f:Point("BOTTOM", UIParent, "CENTER", 0, 100)
|
||||
f:SetScript("OnHide", function()
|
||||
if ElvUIMoverPopupWindowDropDown then
|
||||
UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, "ALL")
|
||||
end
|
||||
end)
|
||||
f:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
||||
f:CreateShadow(5)
|
||||
f:Hide()
|
||||
|
||||
local header = CreateFrame("Button", nil, f)
|
||||
header:SetTemplate(nil, true)
|
||||
header:Width(100)
|
||||
header:Height(25)
|
||||
header:Point("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)
|
||||
header:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
||||
|
||||
local title = header:CreateFontString("OVERLAY")
|
||||
title:FontTemplate()
|
||||
title:Point("CENTER", header, "CENTER")
|
||||
title:SetText("ElvUI")
|
||||
|
||||
local desc = f:CreateFontString("ARTWORK")
|
||||
desc:SetFontObject("GameFontHighlight")
|
||||
desc:SetJustifyV("TOP")
|
||||
desc:SetJustifyH("LEFT")
|
||||
desc:Point("TOPLEFT", 18, -32)
|
||||
desc:Point("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(cb)
|
||||
cb:SetChecked(E.db.general.stickyFrames)
|
||||
end)
|
||||
|
||||
snapping:SetScript("OnClick", function(cb)
|
||||
E.db.general.stickyFrames = cb:GetChecked()
|
||||
end)
|
||||
|
||||
local lock = CreateFrame("Button", f:GetName().."CloseButton", f, "OptionsButtonTemplate")
|
||||
_G[lock:GetName().."Text"]:SetText(L["Lock"])
|
||||
|
||||
lock:SetScript("OnClick", function()
|
||||
E:ToggleMoveMode(true)
|
||||
|
||||
if IsAddOnLoaded("ElvUI_OptionsUI") and E.Libs.AceConfigDialog then
|
||||
E.Libs.AceConfigDialog:Open("ElvUI")
|
||||
end
|
||||
|
||||
selectedValue = "ALL"
|
||||
UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, selectedValue)
|
||||
end)
|
||||
|
||||
local align = CreateFrame("EditBox", f:GetName().."EditBox", f, "InputBoxTemplate")
|
||||
align:Width(24)
|
||||
align:Height(17)
|
||||
align:SetAutoFocus(false)
|
||||
align:SetScript("OnEscapePressed", function(eb)
|
||||
eb:SetText(E.db.gridSize)
|
||||
EditBox_ClearFocus(eb)
|
||||
end)
|
||||
align:SetScript("OnEnterPressed", function(eb)
|
||||
local text = eb:GetText()
|
||||
if tonumber(text) then
|
||||
if tonumber(text) <= 256 and tonumber(text) >= 4 then
|
||||
E.db.gridSize = tonumber(text)
|
||||
else
|
||||
eb:SetText(E.db.gridSize)
|
||||
end
|
||||
else
|
||||
eb:SetText(E.db.gridSize)
|
||||
end
|
||||
E:Grid_Show()
|
||||
EditBox_ClearFocus(eb)
|
||||
end)
|
||||
align:SetScript("OnEditFocusLost", function(eb)
|
||||
eb:SetText(E.db.gridSize)
|
||||
end)
|
||||
align:SetScript("OnEditFocusGained", align.HighlightText)
|
||||
align:SetScript("OnShow", function(eb)
|
||||
EditBox_ClearFocus(eb)
|
||||
eb:SetText(E.db.gridSize)
|
||||
end)
|
||||
|
||||
align.text = align:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
align.text:Point("RIGHT", align, "LEFT", -4, 0)
|
||||
align.text:SetText(L["Grid Size:"])
|
||||
|
||||
--position buttons
|
||||
snapping:Point("BOTTOMLEFT", 14, 10)
|
||||
lock:Point("BOTTOMRIGHT", -14, 14)
|
||||
align:Point("TOPRIGHT", lock, "TOPLEFT", -4, -2)
|
||||
|
||||
S:HandleCheckBox(snapping)
|
||||
S:HandleButton(lock)
|
||||
S:HandleEditBox(align)
|
||||
|
||||
f:RegisterEvent("PLAYER_REGEN_DISABLED")
|
||||
f:SetScript("OnEvent", function(mover)
|
||||
if mover:IsShown() then
|
||||
mover:Hide()
|
||||
E:Grid_Hide()
|
||||
E:ToggleMoveMode(true)
|
||||
end
|
||||
end)
|
||||
|
||||
local configMode = CreateFrame("Frame", f:GetName().."DropDown", f, "UIDropDownMenuTemplate")
|
||||
configMode:Point("BOTTOMRIGHT", lock, "TOPRIGHT", 8, -5)
|
||||
S:HandleDropDownBox(configMode, 148)
|
||||
configMode.text = configMode:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
configMode.text:Point("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:Width(200)
|
||||
nudgeFrame:Height(110)
|
||||
nudgeFrame:SetTemplate("Transparent")
|
||||
nudgeFrame:CreateShadow(5)
|
||||
nudgeFrame:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
||||
nudgeFrame:SetFrameLevel(100)
|
||||
nudgeFrame:Hide()
|
||||
nudgeFrame:EnableMouse(true)
|
||||
nudgeFrame:SetClampedToScreen(true)
|
||||
|
||||
ElvUIMoverPopupWindow:HookScript("OnHide", function() ElvUIMoverNudgeWindow:Hide() end)
|
||||
|
||||
desc = nudgeFrame:CreateFontString("ARTWORK")
|
||||
desc:SetFontObject("GameFontHighlight")
|
||||
desc:SetJustifyV("TOP")
|
||||
desc:SetJustifyH("LEFT")
|
||||
desc:Point("TOPLEFT", 18, -15)
|
||||
desc:Point("BOTTOMRIGHT", -18, 28)
|
||||
desc:SetJustifyH("CENTER")
|
||||
nudgeFrame.title = desc
|
||||
|
||||
header = CreateFrame("Button", nil, nudgeFrame)
|
||||
header:SetTemplate(nil, true)
|
||||
header:Width(100)
|
||||
header:Height(25)
|
||||
header:Point("CENTER", nudgeFrame, "TOP")
|
||||
header:SetFrameLevel(header:GetFrameLevel() + 2)
|
||||
header:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
||||
|
||||
title = header:CreateFontString("OVERLAY")
|
||||
title:FontTemplate()
|
||||
title:Point("CENTER", header, "CENTER")
|
||||
title:SetText(L["Nudge"])
|
||||
|
||||
local xOffset = CreateFrame("EditBox", nudgeFrame:GetName().."XEditBox", nudgeFrame, "InputBoxTemplate")
|
||||
xOffset:Width(50)
|
||||
xOffset:Height(17)
|
||||
xOffset:SetAutoFocus(false)
|
||||
xOffset.currentValue = 0
|
||||
xOffset:SetScript("OnEscapePressed", function(eb)
|
||||
eb:SetText(E:Round(xOffset.currentValue))
|
||||
EditBox_ClearFocus(eb)
|
||||
end)
|
||||
xOffset:SetScript("OnEnterPressed", function(eb)
|
||||
local num = eb:GetText()
|
||||
if tonumber(num) then
|
||||
local diff = num - xOffset.currentValue
|
||||
xOffset.currentValue = num
|
||||
E:NudgeMover(diff)
|
||||
end
|
||||
eb:SetText(E:Round(xOffset.currentValue))
|
||||
EditBox_ClearFocus(eb)
|
||||
end)
|
||||
xOffset:SetScript("OnEditFocusLost", function(eb)
|
||||
eb:SetText(E:Round(xOffset.currentValue))
|
||||
end)
|
||||
xOffset:SetScript("OnEditFocusGained", xOffset.HighlightText)
|
||||
xOffset:SetScript("OnShow", function(eb)
|
||||
EditBox_ClearFocus(eb)
|
||||
eb:SetText(E:Round(xOffset.currentValue))
|
||||
end)
|
||||
|
||||
xOffset.text = xOffset:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
xOffset.text:Point("RIGHT", xOffset, "LEFT", -4, 0)
|
||||
xOffset.text:SetText("X:")
|
||||
xOffset:Point("BOTTOMRIGHT", nudgeFrame, "CENTER", -6, 8)
|
||||
nudgeFrame.xOffset = xOffset
|
||||
S:HandleEditBox(xOffset)
|
||||
|
||||
local yOffset = CreateFrame("EditBox", nudgeFrame:GetName().."YEditBox", nudgeFrame, "InputBoxTemplate")
|
||||
yOffset:Width(50)
|
||||
yOffset:Height(17)
|
||||
yOffset:SetAutoFocus(false)
|
||||
yOffset.currentValue = 0
|
||||
yOffset:SetScript("OnEscapePressed", function(eb)
|
||||
eb:SetText(E:Round(yOffset.currentValue))
|
||||
EditBox_ClearFocus(eb)
|
||||
end)
|
||||
yOffset:SetScript("OnEnterPressed", function(eb)
|
||||
local num = eb:GetText()
|
||||
if tonumber(num) then
|
||||
local diff = num - yOffset.currentValue
|
||||
yOffset.currentValue = num
|
||||
E:NudgeMover(nil, diff)
|
||||
end
|
||||
eb:SetText(E:Round(yOffset.currentValue))
|
||||
EditBox_ClearFocus(eb)
|
||||
end)
|
||||
yOffset:SetScript("OnEditFocusLost", function(eb)
|
||||
eb:SetText(E:Round(yOffset.currentValue))
|
||||
end)
|
||||
yOffset:SetScript("OnEditFocusGained", yOffset.HighlightText)
|
||||
yOffset:SetScript("OnShow", function(eb)
|
||||
EditBox_ClearFocus(eb)
|
||||
eb:SetText(E:Round(yOffset.currentValue))
|
||||
end)
|
||||
|
||||
yOffset.text = yOffset:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
yOffset.text:Point("RIGHT", yOffset, "LEFT", -4, 0)
|
||||
yOffset.text:SetText("Y:")
|
||||
yOffset:Point("BOTTOMLEFT", nudgeFrame, "CENTER", 16, 8)
|
||||
nudgeFrame.yOffset = yOffset
|
||||
S:HandleEditBox(yOffset)
|
||||
|
||||
local resetButton = CreateFrame("Button", nudgeFrame:GetName().."ResetButton", nudgeFrame, "UIPanelButtonTemplate")
|
||||
resetButton:SetText(RESET)
|
||||
resetButton:Point("TOP", nudgeFrame, "CENTER", 0, 2)
|
||||
resetButton:Size(100, 25)
|
||||
resetButton:SetScript("OnClick", function()
|
||||
if ElvUIMoverNudgeWindow.child.textString then
|
||||
E:ResetMovers(ElvUIMoverNudgeWindow.child.textString)
|
||||
end
|
||||
end)
|
||||
S:HandleButton(resetButton)
|
||||
|
||||
local upButton = CreateFrame("Button", nudgeFrame:GetName().."UpButton", nudgeFrame)
|
||||
upButton:Point("BOTTOMRIGHT", nudgeFrame, "BOTTOM", -6, 4)
|
||||
upButton:SetScript("OnClick", function()
|
||||
E:NudgeMover(nil, 1)
|
||||
end)
|
||||
S:HandleNextPrevButton(upButton)
|
||||
upButton:SetSize(22, 22)
|
||||
|
||||
local downButton = CreateFrame("Button", nudgeFrame:GetName().."DownButton", nudgeFrame)
|
||||
downButton:Point("BOTTOMLEFT", nudgeFrame, "BOTTOM", 6, 4)
|
||||
downButton:SetScript("OnClick", function()
|
||||
E:NudgeMover(nil, -1)
|
||||
end)
|
||||
S:HandleNextPrevButton(downButton)
|
||||
downButton:SetSize(22, 22)
|
||||
|
||||
local leftButton = CreateFrame("Button", nudgeFrame:GetName().."LeftButton", nudgeFrame)
|
||||
leftButton:Point("RIGHT", upButton, "LEFT", -6, 0)
|
||||
leftButton:SetScript("OnClick", function()
|
||||
E:NudgeMover(-1)
|
||||
end)
|
||||
S:HandleNextPrevButton(leftButton)
|
||||
leftButton:SetSize(22, 22)
|
||||
|
||||
local rightButton = CreateFrame("Button", nudgeFrame:GetName().."RightButton", nudgeFrame)
|
||||
rightButton:Point("LEFT", downButton, "RIGHT", 6, 0)
|
||||
rightButton:SetScript("OnClick", function()
|
||||
E:NudgeMover(1)
|
||||
end)
|
||||
S:HandleNextPrevButton(rightButton)
|
||||
rightButton:SetSize(22, 22)
|
||||
end
|
||||
@@ -0,0 +1,320 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
--Lua functions
|
||||
local next, ipairs, pairs = next, ipairs, pairs
|
||||
local floor, tinsert = math.floor, table.insert
|
||||
--WoW API / Variables
|
||||
local GetTime = GetTime
|
||||
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
|
||||
|
||||
function E:Cooldown_TextThreshold(cd, now)
|
||||
if cd.parent and cd.parent.textThreshold and cd.endTime then
|
||||
return (cd.endTime - now) >= cd.parent.textThreshold
|
||||
end
|
||||
end
|
||||
|
||||
function E:Cooldown_BelowScale(cd)
|
||||
if cd.parent then
|
||||
if cd.parent.hideText then return true end
|
||||
if cd.parent.skipScale then return end
|
||||
end
|
||||
|
||||
return cd.fontScale and (cd.fontScale < MIN_SCALE)
|
||||
end
|
||||
|
||||
function E:Cooldown_OnUpdate(elapsed)
|
||||
if self.nextUpdate > 0 then
|
||||
self.nextUpdate = self.nextUpdate - elapsed
|
||||
return
|
||||
end
|
||||
|
||||
if not E:Cooldown_IsEnabled(self) then
|
||||
E:Cooldown_StopTimer(self)
|
||||
else
|
||||
local now = GetTime()
|
||||
if self.endCooldown and now >= self.endCooldown then
|
||||
E:Cooldown_StopTimer(self)
|
||||
else
|
||||
if E:Cooldown_BelowScale(self) then
|
||||
self.text:SetText("")
|
||||
self.nextUpdate = 500
|
||||
elseif E:Cooldown_TextThreshold(self, now) then
|
||||
self.text:SetText("")
|
||||
self.nextUpdate = 1
|
||||
elseif self.endTime then
|
||||
local value, id, nextUpdate, remainder = E:GetTimeInfo(self.endTime - now, self.threshold, self.hhmmThreshold, self.mmssThreshold)
|
||||
self.nextUpdate = nextUpdate
|
||||
|
||||
local style = E.TimeFormats[id]
|
||||
if style then
|
||||
local which = (self.textColors and 2 or 1) + (self.showSeconds and 0 or 2)
|
||||
if self.textColors then
|
||||
self.text:SetFormattedText(style[which], value, self.textColors[id], remainder)
|
||||
else
|
||||
self.text:SetFormattedText(style[which], value, remainder)
|
||||
end
|
||||
end
|
||||
|
||||
local color = self.timeColors[id]
|
||||
if color then
|
||||
self.text:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:Cooldown_OnSizeChanged(cd, width, force)
|
||||
local scale = width and (floor(width + 0.5) / ICON_SIZE)
|
||||
|
||||
-- dont bother updating when the fontScale is the same, unless we are passing the force arg
|
||||
if scale and (scale == cd.fontScale) and (force ~= true) then return end
|
||||
cd.fontScale = scale
|
||||
|
||||
-- this is needed because of skipScale variable, we wont allow a font size under the minscale
|
||||
if cd.fontScale and (cd.fontScale < MIN_SCALE) then
|
||||
scale = MIN_SCALE
|
||||
end
|
||||
|
||||
if cd.customFont then -- override font
|
||||
cd.text:FontTemplate(cd.customFont, (scale * cd.customFontSize), cd.customFontOutline)
|
||||
elseif scale then -- default, no override
|
||||
cd.text:FontTemplate(nil, (scale * FONT_SIZE), "OUTLINE")
|
||||
else -- this should never happen but just incase
|
||||
cd.text:FontTemplate()
|
||||
end
|
||||
|
||||
if E:Cooldown_BelowScale(cd) then
|
||||
cd:Hide()
|
||||
elseif cd.enabled then
|
||||
self:Cooldown_ForceUpdate(cd)
|
||||
end
|
||||
end
|
||||
|
||||
function E:Cooldown_IsEnabled(cd)
|
||||
if cd.forceEnabled then
|
||||
return true
|
||||
elseif cd.forceDisabled then
|
||||
return false
|
||||
elseif cd.reverseToggle ~= nil then
|
||||
return cd.reverseToggle
|
||||
else
|
||||
return E.db.cooldown.enable
|
||||
end
|
||||
end
|
||||
|
||||
function E:Cooldown_ForceUpdate(cd)
|
||||
cd.nextUpdate = -1
|
||||
cd:Show()
|
||||
end
|
||||
|
||||
function E:Cooldown_StopTimer(cd)
|
||||
cd.enabled = nil
|
||||
cd:Hide()
|
||||
end
|
||||
|
||||
function E:Cooldown_Options(timer, db, parent)
|
||||
local threshold, colors, icolors, hhmm, mmss, fonts
|
||||
if parent and db.override then
|
||||
threshold = db.threshold
|
||||
icolors = db.useIndicatorColor and E.TimeIndicatorColors[parent.CooldownOverride]
|
||||
colors = E.TimeColors[parent.CooldownOverride]
|
||||
end
|
||||
|
||||
if db.checkSeconds then
|
||||
hhmm, mmss = db.hhmmThreshold, db.mmssThreshold
|
||||
end
|
||||
|
||||
timer.timeColors = colors or E.TimeColors
|
||||
timer.threshold = threshold or E.db.cooldown.threshold or E.TimeThreshold
|
||||
timer.textColors = icolors or (E.db.cooldown.useIndicatorColor and E.TimeIndicatorColors)
|
||||
timer.hhmmThreshold = hhmm or (E.db.cooldown.checkSeconds and E.db.cooldown.hhmmThreshold)
|
||||
timer.mmssThreshold = mmss or (E.db.cooldown.checkSeconds and E.db.cooldown.mmssThreshold)
|
||||
|
||||
if db.reverse ~= nil then
|
||||
timer.reverseToggle = (E.db.cooldown.enable and not db.reverse) or (db.reverse and not E.db.cooldown.enable)
|
||||
else
|
||||
timer.reverseToggle = nil
|
||||
end
|
||||
|
||||
if timer.CooldownOverride ~= "auras" then
|
||||
if (db ~= E.db.cooldown) and db.fonts and db.fonts.enable then
|
||||
fonts = db.fonts -- custom fonts override default fonts
|
||||
elseif E.db.cooldown.fonts and E.db.cooldown.fonts.enable then
|
||||
fonts = E.db.cooldown.fonts -- default global font override
|
||||
end
|
||||
|
||||
if fonts and fonts.enable then
|
||||
timer.customFont = E.Libs.LSM:Fetch("font", fonts.font)
|
||||
timer.customFontSize = fonts.fontSize
|
||||
timer.customFontOutline = fonts.fontOutline
|
||||
else
|
||||
timer.customFont = nil
|
||||
timer.customFontSize = nil
|
||||
timer.customFontOutline = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:CreateCooldownTimer(parent)
|
||||
local timer = CreateFrame("Frame", parent:GetName() and "$parentTimer" or nil, parent)
|
||||
timer:SetFrameLevel(parent:GetFrameLevel() + 1)
|
||||
timer:Hide()
|
||||
timer:SetAllPoints()
|
||||
timer.parent = parent
|
||||
parent.timer = timer
|
||||
|
||||
local text = timer:CreateFontString(nil, "OVERLAY")
|
||||
text:Point("CENTER", 1, 1)
|
||||
text:SetJustifyH("CENTER")
|
||||
timer.text = text
|
||||
|
||||
-- can be used to modify elements created from this function
|
||||
if parent.CooldownPreHook then
|
||||
parent.CooldownPreHook(parent)
|
||||
end
|
||||
|
||||
-- cooldown override settings
|
||||
local db = (parent.CooldownOverride and E.db[parent.CooldownOverride]) or E.db
|
||||
if db and db.cooldown then
|
||||
E:Cooldown_Options(timer, db.cooldown, parent)
|
||||
end
|
||||
|
||||
-- keep an eye on the size so we can rescale the font if needed
|
||||
self:Cooldown_OnSizeChanged(timer, parent:GetWidth())
|
||||
parent:SetScript("OnSizeChanged", function(_, width)
|
||||
self:Cooldown_OnSizeChanged(timer, width)
|
||||
end)
|
||||
|
||||
-- keep this after Cooldown_OnSizeChanged
|
||||
timer:SetScript("OnUpdate", E.Cooldown_OnUpdate)
|
||||
|
||||
return timer
|
||||
end
|
||||
|
||||
E.RegisteredCooldowns = {}
|
||||
function E:OnSetCooldown(start, duration)
|
||||
if (not self.forceDisabled) and (start and duration) and (duration > MIN_DURATION) then
|
||||
local timer = self.timer or E:CreateCooldownTimer(self)
|
||||
timer.start = start
|
||||
timer.duration = duration
|
||||
timer.endTime = start + duration
|
||||
timer.endCooldown = timer.endTime - 0.05
|
||||
timer.nextUpdate = -1
|
||||
timer:Show()
|
||||
elseif self.timer then
|
||||
E:Cooldown_StopTimer(self.timer)
|
||||
end
|
||||
end
|
||||
|
||||
function E:RegisterCooldown(cooldown)
|
||||
if not cooldown.isHooked then
|
||||
hooksecurefunc(cooldown, "SetCooldown", E.OnSetCooldown)
|
||||
cooldown.isHooked = true
|
||||
end
|
||||
|
||||
if not cooldown.isRegisteredCooldown then
|
||||
local module = (cooldown.CooldownOverride or "global")
|
||||
if not E.RegisteredCooldowns[module] then E.RegisteredCooldowns[module] = {} end
|
||||
|
||||
tinsert(E.RegisteredCooldowns[module], cooldown)
|
||||
cooldown.isRegisteredCooldown = true
|
||||
end
|
||||
end
|
||||
|
||||
function E:GetCooldownColors(db)
|
||||
if not db then db = E.db.cooldown end -- just incase someone calls this without a first arg use the global
|
||||
local c13 = E:RGBToHex(db.hhmmColorIndicator.r, db.hhmmColorIndicator.g, db.hhmmColorIndicator.b) -- color for timers that are soon to expire
|
||||
local c12 = E:RGBToHex(db.mmssColorIndicator.r, db.mmssColorIndicator.g, db.mmssColorIndicator.b) -- color for timers that are soon to expire
|
||||
local c11 = E:RGBToHex(db.expireIndicator.r, db.expireIndicator.g, db.expireIndicator.b) -- color for timers that are soon to expire
|
||||
local c10 = E:RGBToHex(db.secondsIndicator.r, db.secondsIndicator.g, db.secondsIndicator.b) -- color for timers that have seconds remaining
|
||||
local c9 = E:RGBToHex(db.minutesIndicator.r, db.minutesIndicator.g, db.minutesIndicator.b) -- color for timers that have minutes remaining
|
||||
local c8 = E:RGBToHex(db.hoursIndicator.r, db.hoursIndicator.g, db.hoursIndicator.b) -- color for timers that have hours remaining
|
||||
local c7 = E:RGBToHex(db.daysIndicator.r, db.daysIndicator.g, db.daysIndicator.b) -- color for timers that have days remaining
|
||||
local c6 = db.hhmmColor -- HH:MM color
|
||||
local c5 = db.mmssColor -- MM:SS color
|
||||
local c4 = db.expiringColor -- color for timers that are soon to expire
|
||||
local c3 = db.secondsColor -- color for timers that have seconds remaining
|
||||
local c2 = db.minutesColor -- color for timers that have minutes remaining
|
||||
local c1 = db.hoursColor -- color for timers that have hours remaining
|
||||
local c0 = db.daysColor -- color for timers that have days remaining
|
||||
return c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13
|
||||
end
|
||||
|
||||
function E:UpdateCooldownOverride(module)
|
||||
local cooldowns = (module and E.RegisteredCooldowns[module])
|
||||
if (not cooldowns) or not next(cooldowns) then return end
|
||||
|
||||
for _, parent in ipairs(cooldowns) do
|
||||
local db = (parent.CooldownOverride and E.db[parent.CooldownOverride]) or self.db
|
||||
if db and db.cooldown then
|
||||
local timer = parent.isHooked and parent.isRegisteredCooldown and parent.timer
|
||||
local cd = timer or parent
|
||||
|
||||
-- cooldown override settings
|
||||
E:Cooldown_Options(cd, db.cooldown, parent)
|
||||
|
||||
-- update font on cooldowns
|
||||
if timer and cd then -- has a parent, these are timers from RegisterCooldown
|
||||
self:Cooldown_OnSizeChanged(cd, parent:GetWidth(), true)
|
||||
|
||||
elseif cd.text then
|
||||
if cd.customFont then
|
||||
cd.text:FontTemplate(cd.customFont, cd.customFontSize, cd.customFontOutline)
|
||||
elseif parent.CooldownOverride == "auras" then
|
||||
-- parent.auraType defined in `A:UpdateHeader` and `A:CreateIcon`
|
||||
local font = E.Libs.LSM:Fetch("font", db.font)
|
||||
if font and parent.auraType then
|
||||
local fontSize = db[parent.auraType] and db[parent.auraType].durationFontSize
|
||||
if fontSize then
|
||||
cd.text:FontTemplate(font, fontSize, db.fontOutline)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- force update top aura cooldowns
|
||||
if parent.CooldownOverride == "auras" then
|
||||
parent.nextUpdate = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:UpdateCooldownSettings(module)
|
||||
local db, timeColors, textColors = E.db.cooldown, E.TimeColors, E.TimeIndicatorColors
|
||||
|
||||
-- update the module timecolors if the config called it but ignore "global" and "all":
|
||||
-- global is the main call from config, all is the core file calls
|
||||
local isModule = module and (module ~= "global" and module ~= "all") and self.db[module] and self.db[module].cooldown
|
||||
if isModule then
|
||||
if not E.TimeColors[module] then E.TimeColors[module] = {} end
|
||||
if not E.TimeIndicatorColors[module] then E.TimeIndicatorColors[module] = {} end
|
||||
db, timeColors, textColors = self.db[module].cooldown, E.TimeColors[module], E.TimeIndicatorColors[module]
|
||||
end
|
||||
|
||||
timeColors[0], timeColors[1], timeColors[2], timeColors[3], timeColors[4], timeColors[5], timeColors[6], textColors[0], textColors[1], textColors[2], textColors[3], textColors[4], textColors[5], textColors[6] = self:GetCooldownColors(db)
|
||||
|
||||
if isModule then
|
||||
E:UpdateCooldownOverride(module)
|
||||
elseif module == "global" then -- this is only a call from the config change
|
||||
for key in pairs(E.RegisteredCooldowns) do
|
||||
E:UpdateCooldownOverride(key)
|
||||
end
|
||||
end
|
||||
|
||||
-- okay update the other override settings if it was one of the core file calls
|
||||
if module and (module == "all") then
|
||||
E:UpdateCooldownSettings("bags")
|
||||
E:UpdateCooldownSettings("nameplates")
|
||||
E:UpdateCooldownSettings("actionbar")
|
||||
E:UpdateCooldownSettings("unitframe")
|
||||
E:UpdateCooldownSettings("auras")
|
||||
end
|
||||
end
|
||||
+1211
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,602 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local D = E:GetModule("Distributor")
|
||||
local LibCompress = E.Libs.Compress
|
||||
local LibBase64 = E.Libs.Base64
|
||||
|
||||
--Lua functions
|
||||
local loadstring = loadstring
|
||||
local pcall = pcall
|
||||
local setfenv = setfenv
|
||||
local tonumber = tonumber
|
||||
local type = type
|
||||
local format, gsub, len, split, sub = string.format, string.gsub, string.len, string.split, string.sub
|
||||
--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"
|
||||
|
||||
local ACECOMMPREFIXES = {
|
||||
[TRANSFER_PREFIX.."\001"] = true,
|
||||
[TRANSFER_PREFIX.."\002"] = true,
|
||||
[TRANSFER_PREFIX.."\003"] = true,
|
||||
}
|
||||
|
||||
-- The active downloads
|
||||
local Downloads = {}
|
||||
local Uploads = {}
|
||||
|
||||
function D:Initialize()
|
||||
self.Initialized = true
|
||||
self:RegisterComm(REQUEST_PREFIX)
|
||||
self:RegisterEvent("CHAT_MSG_ADDON")
|
||||
|
||||
self.statusBar = CreateFrame("StatusBar", "ElvUI_Download", E.UIParent)
|
||||
E:RegisterStatusBar(self.statusBar)
|
||||
self.statusBar:CreateBackdrop("Default")
|
||||
self.statusBar:SetStatusBarTexture(E.media.normTex)
|
||||
self.statusBar:SetStatusBarColor(0.95, 0.15, 0.15)
|
||||
self.statusBar:Size(250, 18)
|
||||
self.statusBar.text = self.statusBar:CreateFontString(nil, "OVERLAY")
|
||||
self.statusBar.text:FontTemplate()
|
||||
self.statusBar.text:Point("CENTER")
|
||||
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
|
||||
|
||||
data = E:RemoveTableDuplicates(data, isGlobal and G or P)
|
||||
|
||||
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(_, prefix, message, _, sender)
|
||||
if not ACECOMMPREFIXES[prefix] or 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:UpdateSendProgress(sentBytes, totalBytes)
|
||||
self.statusBar:SetValue(sentBytes)
|
||||
|
||||
if sentBytes == totalBytes then
|
||||
E:StaticPopupSpecial_Hide(self.statusBar)
|
||||
end
|
||||
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.statusBar:SetMinMaxValues(0, len(Uploads[profileKey].serialData))
|
||||
self.statusBar:SetValue(0)
|
||||
self.statusBar.text:SetFormattedText(L["Data To: %s"], sender)
|
||||
E:StaticPopupSpecial_Show(self.statusBar)
|
||||
|
||||
self:RegisterComm(TRANSFER_COMPLETE_PREFIX)
|
||||
self:SendCommMessage(TRANSFER_PREFIX, Uploads[profileKey].serialData, dist, Uploads[profileKey].target, "BULK", self.UpdateSendProgress, self)
|
||||
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(popup)
|
||||
ElvDB.profiles[popup.editBox:GetText()] = data
|
||||
E.Libs.AceAddon:GetAddon("ElvUI").data:SetProfile(popup.editBox:GetText())
|
||||
E:UpdateAll(true)
|
||||
Downloads[sender] = nil
|
||||
E:StaticPopup_Show("CONFIG_RL")
|
||||
end,
|
||||
OnShow = function(popup) popup.editBox:SetText(profileKey) popup.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
|
||||
E.Libs.AceAddon: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
|
||||
|
||||
--Keys that should not be exported
|
||||
local blacklistedKeys = {
|
||||
profile = {
|
||||
general = {
|
||||
numberPrefixStyle = true,
|
||||
}
|
||||
},
|
||||
private = {},
|
||||
global = {
|
||||
general = {
|
||||
UIScale = true,
|
||||
locale = true,
|
||||
eyefinity = true,
|
||||
ignoreScalePopup = true
|
||||
},
|
||||
chat = {
|
||||
classColorMentionExcludedNames = true
|
||||
},
|
||||
unitframe = {
|
||||
spellRangeCheck = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
--Copy current profile data
|
||||
profileData = E:CopyTable(profileData, ElvDB.profiles[profileKey])
|
||||
--This table will also hold all default values, not just the changed settings.
|
||||
--This makes the table huge, and will cause the WoW client to lock up for several seconds.
|
||||
--We compare against the default table and remove all duplicates from our table. The table is now much smaller.
|
||||
profileData = E:RemoveTableDuplicates(profileData, P)
|
||||
profileData = E:FilterTableFromBlacklist(profileData, blacklistedKeys.profile)
|
||||
elseif profileType == "private" then
|
||||
local privateProfileKey = E.myname.." - "..E.myrealm
|
||||
profileKey = "private"
|
||||
|
||||
profileData = E:CopyTable(profileData, ElvPrivateDB.profiles[privateProfileKey])
|
||||
profileData = E:RemoveTableDuplicates(profileData, V)
|
||||
profileData = E:FilterTableFromBlacklist(profileData, blacklistedKeys.private)
|
||||
elseif profileType == "global" then
|
||||
profileKey = "global"
|
||||
|
||||
profileData = E:CopyTable(profileData, ElvDB.global)
|
||||
profileData = E:RemoveTableDuplicates(profileData, G)
|
||||
profileData = E:FilterTableFromBlacklist(profileData, blacklistedKeys.global)
|
||||
elseif profileType == "filters" then
|
||||
profileKey = "filters"
|
||||
|
||||
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 == "styleFilters" then
|
||||
profileKey = "styleFilters"
|
||||
|
||||
profileData.nameplates = {}
|
||||
profileData.nameplates.filters = {}
|
||||
profileData.nameplates.filters = E:CopyTable(profileData.nameplates.filters, ElvDB.global.nameplates.filters)
|
||||
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 sub(dataString, 1, 1) == "{" then --Basic check to weed out obviously wrong strings
|
||||
stringType = "Table"
|
||||
end
|
||||
|
||||
return stringType
|
||||
end
|
||||
|
||||
function D:Decode(dataString)
|
||||
local profileInfo, profileType, profileKey, profileData
|
||||
local stringType = self:GetImportStringType(dataString)
|
||||
|
||||
if stringType == "Base64" then
|
||||
local decodedData = LibBase64:Decode(dataString)
|
||||
local decompressedData, decompressedMessage = LibCompress:Decompress(decodedData)
|
||||
|
||||
if not decompressedData then
|
||||
E:Print("Error decompressing data:", decompressedMessage)
|
||||
return
|
||||
end
|
||||
|
||||
local serializedData, success
|
||||
serializedData, profileInfo = E:SplitString(decompressedData, "^^::") -- "^^" indicates the end of the AceSerializer string
|
||||
|
||||
if not profileInfo then
|
||||
E:Print("Error importing profile. String is invalid or corrupted!")
|
||||
return
|
||||
end
|
||||
|
||||
serializedData = format("%s%s", serializedData, "^^") --Add back the AceSerializer terminator
|
||||
profileType, profileKey = E:SplitString(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:SplitString(dataString, "}::") -- "}::" indicates the end of the table
|
||||
|
||||
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, "}") --Add back the missing "}"
|
||||
profileDataAsString = gsub(profileDataAsString, "\124\124", "\124") --Remove escape pipe characters
|
||||
profileType, profileKey = E:SplitString(profileInfo, "::")
|
||||
|
||||
local func, err = loadstring(format("%s %s", "return", profileDataAsString))
|
||||
|
||||
if func then
|
||||
setfenv(func, {}) -- execute code in an empty environment
|
||||
local success, res = pcall(func)
|
||||
|
||||
if success then
|
||||
profileData = res
|
||||
else
|
||||
err = res
|
||||
end
|
||||
end
|
||||
|
||||
if err then
|
||||
E:Print("Error converting lua string to table:", err)
|
||||
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
|
||||
profileData = E:FilterTableFromBlacklist(profileData, blacklistedKeys.profile) --Remove unwanted options from import
|
||||
if not ElvDB.profiles[profileKey] or force then
|
||||
if force and E.data.keys.profile == profileKey then
|
||||
--Overwriting an active profile doesn't update when calling SetProfile
|
||||
--So make it look like we use a different profile
|
||||
local tempKey = profileKey.."_Temp"
|
||||
E.data.keys.profile = tempKey
|
||||
end
|
||||
ElvDB.profiles[profileKey] = profileData
|
||||
--Calling SetProfile will now update all settings correctly
|
||||
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
|
||||
profileData = E:FilterTableFromBlacklist(profileData, blacklistedKeys.private) --Remove unwanted options from import
|
||||
local pfKey = ElvPrivateDB.profileKeys[E.myname.." - "..E.myrealm]
|
||||
ElvPrivateDB.profiles[pfKey] = profileData
|
||||
E:StaticPopup_Show("IMPORT_RL")
|
||||
elseif profileType == "global" then
|
||||
profileData = E:FilterTableFromBlacklist(profileData, blacklistedKeys.global) --Remove unwanted options from import
|
||||
E:CopyTable(ElvDB.global, profileData)
|
||||
E:StaticPopup_Show("IMPORT_RL")
|
||||
elseif profileType == "filters" then
|
||||
E:CopyTable(ElvDB.global.unitframe, profileData.unitframe)
|
||||
elseif profileType == "styleFilters" then
|
||||
E:CopyTable(ElvDB.global.nameplates, profileData.nameplates)
|
||||
end
|
||||
|
||||
--Update all ElvUI modules
|
||||
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)
|
||||
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(self) self.editBox:SetText(D.profileKey) self.editBox:SetFocus() end,
|
||||
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,
|
||||
whileDead = 1,
|
||||
hideOnEscape = false,
|
||||
preferredIndex = 3
|
||||
}
|
||||
|
||||
local function InitializeCallback()
|
||||
D:Initialize()
|
||||
end
|
||||
|
||||
E:RegisterModule(D:GetName(), InitializeCallback)
|
||||
@@ -0,0 +1,88 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
--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, #frame.buttons do
|
||||
frame.buttons[i]:Hide()
|
||||
end
|
||||
|
||||
for i = 1, #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]:Height(BUTTON_HEIGHT)
|
||||
frame.buttons[i]:Width(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]:Point("TOPLEFT", frame, "TOPLEFT", PADDING, -PADDING)
|
||||
else
|
||||
frame.buttons[i]:Point("TOPLEFT", frame.buttons[i-1], "BOTTOMLEFT")
|
||||
end
|
||||
end
|
||||
|
||||
frame:Height((#list * BUTTON_HEIGHT) + PADDING * 2)
|
||||
frame:Width(BUTTON_WIDTH + PADDING * 2)
|
||||
|
||||
local UIScale = UIParent:GetScale()
|
||||
local x, y = GetCursorPosition()
|
||||
x = x/UIScale
|
||||
y = y/UIScale
|
||||
frame:ClearAllPoints()
|
||||
frame:Point("TOPLEFT", UIParent, "BOTTOMLEFT", x + xOffset, y + yOffset)
|
||||
|
||||
ToggleFrame(frame)
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
--Lua functions
|
||||
--WoW API / Variables
|
||||
local SetCVar = SetCVar
|
||||
|
||||
local function SetFont(obj, font, size, style, sr, sg, sb, sa, sox, soy, r, g, b)
|
||||
if not obj then return end
|
||||
|
||||
obj:SetFont(font, size, style)
|
||||
if sr and sg and sb then obj:SetShadowColor(sr, sg, sb, sa) 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 NUMBER = self.media.normFont
|
||||
local COMBAT = LSM:Fetch("font", self.private.general.dmgfont)
|
||||
local NAMEFONT = LSM:Fetch("font", self.private.general.namefont)
|
||||
local MONOCHROME = ""
|
||||
|
||||
UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = 12
|
||||
CHAT_FONT_HEIGHTS = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
|
||||
|
||||
if self.db.general.font == "Homespun" then
|
||||
MONOCHROME = "MONOCHROME"
|
||||
end
|
||||
|
||||
if self.eyefinity then
|
||||
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
|
||||
COMBAT = E.Media.Fonts.Invisible
|
||||
end
|
||||
|
||||
UNIT_NAME_FONT = NAMEFONT
|
||||
NAMEPLATE_FONT = NAMEFONT
|
||||
DAMAGE_TEXT_FONT = COMBAT
|
||||
STANDARD_TEXT_FONT = NORMAL
|
||||
|
||||
if self.private.general.replaceBlizzFonts then
|
||||
SetFont(GameTooltipHeader, NORMAL, self.db.general.fontSize)
|
||||
SetFont(NumberFont_OutlineThick_Mono_Small, NUMBER, self.db.general.fontSize, "OUTLINE")
|
||||
SetFont(NumberFont_Outline_Huge, NUMBER, 28, MONOCHROME.."THICKOUTLINE", 28)
|
||||
SetFont(NumberFont_Outline_Large, NUMBER, 15, MONOCHROME.."OUTLINE")
|
||||
SetFont(NumberFont_Outline_Med, NUMBER, self.db.general.fontSize, "OUTLINE")
|
||||
SetFont(NumberFont_Shadow_Med, NORMAL, self.db.general.fontSize)
|
||||
SetFont(NumberFont_Shadow_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(ChatFontSmall, NORMAL, self.db.general.fontSize)
|
||||
SetFont(QuestFontHighlight, NORMAL, self.db.general.fontSize)
|
||||
SetFont(QuestFont, NORMAL, self.db.general.fontSize)
|
||||
SetFont(QuestFont_Large, NORMAL, 14)
|
||||
SetFont(QuestTitleFont, NORMAL, self.db.general.fontSize + 8)
|
||||
SetFont(QuestTitleFontBlackShadow, NORMAL, self.db.general.fontSize + 8)
|
||||
SetFont(SystemFont_Large, NORMAL, 15)
|
||||
SetFont(GameFontNormalMed3, NORMAL, 15)
|
||||
SetFont(SystemFont_Shadow_Huge1, NORMAL, 20, MONOCHROME.."OUTLINE")
|
||||
SetFont(SystemFont_Med1, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SystemFont_Med3, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SystemFont_OutlineThick_Huge2, NORMAL, 20, MONOCHROME.."THICKOUTLINE")
|
||||
SetFont(SystemFont_Outline_Small, NUMBER, self.db.general.fontSize, "OUTLINE")
|
||||
SetFont(SystemFont_Shadow_Large, NORMAL, 15)
|
||||
SetFont(SystemFont_Shadow_Med1, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SystemFont_Shadow_Med3, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SystemFont_Shadow_Outline_Huge2, NORMAL, 20, MONOCHROME.."OUTLINE")
|
||||
SetFont(SystemFont_Shadow_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SystemFont_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SystemFont_Tiny, NORMAL, self.db.general.fontSize)
|
||||
SetFont(Tooltip_Med, NORMAL, self.db.general.fontSize)
|
||||
SetFont(Tooltip_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(FriendsFont_Normal, NORMAL, self.db.general.fontSize)
|
||||
SetFont(FriendsFont_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(FriendsFont_Large, NORMAL, self.db.general.fontSize)
|
||||
SetFont(FriendsFont_UserText, NORMAL, self.db.general.fontSize)
|
||||
SetFont(SpellFont_Small, NORMAL, self.db.general.fontSize*0.9)
|
||||
SetFont(ZoneTextString, NORMAL, 32, MONOCHROME.."OUTLINE")
|
||||
SetFont(SubZoneTextString, NORMAL, 25, MONOCHROME.."OUTLINE")
|
||||
SetFont(PVPInfoTextString, NORMAL, 22, MONOCHROME.."OUTLINE")
|
||||
SetFont(PVPArenaTextString, NORMAL, 22, MONOCHROME.."OUTLINE")
|
||||
SetFont(CombatTextFont, COMBAT, 100, MONOCHROME.."OUTLINE")
|
||||
SetFont(SystemFont_OutlineThick_WTF, NORMAL, 32, MONOCHROME.."OUTLINE")
|
||||
SetFont(SubZoneTextFont, NORMAL, 24, MONOCHROME.."OUTLINE")
|
||||
SetFont(MailFont_Large, NORMAL, 14)
|
||||
SetFont(InvoiceFont_Med, NORMAL, 12)
|
||||
SetFont(InvoiceFont_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(AchievementFont_Small, NORMAL, self.db.general.fontSize)
|
||||
SetFont(ReputationDetailFont, NORMAL, self.db.general.fontSize)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,936 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local UF = E:GetModule("UnitFrames")
|
||||
local S = E:GetModule("Skins")
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local format = format
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
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 ToggleChatColorNamesByClassGroup = ToggleChatColorNamesByClassGroup
|
||||
local FCF_ResetChatWindows = FCF_ResetChatWindows
|
||||
local FCF_SetLocked = FCF_SetLocked
|
||||
local FCF_DockFrame, FCF_UnDockFrame = FCF_DockFrame, FCF_UnDockFrame
|
||||
local FCF_OpenNewWindow = FCF_OpenNewWindow
|
||||
local FCF_SavePositionAndDimensions = FCF_SavePositionAndDimensions
|
||||
local FCF_SetWindowName = FCF_SetWindowName
|
||||
local FCF_StopDragging = FCF_StopDragging
|
||||
local FCF_SetChatWindowFontSize = FCF_SetChatWindowFontSize
|
||||
local CLASS, CONTINUE, PREVIOUS = CLASS, CONTINUE, PREVIOUS
|
||||
local NUM_CHAT_WINDOWS = NUM_CHAT_WINDOWS
|
||||
local LOOT, GENERAL, TRADE, GUILD, WHISPER = LOOT, GENERAL, TRADE, GUILD, WHISPER
|
||||
local GUILD_EVENT_LOG = GUILD_EVENT_LOG
|
||||
|
||||
local CURRENT_PAGE = 0
|
||||
local MAX_PAGE = 8
|
||||
|
||||
local function SetupChat(noDisplayMsg)
|
||||
FCF_ResetChatWindows() -- Monitor this
|
||||
FCF_SetLocked(ChatFrame1, 1)
|
||||
FCF_DockFrame(ChatFrame2)
|
||||
FCF_SetLocked(ChatFrame2, 1)
|
||||
|
||||
FCF_OpenNewWindow(LOOT)
|
||||
FCF_UnDockFrame(ChatFrame3)
|
||||
FCF_SetLocked(ChatFrame3, 1)
|
||||
ChatFrame3:Show()
|
||||
|
||||
FCF_OpenNewWindow(GUILD)
|
||||
FCF_OpenNewWindow(WHISPER)
|
||||
FCF_DockFrame(ChatFrame4)
|
||||
FCF_SetLocked(ChatFrame4, 1)
|
||||
FCF_DockFrame(ChatFrame5)
|
||||
FCF_SetLocked(ChatFrame5, 1)
|
||||
|
||||
FCF_SelectDockFrame(ChatFrame1)
|
||||
|
||||
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:Point("BOTTOMLEFT", LeftChatToggleButton, "TOPLEFT", 1, 3)
|
||||
elseif i == 3 then
|
||||
frame:ClearAllPoints()
|
||||
frame:Point("BOTTOMLEFT", RightChatDataPanel, "TOPLEFT", 1, 3)
|
||||
end
|
||||
|
||||
FCF_SavePositionAndDimensions(frame)
|
||||
FCF_StopDragging(frame)
|
||||
|
||||
-- set default Elvui font size
|
||||
FCF_SetChatWindowFontSize(nil, 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)
|
||||
elseif i == 4 then
|
||||
FCF_SetWindowName(frame, GUILD)
|
||||
elseif i == 5 then
|
||||
FCF_SetWindowName(frame, WHISPER)
|
||||
end
|
||||
end
|
||||
|
||||
local chatGroup = {"SYSTEM", "CHANNEL", "SAY", "EMOTE", "YELL", "WHISPER", "PARTY", "PARTY_LEADER", "RAID", "RAID_LEADER", "RAID_WARNING", "BATTLEGROUND", "BATTLEGROUND_LEADER", "GUILD", "OFFICER", "MONSTER_SAY", "MONSTER_YELL", "MONSTER_EMOTE", "MONSTER_WHISPER", "MONSTER_BOSS_EMOTE", "MONSTER_BOSS_WHISPER", "ERRORS", "AFK", "DND", "IGNORED", "BG_HORDE", "BG_ALLIANCE", "BG_NEUTRAL", "ACHIEVEMENT", "GUILD_ACHIEVEMENT", "BN_WHISPER", "BN_CONVERSATION", "BN_INLINE_TOAST_ALERT"}
|
||||
ChatFrame_RemoveAllMessageGroups(ChatFrame1)
|
||||
for _, v in ipairs(chatGroup) do
|
||||
ChatFrame_AddMessageGroup(ChatFrame1, v)
|
||||
end
|
||||
|
||||
chatGroup = {"COMBAT_XP_GAIN", "COMBAT_HONOR_GAIN", "COMBAT_FACTION_CHANGE", "SKILL", "LOOT", "MONEY"}
|
||||
ChatFrame_RemoveAllMessageGroups(ChatFrame3)
|
||||
for _, v in ipairs(chatGroup) do
|
||||
ChatFrame_AddMessageGroup(ChatFrame3, v)
|
||||
end
|
||||
|
||||
local chatGroup = {"GUILD", "OFFICER", "GUILD_ACHIEVEMENT"}
|
||||
ChatFrame_RemoveAllMessageGroups(ChatFrame4)
|
||||
for _, v in ipairs(chatGroup) do
|
||||
ChatFrame_AddMessageGroup(ChatFrame4, v)
|
||||
end
|
||||
|
||||
local chatGroup = {"WHISPER", "BN_WHISPER"}
|
||||
ChatFrame_RemoveAllMessageGroups(ChatFrame5)
|
||||
for _, v in ipairs(chatGroup) do
|
||||
ChatFrame_AddMessageGroup(ChatFrame5, v)
|
||||
end
|
||||
|
||||
ChatFrame_AddChannel(ChatFrame1, GENERAL)
|
||||
ChatFrame_RemoveChannel(ChatFrame1, TRADE)
|
||||
ChatFrame_RemoveChannel(ChatFrame1, "Ascension")
|
||||
ChatFrame_RemoveChannel(ChatFrame1, "World")
|
||||
ChatFrame_AddChannel(ChatFrame3, TRADE)
|
||||
ChatFrame_AddChannel(ChatFrame3, "Ascension")
|
||||
ChatFrame_AddChannel(ChatFrame3, "World")
|
||||
|
||||
chatGroup = {"SAY", "EMOTE", "YELL", "WHISPER", "PARTY", "PARTY_LEADER", "RAID", "RAID_LEADER", "RAID_WARNING", "BATTLEGROUND", "BATTLEGROUND_LEADER", "GUILD", "OFFICER", "ACHIEVEMENT", "GUILD_ACHIEVEMENT"}
|
||||
for i = 1, MAX_WOW_CHAT_CHANNELS do
|
||||
tinsert(chatGroup, "CHANNEL"..i)
|
||||
end
|
||||
for _, v in ipairs(chatGroup) do
|
||||
ToggleChatColorNamesByClassGroup(true, v)
|
||||
end
|
||||
|
||||
-- Create a list of replacement colors
|
||||
local replacementColors = {
|
||||
["General"] = {195/255, 230/255, 232/255},
|
||||
["Trade"] = {232/255, 158/255, 121/255},
|
||||
["LocalDefense"] = {232/255, 228/255, 121/255},
|
||||
["GuildRecruitment"] = {64/255, 255/255, 64/255},
|
||||
["LookingForGroup"] = {0/255, 206/255, 255/255},
|
||||
["Ascension"] = {255/255, 248/255, 163/255},
|
||||
["World"] = {255/255, 248/255, 163/255},
|
||||
}
|
||||
|
||||
-- Itterate through the channel list, and set the colors for each specific channel
|
||||
-- We need to do this because the channels change around so much
|
||||
-- low level characters start off with channel 1 being Ascension
|
||||
local chanList = { GetChannelList() }
|
||||
for i=1, #chanList, 2 do
|
||||
if replacementColors[chanList[i+1]] ~= nil then
|
||||
ChangeChatColor("CHANNEL"..chanList[i], unpack(replacementColors[chanList[i+1]]))
|
||||
end
|
||||
if chanList[i+1] == "GuildRecruitment" then
|
||||
ChatFrame_AddChannel(ChatFrame1, "GuildRecruitment")
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
if InstallStepComplete and not noDisplayMsg then
|
||||
InstallStepComplete.message = L["Chat Set"]
|
||||
InstallStepComplete:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupCVars(noDisplayMsg)
|
||||
SetCVar("mapQuestDifficulty", 1)
|
||||
SetCVar("ShowClassColorInNameplate", 1)
|
||||
SetCVar("screenshotQuality", 10)
|
||||
SetCVar("chatMouseScroll", 1)
|
||||
SetCVar("chatStyle", "classic")
|
||||
SetCVar("WholeChatWindowClickable", 0)
|
||||
SetCVar("ConversationMode", "inline")
|
||||
SetCVar("showTutorials", 0)
|
||||
SetCVar("showNewbieTips", 0)
|
||||
SetCVar("showLootSpam", 1)
|
||||
SetCVar("UberTooltips", 1)
|
||||
SetCVar("threatWarning", 3)
|
||||
SetCVar("alwaysShowActionBars", 1)
|
||||
SetCVar("lockActionBars", 1)
|
||||
SetCVar("SpamFilter", 0)
|
||||
|
||||
if InstallStepComplete and not noDisplayMsg then
|
||||
InstallStepComplete.message = L["CVars Set"]
|
||||
InstallStepComplete:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function E:GetColor(r, g, b, a)
|
||||
return {r = r, g = g, b = b, a = a}
|
||||
end
|
||||
|
||||
function E:SetupTheme(theme, noDisplayMsg)
|
||||
E.private.theme = theme
|
||||
|
||||
local classColor
|
||||
|
||||
--Set colors
|
||||
if theme == "classic" then
|
||||
E.db.general.bordercolor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(0.31, 0.31, 0.31))
|
||||
E.db.general.backdropcolor = E:GetColor(0.1, 0.1, 0.1)
|
||||
E.db.general.backdropfadecolor = E:GetColor(13/255, 13/255, 13/255, 0.69)
|
||||
E.db.unitframe.colors.borderColor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(0.31, 0.31, 0.31))
|
||||
E.db.unitframe.colors.healthclass = false
|
||||
E.db.unitframe.colors.health = E:GetColor(0.31, 0.31, 0.31)
|
||||
E.db.unitframe.colors.auraBarBuff = E:GetColor(0.31, 0.31, 0.31)
|
||||
E.db.unitframe.colors.castColor = E:GetColor(0.31, 0.31, 0.31)
|
||||
E.db.unitframe.colors.castClassColor = false
|
||||
elseif theme == "class" then
|
||||
classColor = E.media.herocolor
|
||||
|
||||
E.db.general.bordercolor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(0.31, 0.31, 0.31))
|
||||
E.db.general.backdropcolor = E:GetColor(0.1, 0.1, 0.1)
|
||||
E.db.general.backdropfadecolor = E:GetColor(0.06, 0.06, 0.06, 0.8)
|
||||
E.db.unitframe.colors.borderColor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(0.31, 0.31, 0.31))
|
||||
E.db.unitframe.colors.auraBarBuff = E:GetColor(classColor.r, classColor.g, classColor.b)
|
||||
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(0.1, 0.1, 0.1))
|
||||
E.db.general.backdropcolor = E:GetColor(0.1, 0.1, 0.1)
|
||||
E.db.general.backdropfadecolor = E:GetColor(0.054, 0.054, 0.054, 0.8)
|
||||
E.db.unitframe.colors.borderColor = (E.PixelMode and E:GetColor(0, 0, 0) or E:GetColor(0.1, 0.1, 0.1))
|
||||
E.db.unitframe.colors.auraBarBuff = E:GetColor(0.1, 0.1, 0.1)
|
||||
E.db.unitframe.colors.healthclass = false
|
||||
E.db.unitframe.colors.health = E:GetColor(0.1, 0.1, 0.1)
|
||||
E.db.unitframe.colors.castColor = E:GetColor(0.1, 0.1, 0.1)
|
||||
E.db.unitframe.colors.castClassColor = false
|
||||
end
|
||||
|
||||
--Value Color
|
||||
if theme == "class" then
|
||||
E.db.general.valuecolor = E:GetColor(classColor.r, classColor.g, classColor.b)
|
||||
else
|
||||
E.db.general.valuecolor = E:GetColor(254/255, 123/255, 44/255)
|
||||
end
|
||||
|
||||
E:UpdateAll(true)
|
||||
|
||||
if InstallStepComplete and not noDisplayMsg then
|
||||
InstallStepComplete.message = L["Theme Set"]
|
||||
InstallStepComplete:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function E:SetupLayout(layout, noDataReset, noDisplayMsg)
|
||||
if not noDataReset then
|
||||
E.db.layoutSet = layout
|
||||
|
||||
--Unitframes
|
||||
E:CopyTable(E.db.unitframe.units, P.unitframe.units)
|
||||
|
||||
--Shared base layout, tweaks to individual layouts will be below
|
||||
E:ResetMovers("")
|
||||
if not E.db.movers then E.db.movers = {} end
|
||||
|
||||
--ActionBars
|
||||
E.db.actionbar.backdropSpacingConverted = true
|
||||
E.db.actionbar.bar1.buttons = 8
|
||||
E.db.actionbar.bar1.buttonsize = 50
|
||||
E.db.actionbar.bar1.buttonspacing = 1
|
||||
E.db.actionbar.bar2.buttons = 9
|
||||
E.db.actionbar.bar2.buttonsize = 38
|
||||
E.db.actionbar.bar2.buttonspacing = 1
|
||||
E.db.actionbar.bar2.enabled = true
|
||||
E.db.actionbar.bar2.visibility = "[vehicleui] hide; show"
|
||||
E.db.actionbar.bar3.buttons = 8
|
||||
E.db.actionbar.bar3.buttonsize = 50
|
||||
E.db.actionbar.bar3.buttonspacing = 1
|
||||
E.db.actionbar.bar3.buttonsPerRow = 10
|
||||
E.db.actionbar.bar3.visibility = "[vehicleui] hide; show"
|
||||
E.db.actionbar.bar4.enabled = false
|
||||
E.db.actionbar.bar4.visibility = "[vehicleui] hide; show"
|
||||
E.db.actionbar.bar5.enabled = false
|
||||
E.db.actionbar.bar5.visibility = "[vehicleui] hide; show"
|
||||
E.db.actionbar.bar6.visibility = "[vehicleui] hide; show"
|
||||
--Auras
|
||||
E.db.auras.buffs.countFontSize = 10
|
||||
E.db.auras.buffs.size = 40
|
||||
E.db.auras.debuffs.countFontSize = 10
|
||||
E.db.auras.debuffs.size = 40
|
||||
--Bags
|
||||
E.db.bags.bagSize = 42
|
||||
E.db.bags.bagWidth = 472
|
||||
E.db.bags.bankSize = 42
|
||||
E.db.bags.bankWidth = 472
|
||||
--Chat
|
||||
E.db.chat.fontSize = 10
|
||||
E.db.chat.panelColorConverted = true
|
||||
E.db.chat.separateSizes = false
|
||||
E.db.chat.panelHeight = 236
|
||||
E.db.chat.panelWidth = 472
|
||||
E.db.chat.tapFontSize = 10
|
||||
--DataBars
|
||||
E.db.databars.experience.height = 10
|
||||
E.db.databars.experience.orientation = "HORIZONTAL"
|
||||
E.db.databars.experience.textSize = 12
|
||||
E.db.databars.experience.width = 350
|
||||
E.db.databars.reputation.enable = true
|
||||
E.db.databars.reputation.height = 10
|
||||
E.db.databars.reputation.orientation = "HORIZONTAL"
|
||||
E.db.databars.reputation.width = 222
|
||||
--General
|
||||
E.db.general.minimap.size = 220
|
||||
E.db.general.watchFrameHeight = 400
|
||||
E.db.general.totems.growthDirection = "HORIZONTAL"
|
||||
E.db.general.totems.size = 50
|
||||
E.db.general.totems.spacing = 8
|
||||
E.db.general.reminder.enable = false
|
||||
--Movers
|
||||
E.db.movers.AlertFrameMover = "TOP,ElvUIParent,TOP,-1,-18"
|
||||
E.db.movers.BNETMover = "TOPRIGHT,ElvUIParent,TOPRIGHT,-4,-274"
|
||||
E.db.movers.ElvAB_1 = "BOTTOM,ElvUIParent,BOTTOM,0,190"
|
||||
E.db.movers.ElvAB_2 = "BOTTOM,ElvUIParent,BOTTOM,0,4"
|
||||
E.db.movers.ElvAB_3 = "BOTTOM,ElvUIParent,BOTTOM,0,138"
|
||||
E.db.movers.ElvAB_5 = "BOTTOM,ElvUIParent,BOTTOM,-92,57"
|
||||
E.db.movers.ElvBar_Totem = "BOTTOM,ElvUIParent,BOTTOM,0,55"
|
||||
E.db.movers.ElvUF_FocusMover = "BOTTOM,ElvUIParent,BOTTOM,342,59"
|
||||
E.db.movers.ElvUF_PartyMover = "BOTTOMLEFT,ElvUIParent,BOTTOMLEFT,4,248"
|
||||
E.db.movers.ElvUF_PetMover = "BOTTOM,ElvUIParent,BOTTOM,-341,99"
|
||||
E.db.movers.ElvUF_PlayerCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,96"
|
||||
E.db.movers.ElvUF_PlayerMover = "BOTTOM,ElvUIParent,BOTTOM,-341,138"
|
||||
E.db.movers.ElvUF_Raid40Mover = "TOPLEFT,ElvUIParent,BOTTOMLEFT,4,482"
|
||||
E.db.movers.ElvUF_RaidMover = "BOTTOMLEFT,ElvUIParent,BOTTOMLEFT,4,248"
|
||||
E.db.movers.ElvUF_RaidpetMover = "TOPLEFT,ElvUIParent,BOTTOMLEFT,4,737"
|
||||
E.db.movers.ElvUF_TargetCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,242"
|
||||
E.db.movers.ElvUF_TargetMover = "BOTTOM,ElvUIParent,BOTTOM,342,138"
|
||||
E.db.movers.ElvUF_TargetTargetMover = "BOTTOM,ElvUIParent,BOTTOM,342,99"
|
||||
E.db.movers.ExperienceBarMover = "BOTTOM,ElvUIParent,BOTTOM,0,43"
|
||||
E.db.movers.LootFrameMover = "TOPLEFT,ElvUIParent,TOPLEFT,418,-186"
|
||||
E.db.movers.MirrorTimer1Mover = "TOP,ElvUIParent,TOP,-1,-96"
|
||||
E.db.movers.WatchFrameMover = "TOPRIGHT,ElvUIParent,TOPRIGHT,-163,-325"
|
||||
E.db.movers.ReputationBarMover = "TOPRIGHT,ElvUIParent,TOPRIGHT,-2,-245"
|
||||
E.db.movers.ShiftAB = "TOPLEFT,ElvUIParent,BOTTOMLEFT,4,769"
|
||||
E.db.movers.TempEnchantMover = "TOPRIGHT,ElvUIParent,TOPRIGHT,-4,-257"
|
||||
E.db.movers.TotemBarMover = "BOTTOMLEFT,ElvUIParent,BOTTOMLEFT,485,4"
|
||||
E.db.movers.VehicleSeatMover = "TOPLEFT,ElvUIParent,TOPLEFT,4,-4"
|
||||
--Tooltip
|
||||
E.db.tooltip.fontSize = 10
|
||||
E.db.tooltip.healthBar.fontOutline = "MONOCHROMEOUTLINE"
|
||||
E.db.tooltip.healthBar.height = 12
|
||||
--UnitFrames
|
||||
E.db.unitframe.smoothbars = true
|
||||
E.db.unitframe.thinBorders = true
|
||||
--Player
|
||||
E.db.unitframe.units.player.aurabar.height = 26
|
||||
E.db.unitframe.units.player.buffs.perrow = 7
|
||||
E.db.unitframe.units.player.castbar.height = 40
|
||||
E.db.unitframe.units.player.castbar.insideInfoPanel = false
|
||||
E.db.unitframe.units.player.castbar.width = 407
|
||||
E.db.unitframe.units.player.classbar.height = 14
|
||||
E.db.unitframe.units.player.debuffs.perrow = 7
|
||||
E.db.unitframe.units.player.disableMouseoverGlow = true
|
||||
E.db.unitframe.units.player.health.attachTextTo = "InfoPanel"
|
||||
E.db.unitframe.units.player.height = 82
|
||||
E.db.unitframe.units.player.infoPanel.enable = true
|
||||
E.db.unitframe.units.player.power.attachTextTo = "InfoPanel"
|
||||
E.db.unitframe.units.player.power.height = 22
|
||||
--Target
|
||||
E.db.unitframe.units.target.aurabar.height = 26
|
||||
E.db.unitframe.units.target.buffs.anchorPoint = "TOPLEFT"
|
||||
E.db.unitframe.units.target.buffs.perrow = 7
|
||||
E.db.unitframe.units.target.castbar.height = 40
|
||||
E.db.unitframe.units.target.castbar.insideInfoPanel = false
|
||||
E.db.unitframe.units.target.castbar.width = 407
|
||||
E.db.unitframe.units.target.debuffs.anchorPoint = "TOPLEFT"
|
||||
E.db.unitframe.units.target.debuffs.attachTo = "FRAME"
|
||||
E.db.unitframe.units.target.debuffs.enable = false
|
||||
E.db.unitframe.units.target.debuffs.maxDuration = 0
|
||||
E.db.unitframe.units.target.debuffs.perrow = 7
|
||||
E.db.unitframe.units.target.disableMouseoverGlow = true
|
||||
E.db.unitframe.units.target.health.attachTextTo = "InfoPanel"
|
||||
E.db.unitframe.units.target.height = 82
|
||||
E.db.unitframe.units.target.infoPanel.enable = true
|
||||
E.db.unitframe.units.target.name.attachTextTo = "InfoPanel"
|
||||
E.db.unitframe.units.target.name.text_format = "[namecolor][name]"
|
||||
E.db.unitframe.units.target.orientation = "LEFT"
|
||||
E.db.unitframe.units.target.power.attachTextTo = "InfoPanel"
|
||||
E.db.unitframe.units.target.power.height = 22
|
||||
--TargetTarget
|
||||
E.db.unitframe.units.targettarget.debuffs.anchorPoint = "TOPRIGHT"
|
||||
E.db.unitframe.units.targettarget.debuffs.enable = false
|
||||
E.db.unitframe.units.targettarget.disableMouseoverGlow = true
|
||||
E.db.unitframe.units.targettarget.power.enable = false
|
||||
E.db.unitframe.units.targettarget.raidicon.attachTo = "LEFT"
|
||||
E.db.unitframe.units.targettarget.raidicon.enable = false
|
||||
E.db.unitframe.units.targettarget.raidicon.xOffset = 2
|
||||
E.db.unitframe.units.targettarget.raidicon.yOffset = 0
|
||||
E.db.unitframe.units.targettarget.threatStyle = "GLOW"
|
||||
E.db.unitframe.units.targettarget.width = 270
|
||||
--Focus
|
||||
E.db.unitframe.units.focus.castbar.width = 270
|
||||
E.db.unitframe.units.focus.width = 270
|
||||
--Pet
|
||||
E.db.unitframe.units.pet.castbar.iconSize = 32
|
||||
E.db.unitframe.units.pet.castbar.width = 270
|
||||
E.db.unitframe.units.pet.debuffs.anchorPoint = "TOPRIGHT"
|
||||
E.db.unitframe.units.pet.debuffs.enable = true
|
||||
E.db.unitframe.units.pet.disableTargetGlow = false
|
||||
E.db.unitframe.units.pet.infoPanel.height = 14
|
||||
E.db.unitframe.units.pet.portrait.camDistanceScale = 2
|
||||
E.db.unitframe.units.pet.width = 270
|
||||
--Boss
|
||||
E.db.unitframe.units.boss.buffs.maxDuration = 300
|
||||
E.db.unitframe.units.boss.buffs.sizeOverride = 27
|
||||
E.db.unitframe.units.boss.buffs.yOffset = 16
|
||||
E.db.unitframe.units.boss.castbar.width = 246
|
||||
E.db.unitframe.units.boss.debuffs.maxDuration = 300
|
||||
E.db.unitframe.units.boss.debuffs.numrows = 1
|
||||
E.db.unitframe.units.boss.debuffs.sizeOverride = 27
|
||||
E.db.unitframe.units.boss.debuffs.yOffset = -16
|
||||
E.db.unitframe.units.boss.height = 60
|
||||
E.db.unitframe.units.boss.infoPanel.height = 17
|
||||
E.db.unitframe.units.boss.portrait.camDistanceScale = 2
|
||||
E.db.unitframe.units.boss.portrait.width = 45
|
||||
E.db.unitframe.units.boss.width = 246
|
||||
--Party
|
||||
E.db.unitframe.units.party.height = 74
|
||||
E.db.unitframe.units.party.power.height = 13
|
||||
E.db.unitframe.units.party.rdebuffs.font = "PT Sans Narrow"
|
||||
E.db.unitframe.units.party.width = 231
|
||||
--Raid
|
||||
E.db.unitframe.units.raid.growthDirection = "RIGHT_UP"
|
||||
E.db.unitframe.units.raid.health.frequentUpdates = true
|
||||
E.db.unitframe.units.raid.infoPanel.enable = true
|
||||
E.db.unitframe.units.raid.name.attachTextTo = "InfoPanel"
|
||||
E.db.unitframe.units.raid.name.position = "BOTTOMLEFT"
|
||||
E.db.unitframe.units.raid.name.xOffset = 2
|
||||
E.db.unitframe.units.raid.numGroups = 8
|
||||
E.db.unitframe.units.raid.rdebuffs.font = "PT Sans Narrow"
|
||||
E.db.unitframe.units.raid.rdebuffs.size = 30
|
||||
E.db.unitframe.units.raid.rdebuffs.xOffset = 30
|
||||
E.db.unitframe.units.raid.rdebuffs.yOffset = 25
|
||||
E.db.unitframe.units.raid.resurrectIcon.attachTo = "BOTTOMRIGHT"
|
||||
E.db.unitframe.units.raid.visibility = "[@raid6,noexists] hide;show"
|
||||
E.db.unitframe.units.raid.width = 92
|
||||
--Raid40
|
||||
E.db.unitframe.units.raid40.enable = false
|
||||
E.db.unitframe.units.raid40.rdebuffs.font = "PT Sans Narrow"
|
||||
|
||||
--[[
|
||||
-- Layout Tweaks will be handled below.
|
||||
-- These are changes that deviate from the shared base layout
|
||||
--]]
|
||||
|
||||
if layout == "dpsCaster" then
|
||||
E.db.movers.ElvUF_PlayerCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,243"
|
||||
E.db.movers.ElvUF_TargetCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,97"
|
||||
elseif layout == "healer" then
|
||||
E.db.movers.ElvUF_PlayerCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,243"
|
||||
E.db.movers.ElvUF_TargetCastbarMover = "BOTTOM,ElvUIParent,BOTTOM,0,97"
|
||||
E.db.movers.ElvUF_RaidMover = "BOTTOMLEFT,ElvUIParent,BOTTOMLEFT,202,373"
|
||||
E.db.movers.LootFrameMover = "TOPLEFT,ElvUIParent,TOPLEFT,250,-104"
|
||||
E.db.movers.ShiftAB = "TOPLEFT,ElvUIParent,BOTTOMLEFT,4,273"
|
||||
E.db.unitframe.units.party.enable = false
|
||||
E.db.unitframe.units.party.health.frequentUpdates = true
|
||||
E.db.unitframe.units.raid.visibility = "[nogroup] hide;show"
|
||||
E.db.unitframe.units.raid40.health.frequentUpdates = true
|
||||
end
|
||||
end
|
||||
|
||||
E:UpdateAll(true)
|
||||
|
||||
if InstallStepComplete and not noDisplayMsg then
|
||||
InstallStepComplete.message = L["Layout Set"]
|
||||
InstallStepComplete:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupAuras(style, noDisplayMsg)
|
||||
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)
|
||||
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)
|
||||
if frame then
|
||||
UF:Configure_Auras(frame, "Buffs")
|
||||
UF:Configure_Auras(frame, "Debuffs")
|
||||
UF:Configure_AuraBars(frame)
|
||||
end
|
||||
|
||||
if not style then
|
||||
--PLAYER
|
||||
E.db.unitframe.units.player.buffs.enable = true
|
||||
E.db.unitframe.units.player.buffs.attachTo = "FRAME"
|
||||
E.db.unitframe.units.player.debuffs.attachTo = "BUFFS"
|
||||
E.db.unitframe.units.player.aurabar.enable = false
|
||||
if E.private.unitframe.enable then
|
||||
UF:CreateAndUpdateUF("player")
|
||||
end
|
||||
|
||||
--TARGET
|
||||
E.db.unitframe.units.target.debuffs.enable = true
|
||||
E.db.unitframe.units.target.aurabar.enable = false
|
||||
if E.private.unitframe.enable then
|
||||
UF:CreateAndUpdateUF("target")
|
||||
end
|
||||
end
|
||||
|
||||
if InstallStepComplete and not noDisplayMsg 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("")
|
||||
InstallSlider:Hide()
|
||||
InstallSlider.Min:SetText("")
|
||||
InstallSlider.Max:SetText("")
|
||||
InstallSlider.Cur:SetText("")
|
||||
ElvUIInstallFrame.SubTitle:SetText("")
|
||||
ElvUIInstallFrame.Desc1:SetText("")
|
||||
ElvUIInstallFrame.Desc2:SetText("")
|
||||
ElvUIInstallFrame.Desc3:SetText("")
|
||||
ElvUIInstallFrame:Size(550, 400)
|
||||
end
|
||||
|
||||
local function SetPage(PageNum)
|
||||
CURRENT_PAGE = PageNum
|
||||
ResetAll()
|
||||
|
||||
InstallStatus.anim.progress:SetChange(PageNum)
|
||||
InstallStatus.anim.progress:Play()
|
||||
InstallStatus.text:SetText(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)
|
||||
|
||||
if PageNum == MAX_PAGE then
|
||||
InstallNextButton:Disable()
|
||||
else
|
||||
InstallNextButton:Enable()
|
||||
end
|
||||
|
||||
if PageNum == 1 then
|
||||
InstallPrevButton:Disable()
|
||||
else
|
||||
InstallPrevButton:Enable()
|
||||
end
|
||||
|
||||
local f = ElvUIInstallFrame
|
||||
if PageNum == 1 then
|
||||
f.SubTitle:SetFormattedText(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", function() SetupCVars() end)
|
||||
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", function() SetupChat() end)
|
||||
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["UI Scale"])
|
||||
f.Desc1:SetFormattedText(L["Adjust the UI Scale to fit your screen, press the autoscale button to set the UI Scale automatically."])
|
||||
InstallSlider:Show()
|
||||
InstallSlider:SetValueStep(0.01)
|
||||
InstallSlider:SetMinMaxValues(0.4, 1.15)
|
||||
|
||||
local value = E.global.general.UIScale
|
||||
InstallSlider:SetValue(value)
|
||||
InstallSlider.Cur:SetText(value)
|
||||
InstallSlider:SetScript("OnValueChanged", function(self)
|
||||
E.global.general.UIScale = self:GetValue()
|
||||
InstallSlider.Cur:SetText(E.global.general.UIScale)
|
||||
end)
|
||||
|
||||
InstallSlider.Min:SetText(0.4)
|
||||
InstallSlider.Max:SetText(1.15)
|
||||
InstallOption1Button:Show()
|
||||
InstallOption1Button:SetScript("OnClick", function()
|
||||
local scale = E:PixelBestSize()
|
||||
|
||||
-- this is to just keep the slider in place, the values need updated again afterwards
|
||||
InstallSlider:SetValue(scale)
|
||||
|
||||
-- update the values with deeper accuracy
|
||||
E.global.general.UIScale = scale
|
||||
InstallSlider.Cur:SetText(E.global.general.UIScale)
|
||||
end)
|
||||
|
||||
InstallOption1Button:SetText(L["Auto Scale"])
|
||||
InstallOption2Button:Show()
|
||||
InstallOption2Button:SetScript("OnClick", function()
|
||||
E:PixelScaleChanged(nil, true)
|
||||
end)
|
||||
|
||||
InstallOption2Button:SetText(L["Preview"])
|
||||
f.Desc3:SetText(L["Importance: |cff07D400High|r"])
|
||||
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 / Physical DPS"])
|
||||
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("dpsCaster") end)
|
||||
InstallOption3Button: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-WotLK."])
|
||||
f.Desc2:SetText(L["Please click the button below so you can setup variables and ReloadUI."])
|
||||
InstallOption1Button:Show()
|
||||
InstallOption1Button:SetScript("OnClick", function() E:StaticPopup_Show("ELVUI_EDITBOX", nil, nil, "https://discord.gg/UXSc7nt") end)
|
||||
InstallOption1Button:SetText(L["Discord"])
|
||||
InstallOption2Button:Show()
|
||||
InstallOption2Button:SetScript("OnClick", InstallComplete)
|
||||
InstallOption2Button:SetText(L["Finished"])
|
||||
ElvUIInstallFrame:Size(550, 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:Size(418, 72)
|
||||
imsg:Point("TOP", 0, -190)
|
||||
imsg:Hide()
|
||||
imsg:SetScript("OnShow", function(f)
|
||||
if f.message then
|
||||
PlaySoundFile([[Sound\Interface\LevelUp.wav]])
|
||||
f.text:SetText(f.message)
|
||||
UIFrameFadeOut(f, 3.5, 1, 0)
|
||||
E:Delay(4, f.Hide, f)
|
||||
f.message = nil
|
||||
else
|
||||
f:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
imsg.firstShow = false
|
||||
|
||||
imsg.bg = imsg:CreateTexture(nil, "BACKGROUND")
|
||||
imsg.bg:SetTexture([[Interface\AddOns\ElvUI\media\textures\LevelUpTex]])
|
||||
imsg.bg:Point("BOTTOM")
|
||||
imsg.bg:Size(326, 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")
|
||||
imsg.lineTop:SetTexture([[Interface\AddOns\ElvUI\media\textures\LevelUpTex]])
|
||||
imsg.lineTop:Point("TOP")
|
||||
imsg.lineTop:Size(418, 7)
|
||||
imsg.lineTop:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)
|
||||
|
||||
imsg.lineBottom = imsg:CreateTexture(nil, "BACKGROUND")
|
||||
imsg.lineBottom:SetDrawLayer("BACKGROUND")
|
||||
imsg.lineBottom:SetTexture([[Interface\AddOns\ElvUI\media\textures\LevelUpTex]])
|
||||
imsg.lineBottom:Point("BOTTOM")
|
||||
imsg.lineBottom:Size(418, 7)
|
||||
imsg.lineBottom:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)
|
||||
|
||||
imsg.text = imsg:CreateFontString(nil, "OVERLAY")
|
||||
imsg.text:FontTemplate(E.media.normFont, 32, "OUTLINE")
|
||||
imsg.text:Point("BOTTOM", 0, 16)
|
||||
imsg.text:SetTextColor(1, 0.82, 0)
|
||||
imsg.text:SetJustifyH("CENTER")
|
||||
end
|
||||
|
||||
--Create Frame
|
||||
if not ElvUIInstallFrame then
|
||||
local f = CreateFrame("Button", "ElvUIInstallFrame", E.UIParent)
|
||||
f.SetPage = SetPage
|
||||
f:Size(550, 400)
|
||||
f:SetTemplate("Transparent")
|
||||
f:Point("CENTER")
|
||||
f:SetFrameStrata("TOOLTIP")
|
||||
|
||||
f:SetMovable(true)
|
||||
f:EnableMouse(true)
|
||||
f:RegisterForDrag("LeftButton")
|
||||
f:SetScript("OnDragStart", function(frame) frame:StartMoving() frame:SetUserPlaced(false) end)
|
||||
f:SetScript("OnDragStop", function(frame) frame:StopMovingOrSizing() end)
|
||||
|
||||
f.Title = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Title:FontTemplate(nil, 17, nil)
|
||||
f.Title:Point("TOP", 0, -5)
|
||||
f.Title:SetText(L["ElvUI Installation"])
|
||||
|
||||
f.Next = CreateFrame("Button", "InstallNextButton", f, "UIPanelButtonTemplate")
|
||||
f.Next:Size(110, 25)
|
||||
f.Next:Point("BOTTOMRIGHT", -5, 5)
|
||||
f.Next:SetText(CONTINUE)
|
||||
f.Next:Disable()
|
||||
f.Next:SetScript("OnClick", NextPage)
|
||||
S:HandleButton(f.Next, true)
|
||||
|
||||
f.Prev = CreateFrame("Button", "InstallPrevButton", f, "UIPanelButtonTemplate")
|
||||
f.Prev:Size(110, 25)
|
||||
f.Prev:Point("BOTTOMLEFT", 5, 5)
|
||||
f.Prev:SetText(PREVIOUS)
|
||||
f.Prev:Disable()
|
||||
f.Prev:SetScript("OnClick", PreviousPage)
|
||||
S:HandleButton(f.Prev, true)
|
||||
|
||||
f.Status = CreateFrame("StatusBar", "InstallStatus", f)
|
||||
f.Status:SetFrameLevel(f.Status:GetFrameLevel() + 2)
|
||||
f.Status:CreateBackdrop()
|
||||
f.Status:SetStatusBarTexture(E.media.normTex)
|
||||
E:RegisterStatusBar(f.Status)
|
||||
f.Status:SetMinMaxValues(0, MAX_PAGE)
|
||||
f.Status:Point("TOPLEFT", f.Prev, "TOPRIGHT", 6, -2)
|
||||
f.Status:Point("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:SetEasing("Out")
|
||||
f.Status.anim.progress:SetDuration(0.3)
|
||||
|
||||
f.Status.text = f.Status:CreateFontString(nil, "OVERLAY")
|
||||
f.Status.text:FontTemplate()
|
||||
f.Status.text:Point("CENTER")
|
||||
f.Status.text:SetText(CURRENT_PAGE.." / "..MAX_PAGE)
|
||||
|
||||
f.Slider = CreateFrame("Slider", "InstallSlider", f)
|
||||
f.Slider:SetOrientation("HORIZONTAL")
|
||||
f.Slider:Height(15)
|
||||
f.Slider:Width(400)
|
||||
f.Slider:SetHitRectInsets(0, 0, -10, 0)
|
||||
f.Slider:SetPoint("CENTER", 0, 45)
|
||||
S:HandleSliderFrame(f.Slider)
|
||||
f.Slider:Hide()
|
||||
|
||||
f.Slider.Min = f.Slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||
f.Slider.Min:SetPoint("RIGHT", f.Slider, "LEFT", -3, 0)
|
||||
f.Slider.Max = f.Slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||
f.Slider.Max:SetPoint("LEFT", f.Slider, "RIGHT", 3, 0)
|
||||
f.Slider.Cur = f.Slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||
f.Slider.Cur:SetPoint("BOTTOM", f.Slider, "TOP", 0, 10)
|
||||
f.Slider.Cur:FontTemplate(nil, 30, nil)
|
||||
|
||||
f.Option1 = CreateFrame("Button", "InstallOption1Button", f, "UIPanelButtonTemplate")
|
||||
f.Option1:Size(160, 30)
|
||||
f.Option1:Point("BOTTOM", 0, 45)
|
||||
f.Option1:SetText("")
|
||||
f.Option1:Hide()
|
||||
S:HandleButton(f.Option1, true)
|
||||
|
||||
f.Option2 = CreateFrame("Button", "InstallOption2Button", f, "UIPanelButtonTemplate")
|
||||
f.Option2:Size(110, 30)
|
||||
f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45)
|
||||
f.Option2:SetText("")
|
||||
f.Option2:Hide()
|
||||
f.Option2:SetScript("OnShow", function()
|
||||
f.Option1:Width(110)
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("BOTTOMRIGHT", f, "BOTTOM", -4, 45)
|
||||
end)
|
||||
f.Option2:SetScript("OnHide", function()
|
||||
f.Option1:Width(160)
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("BOTTOM", 0, 45)
|
||||
end)
|
||||
S:HandleButton(f.Option2, true)
|
||||
|
||||
f.Option3 = CreateFrame("Button", "InstallOption3Button", f, "UIPanelButtonTemplate")
|
||||
f.Option3:Size(100, 30)
|
||||
f.Option3:Point("LEFT", f.Option2, "RIGHT", 4, 0)
|
||||
f.Option3:SetText("")
|
||||
f.Option3:Hide()
|
||||
f.Option3:SetScript("OnShow", function()
|
||||
f.Option1:Width(100)
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("RIGHT", f.Option2, "LEFT", -4, 0)
|
||||
f.Option2:Width(100)
|
||||
f.Option2:ClearAllPoints()
|
||||
f.Option2:Point("BOTTOM", f, "BOTTOM", 0, 45)
|
||||
end)
|
||||
f.Option3:SetScript("OnHide", function()
|
||||
f.Option1:Width(160)
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("BOTTOM", 0, 45)
|
||||
f.Option2:Width(110)
|
||||
f.Option2:ClearAllPoints()
|
||||
f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45)
|
||||
end)
|
||||
S:HandleButton(f.Option3, true)
|
||||
|
||||
f.Option4 = CreateFrame("Button", "InstallOption4Button", f, "UIPanelButtonTemplate")
|
||||
f.Option4:Size(100, 30)
|
||||
f.Option4:Point("LEFT", f.Option3, "RIGHT", 4, 0)
|
||||
f.Option4:SetText("")
|
||||
f.Option4:Hide()
|
||||
f.Option4:SetScript("OnShow", function()
|
||||
f.Option1:Width(100)
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("RIGHT", f.Option2, "LEFT", -4, 0)
|
||||
f.Option2:Width(100)
|
||||
f.Option2:ClearAllPoints()
|
||||
f.Option2:Point("BOTTOMRIGHT", f, "BOTTOM", -4, 45)
|
||||
end)
|
||||
f.Option4:SetScript("OnHide", function()
|
||||
f.Option1:Width(160)
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("BOTTOM", 0, 45)
|
||||
f.Option2:Width(110)
|
||||
f.Option2:ClearAllPoints()
|
||||
f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45)
|
||||
end)
|
||||
S:HandleButton(f.Option4, true)
|
||||
|
||||
f.SubTitle = f:CreateFontString(nil, "OVERLAY")
|
||||
f.SubTitle:FontTemplate(nil, 15, nil)
|
||||
f.SubTitle:Point("TOP", 0, -40)
|
||||
|
||||
f.Desc1 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc1:FontTemplate()
|
||||
f.Desc1:Point("TOPLEFT", 20, -75)
|
||||
f.Desc1:Width(f:GetWidth() - 40)
|
||||
|
||||
f.Desc2 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc2:FontTemplate()
|
||||
f.Desc2:Point("TOPLEFT", 20, -125)
|
||||
f.Desc2:Width(f:GetWidth() - 40)
|
||||
|
||||
f.Desc3 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc3:FontTemplate()
|
||||
f.Desc3:Point("TOPLEFT", 20, -175)
|
||||
f.Desc3:Width(f:GetWidth() - 40)
|
||||
|
||||
local closeButton = CreateFrame("Button", "InstallCloseButton", f, "UIPanelCloseButton")
|
||||
closeButton:Point("TOPRIGHT", f, "TOPRIGHT")
|
||||
closeButton:SetScript("OnClick", function() f:Hide() end)
|
||||
S:HandleCloseButton(closeButton)
|
||||
|
||||
f.tutorialImage = f:CreateTexture("InstallTutorialImage", "OVERLAY")
|
||||
f.tutorialImage:Size(256, 128)
|
||||
f.tutorialImage:SetTexture(E.Media.Textures.Logo)
|
||||
f.tutorialImage:Point("BOTTOM", 0, 70)
|
||||
end
|
||||
|
||||
ElvUIInstallFrame:Show()
|
||||
NextPage()
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Script file="Core.lua"/>
|
||||
<Script file="Math.lua"/>
|
||||
<Script file="API.lua"/>
|
||||
<Script file="AprilFools.lua"/>
|
||||
<Script file="Fonts.lua"/>
|
||||
<Script file="Install.lua"/>
|
||||
<Script file="PluginInstaller.lua"/>
|
||||
<Script file="PixelPerfect.lua"/>
|
||||
<Script file="Toolkit.lua"/>
|
||||
<Script file="StatusReport.lua"/>
|
||||
<Script file="Commands.lua"/>
|
||||
<Script file="StaticPopups.lua"/>
|
||||
<Script file="Animation.lua"/>
|
||||
<Script file="Smoothie.lua"/>
|
||||
<Script file="Movers.lua"/>
|
||||
<Script file="Config.lua"/>
|
||||
<Script file="Tutorials.lua"/>
|
||||
<Script file="Distributor.lua"/>
|
||||
<Script file="Dropdown.lua"/>
|
||||
<Script file="Cooldowns.lua"/>
|
||||
<Script file="ModuleCopy.lua"/>
|
||||
<Script file="Tags.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,460 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
--Lua functions
|
||||
local pairs, ipairs = pairs, ipairs
|
||||
local next, select, type, unpack = next, select, type, unpack
|
||||
local tonumber, tostring = tonumber, tostring
|
||||
local abs, ceil, floor, fmod, modf = math.abs, math.ceil, math.floor, math.fmod, math.modf
|
||||
local byte, format, gmatch, gsub, strupper, strsub = string.byte, string.format, string.gmatch, string.gsub, strupper, strsub
|
||||
local utf8sub = string.utf8sub
|
||||
local tinsert, tremove, wipe = table.insert, table.remove, table.wipe
|
||||
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
|
||||
|
||||
E.ShortPrefixValues = {}
|
||||
E.ShortPrefixStyles = {
|
||||
["CHINESE"] = {{1e8, "Y"}, {1e4, "W"}},
|
||||
["ENGLISH"] = {{1e12, "T"}, {1e9, "B"}, {1e6, "M"}, {1e3, "K"}},
|
||||
["GERMAN"] = {{1e12, "Bio"}, {1e9, "Mrd"}, {1e6, "Mio"}, {1e3, "Tsd"}},
|
||||
["KOREAN"] = {{1e8, "억"}, {1e4, "만"}, {1e3, "천"}},
|
||||
["METRIC"] = {{1e12, "T"}, {1e9, "G"}, {1e6, "M"}, {1e3, "k"}}
|
||||
}
|
||||
|
||||
E.GetFormattedTextStyles = {
|
||||
["CURRENT"] = "%s",
|
||||
["CURRENT_MAX"] = "%s - %s",
|
||||
["CURRENT_PERCENT"] = "%s - %.1f%%",
|
||||
["CURRENT_MAX_PERCENT"] = "%s - %s | %.1f%%",
|
||||
["PERCENT"] = "%.1f%%",
|
||||
["DEFICIT"] = "-%s"
|
||||
}
|
||||
|
||||
function E:BuildPrefixValues()
|
||||
if next(E.ShortPrefixValues) then wipe(E.ShortPrefixValues) end
|
||||
|
||||
E.ShortPrefixValues = E:CopyTable(E.ShortPrefixValues, E.ShortPrefixStyles[E.db.general.numberPrefixStyle])
|
||||
E.ShortValueDec = format("%%.%df", E.db.general.decimalLength or 1)
|
||||
|
||||
for _, style in ipairs(E.ShortPrefixValues) do
|
||||
style[2] = E.ShortValueDec..style[2]
|
||||
end
|
||||
|
||||
local gftDec = tostring(E.db.general.decimalLength or 1)
|
||||
for style, str in pairs(E.GetFormattedTextStyles) do
|
||||
E.GetFormattedTextStyles[style] = gsub(str, "%d", gftDec)
|
||||
end
|
||||
end
|
||||
|
||||
--Return short value of a number
|
||||
function E:ShortValue(v)
|
||||
local abs_v = v < 0 and -v or v
|
||||
for i = 1, #E.ShortPrefixValues do
|
||||
if abs_v >= E.ShortPrefixValues[i][1] then
|
||||
return format(E.ShortPrefixValues[i][2], v / E.ShortPrefixValues[i][1])
|
||||
end
|
||||
end
|
||||
|
||||
return format("%.0f", v)
|
||||
end
|
||||
|
||||
function E:IsEvenNumber(num)
|
||||
return num % 2 == 0
|
||||
end
|
||||
|
||||
-- http://www.wowwiki.com/ColorGradient
|
||||
function E:ColorGradient(perc, ...)
|
||||
if perc >= 1 then
|
||||
return select(select("#", ...) - 2, ...)
|
||||
elseif perc <= 0 then
|
||||
return ...
|
||||
end
|
||||
|
||||
local num = select("#", ...) / 3
|
||||
local segment, relperc = modf(perc*(num - 1))
|
||||
local r1, g1, b1, r2, g2, b2 = select((segment*3) + 1, ...)
|
||||
|
||||
return r1 + (r2 - r1)*relperc, g1 + (g2 - g1)*relperc, b1 + (b2 - b1)*relperc
|
||||
end
|
||||
|
||||
--Return rounded number
|
||||
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
|
||||
|
||||
--Truncate a number off to n places
|
||||
function E:Truncate(v, decimals)
|
||||
return v - (v % (0.1 ^ (decimals or 0)))
|
||||
end
|
||||
|
||||
--RGB to Hex
|
||||
function E:RGBToHex(r, g, b)
|
||||
r = r <= 1 and r >= 0 and r or 1
|
||||
g = g <= 1 and g >= 0 and g or 1
|
||||
b = b <= 1 and b >= 0 and b or 1
|
||||
return format("|cff%02x%02x%02x", r*255, g*255, b*255)
|
||||
end
|
||||
|
||||
--Hex to RGB
|
||||
function E:HexToRGB(hex)
|
||||
local rhex, ghex, bhex = strsub(hex, 1, 2), strsub(hex, 3, 4), strsub(hex, 5, 6)
|
||||
return tonumber(rhex, 16), tonumber(ghex, 16), tonumber(bhex, 16)
|
||||
end
|
||||
|
||||
--From http://wow.gamepedia.com/UI_coordinates
|
||||
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, frameARight, frameABottom, frameATop = frameA:GetLeft(), frameA:GetRight(), frameA:GetBottom(), frameA:GetTop()
|
||||
local frameBLeft, frameBRight, frameBBottom, frameBTop = frameB:GetLeft(), frameB:GetRight(), frameB:GetBottom(), frameB:GetTop()
|
||||
if not (frameALeft and frameARight and frameABottom and frameATop) then return end
|
||||
if not (frameBLeft and frameBRight and frameBBottom and 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()
|
||||
|
||||
if not (x and y) then
|
||||
return "UNKNOWN", frame:GetName()
|
||||
end
|
||||
|
||||
local point
|
||||
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
|
||||
|
||||
function E:GetFormattedText(style, min, max, dec)
|
||||
if max == 0 then max = 1 end
|
||||
|
||||
if style == "CURRENT" or ((style == "CURRENT_MAX" or style == "CURRENT_MAX_PERCENT" or style == "CURRENT_PERCENT") and min == max) then
|
||||
return format(E.GetFormattedTextStyles.CURRENT, E:ShortValue(min, dec))
|
||||
else
|
||||
local useStyle = E.GetFormattedTextStyles[style]
|
||||
if not useStyle then return end
|
||||
|
||||
if style == "DEFICIT" then
|
||||
local deficit = max - min
|
||||
return (deficit > 0 and format(useStyle, E:ShortValue(deficit, dec))) or ""
|
||||
elseif style == "CURRENT_MAX" then
|
||||
return format(useStyle, E:ShortValue(min, dec), E:ShortValue(max, dec))
|
||||
elseif style == "PERCENT" or style == "CURRENT_PERCENT" or style == "CURRENT_MAX_PERCENT" then
|
||||
if dec then useStyle = gsub(useStyle, "%d", tonumber(dec) or 0) end
|
||||
local perc = min / max * 100
|
||||
|
||||
if style == "PERCENT" then
|
||||
return format(useStyle, perc)
|
||||
elseif style == "CURRENT_PERCENT" then
|
||||
return format(useStyle, E:ShortValue(min, dec), perc)
|
||||
elseif style == "CURRENT_MAX_PERCENT" then
|
||||
return format(useStyle, E:ShortValue(min, dec), E:ShortValue(max, dec), perc)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:ShortenString(str, numChars, dots)
|
||||
local bytes = #str
|
||||
if bytes <= numChars then
|
||||
return str
|
||||
else
|
||||
local len, pos = 0, 1
|
||||
while pos <= bytes do
|
||||
len = len + 1
|
||||
local c = byte(str, 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 strsub(str, 1, pos - 1)..(dots and "..." or "")
|
||||
else
|
||||
return str
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:AbbreviateString(str, allUpper)
|
||||
local newString = ""
|
||||
for word in gmatch(str, "[^%s]+") do
|
||||
word = utf8sub(word, 1, 1) --get only first letter of each word
|
||||
if allUpper then word = strupper(word) end
|
||||
newString = newString..word
|
||||
end
|
||||
|
||||
return newString
|
||||
end
|
||||
|
||||
function E:WaitFunc(elapsed)
|
||||
local total = #E.WaitTable
|
||||
local i = 1
|
||||
|
||||
while i <= total do
|
||||
local data = E.WaitTable[i]
|
||||
|
||||
if data[1] > elapsed then
|
||||
data[1] = data[1] - elapsed
|
||||
i = i + 1
|
||||
else
|
||||
tremove(E.WaitTable, i)
|
||||
|
||||
if data[3] then
|
||||
if data[3] > 1 then
|
||||
data[2](unpack(data[4], 1, data[3]))
|
||||
else
|
||||
data[2](data[4])
|
||||
end
|
||||
else
|
||||
data[2]()
|
||||
end
|
||||
|
||||
total = total - 1
|
||||
end
|
||||
end
|
||||
|
||||
if #E.WaitTable == 0 then
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
E.WaitTable = {}
|
||||
E.WaitFrame = CreateFrame("Frame", "ElvUI_WaitFrame", UIParent)
|
||||
E.WaitFrame:SetScript("OnUpdate", E.WaitFunc)
|
||||
|
||||
--Add time before calling a function
|
||||
function E:Delay(delay, func, ...)
|
||||
if type(delay) ~= "number" then
|
||||
error(format("Bad argument #1 to 'Delay' (number expected, got %s)", delay ~= nil and type(delay) or "no value"), 2)
|
||||
elseif type(func) ~= "function" then
|
||||
error(format("Bad argument #2 to 'Delay' (function expected, got %s)", func ~= nil and type(func) or "no value"), 2)
|
||||
end
|
||||
|
||||
local argCount = select("#", ...)
|
||||
|
||||
tinsert(E.WaitTable, {
|
||||
delay,
|
||||
func,
|
||||
argCount > 0 and argCount,
|
||||
argCount == 1 and (...) or argCount > 1 and {...}
|
||||
})
|
||||
|
||||
E.WaitFrame:Show()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function E:StringTitle(str)
|
||||
return gsub(str, "(.)", strupper, 1)
|
||||
end
|
||||
|
||||
E.TimeThreshold = 3
|
||||
|
||||
E.TimeColors = { --aura time colors
|
||||
[0] = "|cffeeeeee", --days
|
||||
[1] = "|cffeeeeee", --hours
|
||||
[2] = "|cffeeeeee", --minutes
|
||||
[3] = "|cffeeeeee", --seconds
|
||||
[4] = "|cfffe0000", --expire (fade timer)
|
||||
[5] = "|cff909090", --mmss
|
||||
[6] = "|cff707070", --hhmm
|
||||
}
|
||||
|
||||
E.TimeFormats = { -- short / indicator color
|
||||
[0] = {"%dd", "%d%sd|r"},
|
||||
[1] = {"%dh", "%d%sh|r"},
|
||||
[2] = {"%dm", "%d%sm|r"},
|
||||
[3] = {"%ds", "%d%ss|r"},
|
||||
[4] = {"%.1fs", "%.1f%ss|r"},
|
||||
[5] = {"%d:%02d", "%d%s:|r%02d"}, --mmss
|
||||
[6] = {"%d:%02d", "%d%s:|r%02d"}, --hhmm
|
||||
}
|
||||
|
||||
for _, x in pairs(E.TimeFormats) do
|
||||
x[3] = gsub(x[1], "s$", "") -- 1 without seconds
|
||||
x[4] = gsub(x[2], "%%ss", "%%s") -- 2 without seconds
|
||||
end
|
||||
|
||||
E.TimeIndicatorColors = {
|
||||
[0] = "|cff00b3ff",
|
||||
[1] = "|cff00b3ff",
|
||||
[2] = "|cff00b3ff",
|
||||
[3] = "|cff00b3ff",
|
||||
[4] = "|cff00b3ff",
|
||||
[5] = "|cff00b3ff",
|
||||
[6] = "|cff00b3ff",
|
||||
}
|
||||
|
||||
local DAY, HOUR, MINUTE = 86400, 3600, 60 --used for calculating aura time text
|
||||
local DAYISH, HOURISH, MINUTEISH = HOUR * 23.5, MINUTE * 59.5, 59.5 --used for caclculating aura time at transition points
|
||||
local HALFDAYISH, HALFHOURISH, HALFMINUTEISH = DAY/2 + 0.5, HOUR/2 + 0.5, MINUTE/2 + 0.5 --used for calculating next update times
|
||||
|
||||
-- will return the the value to display, the formatter id to use and calculates the next update for the Aura
|
||||
function E:GetTimeInfo(s, threshhold, hhmm, mmss)
|
||||
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
|
||||
if mmss and s < mmss then
|
||||
return s/MINUTE, 5, 0.51, s%MINUTE
|
||||
else
|
||||
local minutes = floor((s/MINUTE)+.5)
|
||||
if hhmm and s < (hhmm * MINUTE) and 60 < minutes then
|
||||
return s/HOUR, 6, minutes > 1 and (s - (minutes*MINUTE - HALFMINUTEISH)) or (s - MINUTEISH), minutes%MINUTE
|
||||
else
|
||||
return ceil(s / MINUTE), 2, minutes > 1 and (s - (minutes*MINUTE - HALFMINUTEISH)) or (s - MINUTEISH)
|
||||
end
|
||||
end
|
||||
elseif s < DAY then
|
||||
if mmss and s < mmss then
|
||||
return s/MINUTE, 5, 0.51, s%MINUTE
|
||||
else
|
||||
local minutes = floor((s/MINUTE)+.5)
|
||||
if hhmm and s < (hhmm * MINUTE) and 60 < minutes then
|
||||
return s/HOUR, 6, minutes > 1 and (s - (minutes*MINUTE - HALFMINUTEISH)) or (s - MINUTEISH), minutes%MINUTE
|
||||
else
|
||||
local hours = floor((s/HOUR)+.5)
|
||||
return ceil(s / HOUR), 1, hours > 1 and (s - (hours*HOUR - HALFHOURISH)) or (s - HOURISH)
|
||||
end
|
||||
end
|
||||
else
|
||||
local days = floor((s/DAY)+.5)
|
||||
return ceil(s / DAY), 0, days > 1 and (s - (days*DAY - HALFDAYISH)) or (s - DAYISH)
|
||||
end
|
||||
end
|
||||
|
||||
--Money text formatting, code taken from Scrooge by thelibrarian (http://www.wowace.com/addons/scrooge/)
|
||||
local COLOR_COPPER, COLOR_SILVER, COLOR_GOLD = "|cffeda55f", "|cffc7c7cf", "|cffffd700"
|
||||
local ICON_COPPER = "|TInterface\\MoneyFrame\\UI-CopperIcon:12:12|t"
|
||||
local ICON_SILVER = "|TInterface\\MoneyFrame\\UI-SilverIcon:12:12|t"
|
||||
local ICON_GOLD = "|TInterface\\MoneyFrame\\UI-GoldIcon:12:12|t"
|
||||
function E:FormatMoney(amount, style, textonly)
|
||||
local coppername = textonly and L["copperabbrev"] or ICON_COPPER
|
||||
local silvername = textonly and L["silverabbrev"] or ICON_SILVER
|
||||
local goldname = textonly and L["goldabbrev"] or ICON_GOLD
|
||||
|
||||
local value = abs(amount)
|
||||
local gold = floor(value / 10000)
|
||||
local silver = floor(fmod(value / 100, 100))
|
||||
local copper = floor(fmod(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
|
||||
|
||||
-- Shouldn't be here; punt
|
||||
return self:FormatMoney(amount, "SMART")
|
||||
end
|
||||
@@ -0,0 +1,276 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local MC = E:GetModule("ModuleCopy")
|
||||
|
||||
--Lua functions
|
||||
local pairs, next, type = pairs, next, type
|
||||
local format, error = format, error
|
||||
--WoW API / Variables
|
||||
-- GLOBALS: ElvDB
|
||||
|
||||
--This table to reserve settings names in E.global.profileCopy. Used in export/imports functions
|
||||
--Pligins can add own values for their internal settings for safechecks here
|
||||
MC.InternalOptions = {
|
||||
["selected"] = true,
|
||||
["movers"] = true,
|
||||
}
|
||||
|
||||
--Default template for a config group for a single module.
|
||||
--Contains header, general group toggle (shown only if the setting actually exists) and imports button.
|
||||
--Usage as seen in ElvUI_OptionsUI\modulecopy.lua
|
||||
function MC:CreateModuleConfigGroup(Name, section, pluginSection)
|
||||
local config = {
|
||||
order = 10,
|
||||
type = "group",
|
||||
name = Name,
|
||||
args = {
|
||||
header = {
|
||||
order = 0,
|
||||
type = "header",
|
||||
name = Name
|
||||
},
|
||||
general = {
|
||||
order = 1,
|
||||
type = "toggle",
|
||||
name = L["General"]
|
||||
},
|
||||
PreButtonSpacer = {
|
||||
order = 200,
|
||||
type = "description",
|
||||
name = ""
|
||||
},
|
||||
import = {
|
||||
order = 201,
|
||||
type = "execute",
|
||||
name = L["Import Now"],
|
||||
func = function()
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.text = format(L["You are going to copy settings for |cffD3CF00\"%s\"|r from |cff4beb2c\"%s\"|r profile to your current |cff4beb2c\"%s\"|r profile. Are you sure?"], Name, E.global.profileCopy.selected, ElvDB.profileKeys[E.myname.." - "..E.myrealm])
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.OnAccept = function()
|
||||
MC:ImportFromProfile(section, pluginSection)
|
||||
end
|
||||
E:StaticPopup_Show("MODULE_COPY_CONFIRM")
|
||||
end
|
||||
},
|
||||
export = {
|
||||
order = 202,
|
||||
type = "execute",
|
||||
name = L["Export Now"],
|
||||
func = function()
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.text = format(L["You are going to copy settings for |cffD3CF00\"%s\"|r from your current |cff4beb2c\"%s\"|r profile to |cff4beb2c\"%s\"|r profile. Are you sure?"], Name, ElvDB.profileKeys[E.myname.." - "..E.myrealm], E.global.profileCopy.selected)
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.OnAccept = function()
|
||||
MC:ExportToProfile(section, pluginSection)
|
||||
end
|
||||
E:StaticPopup_Show("MODULE_COPY_CONFIRM")
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
if pluginSection then
|
||||
config.args.general.hidden = function(info) return E.global.profileCopy[pluginSection][section][ info[#info] ] == nil end
|
||||
config.args.general.get = function(info) return E.global.profileCopy[pluginSection][section][ info[#info] ] end
|
||||
config.args.general.set = function(info, value) E.global.profileCopy[pluginSection][section][ info[#info] ] = value end
|
||||
else
|
||||
config.args.general.hidden = function(info) return E.global.profileCopy[section][ info[#info] ] == nil end
|
||||
config.args.general.get = function(info) return E.global.profileCopy[section][ info[#info] ] end
|
||||
config.args.general.set = function(info, value) E.global.profileCopy[section][ info[#info] ] = value end
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
function MC:CreateMoversConfigGroup()
|
||||
local config = {
|
||||
header = {
|
||||
order = 0,
|
||||
type = "header",
|
||||
name = L["On screen positions for different elements."]
|
||||
},
|
||||
PreButtonSpacer = {
|
||||
order = 200,
|
||||
type = "description",
|
||||
name = ""
|
||||
},
|
||||
import = {
|
||||
order = 201,
|
||||
type = "execute",
|
||||
name = L["Import Now"],
|
||||
func = function()
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.text = format(L["You are going to copy settings for |cffD3CF00\"%s\"|r from |cff4beb2c\"%s\"|r profile to your current |cff4beb2c\"%s\"|r profile. Are you sure?"], L["Movers"], E.global.profileCopy.selected, ElvDB.profileKeys[E.myname.." - "..E.myrealm])
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.OnAccept = function()
|
||||
MC:CopyMovers("import")
|
||||
end
|
||||
E:StaticPopup_Show("MODULE_COPY_CONFIRM")
|
||||
end
|
||||
},
|
||||
export = {
|
||||
order = 202,
|
||||
type = "execute",
|
||||
name = L["Export Now"],
|
||||
func = function()
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.text = format(L["You are going to copy settings for |cffD3CF00\"%s\"|r from your current |cff4beb2c\"%s\"|r profile to |cff4beb2c\"%s\"|r profile. Are you sure?"], L["Movers"], ElvDB.profileKeys[E.myname.." - "..E.myrealm], E.global.profileCopy.selected)
|
||||
E.PopupDialogs.MODULE_COPY_CONFIRM.OnAccept = function()
|
||||
MC:CopyMovers("export")
|
||||
end
|
||||
E:StaticPopup_Show("MODULE_COPY_CONFIRM")
|
||||
end
|
||||
}
|
||||
}
|
||||
for moverName, data in pairs(E.CreatedMovers) do
|
||||
if not G.profileCopy.movers[moverName] then G.profileCopy.movers[moverName] = false end
|
||||
config[moverName] = {
|
||||
order = 1,
|
||||
type = "toggle",
|
||||
name = data.text,
|
||||
get = function(info) return E.global.profileCopy.movers[moverName] end,
|
||||
set = function(info, value) E.global.profileCopy.movers[moverName] = value end
|
||||
}
|
||||
end
|
||||
for moverName, data in pairs(E.DisabledMovers) do
|
||||
if not G.profileCopy.movers[moverName] then G.profileCopy.movers[moverName] = false end
|
||||
config[moverName] = {
|
||||
order = 1,
|
||||
type = "toggle",
|
||||
name = data.text,
|
||||
get = function(info) return E.global.profileCopy.movers[moverName] end,
|
||||
set = function(info, value) E.global.profileCopy.movers[moverName] = value end
|
||||
}
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
function MC:CopyTable(CopyFrom, CopyTo, CopyDefault, module)
|
||||
for key, value in pairs(CopyTo) do
|
||||
if type(value) ~= "table" then
|
||||
if module == true or (type(module) == "table" and (module.general == nil or (not CopyTo.general and module.general))) then --Some dark magic of a logic to figure out stuff
|
||||
--This check is to see if the profile we are copying from has keys absent from defaults.
|
||||
--If key exists, then copy. If not, then clear obsolite key from the profile.
|
||||
if CopyDefault[key] ~= nil then
|
||||
CopyTo[key] = CopyFrom[key] or CopyDefault[key]
|
||||
else
|
||||
CopyFrom[key] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
if module == true then --Copy over entire section of profile subgroup
|
||||
E:CopyTable(CopyTo, CopyDefault)
|
||||
E:CopyTable(CopyTo, CopyFrom)
|
||||
elseif type(module) == "table" and module[key] ~= nil then
|
||||
--Making sure tables actually exist in profiles (e.g absent values in ElvDB.profiles are for default values)
|
||||
CopyFrom[key], CopyTo[key] = MC:TablesExist(CopyFrom[key], CopyTo[key], CopyDefault[key])
|
||||
--If key exists, then copy. If not, then clear obsolite key from the profile.
|
||||
--Someone should double check this logic. Cause for single keys it is fine, but I'm no sure bout whole tables @Darth
|
||||
if CopyFrom[key] ~= nil then
|
||||
MC:CopyTable(CopyFrom[key], CopyTo[key], CopyDefault[key], module[key])
|
||||
else
|
||||
CopyTo[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
* Valid copy templates should be as follows
|
||||
G.profileCopy[YourOptionGroupName] = {
|
||||
[SubGroupName1] = true,
|
||||
[SubGroupName2] = true,
|
||||
...
|
||||
}
|
||||
* For example
|
||||
G.profileCopy.auras = {
|
||||
["general"] = true,
|
||||
["buffs"] = true,
|
||||
["debuffs"] = true,
|
||||
["cooldown"] = true,
|
||||
}
|
||||
* "general" key can refer to a similar named subtable or all non-table variables inside your group
|
||||
* If you leave the table as G.profileCopy[YourOptionGroupName] = {}, this will result in no valid copy template error.
|
||||
* If set to G.profileCopy[YourOptionGroupName] = true, then this will copy everything without selecting
|
||||
any particular subcategory from your settings table.
|
||||
* Plugins can use "pluginSection" argument to determain their own table if they keep settings apart from core ElvUI settings.
|
||||
Examples S&L uses "sle" table, MerathilisUI uses "mui" table, BenikUI uses "benikui" and core table
|
||||
]]
|
||||
|
||||
function MC:TablesExist(CopyFrom, CopyTo, CopyDefault)
|
||||
if not CopyFrom then CopyFrom = CopyDefault end
|
||||
if not CopyTo then CopyTo = CopyDefault end
|
||||
return CopyFrom, CopyTo
|
||||
end
|
||||
|
||||
function MC:ImportFromProfile(section, pluginSection)
|
||||
--Some checks for the occasion someone passes wrong stuff
|
||||
if not section then error("No profile section provided. Usage MC:ImportFromProfile(\"section\")") end
|
||||
if not pluginSection and MC.InternalOptions[section] then error(format("Section name could not be \"%s\". This name is reserved for internal setting"), section) end
|
||||
if pluginSection and (MC.InternalOptions[pluginSection] and MC.InternalOptions[pluginSection][section]) then error(format("Section name for plugin group \"%s\" could not be \"%s\". This name is reserved for internal setting"), pluginSection, section) end
|
||||
|
||||
local module = pluginSection and E.global.profileCopy[pluginSection][section] or E.global.profileCopy[section]
|
||||
if not module then error(format("Provided section name \"%s\" does not have a template for profile copy.", section)) end
|
||||
--Starting digging through the settings
|
||||
local CopyFrom = pluginSection and (ElvDB.profiles[E.global.profileCopy.selected][pluginSection] and ElvDB.profiles[E.global.profileCopy.selected][pluginSection][section] or P[pluginSection][section]) or ElvDB.profiles[E.global.profileCopy.selected][section]
|
||||
local CopyTo = pluginSection and E.db[pluginSection][section] or E.db[section]
|
||||
local CopyDefault = pluginSection and P[pluginSection][section] or P[section]
|
||||
--Making sure tables actually exist in profiles (e.g absent values in ElvDB.profiles are for default values)
|
||||
CopyFrom, CopyTo = MC:TablesExist(CopyFrom, CopyTo, CopyDefault)
|
||||
if type(module) == "table" and next(module) then --This module is not an empty table
|
||||
MC:CopyTable(CopyFrom, CopyTo, CopyDefault, module)
|
||||
elseif type(module) == "boolean" then --Copy over entire section of profile subgroup
|
||||
E:CopyTable(CopyTo, CopyDefault)
|
||||
E:CopyTable(CopyTo, CopyFrom)
|
||||
else
|
||||
error(format("Provided section name \"%s\" does not have a valid copy template.", section))
|
||||
end
|
||||
E:UpdateAll(true)
|
||||
end
|
||||
|
||||
function MC:ExportToProfile(section, pluginSection)
|
||||
--Some checks for the occasion someone passes wrong stuff
|
||||
if not section then error("No profile section provided. Usage MC:ExportToProfile(\"section\")") end
|
||||
if not pluginSection and MC.InternalOptions[section] then error(format("Section name could not be \"%s\". This name is reserved for internal setting"), section) end
|
||||
if pluginSection and MC.InternalOptions[pluginSection][section] then error(format("Section name for plugin group \"%s\" could not be \"%s\". This name is reserved for internal setting"), pluginSection, section) end
|
||||
|
||||
local module = pluginSection and E.global.profileCopy[pluginSection][section] or E.global.profileCopy[section]
|
||||
if not module then error(format("Provided section name \"%s\" does not have a template for profile copy.", section)) end
|
||||
--Making sure tables actually exist
|
||||
if not ElvDB.profiles[E.global.profileCopy.selected][section] then ElvDB.profiles[E.global.profileCopy.selected][section] = {} end
|
||||
if not E.db[section] then E.db[section] = {} end
|
||||
--Starting digging through the settings
|
||||
local CopyFrom = pluginSection and E.db[pluginSection][section] or E.db[section]
|
||||
local CopyTo = pluginSection and ElvDB.profiles[E.global.profileCopy.selected][pluginSection][section] or ElvDB.profiles[E.global.profileCopy.selected][section]
|
||||
local CopyDefault = pluginSection and P[pluginSection][section] or P[section]
|
||||
if type(module) == "table" and next(module) then --This module is not an empty table
|
||||
MC:CopyTable(CopyFrom, CopyTo, CopyDefault, module)
|
||||
elseif type(module) == "boolean" then --Copy over entire section of profile subgroup
|
||||
E:CopyTable(CopyTo, CopyDefault)
|
||||
E:CopyTable(CopyTo, CopyFrom)
|
||||
else
|
||||
error(format("Provided section name \"%s\" does not have a valid copy template.", section))
|
||||
end
|
||||
end
|
||||
|
||||
function MC:CopyMovers(mode)
|
||||
if not E.db.movers then E.db.movers = {} end --Nothing was moved in cutrrent profile
|
||||
if not ElvDB.profiles[E.global.profileCopy.selected].movers then ElvDB.profiles[E.global.profileCopy.selected].movers = {} end --Nothing was moved in selected profile
|
||||
local CopyFrom, CopyTo
|
||||
if mode == "export" then
|
||||
CopyFrom, CopyTo = E.db.movers, ElvDB.profiles[E.global.profileCopy.selected].movers
|
||||
else
|
||||
CopyFrom, CopyTo = ElvDB.profiles[E.global.profileCopy.selected].movers or {}, E.db.movers
|
||||
end
|
||||
|
||||
for moverName in pairs(E.CreatedMovers) do
|
||||
if E.global.profileCopy.movers[moverName] then
|
||||
CopyTo[moverName] = CopyFrom[moverName]
|
||||
end
|
||||
end
|
||||
E:SetMoversPositions()
|
||||
end
|
||||
|
||||
function MC:Initialize()
|
||||
self.Initialized = true
|
||||
end
|
||||
|
||||
local function InitializeCallback()
|
||||
MC:Initialize()
|
||||
end
|
||||
|
||||
E:RegisterModule(MC:GetName(), InitializeCallback)
|
||||
@@ -0,0 +1,527 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local Sticky = E.Libs.SimpleSticky
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local type, unpack, pairs, error = type, unpack, pairs, error
|
||||
local format, split, find = format, strsplit, strfind
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsControlKeyDown = IsControlKeyDown
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local ERR_NOT_IN_COMBAT = ERR_NOT_IN_COMBAT
|
||||
|
||||
E.CreatedMovers = {}
|
||||
E.DisabledMovers = {}
|
||||
|
||||
local function SizeChanged(frame)
|
||||
if InCombatLockdown() then return end
|
||||
|
||||
if frame.dirtyWidth and frame.dirtyHeight then
|
||||
frame.mover:Size(frame.dirtyWidth, frame.dirtyHeight)
|
||||
else
|
||||
frame.mover:Size(frame:GetSize())
|
||||
end
|
||||
end
|
||||
|
||||
local function GetPoint(obj)
|
||||
local point, anchor, secondaryPoint, x, y = obj:GetPoint()
|
||||
if not anchor then anchor = E.UIParent 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:Point(nudgePoint, mover, nudgeInversePoint, coordX, coordY)
|
||||
E:UpdateNudgeFrame(mover, x, y)
|
||||
end
|
||||
|
||||
local isDragging = false
|
||||
local coordFrame = CreateFrame("Frame")
|
||||
coordFrame:SetScript("OnUpdate", UpdateCoords)
|
||||
coordFrame:Hide()
|
||||
|
||||
local function CreateMover(parent, name, text, overlay, snapOffset, postdrag, shouldDisable, configString)
|
||||
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))
|
||||
|
||||
--Use dirtyWidth / dirtyHeight to set initial size if possible
|
||||
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:Width(width)
|
||||
f:Height(height)
|
||||
f:SetTemplate("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.configString = configString
|
||||
|
||||
f:SetFrameLevel(parent:GetFrameLevel() + 1)
|
||||
if overlay == true then
|
||||
f:SetFrameStrata("DIALOG")
|
||||
else
|
||||
f:SetFrameStrata("BACKGROUND")
|
||||
end
|
||||
|
||||
E.CreatedMovers[name].mover = f
|
||||
E.snapBars[#E.snapBars + 1] = f
|
||||
|
||||
local fs = f:CreateFontString(nil, "OVERLAY")
|
||||
fs:FontTemplate()
|
||||
fs:SetJustifyH("CENTER")
|
||||
fs:Point("CENTER")
|
||||
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:Point(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
|
||||
|
||||
--Backward compatibility
|
||||
local delim
|
||||
local anchorString = E.db.movers[name]
|
||||
if find(anchorString, "\031") then
|
||||
delim = "\031"
|
||||
elseif find(anchorString, ",") then
|
||||
delim = ","
|
||||
end
|
||||
|
||||
local point1, anchor1, secondaryPoint1, x1, y1 = split(delim, anchorString)
|
||||
f:Point(point1, anchor1, secondaryPoint1, x1, y1)
|
||||
f.anchor = anchor
|
||||
else
|
||||
f:Point(point, anchor, secondaryPoint, x, y)
|
||||
end
|
||||
|
||||
local function OnDragStart(self)
|
||||
if InCombatLockdown() then E:Print(ERR_NOT_IN_COMBAT) return end
|
||||
|
||||
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)
|
||||
if InCombatLockdown() then E:Print(ERR_NOT_IN_COMBAT) return end
|
||||
isDragging = false
|
||||
if E.db.general.stickyFrames then
|
||||
Sticky:StopMoving(self)
|
||||
else
|
||||
self:StopMovingOrSizing()
|
||||
end
|
||||
|
||||
local x2, y2, point2 = 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:Point(self.positionOverride or point2, E.UIParent, overridePoint and overridePoint or point2, x2, y2)
|
||||
if self.positionOverride then
|
||||
self.parent:ClearAllPoints()
|
||||
self.parent:Point(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(self)
|
||||
if isDragging then return end
|
||||
|
||||
self.text:SetTextColor(1, 1, 1)
|
||||
E.AssignFrameToNudge(self)
|
||||
coordFrame.child = self
|
||||
coordFrame:GetScript("OnUpdate")(coordFrame)
|
||||
end
|
||||
|
||||
local function OnMouseDown(self, button)
|
||||
if button == "LeftButton" and not isDragging then
|
||||
if ElvUIMoverNudgeWindow:IsShown() then
|
||||
ElvUIMoverNudgeWindow:Hide()
|
||||
else
|
||||
ElvUIMoverNudgeWindow:Show()
|
||||
end
|
||||
elseif button == "RightButton" then
|
||||
isDragging = false
|
||||
if E.db.general.stickyFrames then
|
||||
Sticky:StopMoving(self)
|
||||
else
|
||||
self:StopMovingOrSizing()
|
||||
end
|
||||
|
||||
--Allow resetting of anchor by Ctrl+RightClick
|
||||
if IsControlKeyDown() and self.textString then
|
||||
E:ResetMovers(self.textString)
|
||||
elseif IsShiftKeyDown() then --Allow hiding a mover temporarily
|
||||
self:Hide()
|
||||
elseif self.configString then --OpenConfig
|
||||
E:ToggleOptionsUI(self.configString)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnLeave(self)
|
||||
if isDragging then return end
|
||||
self.text:SetTextColor(unpack(E.media.rgbvaluecolor))
|
||||
end
|
||||
|
||||
local function OnShow(self)
|
||||
self: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", OnDragStart)
|
||||
f:SetScript("OnMouseUp", E.AssignFrameToNudge)
|
||||
f:SetScript("OnDragStop", OnDragStop)
|
||||
f:SetScript("OnEnter", OnEnter)
|
||||
f:SetScript("OnMouseDown", OnMouseDown)
|
||||
f:SetScript("OnLeave", OnLeave)
|
||||
f:SetScript("OnShow", OnShow)
|
||||
f:SetScript("OnMouseWheel", OnMouseWheel)
|
||||
|
||||
parent:SetScript("OnSizeChanged", SizeChanged)
|
||||
parent.mover = f
|
||||
|
||||
parent:ClearAllPoints()
|
||||
parent:Point(point, f, 0, 0)
|
||||
|
||||
if postdrag ~= nil and type(postdrag) == "function" then
|
||||
f:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
f:SetScript("OnEvent", function(self)
|
||||
postdrag(f, E:GetScreenQuadrant(f))
|
||||
self: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 and (E.diffGetLeft and E.diffGetRight and E.diffGetTop and E.diffGetBottom) 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
|
||||
|
||||
--Update coordinates if nudged
|
||||
x = x + (nudgeX or 0)
|
||||
y = y + (nudgeY or 0)
|
||||
|
||||
return x, y, point, nudgePoint, nudgeInversePoint
|
||||
end
|
||||
|
||||
function E:UpdatePositionOverride(name)
|
||||
local frame = _G[name]
|
||||
local OnDragStop = frame and frame.GetScript and frame:GetScript("OnDragStop")
|
||||
if OnDragStop then OnDragStop(frame) 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
|
||||
|
||||
local mover = _G[name]
|
||||
local _, anchor = mover:GetPoint()
|
||||
mover.anchor = anchor:GetName()
|
||||
|
||||
E.db.movers[name] = GetPoint(mover)
|
||||
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, configString)
|
||||
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].configString = configString
|
||||
|
||||
E.CreatedMovers[name].type = {}
|
||||
local types = {split(",", moverTypes)}
|
||||
for i = 1, #types do
|
||||
local moverType = types[i]
|
||||
E.CreatedMovers[name].type[moverType] = true
|
||||
end
|
||||
end
|
||||
|
||||
CreateMover(parent, name, text, overlay, snapoffset, postdrag, shouldDisable, configString)
|
||||
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
|
||||
|
||||
--Make sure we add anchor information from a potential profile switch
|
||||
--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:Point(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:Point(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()
|
||||
--E:SetMoversPositions() is the first function called in E:UpdateAll().
|
||||
--Because of that, we can allow ourselves to re-enable all disabled movers here,
|
||||
--as the subsequent updates to these elements will disable them again if needed.
|
||||
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
|
||||
--Backward compatibility
|
||||
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:Point(point, anchor, secondaryPoint, x, y)
|
||||
elseif f then
|
||||
point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name].point)
|
||||
f:ClearAllPoints()
|
||||
f:Point(point, anchor, secondaryPoint, x, y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function E:SetMoversClampedToScreen(value)
|
||||
for name in pairs(E.CreatedMovers) do
|
||||
_G[name]:SetClampedToScreen(value)
|
||||
end
|
||||
end
|
||||
|
||||
--Called from core.lua
|
||||
function E:LoadMovers()
|
||||
for name, t in pairs(E.CreatedMovers) do
|
||||
CreateMover(t.parent, name, t.text, t.overlay, t.snapoffset, t.postdrag, t.shouldDisable, t.configString)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,91 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
--Lua functions
|
||||
local min, max, abs, floor = min, max, abs, floor
|
||||
--WoW API / Variables
|
||||
local UIParent = UIParent
|
||||
|
||||
function E:IsEyefinity(width, height)
|
||||
if E.global.general.eyefinity and width >= 3840 then
|
||||
--HQ resolution
|
||||
if width >= 9840 then return 3280 end --WQSXGA
|
||||
if width >= 7680 and width < 9840 then return 2560 end --WQXGA
|
||||
if width >= 5760 and width < 7680 then return 1920 end --WUXGA & HDTV
|
||||
if width >= 5040 and width < 5760 then return 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 return 1600 end --UXGA & HD+
|
||||
|
||||
--low resolution screen
|
||||
if width >= 4320 and width < 4800 then return 1440 end --WSXGA
|
||||
if width >= 4080 and width < 4320 then return 1360 end --WXGA
|
||||
if width >= 3840 and width < 4080 then return 1224 end --SXGA & SXGA (UVGA) & WXGA & HDTV
|
||||
end
|
||||
end
|
||||
|
||||
function E:UIScale(init)
|
||||
local scale = E.global.general.UIScale
|
||||
if init then --E.OnInitialize
|
||||
--Set variables for pixel scaling
|
||||
local pixel, ratio = 1, 768 / E.screenheight
|
||||
E.mult = (pixel / scale) - ((pixel - ratio) / scale)
|
||||
E.Spacing = (E.PixelMode and 0) or E.mult
|
||||
E.Border = ((not E.twoPixelsPlease) and E.PixelMode and E.mult) or E.mult*2
|
||||
else --E.Initialize
|
||||
UIParent:SetScale(scale)
|
||||
|
||||
--Check if we are using `E.eyefinity`
|
||||
local width, height = E.screenwidth, E.screenheight
|
||||
E.eyefinity = E:IsEyefinity(width, height)
|
||||
|
||||
--Resize E.UIParent if Eyefinity is on.
|
||||
local testingEyefinity = false
|
||||
if testingEyefinity then
|
||||
--Eyefinity Test: 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.
|
||||
local uiWidth, uiHeight = UIParent:GetSize()
|
||||
width, height = uiWidth - 250, uiHeight - 250
|
||||
elseif E.eyefinity then
|
||||
--find a new width value of E.UIParent for screen #1.
|
||||
local uiHeight = UIParent:GetHeight()
|
||||
width, height = E.eyefinity / (height / uiHeight), uiHeight
|
||||
else
|
||||
width, height = UIParent:GetSize()
|
||||
end
|
||||
|
||||
E.UIParent:SetSize(width, height)
|
||||
E.UIParent.origHeight = E.UIParent:GetHeight()
|
||||
|
||||
--Calculate potential coordinate differences
|
||||
E.diffGetLeft = E:Round(abs(UIParent:GetLeft() - E.UIParent:GetLeft()))
|
||||
E.diffGetRight = E:Round(abs(UIParent:GetRight() - E.UIParent:GetRight()))
|
||||
E.diffGetBottom = E:Round(abs(UIParent:GetBottom() - E.UIParent:GetBottom()))
|
||||
E.diffGetTop = E:Round(abs(UIParent:GetTop() - E.UIParent:GetTop()))
|
||||
end
|
||||
end
|
||||
|
||||
function E:PixelBestSize()
|
||||
return max(0.4, min(1.15, 768 / E.screenheight))
|
||||
end
|
||||
|
||||
function E:PixelScaleChanged(event, skip)
|
||||
E:UIScale(true) -- repopulate variables
|
||||
E:UIScale() -- setup the scale
|
||||
|
||||
E:UpdateConfigSize(true) -- reposition config
|
||||
|
||||
if skip or E.global.general.ignoreScalePopup then return end
|
||||
|
||||
if event == "UPDATE_FLOATING_CHAT_WINDOWS" then return end
|
||||
|
||||
if event == "UISCALE_CHANGE" then
|
||||
E:Delay(0.5, E.StaticPopup_Show, E, event)
|
||||
else
|
||||
E:StaticPopup_Show("UISCALE_CHANGE")
|
||||
end
|
||||
end
|
||||
|
||||
function E:Scale(x)
|
||||
local mult = E.mult
|
||||
return mult * floor(x / mult + 0.5)
|
||||
end
|
||||
@@ -0,0 +1,458 @@
|
||||
--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() <Do Some Stuff> end)
|
||||
PluginInstallFrame.Option1:SetText("Text 1")
|
||||
|
||||
PluginInstallFrame.Option2:Show()
|
||||
PluginInstallFrame.Option2:SetScript("OnClick", function() <Do Some Other Stuff> 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(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB, Localize Underscore
|
||||
local PI = E:GetModule("PluginInstaller")
|
||||
local S = E:GetModule("Skins")
|
||||
|
||||
--Lua functions
|
||||
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 CONTINUE, PREVIOUS, UNKNOWN = CONTINUE, PREVIOUS, 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:Size(550, 400)
|
||||
if f.StepTitles then
|
||||
for i = 1, #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, #f.side.Lines do
|
||||
local button = f.side.Lines[i]
|
||||
local color
|
||||
button.text:SetText(f.StepTitles[i])
|
||||
if i == f.CurrentPage then
|
||||
color = f.StepTitlesColorSelected or {0.09, 0.52, 0.82}
|
||||
else
|
||||
color = f.StepTitlesColor or {1, 1, 1}
|
||||
end
|
||||
button.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:Size(418, 72)
|
||||
imsg:Point("TOP", 0, -190)
|
||||
imsg:Hide()
|
||||
imsg:SetScript("OnShow", function(frame)
|
||||
if frame.message then
|
||||
PlaySoundFile([[Sound\Interface\LevelUp.wav]])
|
||||
frame.text:SetText(frame.message)
|
||||
UIFrameFadeOut(frame, 3.5, 1, 0)
|
||||
E:Delay(4, frame.Hide, frame)
|
||||
frame.message = nil
|
||||
else
|
||||
frame:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
imsg.firstShow = false
|
||||
|
||||
imsg.bg = imsg:CreateTexture(nil, "BACKGROUND")
|
||||
imsg.bg:SetTexture([[Interface\LevelUp\LevelUpTex]])
|
||||
imsg.bg:SetPoint("BOTTOM")
|
||||
imsg.bg:Size(326, 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")
|
||||
imsg.lineTop:Size(418, 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")
|
||||
imsg.lineBottom:Size(418, 7)
|
||||
imsg.lineBottom:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)
|
||||
|
||||
imsg.text = imsg:CreateFontString(nil, "ARTWORK")
|
||||
imsg.text:FontTemplate(E.media.normFont, 32, "OUTLINE")
|
||||
imsg.text:Point("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:Size(550, 400)
|
||||
f:SetTemplate("Transparent")
|
||||
f:SetPoint("CENTER")
|
||||
f:SetFrameStrata("TOOLTIP")
|
||||
|
||||
f.Title = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Title:FontTemplate(nil, 17, nil)
|
||||
f.Title:Point("TOP", 0, -5)
|
||||
|
||||
f.Next = CreateFrame("Button", "PluginInstallNextButton", f, "UIPanelButtonTemplate")
|
||||
f.Next:Size(110, 25)
|
||||
f.Next:Point("BOTTOMRIGHT", -5, 5)
|
||||
f.Next:SetText(CONTINUE)
|
||||
f.Next:Disable()
|
||||
f.Next:SetScript("OnClick", NextPage)
|
||||
S:HandleButton(f.Next, true)
|
||||
|
||||
f.Prev = CreateFrame("Button", "PluginInstallPrevButton", f, "UIPanelButtonTemplate")
|
||||
f.Prev:Size(110, 25)
|
||||
f.Prev:Point("BOTTOMLEFT", 5, 5)
|
||||
f.Prev:SetText(PREVIOUS)
|
||||
f.Prev:Disable()
|
||||
f.Prev:SetScript("OnClick", PreviousPage)
|
||||
S:HandleButton(f.Prev, true)
|
||||
|
||||
f.Status = CreateFrame("StatusBar", "PluginInstallStatus", f)
|
||||
f.Status:SetFrameLevel(f.Status:GetFrameLevel() + 2)
|
||||
f.Status:CreateBackdrop("Default", true)
|
||||
f.Status:SetStatusBarTexture(E.media.normTex)
|
||||
f.Status:SetStatusBarColor(unpack(E.media.rgbvaluecolor))
|
||||
f.Status:Point("TOPLEFT", f.Prev, "TOPRIGHT", 6, -2)
|
||||
f.Status:Point("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:SetEasing("Out")
|
||||
f.Status.anim.progress:SetDuration(.3)
|
||||
|
||||
f.Status.text = f.Status:CreateFontString(nil, "OVERLAY")
|
||||
f.Status.text:FontTemplate()
|
||||
f.Status.text:SetPoint("CENTER")
|
||||
|
||||
f.Option1 = CreateFrame("Button", "PluginInstallOption1Button", f, "UIPanelButtonTemplate")
|
||||
f.Option1:Size(160, 30)
|
||||
f.Option1:Point("BOTTOM", 0, 45)
|
||||
f.Option1:SetText("")
|
||||
f.Option1:Hide()
|
||||
S:HandleButton(f.Option1, true)
|
||||
|
||||
f.Option2 = CreateFrame("Button", "PluginInstallOption2Button", f, "UIPanelButtonTemplate")
|
||||
f.Option2:Size(110, 30)
|
||||
f.Option2:Point("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:Point("BOTTOMRIGHT", f, "BOTTOM", -4, 45) end)
|
||||
f.Option2:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:Point("BOTTOM", 0, 45) end)
|
||||
S:HandleButton(f.Option2, true)
|
||||
|
||||
f.Option3 = CreateFrame("Button", "PluginInstallOption3Button", f, "UIPanelButtonTemplate")
|
||||
f.Option3:Size(100, 30)
|
||||
f.Option3:Point("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:Point("RIGHT", f.Option2, "LEFT", -4, 0) f.Option2:SetWidth(100) f.Option2:ClearAllPoints() f.Option2:Point("BOTTOM", f, "BOTTOM", 0, 45) end)
|
||||
f.Option3:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:Point("BOTTOM", 0, 45) f.Option2:SetWidth(110) f.Option2:ClearAllPoints() f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
|
||||
S:HandleButton(f.Option3, true)
|
||||
|
||||
f.Option4 = CreateFrame("Button", "PluginInstallOption4Button", f, "UIPanelButtonTemplate")
|
||||
f.Option4:Size(100, 30)
|
||||
f.Option4:Point("LEFT", f.Option3, "RIGHT", 4, 0)
|
||||
f.Option4:SetText("")
|
||||
f.Option4:Hide()
|
||||
f.Option4:SetScript("OnShow", function()
|
||||
f.Option1:Width(100)
|
||||
f.Option2:Width(100)
|
||||
|
||||
f.Option1:ClearAllPoints()
|
||||
f.Option1:Point("RIGHT", f.Option2, "LEFT", -4, 0)
|
||||
f.Option2:ClearAllPoints()
|
||||
f.Option2:Point("BOTTOMRIGHT", f, "BOTTOM", -4, 45)
|
||||
end)
|
||||
f.Option4:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:Point("BOTTOM", 0, 45) f.Option2:SetWidth(110) f.Option2:ClearAllPoints() f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
|
||||
S:HandleButton(f.Option4, true)
|
||||
|
||||
f.SubTitle = f:CreateFontString(nil, "OVERLAY")
|
||||
f.SubTitle:FontTemplate(nil, 15, nil)
|
||||
f.SubTitle:Point("TOP", 0, -40)
|
||||
|
||||
f.Desc1 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc1:FontTemplate()
|
||||
f.Desc1:Point("TOPLEFT", 20, -75)
|
||||
f.Desc1:Width(f:GetWidth() - 40)
|
||||
|
||||
f.Desc2 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc2:FontTemplate()
|
||||
f.Desc2:Point("TOP", f.Desc1, "BOTTOM", 0, -20)
|
||||
f.Desc2:Width(f:GetWidth() - 40)
|
||||
|
||||
f.Desc3 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc3:FontTemplate()
|
||||
f.Desc3:Point("TOP", f.Desc2, "BOTTOM", 0, -20)
|
||||
f.Desc3:Width(f:GetWidth() - 40)
|
||||
|
||||
f.Desc4 = f:CreateFontString(nil, "OVERLAY")
|
||||
f.Desc4:FontTemplate()
|
||||
f.Desc4:Point("TOP", f.Desc3, "BOTTOM", 0, -20)
|
||||
f.Desc4:Width(f:GetWidth() - 40)
|
||||
|
||||
local close = CreateFrame("Button", "PluginInstallCloseButton", f, "UIPanelCloseButton")
|
||||
close:SetPoint("TOPRIGHT", f, "TOPRIGHT")
|
||||
close:SetScript("OnClick", function() f:Hide() end)
|
||||
S:HandleCloseButton(close)
|
||||
|
||||
f.pending = CreateFrame("Frame", "PluginInstallPendingButton", f)
|
||||
f.pending:Size(20, 20)
|
||||
f.pending:SetPoint("TOPLEFT", f, "TOPLEFT", 8, -8)
|
||||
f.pending.tex = f.pending:CreateTexture(nil, "OVERLAY")
|
||||
f.pending.tex:Point("TOPLEFT", f.pending, "TOPLEFT", 2, -2)
|
||||
f.pending.tex:Point("BOTTOMRIGHT", f.pending, "BOTTOMRIGHT", -2, 2)
|
||||
f.pending.tex:SetTexture([[Interface\OptionsFrame\UI-OptionsFrame-NewFeatureIcon]])
|
||||
f.pending:CreateBackdrop("Transparent")
|
||||
f.pending:SetScript("OnEnter", function(self)
|
||||
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT", E.PixelMode and -7 or -9)
|
||||
GameTooltip:AddLine(L["List of installations in queue:"], 1, 1, 1)
|
||||
GameTooltip:AddLine(" ")
|
||||
for i = 1, #PI.Installs do
|
||||
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
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
f.pending:SetScript("OnLeave", function()
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
|
||||
f.tutorialImage = f:CreateTexture("PluginInstallTutorialImage", "OVERLAY")
|
||||
f.tutorialImage:Size(256, 128)
|
||||
f.tutorialImage:Point("BOTTOM", 0, 70)
|
||||
|
||||
f.side = CreateFrame("Frame", "PluginInstallTitleFrame", f)
|
||||
f.side:SetTemplate("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:Width(140)
|
||||
f.side.text = f.side:CreateFontString(nil, "OVERLAY")
|
||||
f.side.text:SetPoint("TOP", f.side, "TOP", 0, -4)
|
||||
f.side.text:FontTemplate(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:SetSize(130, 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:FontTemplate(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, #(self.Installs)+1, addon)
|
||||
self:RunInstall()
|
||||
end
|
||||
end
|
||||
|
||||
function PI:CloseInstall()
|
||||
tremove(self.Installs, 1)
|
||||
f.side:Hide()
|
||||
for i = 1, #f.side.Lines do
|
||||
f.side.Lines[i].text:SetText("")
|
||||
f.side.Lines[i]:Hide()
|
||||
end
|
||||
if #self.Installs > 0 then
|
||||
E:Delay(1, PI.RunInstall, PI)
|
||||
end
|
||||
end
|
||||
|
||||
function PI:RunInstall()
|
||||
if not E.private.install_complete then return end
|
||||
if self.Installs[1] and not PluginInstallFrame:IsShown() and not (ElvUIInstallFrame and ElvUIInstallFrame:IsShown()) then
|
||||
f.StepTitles = nil
|
||||
f.StepTitlesColor = nil
|
||||
f.StepTitlesColorSelected = nil
|
||||
local db = self.Installs[1]
|
||||
f.CurrentPage = 0
|
||||
f.MaxPage = #(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 E.Media.Textures.Logo)
|
||||
|
||||
f.Pages = db.Pages
|
||||
|
||||
PluginInstallFrame:Show()
|
||||
f:SetPoint("CENTER")
|
||||
if db.StepTitles and #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, #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 #(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.Initialized = true
|
||||
PI:CreateStepComplete()
|
||||
PI:CreateFrame()
|
||||
end
|
||||
|
||||
local function InitializeCallback()
|
||||
PI:Initialize()
|
||||
end
|
||||
|
||||
E:RegisterModule(PI:GetName(), InitializeCallback)
|
||||
@@ -0,0 +1,142 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
|
||||
-- Credit: ls- (lightspark)
|
||||
local abs, next = abs, next
|
||||
local tonumber, assert = tonumber, assert
|
||||
local activeObjects = {}
|
||||
local handledObjects = {}
|
||||
local TARGET_FPS = 60
|
||||
local AMOUNT = 0.33
|
||||
|
||||
local function lerp(startValue, endValue, amount)
|
||||
return (1 - amount) * startValue + amount * endValue
|
||||
end
|
||||
|
||||
local function clamp(v, min, max)
|
||||
min = min or 0
|
||||
max = max or 1
|
||||
|
||||
if v > max then
|
||||
return max
|
||||
elseif v < min then
|
||||
return min
|
||||
end
|
||||
|
||||
return v
|
||||
end
|
||||
|
||||
local function isCloseEnough(new, target, range)
|
||||
if range > 0 then
|
||||
return abs((new - target) / range) <= 0.001
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local frame = CreateFrame("Frame")
|
||||
local function onUpdate(_, elapsed)
|
||||
for object, target in next, activeObjects do
|
||||
local new = lerp(object._value, target, clamp(AMOUNT * elapsed * TARGET_FPS))
|
||||
if isCloseEnough(new, target, object._max - object._min) then
|
||||
new = target
|
||||
activeObjects[object] = nil
|
||||
end
|
||||
|
||||
object:SetValue_(new)
|
||||
object._value = new
|
||||
end
|
||||
end
|
||||
|
||||
local function bar_SetSmoothedValue(self, value)
|
||||
value = tonumber(value)
|
||||
|
||||
assert(value, "bar_SetSmoothedValue requires (value) to be a number.")
|
||||
|
||||
self._value = self:GetValue()
|
||||
activeObjects[self] = clamp(value, self._min, self._max)
|
||||
end
|
||||
|
||||
local function bar_SetSmoothedMinMaxValues(self, min, max)
|
||||
min, max = tonumber(min), tonumber(max)
|
||||
|
||||
assert(min and max, "bar_SetSmoothedMinMaxValues requires (min and max) to be a number.")
|
||||
|
||||
self:SetMinMaxValues_(min, max)
|
||||
|
||||
if self._max and self._max ~= max then
|
||||
local ratio = 1
|
||||
if max ~= 0 and self._max and self._max ~= 0 then
|
||||
ratio = max / (self._max or max)
|
||||
end
|
||||
|
||||
local target = activeObjects[self]
|
||||
if target then
|
||||
activeObjects[self] = target * ratio
|
||||
end
|
||||
|
||||
local cur = self._value
|
||||
if cur then
|
||||
self:SetValue_(cur * ratio)
|
||||
self._value = cur * ratio
|
||||
end
|
||||
end
|
||||
|
||||
self._min = min
|
||||
self._max = max
|
||||
end
|
||||
|
||||
local function SmoothBar(bar)
|
||||
bar._min, bar._max = bar:GetMinMaxValues()
|
||||
bar._value = bar:GetValue()
|
||||
|
||||
if not bar.SetValue_ then
|
||||
bar.SetValue_ = bar.SetValue
|
||||
bar.SetValue = bar_SetSmoothedValue
|
||||
end
|
||||
if not bar.SetMinMaxValues_ then
|
||||
bar.SetMinMaxValues_ = bar.SetMinMaxValues
|
||||
bar.SetMinMaxValues = bar_SetSmoothedMinMaxValues
|
||||
end
|
||||
|
||||
if not frame:GetScript("OnUpdate") then
|
||||
frame:SetScript("OnUpdate", onUpdate)
|
||||
end
|
||||
|
||||
handledObjects[bar] = true
|
||||
end
|
||||
|
||||
local function DesmoothBar(bar)
|
||||
if activeObjects[bar] then
|
||||
bar:SetValue_(activeObjects[bar])
|
||||
activeObjects[bar] = nil
|
||||
end
|
||||
|
||||
if handledObjects[bar] then
|
||||
handledObjects[bar] = nil
|
||||
end
|
||||
|
||||
if bar.SetValue_ then
|
||||
bar.SetValue = bar.SetValue_
|
||||
bar.SetValue_ = nil
|
||||
end
|
||||
if bar.SetMinMaxValues_ then
|
||||
bar.SetMinMaxValues = bar.SetMinMaxValues_
|
||||
bar.SetMinMaxValues_ = nil
|
||||
end
|
||||
|
||||
if not next(handledObjects) then
|
||||
frame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
end
|
||||
|
||||
function E:SetSmoothingAmount(amount)
|
||||
AMOUNT = clamp(amount, 0.2, 0.8)
|
||||
end
|
||||
|
||||
function E:SetSmoothing(bar, enable)
|
||||
if enable then
|
||||
SmoothBar(bar)
|
||||
else
|
||||
DesmoothBar(bar)
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local Skins = E:GetModule("Skins")
|
||||
|
||||
--Lua functions
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
local GetAddOnInfo = GetAddOnInfo
|
||||
local GetCurrentResolution = GetCurrentResolution
|
||||
local GetCVar = GetCVar
|
||||
local GetLocale = GetLocale
|
||||
local GetNumAddOns = GetNumAddOns
|
||||
local GetRealZoneText = GetRealZoneText
|
||||
local GetScreenResolutions = GetScreenResolutions
|
||||
|
||||
local function AreOtherAddOnsEnabled()
|
||||
local name, loadable, reason, _
|
||||
for i = 1, GetNumAddOns() do
|
||||
name, _, _, loadable, reason = GetAddOnInfo(i)
|
||||
if (name ~= "ElvUI" and name ~= "ElvUI_OptionsUI") and (loadable or (not loadable and reason == "DEMAND_LOADED")) then --Loaded or load on demand
|
||||
return "Yes"
|
||||
end
|
||||
end
|
||||
|
||||
return "No"
|
||||
end
|
||||
|
||||
local function GetDisplayMode()
|
||||
local window, maximize = GetCVar("gxWindow"), GetCVar("gxMaximize")
|
||||
local displayMode
|
||||
|
||||
if window == "1" then
|
||||
if maximize == "1" then
|
||||
displayMode = "Windowed (Fullscreen)"
|
||||
else
|
||||
displayMode = "Windowed"
|
||||
end
|
||||
else
|
||||
displayMode = "Fullscreen"
|
||||
end
|
||||
|
||||
return displayMode
|
||||
end
|
||||
|
||||
local function GetResolution()
|
||||
return (({GetScreenResolutions()})[GetCurrentResolution()] or GetCVar("gxWindowedResolution"))
|
||||
end
|
||||
|
||||
function E:CreateStatusFrame()
|
||||
local function CreateSection(width, height, parent, anchor1, anchorTo, anchor2, yOffset)
|
||||
local section = CreateFrame("Frame", nil, parent)
|
||||
section:Size(width, height)
|
||||
section:Point(anchor1, anchorTo, anchor2, 0, yOffset)
|
||||
|
||||
section.Header = CreateFrame("Frame", nil, section)
|
||||
section.Header:Size(300, 30)
|
||||
section.Header:Point("TOP", section)
|
||||
|
||||
section.Header.Text = section.Header:CreateFontString(nil, "ARTWORK", "NumberFont_Outline_Large")
|
||||
section.Header.Text:Point("TOP")
|
||||
section.Header.Text:Point("BOTTOM")
|
||||
section.Header.Text:SetJustifyH("CENTER")
|
||||
section.Header.Text:SetJustifyV("MIDDLE")
|
||||
local font, fontHeight, flags = section.Header.Text:GetFont()
|
||||
section.Header.Text:SetFont(font, fontHeight*1.3, flags)
|
||||
|
||||
section.Header.LeftDivider = section.Header:CreateTexture(nil, "ARTWORK")
|
||||
section.Header.LeftDivider:Height(8)
|
||||
section.Header.LeftDivider:Point("LEFT", section.Header, "LEFT", 5, 0)
|
||||
section.Header.LeftDivider:Point("RIGHT", section.Header.Text, "LEFT", -5, 0)
|
||||
section.Header.LeftDivider:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
section.Header.LeftDivider:SetTexCoord(0.81, 0.94, 0.5, 1)
|
||||
|
||||
section.Header.RightDivider = section.Header:CreateTexture(nil, "ARTWORK")
|
||||
section.Header.RightDivider:Height(8)
|
||||
section.Header.RightDivider:Point("RIGHT", section.Header, "RIGHT", -5, 0)
|
||||
section.Header.RightDivider:Point("LEFT", section.Header.Text, "RIGHT", 5, 0)
|
||||
section.Header.RightDivider:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
section.Header.RightDivider:SetTexCoord(0.81, 0.94, 0.5, 1)
|
||||
|
||||
return section
|
||||
end
|
||||
|
||||
local function CreateContentLines(num, parent, anchorTo)
|
||||
local content = CreateFrame("Frame", nil, parent)
|
||||
content:Size(240, (num * 20) + ((num - 1) * 5)) --20 height and 5 spacing
|
||||
content:Point("TOP", anchorTo, "BOTTOM", 0, -5)
|
||||
for i = 1, num do
|
||||
local line = CreateFrame("Frame", nil, content)
|
||||
line:Size(240, 20)
|
||||
line.Text = line:CreateFontString(nil, "ARTWORK", "NumberFont_Outline_Large")
|
||||
line.Text:SetAllPoints()
|
||||
line.Text:SetJustifyH("LEFT")
|
||||
line.Text:SetJustifyV("MIDDLE")
|
||||
content["Line"..i] = line
|
||||
|
||||
if i == 1 then
|
||||
content["Line"..i]:Point("TOP", content, "TOP")
|
||||
else
|
||||
content["Line"..i]:Point("TOP", content["Line"..(i - 1)], "BOTTOM", 0, -5)
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
--Main frame
|
||||
local StatusFrame = CreateFrame("Frame", "ElvUIStatusReport", E.UIParent)
|
||||
StatusFrame:Size(300, 640)
|
||||
StatusFrame:Point("CENTER", E.UIParent, "CENTER")
|
||||
StatusFrame:SetFrameStrata("HIGH")
|
||||
StatusFrame:CreateBackdrop("Transparent", nil, true)
|
||||
StatusFrame:Hide()
|
||||
StatusFrame:CreateCloseButton()
|
||||
StatusFrame:SetClampedToScreen(true)
|
||||
StatusFrame:SetMovable(true)
|
||||
StatusFrame:EnableMouse(true)
|
||||
StatusFrame:RegisterForDrag("LeftButton", "RightButton")
|
||||
StatusFrame:SetScript("OnDragStart", function(self)
|
||||
self:StartMoving()
|
||||
end)
|
||||
StatusFrame:SetScript("OnDragStop", function(self)
|
||||
self:StopMovingOrSizing()
|
||||
end)
|
||||
|
||||
--Title logo
|
||||
StatusFrame.TitleLogoFrame = CreateFrame("Frame", nil, StatusFrame)
|
||||
StatusFrame.TitleLogoFrame:Size(128, 64)
|
||||
StatusFrame.TitleLogoFrame:Point("CENTER", StatusFrame, "TOP", 0, 0)
|
||||
StatusFrame.TitleLogoFrame.Texture = StatusFrame.TitleLogoFrame:CreateTexture(nil, "ARTWORK")
|
||||
StatusFrame.TitleLogoFrame.Texture:SetTexture(E.Media.Textures.Logo)
|
||||
StatusFrame.TitleLogoFrame.Texture:SetAllPoints()
|
||||
|
||||
--Sections
|
||||
StatusFrame.Section1 = CreateSection(300, 150, StatusFrame, "TOP", StatusFrame, "TOP", -30)
|
||||
StatusFrame.Section2 = CreateSection(300, 175, StatusFrame, "TOP", StatusFrame.Section1, "BOTTOM", 0)
|
||||
StatusFrame.Section3 = CreateSection(300, 220, StatusFrame, "TOP", StatusFrame.Section2, "BOTTOM", 0)
|
||||
StatusFrame.Section4 = CreateSection(300, 60, StatusFrame, "TOP", StatusFrame.Section3, "BOTTOM", 0)
|
||||
|
||||
--Section headers
|
||||
StatusFrame.Section1.Header.Text:SetText("|cfffe7b2cAddOn Info|r")
|
||||
StatusFrame.Section2.Header.Text:SetText("|cfffe7b2cWoW Info|r")
|
||||
StatusFrame.Section3.Header.Text:SetText("|cfffe7b2cCharacter Info|r")
|
||||
StatusFrame.Section4.Header.Text:SetText("|cfffe7b2cExport To|r")
|
||||
|
||||
--Section content
|
||||
StatusFrame.Section1.Content = CreateContentLines(4, StatusFrame.Section1, StatusFrame.Section1.Header)
|
||||
StatusFrame.Section2.Content = CreateContentLines(5, StatusFrame.Section2, StatusFrame.Section2.Header)
|
||||
StatusFrame.Section3.Content = CreateContentLines(5, StatusFrame.Section3, StatusFrame.Section3.Header)
|
||||
StatusFrame.Section4.Content = CreateFrame("Frame", nil, StatusFrame.Section4)
|
||||
StatusFrame.Section4.Content:Size(240, 25)
|
||||
StatusFrame.Section4.Content:Point("TOP", StatusFrame.Section4.Header, "BOTTOM", 0, 0)
|
||||
|
||||
--Content lines
|
||||
StatusFrame.Section1.Content.Line1.Text:SetFormattedText("Version of ElvUI: |cff4beb2c%s|r", E.version)
|
||||
StatusFrame.Section1.Content.Line2.Text:SetFormattedText("Other AddOns Enabled: |cff4beb2c%s|r", AreOtherAddOnsEnabled())
|
||||
StatusFrame.Section1.Content.Line3.Text:SetFormattedText("Recommended Scale: |cff4beb2c%s|r", E:PixelBestSize())
|
||||
StatusFrame.Section1.Content.Line4.Text:SetFormattedText("UI Scale Is: |cff4beb2c%s|r", E.global.general.UIScale)
|
||||
|
||||
StatusFrame.Section2.Content.Line1.Text:SetFormattedText("Version of WoW: |cff4beb2c%s (build %s)|r", E.wowpatch, E.wowbuild)
|
||||
StatusFrame.Section2.Content.Line2.Text:SetFormattedText("Client Language: |cff4beb2c%s|r", GetLocale())
|
||||
StatusFrame.Section2.Content.Line3.Text:SetFormattedText("Display Mode: |cff4beb2c%s|r", GetDisplayMode())
|
||||
StatusFrame.Section2.Content.Line4.Text:SetFormattedText("Resolution: |cff4beb2c%s|r", GetResolution())
|
||||
StatusFrame.Section2.Content.Line5.Text:SetFormattedText("Using Mac Client: |cff4beb2c%s|r", (E.isMacClient == true and "Yes" or "No"))
|
||||
|
||||
StatusFrame.Section3.Content.Line1.Text:SetFormattedText("Faction: |cff4beb2c%s|r", E.myfaction)
|
||||
StatusFrame.Section3.Content.Line2.Text:SetFormattedText("Race: |cff4beb2c%s|r", E.myrace)
|
||||
StatusFrame.Section3.Content.Line3.Text:SetFormattedText("Level: |cff4beb2c%s|r", E.mylevel)
|
||||
StatusFrame.Section3.Content.Line4.Text:SetFormattedText("Zone: |cff4beb2c%s|r", GetRealZoneText())
|
||||
StatusFrame.Section3.Content.Line5.Text:SetFormattedText("Realm: |cff4beb2c%s|r", E.myrealm)
|
||||
|
||||
--Export buttons
|
||||
StatusFrame.Section4.Content.Button1 = CreateFrame("Button", nil, StatusFrame.Section4.Content, "UIPanelButtonTemplate")
|
||||
StatusFrame.Section4.Content.Button1:Size(100, 25)
|
||||
StatusFrame.Section4.Content.Button1:Point("LEFT", StatusFrame.Section4.Content, "LEFT")
|
||||
StatusFrame.Section4.Content.Button1:SetText("Forum")
|
||||
StatusFrame.Section4.Content.Button1:SetButtonState("DISABLED")
|
||||
Skins:HandleButton(StatusFrame.Section4.Content.Button1, true)
|
||||
|
||||
StatusFrame.Section4.Content.Button2 = CreateFrame("Button", nil, StatusFrame.Section4.Content, "UIPanelButtonTemplate")
|
||||
StatusFrame.Section4.Content.Button2:Size(100, 25)
|
||||
StatusFrame.Section4.Content.Button2:Point("RIGHT", StatusFrame.Section4.Content, "RIGHT")
|
||||
StatusFrame.Section4.Content.Button2:SetText("Ticket")
|
||||
StatusFrame.Section4.Content.Button2:SetButtonState("DISABLED")
|
||||
Skins:HandleButton(StatusFrame.Section4.Content.Button2, true)
|
||||
|
||||
E.StatusFrame = StatusFrame
|
||||
end
|
||||
|
||||
local function UpdateDynamicValues()
|
||||
E.StatusFrame.Section2.Content.Line3.Text:SetFormattedText("Display Mode: |cff4beb2c%s|r", GetDisplayMode())
|
||||
E.StatusFrame.Section2.Content.Line4.Text:SetFormattedText("Resolution: |cff4beb2c%s|r", GetResolution())
|
||||
E.StatusFrame.Section3.Content.Line3.Text:SetFormattedText("Level: |cff4beb2c%s|r", E.mylevel)
|
||||
E.StatusFrame.Section3.Content.Line4.Text:SetFormattedText("Zone: |cff4beb2c%s|r", GetRealZoneText())
|
||||
end
|
||||
|
||||
function E:ShowStatusReport()
|
||||
if not self.StatusFrame then
|
||||
self:CreateStatusFrame()
|
||||
end
|
||||
|
||||
if not self.StatusFrame:IsShown() then
|
||||
UpdateDynamicValues()
|
||||
self.StatusFrame:Raise() --Set framelevel above everything else
|
||||
self.StatusFrame:Show()
|
||||
else
|
||||
self.StatusFrame:Hide()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,756 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local ElvUF = E.oUF
|
||||
|
||||
local Translit = E.Libs.Translit
|
||||
local translitMark = "!"
|
||||
|
||||
--Lua functions
|
||||
local select = select
|
||||
local tonumber = tonumber
|
||||
local find = string.find
|
||||
local floor = math.floor
|
||||
local format = string.format
|
||||
local gmatch = gmatch
|
||||
local gsub = gsub
|
||||
local match = string.match
|
||||
local utf8lower = string.utf8lower
|
||||
local utf8sub = string.utf8sub
|
||||
--WoW API / Variables
|
||||
local GetGuildInfo = GetGuildInfo
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local GetNumPartyMembers = GetNumPartyMembers
|
||||
local GetPVPTimer = GetPVPTimer
|
||||
local GetQuestGreenRange = GetQuestGreenRange
|
||||
local GetThreatStatusColor = GetThreatStatusColor
|
||||
local GetTime = GetTime
|
||||
local GetUnitSpeed = GetUnitSpeed
|
||||
local UnitClass = UnitClass
|
||||
local UnitClassification = UnitClassification
|
||||
local UnitDetailedThreatSituation = UnitDetailedThreatSituation
|
||||
local UnitExists = UnitExists
|
||||
local UnitGUID = UnitGUID
|
||||
local UnitHealth = UnitHealth
|
||||
local UnitHealthMax = UnitHealthMax
|
||||
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 UnitIsUnit = UnitIsUnit
|
||||
local UnitLevel = UnitLevel
|
||||
local UnitName = UnitName
|
||||
local UnitPVPName = UnitPVPName
|
||||
local UnitPower = UnitPower
|
||||
local UnitPowerMax = UnitPowerMax
|
||||
local UnitPowerType = UnitPowerType
|
||||
local UnitReaction = UnitReaction
|
||||
local DEFAULT_AFK_MESSAGE = DEFAULT_AFK_MESSAGE
|
||||
local SPELL_POWER_MANA = SPELL_POWER_MANA
|
||||
local PVP = PVP
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Tags
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local function abbrev(name)
|
||||
local letters, lastWord = "", match(name, ".+%s(.+)$")
|
||||
if lastWord then
|
||||
for word in gmatch(name, ".-%s") do
|
||||
local firstLetter = utf8sub(gsub(word, "^[%s%p]*", ""), 1, 1)
|
||||
if firstLetter ~= utf8lower(firstLetter) then
|
||||
letters = format("%s%s. ", letters, firstLetter)
|
||||
end
|
||||
end
|
||||
name = format("%s%s", letters, lastWord)
|
||||
end
|
||||
return name
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["afk"] = "PLAYER_FLAGS_CHANGED"
|
||||
ElvUF.Tags.Methods["afk"] = function(unit)
|
||||
local isAFK = UnitIsAFK(unit)
|
||||
if isAFK then
|
||||
return format("|cffFFFFFF[|r|cffFF0000%s|r|cFFFFFFFF]|r", DEFAULT_AFK_MESSAGE)
|
||||
else
|
||||
return nil
|
||||
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["name:abbrev"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["name:abbrev"] = function(unit)
|
||||
local name = UnitName(unit)
|
||||
|
||||
if name and find(name, "%s") then
|
||||
name = abbrev(name)
|
||||
end
|
||||
|
||||
return name ~= nil and name or ""
|
||||
end
|
||||
|
||||
for textFormat in pairs(E.GetFormattedTextStyles) do
|
||||
local tagTextFormat = strlower(gsub(textFormat, "_", "-"))
|
||||
ElvUF.Tags.Events[format("health:%s", tagTextFormat)] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
|
||||
ElvUF.Tags.Methods[format("health:%s", tagTextFormat)] = 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(textFormat, UnitHealth(unit), UnitHealthMax(unit))
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("health:%s-nostatus", tagTextFormat)] = "UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH"
|
||||
ElvUF.Tags.Methods[format("health:%s-nostatus", tagTextFormat)] = function(unit)
|
||||
return E:GetFormattedText(textFormat, UnitHealth(unit), UnitHealthMax(unit))
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("power:%s", tagTextFormat)] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER"
|
||||
ElvUF.Tags.Methods[format("power:%s", tagTextFormat)] = function(unit)
|
||||
local pType = UnitPowerType(unit)
|
||||
local min = UnitPower(unit, pType)
|
||||
|
||||
if min == 0 and tagTextFormat ~= "deficit" then
|
||||
return ""
|
||||
else
|
||||
return E:GetFormattedText(textFormat, UnitPower(unit, pType), UnitPowerMax(unit, pType))
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("mana:%s", tagTextFormat)] = "UNIT_MANA UNIT_MAXMANA"
|
||||
ElvUF.Tags.Methods[format("mana:%s", tagTextFormat)] = function(unit)
|
||||
local min = UnitPower(unit, SPELL_POWER_MANA)
|
||||
|
||||
if min == 0 and tagTextFormat ~= "deficit" then
|
||||
return ""
|
||||
else
|
||||
return E:GetFormattedText(textFormat, UnitPower(unit, SPELL_POWER_MANA), UnitPowerMax(unit, SPELL_POWER_MANA))
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("energy:%s", tagTextFormat)] = "UNIT_MAXENERGY UNIT_ENERGY_FREQUENT"
|
||||
ElvUF.Tags.Methods[format("energy:%s", tagTextFormat)] = function(unit)
|
||||
local min = UnitPower(unit, 3)
|
||||
|
||||
if min == 0 and tagTextFormat ~= "deficit" then
|
||||
return ""
|
||||
else
|
||||
return E:GetFormattedText(textFormat, UnitPower(unit, 3), UnitPowerMax(unit, 3))
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("rage:%s", tagTextFormat)] = "UNIT_MAXRAGE UNIT_RAGE_FREQUENT"
|
||||
ElvUF.Tags.Methods[format("rage:%s", tagTextFormat)] = function(unit)
|
||||
local min = UnitPower(unit, 1)
|
||||
|
||||
if min == 0 and tagTextFormat ~= "deficit" then
|
||||
return ""
|
||||
else
|
||||
return E:GetFormattedText(textFormat, UnitPower(unit, 1), UnitPowerMax(unit, 1))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for textFormat, length in pairs({veryshort = 5, short = 10, medium = 15, long = 20}) do
|
||||
ElvUF.Tags.Events[format("health:deficit-percent:name-%s", textFormat)] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION PLAYER_FLAGS_CHANGED"
|
||||
ElvUF.Tags.Methods[format("health:deficit-percent:name-%s", textFormat)] = function(unit)
|
||||
local cur, max = UnitHealth(unit), UnitHealthMax(unit)
|
||||
local deficit = max - cur
|
||||
|
||||
if deficit > 0 and cur > 0 then
|
||||
return _TAGS["health:percent-nostatus"](unit)
|
||||
else
|
||||
return _TAGS[format("name:%s", textFormat)](unit)
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("name:abbrev:%s", textFormat)] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods[format("name:abbrev:%s", textFormat)] = function(unit)
|
||||
local name = UnitName(unit)
|
||||
|
||||
if name and find(name, "%s") then
|
||||
name = abbrev(name)
|
||||
end
|
||||
|
||||
return name ~= nil and E:ShortenString(name, length) or ""
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("name:%s", textFormat)] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods[format("name:%s", textFormat)] = function(unit)
|
||||
local name = UnitName(unit)
|
||||
return name ~= nil and E:ShortenString(name, length) or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("name:%s:status", textFormat)] = "UNIT_NAME_UPDATE UNIT_CONNECTION PLAYER_FLAGS_CHANGED UNIT_HEALTH_FREQUENT"
|
||||
ElvUF.Tags.Methods[format("name:%s:status", textFormat)] = 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, length) or nil
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("name:%s:translit", textFormat)] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods[format("name:%s:translit", textFormat)] = function(unit)
|
||||
local name = Translit:Transliterate(UnitName(unit), translitMark)
|
||||
return name ~= nil and E:ShortenString(name, length) or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("target:%s", textFormat)] = "UNIT_TARGET"
|
||||
ElvUF.Tags.Methods[format("target:%s", textFormat)] = function(unit)
|
||||
local targetName = UnitName(unit.."target")
|
||||
return targetName ~= nil and E:ShortenString(targetName, length) or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events[format("target:%s:translit", textFormat)] = "UNIT_TARGET"
|
||||
ElvUF.Tags.Methods[format("target:%s:translit", textFormat)] = function(unit)
|
||||
local targetName = Translit:Transliterate(UnitName(unit.."target"), translitMark)
|
||||
return targetName ~= nil and E:ShortenString(targetName, length) or nil
|
||||
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: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["power:max"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER"
|
||||
ElvUF.Tags.Methods["power:max"] = function(unit)
|
||||
local pType = UnitPowerType(unit)
|
||||
local max = UnitPowerMax(unit, pType)
|
||||
|
||||
return E:GetFormattedText("CURRENT", max, max)
|
||||
end
|
||||
|
||||
ElvUF.Tags.Methods["manacolor"] = function()
|
||||
local mana = PowerBarColor.MANA
|
||||
local altR, altG, altB = mana.r, mana.g, 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:max"] = "UNIT_MAXMANA"
|
||||
ElvUF.Tags.Methods["mana:max"] = function(unit)
|
||||
local max = UnitPowerMax(unit, SPELL_POWER_MANA)
|
||||
|
||||
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
|
||||
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 UNIT_FACTION"
|
||||
ElvUF.Tags.Methods["namecolor"] = function(unit)
|
||||
local unitReaction = UnitReaction(unit, "player")
|
||||
local unitPlayer = UnitIsPlayer(unit)
|
||||
if unitPlayer then
|
||||
return Hex(E.media.herocolor.r, E.media.herocolor.g, E.media.herocolor.b)
|
||||
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["realm"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["realm"] = function(unit)
|
||||
local _, realm = UnitName(unit)
|
||||
|
||||
if realm and realm ~= "" then
|
||||
return realm
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["realm:dash"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["realm:dash"] = function(unit)
|
||||
local _, realm = UnitName(unit)
|
||||
|
||||
if realm and (realm ~= "" and realm ~= E.myrealm) then
|
||||
realm = format("-%s", realm)
|
||||
elseif realm == "" then
|
||||
realm = nil
|
||||
end
|
||||
|
||||
return realm
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["realm:translit"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["realm:translit"] = function(unit)
|
||||
local _, realm = Translit:Transliterate(UnitName(unit), translitMark)
|
||||
|
||||
if realm and realm ~= "" then
|
||||
return realm
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["realm:dash:translit"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["realm:dash:translit"] = function(unit)
|
||||
local _, realm = Translit:Transliterate(UnitName(unit), translitMark)
|
||||
|
||||
if realm and (realm ~= "" and realm ~= E.myrealm) then
|
||||
realm = format("-%s", realm)
|
||||
elseif realm == "" then
|
||||
realm = nil
|
||||
end
|
||||
|
||||
return realm
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["threat:percent"] = "UNIT_THREAT_SITUATION_UPDATE UNIT_THREAT_LIST_UPDATE"
|
||||
ElvUF.Tags.Methods["threat:percent"] = function(unit)
|
||||
local _, _, percent = UnitDetailedThreatSituation("player", unit)
|
||||
if percent and percent > 0 and (GetNumPartyMembers() or UnitExists("pet")) then
|
||||
return format("%.0f%%", percent)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["threat:current"] = "UNIT_THREAT_SITUATION_UPDATE UNIT_THREAT_LIST_UPDATE"
|
||||
ElvUF.Tags.Methods["threat:current"] = function(unit)
|
||||
local _, _, percent, _, threatvalue = UnitDetailedThreatSituation("player", unit)
|
||||
if percent and percent > 0 and (GetNumPartyMembers() or UnitExists("pet")) then
|
||||
return E:ShortValue(threatvalue)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["threatcolor"] = "UNIT_THREAT_SITUATION_UPDATE UNIT_THREAT_LIST_UPDATE"
|
||||
ElvUF.Tags.Methods["threatcolor"] = function(unit)
|
||||
local _, status = UnitDetailedThreatSituation("player", unit)
|
||||
if status and (GetNumPartyMembers() > 0 or UnitExists("pet")) then
|
||||
return Hex(GetThreatStatusColor(status))
|
||||
else
|
||||
return nil
|
||||
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 format("%s (%01.f:%02.f)", status, mins, secs)
|
||||
else
|
||||
return nil
|
||||
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 format("%s (%01.f:%02.f)", PVP, mins, secs)
|
||||
else
|
||||
return PVP
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local baseSpeed = 7
|
||||
local speedText = SPEED
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:percent"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:percent"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
local currentSpeedInPercent = (currentSpeedInYards / baseSpeed) * 100
|
||||
|
||||
return format("%s: %d%%", speedText, currentSpeedInPercent)
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:percent-moving"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:percent-moving"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
local currentSpeedInPercent = currentSpeedInYards > 0 and ((currentSpeedInYards / baseSpeed) * 100)
|
||||
|
||||
if currentSpeedInPercent then
|
||||
currentSpeedInPercent = format("%s: %d%%", speedText, currentSpeedInPercent)
|
||||
end
|
||||
|
||||
return currentSpeedInPercent or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:percent-raw"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:percent-raw"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
local currentSpeedInPercent = (currentSpeedInYards / baseSpeed) * 100
|
||||
|
||||
return format("%d%%", currentSpeedInPercent)
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:percent-moving-raw"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:percent-moving-raw"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
local currentSpeedInPercent = currentSpeedInYards > 0 and ((currentSpeedInYards / baseSpeed) * 100)
|
||||
|
||||
if currentSpeedInPercent then
|
||||
currentSpeedInPercent = format("%d%%", currentSpeedInPercent)
|
||||
end
|
||||
|
||||
return currentSpeedInPercent or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:yardspersec"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:yardspersec"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
|
||||
return format("%s: %.1f", speedText, currentSpeedInYards)
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:yardspersec-moving"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:yardspersec-moving"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
|
||||
return currentSpeedInYards > 0 and format("%s: %.1f", speedText, currentSpeedInYards) or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:yardspersec-raw"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:yardspersec-raw"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
return format("%.1f", currentSpeedInYards)
|
||||
end
|
||||
|
||||
ElvUF.Tags.OnUpdateThrottle["speed:yardspersec-moving-raw"] = 0.1
|
||||
ElvUF.Tags.Methods["speed:yardspersec-moving-raw"] = function(unit)
|
||||
local currentSpeedInYards = GetUnitSpeed(unit)
|
||||
|
||||
return currentSpeedInYards > 0 and format("%.1f", currentSpeedInYards) or nil
|
||||
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.SharedEvents.PLAYER_GUILD_UPDATE = true
|
||||
|
||||
ElvUF.Tags.Events["guild"] = "UNIT_NAME_UPDATE PLAYER_GUILD_UPDATE"
|
||||
ElvUF.Tags.Methods["guild"] = function(unit)
|
||||
if (UnitIsPlayer(unit)) then
|
||||
return GetGuildInfo(unit) or nil
|
||||
end
|
||||
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 nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["guild:translit"] = "UNIT_NAME_UPDATE PLAYER_GUILD_UPDATE"
|
||||
ElvUF.Tags.Methods["guild:translit"] = function(unit)
|
||||
if UnitIsPlayer(unit) then
|
||||
return Translit:Transliterate(GetGuildInfo(unit), translitMark) or nil
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["guild:brackets:translit"] = "PLAYER_GUILD_UPDATE"
|
||||
ElvUF.Tags.Methods["guild:brackets:translit"] = function(unit)
|
||||
local guildName = Translit:Transliterate(GetGuildInfo(unit), translitMark)
|
||||
|
||||
return guildName and format("<%s>", guildName) or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["target"] = "UNIT_TARGET"
|
||||
ElvUF.Tags.Methods["target"] = function(unit)
|
||||
local targetName = UnitName(unit.."target")
|
||||
return targetName or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["target:translit"] = "UNIT_TARGET"
|
||||
ElvUF.Tags.Methods["target:translit"] = function(unit)
|
||||
local targetName = Translit:Transliterate(UnitName(unit.."target"), translitMark)
|
||||
return targetName or nil
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["guild:rank"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["guild:rank"] = function(unit)
|
||||
if (UnitIsPlayer(unit)) then
|
||||
return select(2, GetGuildInfo(unit)) or ""
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["arena:number"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["arena:number"] = function(unit)
|
||||
local _, instanceType = GetInstanceInfo()
|
||||
if instanceType == "arena" then
|
||||
for i = 1, 5 do
|
||||
if UnitIsUnit(unit, "arena"..i) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["class"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["class"] = function(unit)
|
||||
return UnitClass(unit)
|
||||
end
|
||||
|
||||
ElvUF.Tags.Events["name:title"] = "UNIT_NAME_UPDATE"
|
||||
ElvUF.Tags.Methods["name:title"] = function(unit)
|
||||
if UnitIsPlayer(unit) then
|
||||
return UnitPVPName(unit)
|
||||
end
|
||||
end
|
||||
E.TagInfo = {
|
||||
--Colors
|
||||
["namecolor"] = {category = "Colors", description = "Colors names by player class or NPC reaction"},
|
||||
["powercolor"] = {category = "Colors", description = "Colors the power text based upon its type"},
|
||||
["energycolor"] = {category = "Colors", description = "Colors the energy text based upon its type"},
|
||||
["ragecolor"] = {category = "Colors", description = "Colors the rage text based upon its type"},
|
||||
["difficultycolor"] = {category = "Colors", description = "Colors the following tags by difficulty, red for impossible, orange for hard, green for easy"},
|
||||
["healthcolor"] = {category = "Colors", description = "Changes color of health text, depending on the unit's current health"},
|
||||
["threatcolor"] = {category = "Colors", description = "Changes color of health, depending on the unit's threat situation"},
|
||||
["classificationcolor"] = {category = "Colors", description = "Changes color of health, depending on the unit's classification"},
|
||||
--Classification
|
||||
["classification"] = {category = "Classification", description = "Displays the unit's classification (e.g. 'ELITE' and 'RARE')"},
|
||||
["shortclassification"] = {category = "Classification", description = "Displays the unit's classification in short form (e.g. '+' for ELITE and 'R' for RARE)"},
|
||||
["rare"] = {category = "Classification", description = "Displays 'Rare' when the unit is a rare or rareelite"},
|
||||
--Guild
|
||||
["guild"] = {category = "Guild", description = "Displays the guild name"},
|
||||
["guild:brackets"] = {category = "Guild", description = "Displays the guild name with < > brackets (e.g. <GUILD>)"},
|
||||
["guild:brackets:translit"] = {category = "Guild", description = "Displays the guild name with < > and transliteration (e.g. <GUILD>)"},
|
||||
["guild:rank"] = {category = "Guild", description = "Displays the guild rank"},
|
||||
["guild:translit"] = {category = "Guild", description = "Displays the guild name with transliteration for cyrillic letters"},
|
||||
--Health
|
||||
["curhp"] = {category = "Health", description = "Displays the current HP without decimals"},
|
||||
["perhp"] = {category = "Health", description = "Displays percentage HP without decimals"},
|
||||
["maxhp"] = {category = "Health", description = "Displays max HP without decimals"},
|
||||
["deficit:name"] = {category = "Health", description = "Displays the health as a deficit and the name at full health"},
|
||||
["health:current"] = {category = "Health", description = "Displays the current health of the unit"},
|
||||
["health:current-max"] = {category = "Health", description = "Displays the current and maximum health of the unit, separated by a dash"},
|
||||
["health:current-max-nostatus"] = {category = "Health", description = "Displays the current and maximum health of the unit, separated by a dash, without status"},
|
||||
["health:current-max-percent"] = {category = "Health", description = "Displays the current and max hp of the unit, separated by a dash (% when not full hp)"},
|
||||
["health:current-max-percent-nostatus"] = {category = "Health", description = "Displays the current and max hp of the unit, separated by a dash (% when not full hp), without status"},
|
||||
["health:current-nostatus"] = {category = "Health", description = "Displays the current health of the unit, without status"},
|
||||
["health:current-percent"] = {category = "Health", description = "Displays the current hp of the unit (% when not full hp)"},
|
||||
["health:current-percent-nostatus"] = {category = "Health", description = "Displays the current hp of the unit (% when not full hp), without status"},
|
||||
["health:deficit"] = {category = "Health", description = "Displays the health of the unit as a deficit (Total Health - Current Health = -Deficit)"},
|
||||
["health:deficit-nostatus"] = {category = "Health", description = "Displays the health of the unit as a deficit, without status"},
|
||||
["health:deficit-percent:name"] = {category = "Health", description = "Displays the health deficit as a percentage and the full name of the unit"},
|
||||
["health:deficit-percent:name-long"] = {category = "Health", description = "Displays the health deficit as a percentage and the name of the unit (limited to 20 letters)"},
|
||||
["health:deficit-percent:name-medium"] = {category = "Health", description = "Displays the health deficit as a percentage and the name of the unit (limited to 15 letters)"},
|
||||
["health:deficit-percent:name-short"] = {category = "Health", description = "Displays the health deficit as a percentage and the name of the unit (limited to 10 letters)"},
|
||||
["health:deficit-percent:name-veryshort"] = {category = "Health", description = "Displays the health deficit as a percentage and the name of the unit (limited to 5 letters)"},
|
||||
["health:max"] = {category = "Health", description = "Displays the maximum health of the unit"},
|
||||
["health:percent"] = {category = "Health", description = "Displays the current health of the unit as a percentage"},
|
||||
["health:percent-nostatus"] = {category = "Health", description = "Displays the unit's current health as a percentage, without status"},
|
||||
["missinghp"] = {category = "Health", description = "Displays the missing health of the unit in whole numbers, when not at full health"},
|
||||
--Level
|
||||
["smartlevel"] = {category = "Level", description = "Only display the unit's level if it is not the same as yours"},
|
||||
["level"] = {category = "Level", description = "Displays the level of the unit"},
|
||||
--Mana
|
||||
["mana:current"] = {category = "Mana", description = "Displays the unit's current amount of mana (e.g. 97200)"},
|
||||
["mana:current-percent"] = {category = "Mana", description = "Displays the current amount of mana as a whole number and a percentage, separated by a dash"},
|
||||
["mana:current-max"] = {category = "Mana", description = "Displays the current mana and max mana, separated by a dash"},
|
||||
["mana:current-max-percent"] = {category = "Mana", description = "Displays the current mana and max mana, separated by a dash (% when not full power)"},
|
||||
["mana:percent"] = {category = "Mana", description = "Displays the mana of the unit as a percentage value"},
|
||||
["mana:max"] = {category = "Mana", description = "Displays the unit's maximum mana"},
|
||||
["mana:deficit"] = {category = "Mana", description = "Displays the mana deficit (Total Mana - Current Mana = -Deficit)"},
|
||||
["curmana"] = {category = "Mana", description = "Displays the current mana without decimals"},
|
||||
["maxmana"] = {category = "Mana", description = "Displays the max amount of mana the unit can have"},
|
||||
--Names
|
||||
["name"] = {category = "Names", description = "Displays the full name of the unit without any letter limitation"},
|
||||
["name:veryshort"] = {category = "Names", description = "Displays the name of the unit (limited to 5 letters)"},
|
||||
["name:short"] = {category = "Names", description = "Displays the name of the unit (limited to 10 letters)"},
|
||||
["name:medium"] = {category = "Names", description = "Displays the name of the unit (limited to 15 letters)"},
|
||||
["name:long"] = {category = "Names", description = "Displays the name of the unit (limited to 20 letters)"},
|
||||
["name:veryshort:translit"] = {category = "Names", description = "Displays the name of the unit with transliteration for cyrillic letters (limited to 5 letters)"},
|
||||
["name:short:translit"] = {category = "Names", description = "Displays the name of the unit with transliteration for cyrillic letters (limited to 10 letters)"},
|
||||
["name:medium:translit"] = {category = "Names", description = "Displays the name of the unit with transliteration for cyrillic letters (limited to 15 letters)"},
|
||||
["name:long:translit"] = {category = "Names", description = "Displays the name of the unit with transliteration for cyrillic letters (limited to 20 letters)"},
|
||||
["name:abbrev"] = {category = "Names", description = "Displays the name of the unit with abbreviation (e.g. 'Shadowfury Witch Doctor' becomes 'S. W. Doctor')"},
|
||||
["name:abbrev:veryshort"] = {category = "Names", description = "Displays the name of the unit with abbreviation (limited to 5 letters)"},
|
||||
["name:abbrev:short"] = {category = "Names", description = "Displays the name of the unit with abbreviation (limited to 10 letters)"},
|
||||
["name:abbrev:medium"] = {category = "Names", description = "Displays the name of the unit with abbreviation (limited to 15 letters)"},
|
||||
["name:abbrev:long"] = {category = "Names", description = "Displays the name of the unit with abbreviation (limited to 20 letters)"},
|
||||
["name:veryshort:status"] = {category = "Names", description = "Replace the name of the unit with 'DEAD' or 'OFFLINE' if applicable (limited to 5 letters)"},
|
||||
["name:short:status"] = {category = "Names", description = "Replace the name of the unit with 'DEAD' or 'OFFLINE' if applicable (limited to 10 letters)"},
|
||||
["name:medium:status"] = {category = "Names", description = "Replace the name of the unit with 'DEAD' or 'OFFLINE' if applicable (limited to 15 letters)"},
|
||||
["name:long:status"] = {category = "Names", description = "Replace the name of the unit with 'DEAD' or 'OFFLINE' if applicable (limited to 20 letters)"},
|
||||
["name:title"] = {category = "Names", description = "Displays player name and title"},
|
||||
--Party and Raid
|
||||
["group"] = {category = "Party and Raid", description = "Displays the group number the unit is in ('1' - '8')"},
|
||||
["leader"] = {category = "Party and Raid", description = "Displays 'L' if the unit is the group/raid leader"},
|
||||
["leaderlong"] = {category = "Party and Raid", description = "Displays 'Leader' if the unit is the group/raid leader"},
|
||||
--Power
|
||||
["power:current"] = {category = "Power", description = "Displays the unit's current amount of power"},
|
||||
["power:current-percent"] = {category = "Power", description = "Displays the current power and power as a percentage, separated by a dash"},
|
||||
["power:current-max"] = {category = "Power", description = "Displays the current power and max power, separated by a dash"},
|
||||
["power:current-max-percent"] = {category = "Power", description = "Displays the current power and max power, separated by a dash (% when not full power)"},
|
||||
["power:percent"] = {category = "Power", description = "Displays the unit's power as a percentage"},
|
||||
["power:max"] = {category = "Power", description = "Displays the unit's maximum power"},
|
||||
["power:deficit"] = {category = "Power", description = "Displays the power as a deficit (Total Power - Current Power = -Deficit)"},
|
||||
["curpp"] = {category = "Power", description = "Displays the unit's current power without decimals"},
|
||||
["perpp"] = {category = "Power", description = "Displays the unit's percentage power without decimals "},
|
||||
["maxpp"] = {category = "Power", description = "Displays the max amount of power of the unit in whole numbers without decimals"},
|
||||
["missingpp"] = {category = "Power", description = "Displays the missing power of the unit in whole numbers when not at full power"},
|
||||
--Energy
|
||||
["energy:current"] = {category = "Energy", description = "Displays the unit's current amount of energy"},
|
||||
["energy:current-percent"] = {category = "Energy", description = "Displays the current energy and energy as a percentage, separated by a dash"},
|
||||
["energy:current-max"] = {category = "Energy", description = "Displays the current energy and max energy, separated by a dash"},
|
||||
["energy:current-max-percent"] = {category = "Energy", description = "Displays the current energy and max energy, separated by a dash (% when not full energy)"},
|
||||
["energy:percent"] = {category = "Energy", description = "Displays the unit's energy as a percentage"},
|
||||
["energy:max"] = {category = "Energy", description = "Displays the unit's maximum energy"},
|
||||
["energy:deficit"] = {category = "Energy", description = "Displays the energy as a deficit (Total Energy - Current Energy = -Deficit)"},
|
||||
--Rage
|
||||
["rage:current"] = {category = "Rage", description = "Displays the unit's current amount of rage"},
|
||||
["rage:current-percent"] = {category = "Rage", description = "Displays the current rage and rage as a percentage, separated by a dash"},
|
||||
["rage:current-max"] = {category = "Rage", description = "Displays the current rage and max rage, separated by a dash"},
|
||||
["rage:current-max-percent"] = {category = "Rage", description = "Displays the current rage and max rage, separated by a dash (% when not full rage)"},
|
||||
["rage:percent"] = {category = "Rage", description = "Displays the unit's rage as a percentage"},
|
||||
["rage:max"] = {category = "Rage", description = "Displays the unit's maximum rage"},
|
||||
["rage:deficit"] = {category = "Rage", description = "Displays the rage as a deficit (Total Rage - Current Rage = -Deficit)"},
|
||||
--Realm
|
||||
["realm"] = {category = "Realm", description = "Displays the server name"},
|
||||
["realm:translit"] = {category = "Realm", description = "Displays the server name with transliteration for cyrillic letters"},
|
||||
["realm:dash"] = {category = "Realm", description = "Displays the server name with a dash in front (e.g. -Realm)"},
|
||||
["realm:dash:translit"] = {category = "Realm", description = "Displays the server name with transliteration for cyrillic letters and a dash in front"},
|
||||
--Status
|
||||
["status"] = {category = "Status", description = "Displays zzz, dead, ghost, offline"},
|
||||
["statustimer"] = {category = "Status", description = "Displays a timer for how long a unit has had the status (e.g 'DEAD - 0:34')"},
|
||||
["afk"] = {category = "Status", description = "Displays <AFK> if the Unit is afk"},
|
||||
["dead"] = {category = "Status", description = "Displays <DEAD> if the unit is dead"},
|
||||
["resting"] = {category = "Status", description = "Displays zzz if the unit is dead"},
|
||||
["pvp"] = {category = "Status", description = "Displays 'PvP' if the unit is pvp flagged"},
|
||||
["offline"] = {category = "Status", description = "Displays 'OFFLINE' if the unit is disconnected"},
|
||||
--Target
|
||||
["target"] = {category = "Target", description = "Displays the current target of the unit"},
|
||||
["target:veryshort"] = {category = "Target", description = "Displays the current target of the unit (limited to 5 letters)"},
|
||||
["target:short"] = {category = "Target", description = "Displays the current target of the unit (limited to 10 letters)"},
|
||||
["target:medium"] = {category = "Target", description = "Displays the current target of the unit (limited to 15 letters)"},
|
||||
["target:long"] = {category = "Target", description = "Displays the current target of the unit (limited to 20 letters)"},
|
||||
["target:translit"] = {category = "Target", description = "Displays the current target of the unit with transliteration for cyrillic letters"},
|
||||
["target:veryshort:translit"] = {category = "Target", description = "Displays the current target of the unit with transliteration for cyrillic letters (limited to 5 letters)"},
|
||||
["target:short:translit"] = {category = "Target", description = "Displays the current target of the unit with transliteration for cyrillic letters (limited to 10 letters)"},
|
||||
["target:medium:translit"] = {category = "Target", description = "Displays the current target of the unit with transliteration for cyrillic letters (limited to 15 letters)"},
|
||||
["target:long:translit"] = {category = "Target", description = "Displays the current target of the unit with transliteration for cyrillic letters (limited to 20 letters)"},
|
||||
--Threat
|
||||
["threat"] = {category = "Threat", description = "Displays the current threat"},
|
||||
["threat:percent"] = {category = "Threat", description = "Displays the current threat as a percent"},
|
||||
["threat:current"] = {category = "Threat", description = "Displays the current threat as a value"},
|
||||
--Miscellaneous
|
||||
["smartclass"] = {category = "Miscellaneous", description = "Displays the player's class or creature's type"},
|
||||
["class"] = {category = "Miscellaneous", description = "Displays the class of the unit, if that unit is a player"},
|
||||
["difficulty"] = {category = "Miscellaneous", description = "Changes color of the next tag based on how difficult the unit is compared to the players level"},
|
||||
["faction"] = {category = "Miscellaneous", description = "Displays 'Aliance' or 'Horde'"},
|
||||
["plus"] = {category = "Miscellaneous", description = "Displays the character '+' if the unit is an elite or rare-elite"},
|
||||
["arena:number"] = {category = "Miscellaneous", description = "Displays the arena number 1-5"},
|
||||
}
|
||||
|
||||
function E:AddTagInfo(tagName, category, description, order)
|
||||
if order then order = tonumber(order) + 10 end
|
||||
|
||||
E.TagInfo[tagName] = E.TagInfo[tagName] or {}
|
||||
E.TagInfo[tagName].category = category or "Miscellaneous"
|
||||
E.TagInfo[tagName].description = description or ""
|
||||
E.TagInfo[tagName].order = order or nil
|
||||
end
|
||||
@@ -0,0 +1,346 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local unpack, type, select, getmetatable, assert = unpack, type, select, getmetatable, assert
|
||||
--WoW API / Variables
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
local backdropr, backdropg, backdropb, backdropa, borderr, borderg, borderb = 0, 0, 0, 1, 0, 0, 0
|
||||
local function GetTemplate(template, isUnitFrameElement)
|
||||
backdropa = 1
|
||||
|
||||
if template == "ClassColor" then
|
||||
local color = E.media.herocolor
|
||||
borderr, borderg, borderb = color.r, color.g, color.b
|
||||
backdropr, backdropg, backdropb = unpack(E.media.backdropcolor)
|
||||
elseif template == "Transparent" then
|
||||
borderr, borderg, borderb = unpack(isUnitFrameElement and E.media.unitframeBorderColor or E.media.bordercolor)
|
||||
backdropr, backdropg, backdropb, backdropa = unpack(E.media.backdropfadecolor)
|
||||
else
|
||||
borderr, borderg, borderb = unpack(isUnitFrameElement and E.media.unitframeBorderColor or E.media.bordercolor)
|
||||
backdropr, backdropg, backdropb = unpack(E.media.backdropcolor)
|
||||
end
|
||||
end
|
||||
|
||||
local function Size(frame, width, height)
|
||||
assert(width)
|
||||
frame:SetSize(E:Scale(width), E:Scale(height or width))
|
||||
end
|
||||
|
||||
local function Width(frame, width)
|
||||
assert(width)
|
||||
frame:SetWidth(E:Scale(width))
|
||||
end
|
||||
|
||||
local function Height(frame, height)
|
||||
assert(height)
|
||||
frame:SetHeight(E:Scale(height))
|
||||
end
|
||||
|
||||
local function Point(obj, arg1, arg2, arg3, arg4, arg5)
|
||||
if arg2 == nil then arg2 = obj:GetParent() 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
|
||||
|
||||
local function 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:Point("TOPLEFT", anchor, "TOPLEFT", -xOffset, yOffset)
|
||||
obj:Point("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", xOffset, -yOffset)
|
||||
end
|
||||
|
||||
local function 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:Point("TOPLEFT", anchor, "TOPLEFT", xOffset, -yOffset)
|
||||
obj:Point("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", -xOffset, yOffset)
|
||||
end
|
||||
|
||||
local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
|
||||
GetTemplate(template, isUnitFrameElement)
|
||||
|
||||
frame.template = template or "Default"
|
||||
if glossTex then frame.glossTex = glossTex end
|
||||
if ignoreUpdates then frame.ignoreUpdates = ignoreUpdates end
|
||||
if forcePixelMode then frame.forcePixelMode = forcePixelMode end
|
||||
if isUnitFrameElement then frame.isUnitFrameElement = isUnitFrameElement end
|
||||
|
||||
local bgFile = glossTex and E.media.glossTex or E.media.blankTex
|
||||
|
||||
if template ~= "NoBackdrop" then
|
||||
frame:SetBackdrop({
|
||||
bgFile = bgFile,
|
||||
edgeFile = E.media.blankTex,
|
||||
tile = false, tileSize = 0, edgeSize = E.mult,
|
||||
insets = {left = 0, right = 0, top = 0, bottom = 0}
|
||||
})
|
||||
|
||||
frame:SetBackdropColor(backdropr, backdropg, backdropb, backdropa)
|
||||
|
||||
if not E.PixelMode and not frame.forcePixelMode then
|
||||
if not frame.iborder then
|
||||
local border = CreateFrame("Frame", nil, frame)
|
||||
border:SetInside(frame, 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)
|
||||
frame.iborder = border
|
||||
end
|
||||
|
||||
if not frame.oborder then
|
||||
local border = CreateFrame("Frame", nil, frame)
|
||||
border:SetOutside(frame, E.mult, E.mult)
|
||||
border:SetFrameLevel(frame: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)
|
||||
frame.oborder = border
|
||||
end
|
||||
end
|
||||
else
|
||||
frame:SetBackdrop(nil)
|
||||
end
|
||||
frame:SetBackdropBorderColor(borderr, borderg, borderb)
|
||||
|
||||
if not frame.ignoreUpdates then
|
||||
if frame.isUnitFrameElement then
|
||||
E.unitFrameElements[frame] = true
|
||||
else
|
||||
E.frames[frame] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateBackdrop(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
|
||||
if not template then template = "Default" end
|
||||
|
||||
local parent = (frame.IsObjectType and frame:IsObjectType("Texture") and frame:GetParent()) or frame
|
||||
local backdrop = frame.backdrop or CreateFrame("Frame", nil, parent)
|
||||
if not frame.backdrop then frame.backdrop = backdrop end
|
||||
|
||||
if frame.forcePixelMode or forcePixelMode then
|
||||
backdrop:SetOutside(frame, E.mult, E.mult)
|
||||
else
|
||||
backdrop:SetOutside(frame)
|
||||
end
|
||||
|
||||
backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
|
||||
|
||||
local frameLevel = parent.GetFrameLevel and parent:GetFrameLevel()
|
||||
local frameLevelMinusOne = frameLevel and (frameLevel - 1)
|
||||
if frameLevelMinusOne and (frameLevelMinusOne >= 0) then
|
||||
backdrop:SetFrameLevel(frameLevelMinusOne)
|
||||
else
|
||||
backdrop:SetFrameLevel(0)
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateShadow(frame, size)
|
||||
if frame.shadow then return end
|
||||
|
||||
backdropr, backdropg, backdropb, borderr, borderg, borderb = 0, 0, 0, 0, 0, 0
|
||||
|
||||
local shadow = CreateFrame("Frame", nil, frame)
|
||||
shadow:SetFrameLevel(1)
|
||||
shadow:SetFrameStrata(frame:GetFrameStrata())
|
||||
shadow:SetOutside(frame, size or 3, size or 3)
|
||||
shadow:SetBackdrop({edgeFile = LSM:Fetch("border", "ElvUI GlowBorder"), edgeSize = E:Scale(size or 3)})
|
||||
shadow:SetBackdropColor(backdropr, backdropg, backdropb, 0)
|
||||
shadow:SetBackdropBorderColor(borderr, borderg, borderb, 0.9)
|
||||
frame.shadow = shadow
|
||||
end
|
||||
|
||||
local function Kill(object)
|
||||
if object.UnregisterAllEvents then
|
||||
object:UnregisterAllEvents()
|
||||
object:SetParent(E.HiddenFrame)
|
||||
else
|
||||
object.Show = object.Hide
|
||||
end
|
||||
|
||||
object:Hide()
|
||||
end
|
||||
|
||||
local function StripTextures(object, kill, alpha)
|
||||
if object:IsObjectType("Texture") then
|
||||
if kill then
|
||||
object:Kill()
|
||||
elseif alpha then
|
||||
object:SetAlpha(0)
|
||||
else
|
||||
object:SetTexture()
|
||||
end
|
||||
else
|
||||
if object.GetNumRegions then
|
||||
for i = 1, object:GetNumRegions() do
|
||||
local region = select(i, object:GetRegions())
|
||||
if region and region.IsObjectType and region:IsObjectType("Texture") then
|
||||
if kill then
|
||||
region:Kill()
|
||||
elseif alpha then
|
||||
region:SetAlpha(0)
|
||||
else
|
||||
region:SetTexture()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function 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
|
||||
fontStyle = fontStyle or E.db.general.fontStyle
|
||||
|
||||
if fontStyle == "OUTLINE" and E.db.general.font == "Homespun" and (fontSize > 10 and not fs.fontSize) then
|
||||
fontSize, fontStyle = 10, "MONOCHROMEOUTLINE"
|
||||
end
|
||||
|
||||
fs:SetFont(font, fontSize, fontStyle)
|
||||
|
||||
if fontStyle == "NONE" then
|
||||
local s = E.mult or 1
|
||||
fs:SetShadowOffset(s, -s/2)
|
||||
fs:SetShadowColor(0, 0, 0, 1)
|
||||
else
|
||||
fs:SetShadowOffset(0, 0)
|
||||
fs:SetShadowColor(0, 0, 0, 0)
|
||||
end
|
||||
|
||||
E.texts[fs] = true
|
||||
end
|
||||
|
||||
local function StyleButton(button, noHover, noPushed, noChecked)
|
||||
if button.SetHighlightTexture and not button.hover and not noHover then
|
||||
local hover = button:CreateTexture()
|
||||
hover:SetInside()
|
||||
hover:SetTexture(1, 1, 1, 0.3)
|
||||
button:SetHighlightTexture(hover)
|
||||
button.hover = hover
|
||||
end
|
||||
|
||||
if button.SetPushedTexture and not button.pushed and not noPushed then
|
||||
local pushed = button:CreateTexture()
|
||||
pushed:SetInside()
|
||||
pushed:SetTexture(0.9, 0.8, 0.1, 0.3)
|
||||
button:SetPushedTexture(pushed)
|
||||
button.pushed = pushed
|
||||
end
|
||||
|
||||
if button.SetCheckedTexture and not button.checked and not noChecked then
|
||||
local checked = button:CreateTexture()
|
||||
checked:SetInside()
|
||||
checked:SetTexture(1, 1, 1, 0.3)
|
||||
button:SetCheckedTexture(checked)
|
||||
button.checked = checked
|
||||
end
|
||||
|
||||
local name = button.GetName and button:GetName()
|
||||
local cooldown = name and _G[name.."Cooldown"]
|
||||
if cooldown then
|
||||
cooldown:ClearAllPoints()
|
||||
cooldown:SetInside()
|
||||
end
|
||||
end
|
||||
|
||||
local CreateCloseButton
|
||||
do
|
||||
local CloseButtonOnClick = function(btn) btn:GetParent():Hide() end
|
||||
local CloseButtonOnEnter = function(btn) if btn.Texture then btn.Texture:SetVertexColor(unpack(E.media.rgbvaluecolor)) end end
|
||||
local CloseButtonOnLeave = function(btn) if btn.Texture then btn.Texture:SetVertexColor(1, 1, 1) end end
|
||||
CreateCloseButton = function(frame, size, offset, texture, backdrop)
|
||||
if frame.CloseButton then return end
|
||||
|
||||
local CloseButton = CreateFrame("Button", nil, frame)
|
||||
CloseButton:Size(size or 16)
|
||||
CloseButton:Point("TOPRIGHT", offset or -6, offset or -6)
|
||||
if backdrop then CloseButton:CreateBackdrop(nil, true) end
|
||||
|
||||
CloseButton.Texture = CloseButton:CreateTexture(nil, "OVERLAY")
|
||||
CloseButton.Texture:SetAllPoints()
|
||||
CloseButton.Texture:SetTexture(texture or E.Media.Textures.Close)
|
||||
|
||||
CloseButton:SetScript("OnClick", CloseButtonOnClick)
|
||||
CloseButton:SetScript("OnEnter", CloseButtonOnEnter)
|
||||
CloseButton:SetScript("OnLeave", CloseButtonOnLeave)
|
||||
|
||||
frame.CloseButton = CloseButton
|
||||
end
|
||||
end
|
||||
|
||||
local function GetNamedChild(frame, childName, index)
|
||||
local name = frame and frame.GetName and frame:GetName()
|
||||
if not name or not childName then return nil end
|
||||
return _G[name..childName..(index or "")]
|
||||
end
|
||||
|
||||
local function addapi(object)
|
||||
local mt = getmetatable(object).__index
|
||||
if not object.Size then mt.Size = Size end
|
||||
if not object.Point then mt.Point = Point end
|
||||
if not object.SetOutside then mt.SetOutside = SetOutside end
|
||||
if not object.SetInside then mt.SetInside = SetInside end
|
||||
if not object.SetTemplate then mt.SetTemplate = SetTemplate end
|
||||
if not object.CreateBackdrop then mt.CreateBackdrop = CreateBackdrop end
|
||||
if not object.CreateShadow then mt.CreateShadow = CreateShadow end
|
||||
if not object.Kill then mt.Kill = Kill end
|
||||
if not object.Width then mt.Width = Width end
|
||||
if not object.Height then mt.Height = Height end
|
||||
if not object.FontTemplate then mt.FontTemplate = FontTemplate end
|
||||
if not object.StripTextures then mt.StripTextures = StripTextures end
|
||||
if not object.StyleButton then mt.StyleButton = StyleButton end
|
||||
if not object.CreateCloseButton then mt.CreateCloseButton = CreateCloseButton end
|
||||
if not object.GetNamedChild then mt.GetNamedChild = GetNamedChild end
|
||||
end
|
||||
|
||||
local handled = {["Frame"] = true}
|
||||
local object = CreateFrame("Frame")
|
||||
addapi(object)
|
||||
addapi(object:CreateTexture())
|
||||
addapi(object:CreateFontString())
|
||||
|
||||
object = EnumerateFrames()
|
||||
while object do
|
||||
if not handled[object:GetObjectType()] then
|
||||
addapi(object)
|
||||
handled[object:GetObjectType()] = true
|
||||
end
|
||||
|
||||
object = EnumerateFrames(object)
|
||||
end
|
||||
|
||||
--Add API to `CreateFont` objects without actually creating one
|
||||
addapi(GameFontNormal)
|
||||
@@ -0,0 +1,120 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local Skins = E:GetModule("Skins")
|
||||
|
||||
--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-WotLK."],
|
||||
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 <mover name>.\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 > #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 = #E.TutorialList
|
||||
end
|
||||
|
||||
ElvUITutorialWindow.desc:SetText(E.TutorialList[self.db.currentTutorial])
|
||||
end
|
||||
|
||||
function E:SpawnTutorialFrame()
|
||||
local f = CreateFrame("Frame", "ElvUITutorialWindow", E.UIParent)
|
||||
f:SetFrameStrata("DIALOG")
|
||||
f:SetToplevel(true)
|
||||
f:SetClampedToScreen(true)
|
||||
f:Width(360)
|
||||
f:Height(110)
|
||||
f:SetTemplate("Transparent")
|
||||
f:Hide()
|
||||
|
||||
local header = CreateFrame("Button", nil, f)
|
||||
header:SetTemplate("Default", true)
|
||||
header:Width(120)
|
||||
header:Height(25)
|
||||
header:Point("CENTER", f, "TOP")
|
||||
header:SetFrameLevel(header:GetFrameLevel() + 2)
|
||||
|
||||
local title = header:CreateFontString("OVERLAY")
|
||||
title:FontTemplate()
|
||||
title:Point("CENTER", header, "CENTER")
|
||||
title:SetText("ElvUI")
|
||||
|
||||
local desc = f:CreateFontString("ARTWORK")
|
||||
desc:SetFontObject("GameFontHighlight")
|
||||
desc:SetJustifyV("TOP")
|
||||
desc:SetJustifyH("LEFT")
|
||||
desc:Point("TOPLEFT", 18, -32)
|
||||
desc:Point("BOTTOMRIGHT", -18, 30)
|
||||
f.desc = desc
|
||||
|
||||
f.disableButton = CreateFrame("CheckButton", f:GetName().."DisableButton", f, "OptionsCheckButtonTemplate")
|
||||
_G[f.disableButton:GetName().."Text"]:SetText(DISABLE)
|
||||
f.disableButton:Point("BOTTOMLEFT")
|
||||
Skins:HandleCheckBox(f.disableButton)
|
||||
f.disableButton:SetScript("OnShow", function(self) self:SetChecked(E.db.hideTutorial) end)
|
||||
|
||||
f.disableButton:SetScript("OnClick", function(self) E.db.hideTutorial = self:GetChecked() end)
|
||||
|
||||
f.hideButton = CreateFrame("Button", f:GetName().."HideButton", f, "OptionsButtonTemplate")
|
||||
f.hideButton:Point("BOTTOMRIGHT", -5, 5)
|
||||
Skins:HandleButton(f.hideButton)
|
||||
_G[f.hideButton:GetName().."Text"]:SetText(HIDE)
|
||||
f.hideButton:SetScript("OnClick", function(self) E:StaticPopupSpecial_Hide(self:GetParent()) end)
|
||||
|
||||
f.nextButton = CreateFrame("Button", f:GetName().."NextButton", f, "OptionsButtonTemplate")
|
||||
f.nextButton:Point("RIGHT", f.hideButton, "LEFT", -4, 0)
|
||||
f.nextButton:Width(20)
|
||||
Skins: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:Point("RIGHT", f.nextButton, "LEFT", -4, 0)
|
||||
f.prevButton:Width(20)
|
||||
Skins: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
|
||||
Reference in New Issue
Block a user