This commit is contained in:
Andrew6810
2022-10-21 07:09:01 -07:00
parent cbdabfbcca
commit 60ef8a38af
614 changed files with 138573 additions and 2 deletions
+260
View File
@@ -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
+294
View File
@@ -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
+369
View File
@@ -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
+280
View File
@@ -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
+509
View File
@@ -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
+320
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+602
View File
@@ -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)
+88
View File
@@ -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
+99
View File
@@ -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
+936
View File
@@ -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
+24
View File
@@ -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>
+460
View File
@@ -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
+276
View File
@@ -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)
+527
View File
@@ -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
+91
View File
@@ -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
+458
View File
@@ -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)
+142
View File
@@ -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
+208
View File
@@ -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
+756
View File
@@ -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
+346
View File
@@ -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)
+120
View File
@@ -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