From 3a6f9b14fc26cd5e7bcd0ce07fd9b1802aed5616 Mon Sep 17 00:00:00 2001 From: Bunny67 Date: Thu, 14 Dec 2017 02:13:25 +0300 Subject: [PATCH] 123 --- 2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua | 511 ++++++++++++++++++ .../5/6/7/ElvUI/Modules/Auras/Load_Auras.xml | 3 + 2/3/4/5/6/7/ElvUI/Modules/Load_Modules.xml | 1 + 2/3/4/5/6/7/ElvUI/Settings/Private.lua | 5 + 2/3/4/5/6/7/ElvUI/Settings/Profile.lua | 34 ++ 5 files changed, 554 insertions(+) create mode 100644 2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua create mode 100644 2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml diff --git a/2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua b/2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua new file mode 100644 index 0000000..28e1be2 --- /dev/null +++ b/2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua @@ -0,0 +1,511 @@ +local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB +local A = E:NewModule("Auras", "AceEvent-3.0"); +local LSM = LibStub("LibSharedMedia-3.0"); + +--Cache global variables +--Lua functions +local GetTime = GetTime +local _G = _G +local unpack, select, pairs, ipairs = unpack, select, pairs, ipairs +local floor, min, max, huge = math.floor, math.min, math.max, math.huge +local format = string.format +local wipe, tinsert, tsort, tremove = table.wipe, table.insert, table.sort, table.remove +--WoW API / Variables +local CreateFrame = CreateFrame +local UnitAura = UnitAura +local CancelItemTempEnchantment = CancelItemTempEnchantment +local CancelUnitBuff = CancelUnitBuff +local GetInventoryItemQuality = GetInventoryItemQuality +local GetItemQualityColor = GetItemQualityColor +local GetWeaponEnchantInfo = GetWeaponEnchantInfo +local GetInventoryItemTexture = GetInventoryItemTexture + +local DIRECTION_TO_POINT = { + DOWN_RIGHT = "TOPLEFT", + DOWN_LEFT = "TOPRIGHT", + UP_RIGHT = "BOTTOMLEFT", + UP_LEFT = "BOTTOMRIGHT", + RIGHT_DOWN = "TOPLEFT", + RIGHT_UP = "BOTTOMLEFT", + LEFT_DOWN = "TOPRIGHT", + LEFT_UP = "BOTTOMRIGHT" +} + +local DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER = { + DOWN_RIGHT = 1, + DOWN_LEFT = -1, + UP_RIGHT = 1, + UP_LEFT = -1, + RIGHT_DOWN = 1, + RIGHT_UP = 1, + LEFT_DOWN = -1, + LEFT_UP = -1 +} + +local DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER = { + DOWN_RIGHT = -1, + DOWN_LEFT = -1, + UP_RIGHT = 1, + UP_LEFT = 1, + RIGHT_DOWN = -1, + RIGHT_UP = 1, + LEFT_DOWN = -1, + LEFT_UP = 1 +} + +local IS_HORIZONTAL_GROWTH = { + RIGHT_DOWN = true, + RIGHT_UP = true, + LEFT_DOWN = true, + LEFT_UP = true +} + +function A:UpdateTime(elapsed) + if self.offset then + local expiration = select(self.offset, GetWeaponEnchantInfo()) + if expiration then + self.timeLeft = expiration / 1e3 + else + self.timeLeft = 0 + end + else + self.timeLeft = self.timeLeft - elapsed + end + + if self.nextUpdate > 0 then + self.nextUpdate = not self.offset and self.nextUpdate - elapsed or 1 + return + end + + local timerValue, formatID + timerValue, formatID, self.nextUpdate = E:GetTimeInfo(self.timeLeft, A.db.fadeThreshold) + --print(timervalue) + --self.time:SetText(format("%s%s|r", E.TimeColors[formatID], format(E.TimeFormats[formatID][2], timervalue))) + + if self.timeLeft > E.db.auras.fadeThreshold then + -- E:StopFlash(self) + else + -- E:Flash(self, 1) + end +end + +local UpdateTooltip = function(self) + if self.offset then + GameTooltip:SetInventoryItem("player", self.offset == 2 and 16 or 17) + else + GameTooltip:SetUnitAura("player", self:GetID(), self:GetParent().filter) + end +end + +local OnEnter = function(self) + if not self:IsVisible() then return end + + GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT", -5, -5) + self:UpdateTooltip() +end + +local OnLeave = function() + GameTooltip:Hide() +end + +local OnClick = function(self) + if self.offset then + if self.offset == 2 then + CancelPlayerBuff(17) + elseif self.offset == 5 then + CancelPlayerBuff(16) + end + else + CancelUnitBuff("player", self:GetID(), self:GetParent().filter) + end +end + +function A:CreateIcon(button) + local font = LSM:Fetch("font", self.db.font) + button:RegisterForClicks("RightButtonUp") + + button.texture = button:CreateTexture(nil, "BORDER") + E:SetInside(button.texture) + button.texture:SetTexCoord(unpack(E.TexCoords)) + + button.count = button:CreateFontString(nil, "ARTWORK") + button.count:SetPoint("BOTTOMRIGHT", -1 + self.db.countXOffset, 1 + self.db.countYOffset) + E:FontTemplate(button.count, font, self.db.fontSize, self.db.fontOutline) + + button.time = button:CreateFontString(nil, "ARTWORK") + button.time:SetPoint("TOP", button, "BOTTOM", 1 + self.db.timeXOffset, 0 + self.db.timeYOffset) + E:FontTemplate(button.time, font, self.db.fontSize, self.db.fontOutline) + + button.highlight = button:CreateTexture(nil, "HIGHLIGHT") + button.highlight:SetTexture(1, 1, 1, 0.45) + E:SetInside(button.highlight) + + button.UpdateTooltip = UpdateTooltip + button:SetScript("OnEnter",function() OnEnter(this) end) + button:SetScript("OnLeave", function() OnLeave(this) end) + button:SetScript("OnClick", function() OnClick(this) end) + + E:SetTemplate(button, "Default") +end + +local enchantableSlots = { + [1] = 16, + [2] = 17 +} + +local buttons = {} +function A:ConfigureAuras(header, auraTable, weaponPosition) + local headerName = header:GetName() + + local db = self.db.debuffs + if header.filter == "HELPFUL" then + db = self.db.buffs + end + + local size = db.size + local point = DIRECTION_TO_POINT[db.growthDirection] + local xOffset = 0 + local yOffset = 0 + local wrapXOffset = 0 + local wrapYOffset = 0 + local wrapAfter = db.wrapAfter + local maxWraps = db.maxWraps + local minWidth = 0 + local minHeight = 0 + + if IS_HORIZONTAL_GROWTH[db.growthDirection] then + minWidth = ((wrapAfter == 1 and 0 or db.horizontalSpacing) + size) * wrapAfter + minHeight = (db.verticalSpacing + size) * maxWraps + xOffset = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + size) + yOffset = 0 + wrapXOffset = 0 + wrapYOffset = DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + size) + else + minWidth = (db.horizontalSpacing + size) * maxWraps + minHeight = ((wrapAfter == 1 and 0 or db.verticalSpacing) + size) * wrapAfter + xOffset = 0 + yOffset = DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + size) + wrapXOffset = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + size) + wrapYOffset = 0 + end + + wipe(buttons) + local button + for i = 1, getn(auraTable) do + button = _G[headerName.."AuraButton"..i] + if button then + if button:IsShown() then button:Hide() end + else + button = CreateFrame("Button", "$parentAuraButton"..i, header) + self:CreateIcon(button) + end + local buffInfo = auraTable[i] + button:SetID(buffInfo.index) + + if buffInfo.duration > 0 and buffInfo.expires then + local timeLeft = buffInfo.expires - GetTime() + if not button.timeLeft then + button.timeLeft = timeLeft + button:SetScript("OnUpdate", function() self.UpdateTime(this, arg1) end) + else + button.timeLeft = timeLeft + end + + button.nextUpdate = -1 + self.UpdateTime(button, 0) + else + button.timeLeft = nil + button.time:SetText("") + button:SetScript("OnUpdate", nil) + end + + if buffInfo.count > 1 then + button.count:SetText(buffInfo.count) + else + button.count:SetText("") + end + + if buffInfo.filter == "HARMFUL" then + local color = DebuffTypeColor[buffInfo.dispelType or ""] + button:SetBackdropBorderColor(color.r, color.g, color.b) + else + button:SetBackdropBorderColor(unpack(E.media.bordercolor)) + end + + button.texture:SetTexture(buffInfo.icon) + + buttons[i] = button + end + + if weaponPosition then + local hasMainHandEnchant, mainHandExpiration, _, hasOffHandEnchant, offHandExpiration = GetWeaponEnchantInfo() + for weapon = 2, 1, -1 do + button = _G["ElvUIPlayerBuffsTempEnchant"..weapon] + if select(weapon, hasMainHandEnchant, hasOffHandEnchant) then + if not button then + button = CreateFrame("Button", "$parentTempEnchant"..weapon, header) + self:CreateIcon(button) + end + if button then + if button:IsShown() then button:Hide() end + + local index = enchantableSlots[weapon] + local quality = GetInventoryItemQuality("player", index) + button.texture:SetTexture(GetInventoryItemTexture("player", index)) + + if quality then + button:SetBackdropBorderColor(GetItemQualityColor(quality)) + end + + local expirationTime = select(weapon, mainHandExpiration, offHandExpiration) + if expirationTime then + button.offset = select(weapon, 2, 5) + button:SetScript("OnUpdate", function() self.UpdateTime(this, arg1) end) + button.nextUpdate = -1 + A.UpdateTime(button, 0) + else + button.timeLeft = nil + button.offset = nil + button:SetScript("OnUpdate", nil) + button.time:SetText("") + end + + buttons[getn(buttons)+1] = button + end + else + if button and type(button.Hide) == "function" then + button.offset = nil + button:Hide() + end + end + end + end + + local display = getn(buttons) + if wrapAfter and maxWraps then + display = min(display, wrapAfter * maxWraps) + end + + local left, right, top, bottom = huge, -huge, -huge, huge + for index = 1, display do + button = buttons[index] + local tick, cycle = floor(mod((index - 1), wrapAfter)), floor((index - 1) / wrapAfter) + button:ClearAllPoints() + button:SetPoint(point, header, cycle * wrapXOffset + tick * xOffset, cycle * wrapYOffset + tick * yOffset) + + button:SetWidth(size) + button:SetHeight(size) + + if button.time then + local font = LSM:Fetch("font", self.db.font) + button.time:ClearAllPoints() + button.time:SetPoint("TOP", button, "BOTTOM", 1 + self.db.timeXOffset, 0 + self.db.timeYOffset) + E:FontTemplate(button.time, font, self.db.fontSize, self.db.fontOutline) + + button.count:ClearAllPoints() + button.count:SetPoint("BOTTOMRIGHT", -1 + self.db.countXOffset, 0 + self.db.countYOffset) + E:FontTemplate(button.count, font, self.db.fontSize, self.db.fontOutline) + end + + button:Show() + left = min(left, button:GetLeft() or huge) + right = max(right, button:GetRight() or -huge) + top = max(top, button:GetTop() or -huge) + bottom = min(bottom, button:GetBottom() or huge) + end + local deadIndex = getn(auraTable) + 1 + button = _G[headerName.."AuraButton"..deadIndex] + while button do + if button:IsShown() then button:Hide() end + deadIndex = deadIndex + 1 + button = _G[headerName.."AuraButton"..deadIndex] + end + + if display >= 1 then + header:SetWidth(max(right - left, minWidth)) + header:SetHeight(max(top - bottom, minHeight)) + else + header:SetWidth(minWidth) + header:SetHeight(minHeight) + end +end + +local freshTable +local releaseTable +do + local tableReserve = {} + freshTable = function () + local t = next(tableReserve) or {} + tableReserve[t] = nil + return t + end + releaseTable = function (t) + tableReserve[t] = wipe(t) + end +end + +local function sortFactory(key, separateOwn, reverse) + if separateOwn ~= 0 then + if reverse then + return function(a, b) + if a.filter == b.filter then + local ownA, ownB = a.caster == "player", b.caster == "player" + if ownA ~= ownB then + return ownA == (separateOwn > 0) + end + return a[key] > b[key] + else + return a.filter < b.filter + end + end; + else + return function(a, b) + if a.filter == b.filter then + local ownA, ownB = a.caster == "player", b.caster == "player" + if ownA ~= ownB then + return ownA == (separateOwn > 0) + end + return a[key] < b[key] + else + return a.filter < b.filter + end + end; + end + else + if reverse then + return function(a, b) + if a.filter == b.filter then + return a[key] > b[key] + else + return a.filter < b.filter + end + end; + else + return function(a, b) + if a.filter == b.filter then + return a[key] < b[key] + else + return a.filter < b.filter + end + end; + end + end +end + +local sorters = {} +for _, key in ipairs{"index", "name", "expires"} do + local label = string.upper(key) + sorters[label] = {} + for bool in pairs{[true] = true, [false] = false} do + sorters[label][bool] = {} + for sep = -1, 1 do + sorters[label][bool][sep] = sortFactory(key, sep, bool) + end + end +end +sorters.TIME = sorters.EXPIRES + +local sortingTable = {} +function A:UpdateHeader(header) + local filter = header.filter + local db = self.db.debuffs + + wipe(sortingTable) + + local weaponPosition + if filter == "HELPFUL" then + db = self.db.buffs + weaponPosition = 0 + end + + local aura, _ + for i = 1, 16 do + aura, _ = freshTable() + aura.buffIndex, aura.untilCancelled = GetPlayerBuff(i, filter) + if aura.buffIndex > 0 then + aura.icon, aura.count, aura.dispelType, aura.duration = GetPlayerBuffTexture(aura.buffIndex), GetPlayerBuffApplications(aura.buffIndex), GetPlayerBuffDispelType(aura.buffIndex), GetPlayerBuffTimeLeft(aura.buffIndex) + aura.filter = filter + aura.index = i + + tinsert(sortingTable, aura) + else + releaseTable(aura) + end + end + + local sortMethod = (sorters[db.sortMethod] or sorters["INDEX"])[db.sortDir == "-"][db.seperateOwn] + --tsort(sortingTable, sortMethod) + + self:ConfigureAuras(header, sortingTable, weaponPosition) + while sortingTable[1] do + releaseTable(tremove(sortingTable)) + end +end + +function A:CreateAuraHeader(filter) + local name = "ElvUIPlayerDebuffs" + if filter == "HELPFUL" then + name = "ElvUIPlayerBuffs" + end + + local header = CreateFrame("Frame", name, UIParent) + header:SetClampedToScreen(true) + header.filter = filter + + header:RegisterEvent("PLAYER_AURAS_CHANGED") + header:SetScript("OnEvent", function() + A:UpdateHeader(this) + end) + + self:UpdateHeader(header) + + return header +end + +function A:Initialize() + if self.db then return end + + if E.private.auras.disableBlizzard then + E:Kill(BuffFrame) + E:Kill(TemporaryEnchantFrame) + end + + if not E.private.auras.enable then return end + + self.db = E.db.auras + + self.BuffFrame = self:CreateAuraHeader("HELPFUL") + self.BuffFrame:SetPoint("TOPRIGHT", MMHolder, "TOPLEFT", -(6 + E.Border), -E.Border - E.Spacing) + E:CreateMover(self.BuffFrame, "BuffsMover", L["Player Buffs"]) + + self.BuffFrame.GetUpdateWeaponEnchant = function(self) + local hasMainHandEnchant, _, _, hasOffHandEnchant = GetWeaponEnchantInfo() + if hasMainHandEnchant and not self.hasMainHandEnchant then + self.hasMainHandEnchant = true + return true + elseif hasOffHandEnchant and not self.hasOffHandEnchant then + self.hasOffHandEnchant = true + return true + elseif self.hasMainHandEnchant and not hasMainHandEnchant then + self.hasMainHandEnchant = false + return true + elseif self.hasOffHandEnchant and not hasOffHandEnchant then + self.hasOffHandEnchant = false + return true + end + end + + self.BuffFrame:SetScript("OnUpdate", function() + if this:GetUpdateWeaponEnchant() then A:UpdateHeader(this) end + end) + + self.DebuffFrame = self:CreateAuraHeader("HARMFUL") + self.DebuffFrame:SetPoint("BOTTOMRIGHT", MMHolder, "BOTTOMLEFT", -(6 + E.Border), E.Border + E.Spacing) + E:CreateMover(self.DebuffFrame, "DebuffsMover", L["Player Debuffs"]) +end + +local function InitializeCallback() + A:Initialize() +end + +E:RegisterModule(A:GetName(), InitializeCallback) \ No newline at end of file diff --git a/2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml b/2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml new file mode 100644 index 0000000..2be9b8a --- /dev/null +++ b/2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml @@ -0,0 +1,3 @@ + +