diff --git a/ElvUI/Libraries/oUF/elements/auras.lua b/ElvUI/Libraries/oUF/elements/auras.lua index e8f834b..c67bac0 100644 --- a/ElvUI/Libraries/oUF/elements/auras.lua +++ b/ElvUI/Libraries/oUF/elements/auras.lua @@ -65,7 +65,7 @@ local ns = oUF local oUF = ns.oUF local tinsert = table.insert -local floor = math.floor +local floor, min = math.floor, math.min local CreateFrame = CreateFrame local GetTime = GetTime @@ -83,7 +83,7 @@ local function UpdateTooltip(self) end local function onEnter(self) - if(not self:IsVisible()) then return end + if not self:IsVisible() then return end GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT') self:UpdateTooltip() @@ -126,15 +126,13 @@ local function createAuraIcon(element, index) * self - the widget holding the aura buttons * button - the newly created aura button (Button) --]] - if(element.PostCreateIcon) then element:PostCreateIcon(button) end + if element.PostCreateIcon then element:PostCreateIcon(button) end return button end local function customFilter(element, unit, button, name) - if(name) then - return true - end + if name then return true end end local function updateIcon(element, unit, index, offset, filter, isDebuff, visible) @@ -185,12 +183,12 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl show = (element.CustomFilter or customFilter) (element, unit, button, name, rank, texture, count, dispelType, duration, expiration) end - if(show) then + if show then -- We might want to consider delaying the creation of an actual cooldown -- object to this point, but I think that will just make things needlessly -- complicated. - if(button.cd and not element.disableCooldown) then - if(duration and duration > 0) then + if button.cd and not element.disableCooldown then + if duration and duration > 0 then button.cd:SetCooldown(GetTime() - (duration - expiration), duration) button.cd:Show() else @@ -198,8 +196,8 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl end end - if(button.overlay) then - if((isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType) then + if button.overlay then + if (isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType then local color = DebuffTypeColor[dispelType] or DebuffTypeColor.none button.overlay:SetVertexColor(color.r, color.g, color.b) @@ -209,8 +207,8 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl end end - if(button.icon) then button.icon:SetTexture(texture) end - if(button.count) then button.count:SetText(count > 1 and count) end + if button.icon then button.icon:SetTexture(texture) end + if button.count then button.count:SetText(count > 1 and count) end local size = element.size or 16 button:SetSize(size, size) @@ -228,7 +226,7 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl * index - the index of the aura (number) * position - the actual position of the aura button (number) --]] - if(element.PostUpdateIcon) then + if element.PostUpdateIcon then element:PostUpdateIcon(unit, button, index, position) end @@ -261,24 +259,24 @@ local function SetPosition(element, from, to) end local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontHide) - if(not offset) then offset = 0 end + if not offset then offset = 0 end local index = 1 local visible = 0 local hidden = 0 - while(visible < limit) do + while visible < limit do local result = updateIcon(element, unit, index, offset, filter, isDebuff, visible) - if(not result) then + if not result then break - elseif(result == VISIBLE) then + elseif result == VISIBLE then visible = visible + 1 - elseif(result == HIDDEN) then + elseif result == HIDDEN then hidden = hidden + 1 end index = index + 1 end - if(not dontHide) then + if not dontHide then for i = visible + offset + 1, #element do element[i]:Hide() end @@ -288,42 +286,42 @@ local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontH end local function UpdateAuras(self, event, unit) - if(self.unit ~= unit) then return end + if self.unit ~= unit then return end local auras = self.Auras - if(auras) then + if auras then --[[ Callback: Auras:PreUpdate(unit) Called before the element has been updated. * self - the widget holding the aura buttons * unit - the unit for which the update has been triggered (string) --]] - if(auras.PreUpdate) then auras:PreUpdate(unit) end + if auras.PreUpdate then auras:PreUpdate(unit) end local numBuffs = auras.numBuffs or 32 local numDebuffs = auras.numDebuffs or 40 local max = auras.numTotal or numBuffs + numDebuffs - local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', math.min(numBuffs, max), nil, 0, true) + local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', min(numBuffs, max), nil, 0, true) local hasGap - if(visibleBuffs ~= 0 and auras.gap) then + if visibleBuffs ~= 0 and auras.gap then hasGap = true visibleBuffs = visibleBuffs + 1 local button = auras[visibleBuffs] - if(not button) then + if not button then button = (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs) tinsert(auras, button) auras.createdIcons = auras.createdIcons + 1 end -- Prevent the button from displaying anything. - if(button.cd) then button.cd:Hide() end - if(button.icon) then button.icon:SetTexture() end - if(button.overlay) then button.overlay:Hide() end - if(button.stealable) then button.stealable:Hide() end - if(button.count) then button.count:SetText() end + if button.cd then button.cd:Hide() end + if button.icon then button.icon:SetTexture() end + if button.overlay then button.overlay:Hide() end + if button.stealable then button.stealable:Hide() end + if button.count then button.count:SetText() end button:EnableMouse(false) button:Show() @@ -341,10 +339,10 @@ local function UpdateAuras(self, event, unit) end end - local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', math.min(numDebuffs, max - visibleBuffs), true, visibleBuffs) + local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', min(numDebuffs, max - visibleBuffs), true, visibleBuffs) auras.visibleDebuffs = visibleDebuffs - if(hasGap and visibleDebuffs == 0) then + if hasGap and visibleDebuffs == 0 then auras[visibleBuffs]:Hide() visibleBuffs = visibleBuffs - 1 end @@ -364,11 +362,11 @@ local function UpdateAuras(self, event, unit) * from - the offset of the first aura button to be (re-)anchored (number) * to - the offset of the last aura button to be (re-)anchored (number) --]] - if(auras.PreSetPosition) then + if auras.PreSetPosition then fromRange, toRange = auras:PreSetPosition(max) end - if(fromRange or auras.createdIcons > auras.anchoredIcons) then + if fromRange or auras.createdIcons > auras.anchoredIcons then --[[ Override: Auras:SetPosition(from, to) Used to (re-)anchor the aura buttons. Called when new aura buttons have been created or if :PreSetPosition is defined. @@ -387,72 +385,72 @@ local function UpdateAuras(self, event, unit) * self - the widget holding the aura buttons * unit - the unit for which the update has been triggered (string) --]] - if(auras.PostUpdate) then auras:PostUpdate(unit) end + if auras.PostUpdate then auras:PostUpdate(unit) end end local buffs = self.Buffs - if(buffs) then - if(buffs.PreUpdate) then buffs:PreUpdate(unit) end + if buffs then + if buffs.PreUpdate then buffs:PreUpdate(unit) end local numBuffs = buffs.num or 32 local visibleBuffs, hiddenBuffs = filterIcons(buffs, unit, buffs.filter or 'HELPFUL', numBuffs) buffs.visibleBuffs = visibleBuffs local fromRange, toRange - if(buffs.PreSetPosition) then + if buffs.PreSetPosition then fromRange, toRange = buffs:PreSetPosition(numBuffs) end - if(fromRange or buffs.createdIcons > buffs.anchoredIcons) then + if fromRange or buffs.createdIcons > buffs.anchoredIcons then (buffs.SetPosition or SetPosition) (buffs, fromRange or buffs.anchoredIcons + 1, toRange or buffs.createdIcons) buffs.anchoredIcons = buffs.createdIcons end - if(buffs.PostUpdate) then buffs:PostUpdate(unit) end + if buffs.PostUpdate then buffs:PostUpdate(unit) end end local debuffs = self.Debuffs - if(debuffs) then - if(debuffs.PreUpdate) then debuffs:PreUpdate(unit) end + if debuffs then + if debuffs.PreUpdate then debuffs:PreUpdate(unit) end local numDebuffs = debuffs.num or 40 local visibleDebuffs, hiddenDebuffs = filterIcons(debuffs, unit, debuffs.filter or 'HARMFUL', numDebuffs, true) debuffs.visibleDebuffs = visibleDebuffs local fromRange, toRange - if(debuffs.PreSetPosition) then + if debuffs.PreSetPosition then fromRange, toRange = debuffs:PreSetPosition(numDebuffs) end - if(fromRange or debuffs.createdIcons > debuffs.anchoredIcons) then + if fromRange or debuffs.createdIcons > debuffs.anchoredIcons then (debuffs.SetPosition or SetPosition) (debuffs, fromRange or debuffs.anchoredIcons + 1, toRange or debuffs.createdIcons) debuffs.anchoredIcons = debuffs.createdIcons end - if(debuffs.PostUpdate) then debuffs:PostUpdate(unit) end + if debuffs.PostUpdate then debuffs:PostUpdate(unit) end end end local function Update(self, event, unit) - if(self.unit ~= unit) then return end + if self.unit ~= unit then return end UpdateAuras(self, event, unit) -- Assume no event means someone wants to re-anchor things. This is usually -- done by UpdateAllElements and :ForceUpdate. - if(event == 'ForceUpdate' or not event) then + if event == 'ForceUpdate' or not event then local buffs = self.Buffs - if(buffs) then + if buffs then (buffs.SetPosition or SetPosition) (buffs, 1, buffs.createdIcons) end local debuffs = self.Debuffs - if(debuffs) then + if debuffs then (debuffs.SetPosition or SetPosition) (debuffs, 1, debuffs.createdIcons) end local auras = self.Auras - if(auras) then + if auras then (auras.SetPosition or SetPosition) (auras, 1, auras.createdIcons) end end @@ -463,11 +461,11 @@ local function ForceUpdate(element) end local function Enable(self) - if(self.Buffs or self.Debuffs or self.Auras) then + if self.Buffs or self.Debuffs or self.Auras then self:RegisterEvent('UNIT_AURA', UpdateAuras) local buffs = self.Buffs - if(buffs) then + if buffs then buffs.__owner = self buffs.ForceUpdate = ForceUpdate @@ -478,7 +476,7 @@ local function Enable(self) end local debuffs = self.Debuffs - if(debuffs) then + if debuffs then debuffs.__owner = self debuffs.ForceUpdate = ForceUpdate @@ -489,7 +487,7 @@ local function Enable(self) end local auras = self.Auras - if(auras) then + if auras then auras.__owner = self auras.ForceUpdate = ForceUpdate @@ -504,13 +502,13 @@ local function Enable(self) end local function Disable(self) - if(self.Buffs or self.Debuffs or self.Auras) then + if self.Buffs or self.Debuffs or self.Auras then self:UnregisterEvent('UNIT_AURA', UpdateAuras) - if(self.Buffs) then self.Buffs:Hide() end - if(self.Debuffs) then self.Debuffs:Hide() end - if(self.Auras) then self.Auras:Hide() end + if self.Buffs then self.Buffs:Hide() end + if self.Debuffs then self.Debuffs:Hide() end + if self.Auras then self.Auras:Hide() end end end -oUF:AddElement('Auras', Update, Enable, Disable) \ No newline at end of file +oUF:AddElement('Auras', Update, Enable, Disable) diff --git a/ElvUI/Modules/UnitFrames/Elements/Auras.lua b/ElvUI/Modules/UnitFrames/Elements/Auras.lua new file mode 100644 index 0000000..4826162 --- /dev/null +++ b/ElvUI/Modules/UnitFrames/Elements/Auras.lua @@ -0,0 +1,593 @@ +local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB +local UF = E:GetModule("UnitFrames"); +local LSM = LibStub("LibSharedMedia-3.0"); + +--Cache global variables +--Lua functions +local unpack = unpack +local find, format = string.find, string.format +local strsplit = strsplit +local tsort, getn = table.sort, table.getn +local ceil = math.ceil +--WoW API / Variables +local GetTime = GetTime +local CreateFrame = CreateFrame +local IsShiftKeyDown = IsShiftKeyDown +local IsAltKeyDown = IsAltKeyDown +local IsControlKeyDown = IsControlKeyDown +local UnitCanAttack = UnitCanAttack +local UnitIsFriend = UnitIsFriend +local UnitIsUnit = UnitIsUnit + +function UF:Construct_Buffs(frame) + local buffs = CreateFrame("Frame", frame:GetName().."Buffs", frame) + buffs.spacing = E.Spacing + buffs.PreSetPosition = (not frame:GetScript("OnUpdate")) and self.SortAuras or nil + buffs.PostCreateIcon = self.Construct_AuraIcon + buffs.PostUpdateIcon = self.PostUpdateAura + buffs.CustomFilter = self.AuraFilter + buffs:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 10) --Make them appear above any text element + buffs.type = "buffs" + --Set initial width to prevent division by zero. This value doesn't matter, as it will be updated later + buffs:Width(100) + + return buffs +end + +function UF:Construct_Debuffs(frame) + local debuffs = CreateFrame("Frame", frame:GetName().."Debuffs", frame) + debuffs.spacing = E.Spacing + debuffs.PreSetPosition = (not frame:GetScript("OnUpdate")) and self.SortAuras or nil + debuffs.PostCreateIcon = self.Construct_AuraIcon + debuffs.PostUpdateIcon = self.PostUpdateAura + debuffs.CustomFilter = self.AuraFilter + debuffs.type = "debuffs" + debuffs:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 10) --Make them appear above any text element + --Set initial width to prevent division by zero. This value doesn't matter, as it will be updated later + debuffs:Width(100) + + return debuffs +end + +function UF:Construct_AuraIcon(button) + local offset = UF.thinBorders and E.mult or E.Border + + button.text = button.cd:CreateFontString(nil, "OVERLAY") + button.text:Point("CENTER", 1, 1) + button.text:SetJustifyH("CENTER") + + button:SetTemplate("Default", nil, nil, UF.thinBorders, true) + + button.cd.noOCC = true + button.cd.noCooldownCount = true + button.cd:SetReverse(true) + button.cd:SetDrawEdge(true) + button.cd:SetInside(button, offset, offset) + + button.icon:SetInside(button, offset, offset) + button.icon:SetTexCoord(unpack(E.TexCoords)) + button.icon:SetDrawLayer("ARTWORK") + + button.count:ClearAllPoints() + button.count:Point("BOTTOMRIGHT", 1, 1) + button.count:SetJustifyH("RIGHT") + + button.overlay:SetTexture(nil) + button.stealable:SetTexture(nil) + + button:RegisterForClicks("RightButtonUp") + button:SetScript("OnClick", function(self) + if E.db.unitframe.auraBlacklistModifier == "NONE" or not ((E.db.unitframe.auraBlacklistModifier == "SHIFT" and IsShiftKeyDown()) or (E.db.unitframe.auraBlacklistModifier == "ALT" and IsAltKeyDown()) or (E.db.unitframe.auraBlacklistModifier == "CTRL" and IsControlKeyDown())) then return; end + local auraName = self.name + + if auraName then + E:Print(format(L["The spell '%s' has been added to the Blacklist unitframe aura filter."], auraName)) + E.global["unitframe"]["aurafilters"]["Blacklist"]["spells"][auraName] = { + ["enable"] = true, + ["priority"] = 0, + } + + UF:Update_AllFrames() + end + end) + + UF:UpdateAuraIconSettings(button, true) +end + +function UF:EnableDisable_Auras(frame) + if frame.db.debuffs.enable or frame.db.buffs.enable then + if not frame:IsElementEnabled("Aura") then + frame:EnableElement("Aura") + end + else + if frame:IsElementEnabled("Aura") then + frame:DisableElement("Aura") + end + end +end + +local function ReverseUpdate(frame) + UF:Configure_Auras(frame, "Debuffs") + UF:Configure_Auras(frame, "Buffs") +end + +function UF:Configure_Auras(frame, auraType) + if not frame.VARIABLES_SET then return end + local db = frame.db + + local auras = frame[auraType] + auraType = auraType:lower() + local rows = db[auraType].numrows + + local totalWidth = frame.UNIT_WIDTH - frame.SPACING*2 + if frame.USE_POWERBAR_OFFSET then + local powerOffset = ((frame.ORIENTATION == "MIDDLE" and 2 or 1) * frame.POWERBAR_OFFSET) + + if not (db[auraType].attachTo == "POWER" and frame.ORIENTATION == "MIDDLE") then + totalWidth = totalWidth - powerOffset + end + end + auras:Width(totalWidth) + + auras.forceShow = frame.forceShowAuras + auras.num = db[auraType].perrow * rows + auras.size = db[auraType].sizeOverride ~= 0 and db[auraType].sizeOverride or ((((auras:GetWidth() - (auras.spacing*(auras.num/rows - 1))) / auras.num)) * rows) + + if db[auraType].sizeOverride and db[auraType].sizeOverride > 0 then + auras:Width(db[auraType].perrow * db[auraType].sizeOverride) + end + + local attachTo = self:GetAuraAnchorFrame(frame, db[auraType].attachTo, db.debuffs.attachTo == "BUFFS" and db.buffs.attachTo == "DEBUFFS") + local x, y = E:GetXYOffset(db[auraType].anchorPoint, frame.SPACING) --Use frame.SPACING override since it may be different from E.Spacing due to forced thin borders + + if db[auraType].attachTo == "FRAME" then + y = 0 + elseif db[auraType].attachTo == "HEALTH" or db[auraType].attachTo == "POWER" then + local newX = E:GetXYOffset(db[auraType].anchorPoint, -frame.BORDER) + local _, newY = E:GetXYOffset(db[auraType].anchorPoint, (frame.BORDER + frame.SPACING)) + x = newX + y = newY + else + x = 0 + end + + if (auraType == "buffs" and frame.Debuffs.attachTo and frame.Debuffs.attachTo == frame.Buffs and db[auraType].attachTo == "DEBUFFS") then + --Update Debuffs first, as we would otherwise get conflicting anchor points + --This is usually only an issue on profile change + ReverseUpdate(frame) + return + end + + auras:ClearAllPoints() + auras:Point(E.InversePoints[db[auraType].anchorPoint], attachTo, db[auraType].anchorPoint, x + db[auraType].xOffset, y + db[auraType].yOffset) + auras:Height(auras.size * rows) + auras["growth-y"] = find(db[auraType].anchorPoint, "TOP") and "UP" or "DOWN" + auras["growth-x"] = db[auraType].anchorPoint == "LEFT" and "LEFT" or db[auraType].anchorPoint == "RIGHT" and "RIGHT" or (find(db[auraType].anchorPoint, "LEFT") and "RIGHT" or "LEFT") + auras.initialAnchor = E.InversePoints[db[auraType].anchorPoint] + + --These are needed for SmartAuraPosition + auras.attachTo = attachTo + auras.point = E.InversePoints[db[auraType].anchorPoint] + auras.anchorPoint = db[auraType].anchorPoint + auras.xOffset = x + db[auraType].xOffset + auras.yOffset = y + db[auraType].yOffset + + if db[auraType].enable then + auras:Show() + UF:UpdateAuraIconSettings(auras) + else + auras:Hide() + end + + local position = db.smartAuraPosition + if position == "BUFFS_ON_DEBUFFS" then + if db.debuffs.attachTo == "BUFFS" then + E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Buffs"], L["Debuffs"], L["Frame"])) + db.debuffs.attachTo = "FRAME" + frame.Debuffs.attachTo = frame + end + frame.Buffs.PostUpdate = nil + frame.Debuffs.PostUpdate = UF.UpdateBuffsHeaderPosition + elseif position == "DEBUFFS_ON_BUFFS" then + if db.buffs.attachTo == "DEBUFFS" then + E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Debuffs"], L["Buffs"], L["Frame"])) + db.buffs.attachTo = "FRAME" + frame.Buffs.attachTo = frame + end + frame.Buffs.PostUpdate = UF.UpdateDebuffsHeaderPosition + frame.Debuffs.PostUpdate = nil + elseif position == "FLUID_BUFFS_ON_DEBUFFS" then + if db.debuffs.attachTo == "BUFFS" then + E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Buffs"], L["Debuffs"], L["Frame"])) + db.debuffs.attachTo = "FRAME" + frame.Debuffs.attachTo = frame + end + frame.Buffs.PostUpdate = UF.UpdateBuffsHeight + frame.Debuffs.PostUpdate = UF.UpdateBuffsPositionAndDebuffHeight + elseif position == "FLUID_DEBUFFS_ON_BUFFS" then + if db.buffs.attachTo == "DEBUFFS" then + E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Debuffs"], L["Buffs"], L["Frame"])) + db.buffs.attachTo = "FRAME" + frame.Buffs.attachTo = frame + end + frame.Buffs.PostUpdate = UF.UpdateDebuffsPositionAndBuffHeight + frame.Debuffs.PostUpdate = UF.UpdateDebuffsHeight + else + frame.Buffs.PostUpdate = nil + frame.Debuffs.PostUpdate = nil + end +end + +local function SortAurasByTime(a, b) + if (a and b and a:GetParent().db) then + if a:IsShown() and b:IsShown() then + local sortDirection = a:GetParent().db.sortDirection + local aTime = a.expiration or -1 + local bTime = b.expiration or -1 + if (aTime and bTime) then + if(sortDirection == "DESCENDING") then + return aTime < bTime + else + return aTime > bTime + end + end + elseif a:IsShown() then + return true + end + end +end + +local function SortAurasByName(a, b) + if (a and b and a:GetParent().db) then + if a:IsShown() and b:IsShown() then + local sortDirection = a:GetParent().db.sortDirection + local aName = a.spell or "" + local bName = b.spell or "" + if (aName and bName) then + if(sortDirection == "DESCENDING") then + return aName < bName + else + return aName > bName + end + end + elseif a:IsShown() then + return true + end + end +end + +local function SortAurasByDuration(a, b) + if (a and b and a:GetParent().db) then + if a:IsShown() and b:IsShown() then + local sortDirection = a:GetParent().db.sortDirection + local aTime = a.duration or -1 + local bTime = b.duration or -1 + if (aTime and bTime) then + if(sortDirection == "DESCENDING") then + return aTime < bTime + else + return aTime > bTime + end + end + elseif a:IsShown() then + return true + end + end +end + +local function SortAurasByCaster(a, b) + if (a and b and a:GetParent().db) then + if a:IsShown() and b:IsShown() then + local sortDirection = a:GetParent().db.sortDirection + local aPlayer = a.isPlayer or false + local bPlayer = b.isPlayer or false + if(sortDirection == "DESCENDING") then + return (aPlayer and not bPlayer) + else + return (not aPlayer and bPlayer) + end + elseif a:IsShown() then + return true + end + end +end + +function UF:SortAuras() + if not self.db then return end + + --Sorting by Index is Default + if(self.db.sortMethod == "TIME_REMAINING") then + tsort(self, SortAurasByTime) + elseif(self.db.sortMethod == "NAME") then + tsort(self, SortAurasByName) + elseif(self.db.sortMethod == "DURATION") then + tsort(self, SortAurasByDuration) + elseif (self.db.sortMethod == "PLAYER") then + tsort(self, SortAurasByCaster) + end + + --Look into possibly applying filter priorities for auras here. + + return 1, getn(self) --from/to range needed for the :SetPosition call in oUF aura element. Without this aura icon position gets all whacky when not sorted by index +end + +function UF:UpdateAuraIconSettings(auras, noCycle) + local frame = auras:GetParent() + local type = auras.type + if(noCycle) then + frame = auras:GetParent():GetParent() + type = auras:GetParent().type + end + if(not frame.db) then return end + + local db = frame.db[type] + local unitframeFont = LSM:Fetch("font", E.db["unitframe"].font) + local unitframeFontOutline = E.db["unitframe"].fontOutline + local index = 1 + auras.db = db + if(db) then + if(not noCycle) then + while(auras[index]) do + local button = auras[index] + button.text:FontTemplate(unitframeFont, db.fontSize, unitframeFontOutline) + button.count:FontTemplate(unitframeFont, db.countFontSize or db.fontSize, unitframeFontOutline) + + if db.clickThrough and button:IsMouseEnabled() then + button:EnableMouse(false) + elseif not db.clickThrough and not button:IsMouseEnabled() then + button:EnableMouse(true) + end + index = index + 1 + end + else + auras.text:FontTemplate(unitframeFont, db.fontSize, unitframeFontOutline) + auras.count:FontTemplate(unitframeFont, db.countFontSize or db.fontSize, unitframeFontOutline) + + if db.clickThrough and auras:IsMouseEnabled() then + auras:EnableMouse(false) + elseif not db.clickThrough and not auras:IsMouseEnabled() then + auras:EnableMouse(true) + end + end + end +end + +local unstableAffliction = GetSpellInfo(30108) +local vampiricTouch = GetSpellInfo(34914) +function UF:PostUpdateAura(unit, button) + local auras = button:GetParent() + local frame = auras:GetParent() + local type = auras.type + local db = frame.db and frame.db[type] + + if db then + if db.clickThrough and button:IsMouseEnabled() then + button:EnableMouse(false) + elseif not db.clickThrough and not button:IsMouseEnabled() then + button:EnableMouse(true) + end + end + + if button.isDebuff then + if(not button.isFriend and not button.isPlayer) then --[[and (not E.isDebuffWhiteList[name])]] + button:SetBackdropBorderColor(0.9, 0.1, 0.1) + button.icon:SetDesaturated((unit and not find(unit, "arena%d")) and true or false) + else + local color = (button.dtype and DebuffTypeColor[button.dtype]) or DebuffTypeColor.none + if button.name and (button.name == unstableAffliction or button.name == vampiricTouch) and E.myclass ~= "WARLOCK" then + button:SetBackdropBorderColor(0.05, 0.85, 0.94) + else + button:SetBackdropBorderColor(color.r * 0.6, color.g * 0.6, color.b * 0.6) + end + button.icon:SetDesaturated(false) + end + else + if button.isStealable and not button.isFriend then + button:SetBackdropBorderColor(237/255, 234/255, 142/255) + else + button:SetBackdropBorderColor(unpack(E["media"].unitframeBorderColor)) + end + end + + local size = button:GetParent().size + if size then + button:SetSize(size, size) + end + + if button.expiration and button.duration and (button.duration ~= 0) then + local getTime = GetTime() + if not button:GetScript("OnUpdate") then + button.expirationTime = button.expiration + button.expirationSaved = button.expiration - getTime + button.nextupdate = -1 + button:SetScript("OnUpdate", UF.UpdateAuraTimer) + end + if (button.expirationTime ~= button.expiration) or (button.expirationSaved ~= (button.expiration - getTime)) then + button.expirationTime = button.expiration + button.expirationSaved = button.expiration - getTime + button.nextupdate = -1 + end + end + + if button.expiration and button.duration and (button.duration == 0 or button.expiration <= 0) then + button.expirationTime = nil + button.expirationSaved = nil + button:SetScript("OnUpdate", nil) + if button.text:GetFont() then + button.text:SetText("") + end + end +end + +function UF:UpdateAuraTimer(elapsed) + self.expirationSaved = self.expirationSaved - elapsed + if self.nextupdate > 0 then + self.nextupdate = self.nextupdate - elapsed + return + end + + if self.expirationSaved <= 0 then + self:SetScript("OnUpdate", nil) + + if(self.text:GetFont()) then + self.text:SetText("") + end + + return + end + + local timervalue, formatid + timervalue, formatid, self.nextupdate = E:GetTimeInfo(self.expirationSaved, 4) + if self.text:GetFont() then + self.text:SetFormattedText(format("%s%s|r", E.TimeColors[formatid], E.TimeFormats[formatid][2]), timervalue) + elseif self:GetParent():GetParent().db then + self.text:FontTemplate(LSM:Fetch("font", E.db["unitframe"].font), self:GetParent():GetParent().db[self:GetParent().type].fontSize, E.db["unitframe"].fontOutline) + self.text:SetFormattedText(format("%s%s|r", E.TimeColors[formatid], E.TimeFormats[formatid][2]), timervalue) + end +end + +function UF:AuraFilter(unit, button, name, _, _, _, dispelType, duration, expiration, caster, isStealable, _, spellID) + local db = self:GetParent().db + if not db or not db[self.type] then return true; end + + db = db[self.type] + + if not name then return nil end + local filterCheck, isUnit, isFriend, isPlayer, canDispell, allowDuration, noDuration, spellPriority + + isPlayer = (caster == "player" or caster == "vehicle") + isFriend = unit and UnitIsFriend("player", unit) and not UnitCanAttack("player", unit) + + button.isPlayer = isPlayer + button.isFriend = isFriend + button.isStealable = isStealable + button.dtype = dispelType + button.duration = duration + button.expiration = expiration + button.name = name + button.owner = caster --what uses this? + button.spell = name --what uses this? (SortAurasByName?) + button.priority = 0 + + noDuration = (not duration or duration == 0) + allowDuration = noDuration or (duration and (duration > 0) and (db.maxDuration == 0 or duration <= db.maxDuration) and (db.minDuration == 0 or duration >= db.minDuration)) + + if db.priority ~= "" then + isUnit = unit and caster and UnitIsUnit(unit, caster) + canDispell = (self.type == "buffs" and isStealable) or (self.type == "debuffs" and dispelType and E:IsDispellableByMe(dispelType)) + filterCheck, spellPriority = UF:CheckFilter(name, caster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, strsplit(",", db.priority)) + if spellPriority then button.priority = spellPriority end -- this is the only difference from auarbars code + else + filterCheck = allowDuration and true -- Allow all auras to be shown when the filter list is empty, while obeying duration sliders + end + + return filterCheck +end + +function UF:UpdateBuffsHeaderPosition() + local parent = self:GetParent() + local buffs = parent.Buffs + local debuffs = parent.Debuffs + local numDebuffs = self.visibleDebuffs + + if numDebuffs == 0 then + buffs:ClearAllPoints() + buffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset) + else + buffs:ClearAllPoints() + buffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset) + end +end + +function UF:UpdateDebuffsHeaderPosition() + local parent = self:GetParent() + local debuffs = parent.Debuffs + local buffs = parent.Buffs + local numBuffs = self.visibleBuffs + + if numBuffs == 0 then + debuffs:ClearAllPoints() + debuffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset) + else + debuffs:ClearAllPoints() + debuffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset) + end +end + +function UF:UpdateBuffsPositionAndDebuffHeight() + local parent = self:GetParent() + local db = parent.db + local buffs = parent.Buffs + local debuffs = parent.Debuffs + local numDebuffs = self.visibleDebuffs + + if numDebuffs == 0 then + buffs:ClearAllPoints() + buffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset) + else + buffs:ClearAllPoints() + buffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset) + end + + if numDebuffs > 0 then + local numRows = ceil(numDebuffs/db.debuffs.perrow) + debuffs:Height(debuffs.size * (numRows > db.debuffs.numrows and db.debuffs.numrows or numRows)) + else + debuffs:Height(debuffs.size) + end +end + +function UF:UpdateDebuffsPositionAndBuffHeight() + local parent = self:GetParent() + local db = parent.db + local debuffs = parent.Debuffs + local buffs = parent.Buffs + local numBuffs = self.visibleBuffs + + if numBuffs == 0 then + debuffs:ClearAllPoints() + debuffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset) + else + debuffs:ClearAllPoints() + debuffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset) + end + + if numBuffs > 0 then + local numRows = ceil(numBuffs/db.buffs.perrow) + buffs:Height(buffs.size * (numRows > db.buffs.numrows and db.buffs.numrows or numRows)) + else + buffs:Height(buffs.size) + end +end + +function UF:UpdateBuffsHeight() + local parent = self:GetParent() + local db = parent.db + local buffs = parent.Buffs + local numBuffs = self.visibleBuffs + + if numBuffs > 0 then + local numRows = ceil(numBuffs/db.buffs.perrow) + buffs:Height(buffs.size * (numRows > db.buffs.numrows and db.buffs.numrows or numRows)) + else + buffs:Height(buffs.size) + -- Any way to get rid of the last row as well? + -- Using buffs:SetHeight(0) makes frames anchored to this one disappear + end +end + +function UF:UpdateDebuffsHeight() + local parent = self:GetParent() + local db = parent.db + local debuffs = parent.Debuffs + local numDebuffs = self.visibleDebuffs + + if numDebuffs > 0 then + local numRows = ceil(numDebuffs/db.debuffs.perrow) + debuffs:Height(debuffs.size * (numRows > db.debuffs.numrows and db.debuffs.numrows or numRows)) + else + debuffs:Height(debuffs.size) + -- Any way to get rid of the last row as well? + -- Using debuffs:SetHeight(0) makes frames anchored to this one disappear + end +end \ No newline at end of file diff --git a/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml b/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml index c380c5b..adc58a4 100644 --- a/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml +++ b/ElvUI/Modules/UnitFrames/Elements/Load_Elements.xml @@ -1,4 +1,5 @@ +