diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua
index 590e5a8d..5f050f0a 100644
--- a/Libs/DF/fw.lua
+++ b/Libs/DF/fw.lua
@@ -1,6 +1,6 @@
-local dversion = 464
+local dversion = 468
local major, minor = "DetailsFramework-1.0", dversion
local DF, oldminor = LibStub:NewLibrary(major, minor)
diff --git a/Libs/DF/icon.lua b/Libs/DF/icon.lua
index a08c7f32..bd83e267 100644
--- a/Libs/DF/icon.lua
+++ b/Libs/DF/icon.lua
@@ -10,6 +10,43 @@ local CreateFrame = CreateFrame
local PixelUtil = PixelUtil
local GetTime = GetTime
+detailsFramework.GrowDirectionBySide = {
+ [1] = 1,
+ [2] = 2,
+ [3] = 1,
+ [4] = 1,
+ [5] = 2,
+ [6] = 1,
+ [7] = 2,
+ [8] = 1,
+ [9] = 1,
+ [10] = 1,
+ [11] = 2,
+ [12] = 1,
+ [13] = 1,
+ [14] = 1,
+ [15] = 1,
+ [16] = 2,
+ [17] = 2,
+}
+
+detailsFramework.ShouldCenterAlign = {
+ [9] = true,
+ [10] = true,
+ [12] = true,
+}
+
+detailsFramework.SideIsCorner = {
+ [1] = true,
+ [3] = true,
+ [5] = true,
+ [7] = true,
+ [14] = true,
+ [15] = true,
+ [16] = true,
+ [17] = true,
+}
+
---@class df_icon : frame
---@field spellId number
---@field startTime number
@@ -38,9 +75,6 @@ local GetTime = GetTime
---@field StackTextShadow fontstring
---@field Desc fontstring
---@field Cooldown cooldown
----@field CountdownText fontstring
----@field SimpleCooldownTexture texture
----@field SimpleCountdownText fontstring
---@field parentIconRow df_iconrow
---@field cooldownLooper timer
@@ -50,16 +84,12 @@ local GetTime = GetTime
---@field IconPool df_icon[]
---@field AuraCache table
---@field shownAmount number
----@field CreateIcon fun(self:df_iconrow, iconName:string?, bIsSimple:boolean?):frame
----@field GetIcon fun(self:df_iconrow, bIsSimple:boolean?):frame
+---@field CreateIcon fun(self:df_iconrow, iconName:string?):frame
+---@field GetIcon fun(self:df_iconrow):frame
---@field AddSpecificIcon fun(self:df_iconrow, identifierKey:string, spellId:number?, borderColor:table?, startTime:number?, duration:number?, forceTexture:string|number|nil, descText:table?, count:number?, debuffType:string?, caster:string?, canStealOrPurge:boolean?, spellName:string?, isBuff:boolean?)
----@field AddSpecificIconSimple fun(self:df_iconrow, identifierKey:string, spellId:number?, borderColor:table?, startTime:number?, duration:number?, forceTexture:string|number|nil, descText:table?, count:number?, debuffType:string?, caster:string?, canStealOrPurge:boolean?, spellName:string?, isBuff:boolean?, modRate:number?, iconSettings:table?)
---@field SetIcon fun(self:df_iconrow, spellId:number?, borderColor:table?, startTime:number?, duration:number?, forceTexture:string?, descText:table?, count:number?, debuffType:string?, caster:string?, canStealOrPurge:boolean?, spellName:string?, isBuff:boolean?, modRate:number?):frame
----@field SetIconSimple fun(self:df_iconrow, spellId:number?, borderColor:table?, startTime:number?, duration:number?, iconTexture:any, descText:table?, count:number?, debuffType:string?, caster:string?, canStealOrPurge:boolean?, spellName:string?, isBuff:boolean?, modRate:number?, iconSettings:table?):frame
----@field SetAuraIconSimpleWithIconTemplate fun(self:df_iconrow, aI:aurainfo, iconTemplateTable:df_icontemplate)
---@field SetStacks fun(self:df_iconrow, iconFrame:table, bIsShown:boolean, stacksAmount:number?) is shown false to hide the stack text
---@field OnIconTick fun(self:df_icon, deltaTime:number)
----@field OnIconSimpleTick fun(self:df_icon)
---@field FormatCooldownTime fun(thisTime:number):string
---@field FormatCooldownTimeDecimal fun(formattedTime:number):string
---@field RemoveSpecificIcon fun(self:df_iconrow, identifierKey:any)
@@ -99,9 +129,9 @@ detailsFramework.IconMixin = {
---@param self df_iconrow the parent frame
---@param iconName string the name of the icon frame
---@return df_icon
- CreateIcon = function(self, iconName, bIsSimple)
+ CreateIcon = function(self, iconName)
---@type df_icon
- local iconFrame = CreateFrame("frame", iconName, self, not bIsSimple and "BackdropTemplate")
+ local iconFrame = CreateFrame("frame", iconName, self, "BackdropTemplate")
---@type texture
iconFrame.Texture = iconFrame:CreateTexture(nil, "artwork")
@@ -138,20 +168,6 @@ detailsFramework.IconMixin = {
iconFrame.CountdownText:SetPoint("center", iconFrame, "center", 0, 0)
iconFrame.CountdownText:Hide()
- if (bIsSimple) then
- --create a overlay texture which will indicate the cooldown time
- iconFrame.SimpleCooldownTexture = iconFrame:CreateTexture(self:GetName() .. "SimpleCooldownTexture", "overlay", nil, 7)
- iconFrame.SimpleCooldownTexture:SetTexture([[Interface\Azerite\AzeriteTooltipBackground]], "CLAMP", "CLAMP", "NEAREST")
- iconFrame.SimpleCooldownTexture:SetPoint("bottomleft", iconFrame.Texture, "bottomleft", 0, 0)
- iconFrame.SimpleCooldownTexture:SetPoint("bottomright", iconFrame.Texture, "bottomright", 0, 0)
- iconFrame.SimpleCooldownTexture:SetHeight(1)
- iconFrame.SimpleCooldownTexture:Hide()
-
- iconFrame.SimpleCountdownText = iconFrame:CreateFontString(self:GetName() .. "SimpleCooldownText", "overlay", "GameFontNormal")
- iconFrame.SimpleCountdownText:SetPoint("center", iconFrame, "center", 0, 0)
- iconFrame.SimpleCountdownText:Hide()
- end
-
iconFrame.stacks = 0
iconFrame:SetScript("OnHide", iconFrameOnHideScript)
@@ -160,46 +176,26 @@ detailsFramework.IconMixin = {
---get an icon frame from the pool
---@param self df_iconrow the parent frame
- ---@param bIsSimple boolean if true, the icon will be created with a simple template
---@return df_icon
- GetIcon = function(self, bIsSimple)
+ GetIcon = function(self)
---@type df_icon
local iconFrame = self.IconPool[self.NextIcon]
if (not iconFrame) then
---@type df_icon
- iconFrame = self:CreateIcon("$parentIcon" .. self.NextIcon, bIsSimple)
+ iconFrame = self:CreateIcon("$parentIcon" .. self.NextIcon)
iconFrame.parentIconRow = self
- if (bIsSimple) then
- iconFrame.Cooldown:Hide()
- iconFrame.Desc:Hide()
- iconFrame.Texture:SetTexCoord(0.1, 0.9, 0.1, 0.9)
- --newIconFrame:SetBackdropBorderColor(0, 0, 0, 0)
- iconFrame.Border:ClearAllPoints()
- iconFrame.Border:SetPoint("topleft", iconFrame, "topleft", -1, 1)
- iconFrame.Border:SetPoint("bottomright", iconFrame, "bottomright", 1, -1)
- iconFrame.Border:SetTexture(130759)
- iconFrame.Border:SetTexCoord(0.296875, 0.5703125, 0, 0.515625)
- iconFrame.Border:SetDrawLayer("overlay", 7)
+ iconFrame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
+ iconFrame:SetBackdropBorderColor(0, 0, 0, 0)
+ iconFrame:EnableMouse(false)
+ iconFrame.Cooldown:SetHideCountdownNumbers(self.options.surpress_blizzard_cd_timer)
+ iconFrame.Cooldown.noCooldownCount = self.options.surpress_tulla_omni_cc
+ iconFrame.CountdownText:ClearAllPoints()
+ iconFrame.CountdownText:SetPoint(self.options.text_anchor or "center", iconFrame, self.options.text_rel_anchor or "center", self.options.text_x_offset or 0, self.options.text_y_offset or 0)
+ iconFrame.Desc:ClearAllPoints()
+ iconFrame.Desc:SetPoint(self.options.desc_text_anchor or "bottom", iconFrame, self.options.desc_text_rel_anchor or "top", self.options.desc_text_x_offset or 0, self.options.desc_text_y_offset or 2)
- iconFrame.StackText:SetTextColor(detailsFramework:ParseColors(self.options.stack_text_color))
- detailsFramework:SetFontSize(iconFrame.StackText, self.options.stack_text_size)
- detailsFramework:SetFontFace(iconFrame.StackText, self.options.stack_text_font)
- detailsFramework:SetFontOutline(iconFrame.StackText, self.options.stack_text_outline)
- detailsFramework:SetFontFace(iconFrame.StackTextShadow, self.options.stack_text_font)
- detailsFramework:SetFontSize(iconFrame.StackTextShadow, self.options.stack_text_size+1)
- else
- iconFrame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
- iconFrame:SetBackdropBorderColor(0, 0, 0, 0)
- iconFrame:EnableMouse(false)
- iconFrame.Cooldown:SetHideCountdownNumbers(self.options.surpress_blizzard_cd_timer)
- iconFrame.Cooldown.noCooldownCount = self.options.surpress_tulla_omni_cc
- iconFrame.CountdownText:ClearAllPoints()
- iconFrame.CountdownText:SetPoint(self.options.text_anchor or "center", iconFrame, self.options.text_rel_anchor or "center", self.options.text_x_offset or 0, self.options.text_y_offset or 0)
- iconFrame.Desc:ClearAllPoints()
- iconFrame.Desc:SetPoint(self.options.desc_text_anchor or "bottom", iconFrame, self.options.desc_text_rel_anchor or "top", self.options.desc_text_x_offset or 0, self.options.desc_text_y_offset or 2)
- end
iconFrame.StackText:ClearAllPoints()
iconFrame.StackText:SetPoint(self.options.stack_text_anchor or "center", iconFrame, self.options.stack_text_rel_anchor or "center", self.options.stack_text_x_offset or 0, self.options.stack_text_y_offset or 0)
@@ -370,6 +366,7 @@ detailsFramework.IconMixin = {
iconFrame.canStealOrPurge = canStealOrPurge
iconFrame.isBuff = isBuff
iconFrame.spellName = spellName
+ iconFrame.modRate = modRate
iconFrame.identifierKey = nil -- only used for "specific" add/remove
@@ -400,295 +397,12 @@ detailsFramework.IconMixin = {
end
end,
- ---this function return true if an update is required to be performed, return false if the icons shown are the same as the ones received in the auraList
- ---'amount' are the amount of auras the check in the list received against the icons shown, the function which called this function know how much icons it's showing
- ---'auraList' are the list of auras which can be a simple array or an array of sub-arrays
- ---if valid, 'auraInfoIndex' is the index where the auraInfo is found on the sub-array
- ---@param self df_iconrow
- ---@param auraList table
- ---@param amount number
- ---@param auraInfoIndex number?
- ---@return boolean?
- NeedUpdate = function(self, auraList, amount, auraInfoIndex)
- if (not auraList or not amount) then
- return false, "no aura list or amount"
- end
-
- local iconPool = self.IconPool
- local iconPoolAmount = #iconPool
- local currentlyShown = self.shownAmount
- local auraListAmount = #auraList
- local amountToShow = math.min(amount, auraListAmount)
-
- --quick exit if the parameters already have divergences
- if (amountToShow ~= currentlyShown) then
- return true
- end
-
- --the amount of icons shown is the same as the amount of auras that are needed to show
- --now check if it's showing the same auras
-
- for i = 1, amount do
- local auraInfo = auraInfoIndex and auraList[i][auraInfoIndex] or auraList[i]
- local iconFrame = iconPool[i]
- if (iconFrame.Texture.texture ~= auraInfo.icon) then
- return true
- end
-
- local auraStartTime = auraInfo.expirationTime - auraInfo.duration
- local iconFrameStartTime = iconFrame.startTime
-
- --if they are more than 200 miliseconds apart, then it's a different aura
- if (math.abs(auraStartTime - iconFrameStartTime) > 0.2) then
- return true, "aura start has changed"
- end
- end
-
- return false, "nothing changed"
- end,
-
- ---adds only if not existing already in the cache
- ---@param self df_iconrow the parent frame
- AddSpecificIconSimple = function(self, identifierKey, spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff, modRate, iconSettings)
- if (not identifierKey or identifierKey == "") then
- return
- end
-
- if (not self.AuraCache[identifierKey]) then
- ---@type df_icon
- local icon = self:SetIconSimple(spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff or false, modRate, iconSettings)
- icon.identifierKey = identifierKey
- self.AuraCache[identifierKey] = true
- end
- end,
-
- ---set an icon frame with a simple template
- ---@param self df_iconrow the parent frame
- ---@param aI aurainfo
- ---@param iconTemplateTable df_icontemplate
- SetAuraIconSimpleWithIconTemplate = function(self, aI, iconTemplateTable)
- local startTime = aI.expirationTime - aI.duration
- ---@type df_icon
- local iconFrame = self:SetIconSimple(aI.spellId, nil, startTime, aI.duration, aI.icon, nil, aI.applications, aI.dispelName, aI.sourceUnit, aI.isStealable, aI.name, aI.isHelpful, aI.timeMod, iconTemplateTable)
- if (iconFrame) then
- iconFrame.expirationTime = aI.expirationTime
- end
- end,
-
- AddSpecificIconWithTemplate = function(self, iconTemplateTable)
- self:AddSpecificIconSimple(iconTemplateTable.id, iconTemplateTable.id, nil, iconTemplateTable.startTime, iconTemplateTable.duration, nil, nil, iconTemplateTable.count, nil, nil, nil, nil, nil, nil, iconTemplateTable)
- end,
-
- ---set an icon frame with a simple template
- ---@param self df_iconrow the parent frame
- ---@return df_icon?
- SetIconSimple = function(self, spellId, borderColor, startTime, duration, iconTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff, modRate, iconSettings)
- local actualSpellName, spellIcon = spellNameCache[spellId], spellIconCache[spellId]
-
- iconSettings = iconSettings or emptyTable
-
- if (not actualSpellName) then
- actualSpellName, _, spellIcon = GetSpellInfo(spellId)
- spellIconCache[spellId] = spellIcon
- spellNameCache[spellId] = actualSpellName
- end
-
- if iconTexture then
- spellIcon = iconTexture
- end
-
- if (not spellIcon) then
- if (iconSettings.texture) then
- spellIcon = iconSettings.texture
- end
- end
-
- if (spellIcon) then
- spellName = spellName or actualSpellName or "unknown_aura"
- modRate = modRate or 1
-
- local bIsSimple = true
- ---@type df_icon
- local iconFrame = self:GetIcon(bIsSimple)
- self.shownAmount = self.NextIcon - 1
-
- if (iconFrame.Texture.texture ~= spellIcon or (iconSettings.coords and iconSettings.coords ~= iconFrame.currentCoords)) then
- iconFrame.Texture:SetTexture(spellIcon, "CLAMP", "CLAMP", iconSettings.textureFilter or "LINEAR")
-
- if (iconSettings.coords) then
- iconFrame.Texture:SetTexCoord(unpack(iconSettings.coords))
- iconFrame.currentCoords = iconSettings.coords
-
- elseif (self.options.texcoord ~= iconFrame.currentCoords) then
- iconFrame.Texture:SetTexCoord(unpack(self.options.texcoord))
- iconFrame.currentCoords = self.options.texcoord
- else
- iconFrame.Texture:SetTexCoord(0, 1, 0, 1)
- end
-
- iconFrame.Texture:ClearAllPoints()
- if (iconSettings.points) then
- for i = 1, #iconSettings.points do
- local point = iconSettings.points[i]
- iconFrame.Texture:SetPoint(point[1], iconFrame, point[2], point[3], point[4])
- end
-
- if (iconSettings.width) then
- iconFrame.Texture:SetWidth(iconSettings.width)
- else
- iconFrame.Texture:SetWidth(self.options.icon_width)
- end
-
- if (iconSettings.height) then
- iconFrame.Texture:SetHeight(iconSettings.height)
- else
- iconFrame.Texture:SetHeight(self.options.icon_height)
- end
- else
- if (iconSettings.width) then
- iconFrame.Texture:SetWidth(iconSettings.width)
- iconFrame.Texture:SetHeight(iconSettings.height or iconSettings.width)
- PixelUtil.SetPoint(iconFrame.Texture, "center", iconFrame, "center", 0, 0)
- else
- PixelUtil.SetPoint(iconFrame.Texture, "topleft", iconFrame, "topleft", 1, -1)
- PixelUtil.SetPoint(iconFrame.Texture, "bottomright", iconFrame, "bottomright", -1, 1)
- end
- end
-
- iconFrame.Texture.texture = spellIcon
- else
- if (self.options.texcoord ~= iconFrame.currentCoords) then
- iconFrame.Texture:SetTexCoord(unpack(self.options.texcoord))
- iconFrame.currentCoords = self.options.texcoord
- else
- iconFrame.Texture:SetTexCoord(0, 1, 0, 1)
- end
- end
-
- if (borderColor) then
- iconFrame.Border:Show()
- iconFrame.Border:SetVertexColor(unpack(borderColor))
- else
- if (iconSettings.borderColor) then
- iconFrame.Border:Show()
- iconFrame.Border:SetTexture(iconSettings.borderTexture or 130759)
- iconFrame.Border:SetVertexColor(unpack(iconSettings.borderColor or white))
- else
- iconFrame.Border:Hide()
- end
- end
-
- if (count and count > 1 and self.options.stack_text) then
- self:SetStacks(iconFrame, true, count)
- else
- self:SetStacks(iconFrame, false)
- end
-
- iconFrame.stacks = count or 0
-
- if (iconSettings.scale) then
- iconFrame.Texture:SetScale(iconSettings.scale)
- else
- iconFrame.Texture:SetScale(1)
- end
-
- if (iconSettings.alpha) then
- iconFrame.Texture:SetAlpha(iconSettings.alpha)
- else
- iconFrame.Texture:SetAlpha(1)
- end
-
- --cache size
- iconFrame.width = self.options.icon_width
- iconFrame.height = self.options.icon_height
-
- PixelUtil.SetSize(iconFrame, iconFrame.width, iconFrame.height)
- iconFrame:Show()
-
- iconFrame.textureWidth = iconFrame.Texture:GetWidth()
- iconFrame.textureHeight = iconFrame.Texture:GetHeight()
-
- --update the size of the frame
- self:SetWidth((self.options.left_padding * 2) + (self.options.icon_padding * (self.NextIcon-2)) + (self.options.icon_width * (self.NextIcon - 1)))
- self:SetHeight(self.options.icon_height + (self.options.top_padding * 2))
-
- --make information available
- iconFrame.spellId = spellId
- iconFrame.startTime = startTime
- iconFrame.duration = duration
- iconFrame.endTime = (startTime and duration and startTime + duration) or 0
- iconFrame.count = count
- iconFrame.debuffType = debuffType
- iconFrame.caster = caster
- iconFrame.canStealOrPurge = canStealOrPurge
- iconFrame.isBuff = isBuff
- iconFrame.spellName = spellName
-
- if (startTime and duration and duration > 0) then
- local endTime = startTime + duration
- local now = GetTime()
- if (endTime > now) then
- iconFrame.SimpleCooldownTexture:Show()
- iconFrame.SimpleCooldownTexture:SetHeight(1)
- self:SetSimpleCooldown(iconFrame)
- end
- else
- iconFrame.SimpleCooldownTexture:Hide()
- end
-
- iconFrame.identifierKey = nil -- only used for "specific" add/remove
-
- --add the spell into the cache
- self.AuraCache[spellId or -1] = true
- self.AuraCache[spellName] = true
- self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or canStealOrPurge
- self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or debuffType == "" --yes, enrages are empty-string...
-
- --show the frame
- self:Show()
-
- self:AlignAuraIcons()
-
- return iconFrame
- end
- end,
-
- ---@param self df_iconrow the parent frame
- ---@param iconFrame df_icon
- SetSimpleCooldown = function(self, iconFrame)
- if (iconFrame.cooldownLooper) then
- iconFrame.cooldownLooper:Cancel()
- end
-
- self.OnIconSimpleTick(iconFrame)
-
- local amountOfLoops = math.floor(iconFrame.duration / 0.5)
- local loopEndCallback = nil
- local checkPointCallback = nil
-
- local newLooper = detailsFramework.Schedules.NewLooper(0.5, self.OnIconSimpleTick, amountOfLoops, loopEndCallback, checkPointCallback, iconFrame)
- iconFrame.cooldownLooper = newLooper
- end,
-
- ---@param iconFrame df_icon
- OnIconSimpleTick = function(iconFrame)
- local now = GetTime()
- local percent = (now - iconFrame.startTime) / iconFrame.duration
- --percent = abs(percent - 1)
-
- local newHeight = math.min(iconFrame.textureHeight * percent, iconFrame.textureHeight)
- iconFrame.SimpleCooldownTexture:SetHeight(newHeight)
-
- iconFrame.SimpleCountdownText:SetText(iconFrame.parentIconRow.FormatCooldownTime(iconFrame.duration - (now - iconFrame.startTime)))
- --self.SimpleCountdownText:Show()
- end,
-
---@param self df_icon
---@param deltaTime number
OnIconTick = function(self, deltaTime)
local now = GetTime()
if (self.lastUpdateCooldown + 0.05) <= now then
- self.timeRemaining = self.expirationTime - now
+ self.timeRemaining = (self.expirationTime - now) / (self.modRate or 1)
if self.timeRemaining > 0 then
if self.parentIconRow.options.decimal_timer then
self.CountdownText:SetText(self.parentIconRow.FormatCooldownTimeDecimal(self.timeRemaining))
@@ -772,6 +486,7 @@ detailsFramework.IconMixin = {
table.wipe(self.AuraCache)
local iconPool = self.IconPool
+ local iconsActive = 0
for i = 1, self.NextIcon -1 do
local iconFrame = iconPool[i]
@@ -792,15 +507,12 @@ detailsFramework.IconMixin = {
self.AuraCache[iconFrame.spellName] = true
self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or iconFrame.canStealOrPurge
self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or iconFrame.debuffType == "" --yes, enrages are empty-string...
+ iconsActive = iconsActive + 1
end
end
- --if there's nothing to show, no need to align
- if (not next(self.AuraCache)) then
- self:Hide()
- else
- self:AlignAuraIcons()
- end
+ -- this is needed in any case, to ensure updated 'self.NextIcon'
+ self:AlignAuraIcons()
end,
---@param self df_iconrow the parent frame
@@ -849,8 +561,6 @@ detailsFramework.IconMixin = {
end
end
- --icon.lua:847: attempt to perform arithmetic on field 'width'(a nil value)
- --but .width is set on SetIconSimple and SetIcon, getting the width from the iconFrame it self instead from cache is the cache fails
width = width + ((iconFrame.width or iconFrame:GetWidth()) * iconFrame:GetScale()) + xPadding
end
@@ -860,41 +570,22 @@ detailsFramework.IconMixin = {
self.shownAmount = shownAmount
end
+
+ if countStillShown > 0 then
+ self:Show()
+ end
self.NextIcon = countStillShown + 1
+
+ if countStillShown > 0 then
+ self:Show()
+ end
end,
---@param self df_iconrow the parent frame
GetIconGrowDirection = function(self)
local side = self.options.anchor.side
-
- if (side == 1) then
- return 1
- elseif (side == 2) then
- return 2
- elseif (side == 3) then
- return 1
- elseif (side == 4) then
- return 1
- elseif (side == 5) then
- return 2
- elseif (side == 6) then
- return 1
- elseif (side == 7) then
- return 2
- elseif (side == 8) then
- return 1
- elseif (side == 9) then
- return 1
- elseif (side == 10) then
- return 1
- elseif (side == 11) then
- return 2
- elseif (side == 12) then
- return 1
- elseif (side == 13) then
- return 1
- end
+ return detailsFramework.GrowDirectionBySide[side]
end,
---@param self df_iconrow the parent frame
diff --git a/Libs/DF/icongeneric.lua b/Libs/DF/icongeneric.lua
new file mode 100644
index 00000000..bfc6de6e
--- /dev/null
+++ b/Libs/DF/icongeneric.lua
@@ -0,0 +1,717 @@
+
+local detailsFramework = DetailsFramework
+
+if (not detailsFramework or not DetailsFrameworkCanLoad) then
+ return
+end
+
+---@class df_icongeneric : table, df_icon
+---@field expirationTime number
+---@field CooldownBrightnessTexture texture
+---@field CooldownTexture texture
+---@field CountdownText fontstring
+---@field CooldownEdge texture
+---@field options table
+
+local unpack = unpack
+local CreateFrame = CreateFrame
+local PixelUtil = PixelUtil
+local GetTime = GetTime
+
+local spellIconCache = {}
+local spellNameCache = {}
+local emptyTable = {}
+local white = {1, 1, 1, 1}
+
+local iconFrameOnHideScript = function(self)
+ if (self.cooldownLooper) then
+ self.cooldownLooper:Cancel()
+ end
+end
+
+detailsFramework.IconGenericMixin = {
+ ---create a new icon frame
+ ---@param self df_iconrow the parent frame
+ ---@param iconName string the name of the icon frame
+ ---@return df_icongeneric
+ CreateIcon = function(self, iconName)
+ ---@type df_icongeneric
+ local newIcon = CreateFrame("frame", iconName, self)
+
+ ---@type texture
+ newIcon.Texture = newIcon:CreateTexture(nil, "artwork", nil, 1)
+ PixelUtil.SetPoint(newIcon.Texture, "topleft", newIcon, "topleft", 1, -1)
+ PixelUtil.SetPoint(newIcon.Texture, "bottomright", newIcon, "bottomright", -1, 1)
+
+ ---@type texture
+ newIcon.CooldownBrightnessTexture = newIcon:CreateTexture(nil, "artwork", nil, 2)
+ newIcon.CooldownBrightnessTexture:SetBlendMode("ADD")
+ newIcon.CooldownBrightnessTexture:SetAlpha(1)
+ PixelUtil.SetPoint(newIcon.CooldownBrightnessTexture, "topleft", newIcon, "topleft", 0, 0)
+ PixelUtil.SetPoint(newIcon.CooldownBrightnessTexture, "bottomright", newIcon, "bottomright", 0, 0)
+
+ ---@type texture
+ newIcon.Border = newIcon:CreateTexture(nil, "background")
+ newIcon.Border:SetAllPoints()
+ newIcon.Border:SetColorTexture(0, 0, 0)
+
+ ---@type fontstring
+ newIcon.StackText = newIcon:CreateFontString(nil, "overlay", "GameFontNormal")
+ newIcon.StackText:SetPoint("bottomright", newIcon, "bottomright", 0, 0)
+ newIcon.StackText:Hide()
+ newIcon.StackTextShadow = newIcon:CreateFontString(nil, "artwork", "GameFontNormal")
+ newIcon.StackTextShadow:SetPoint("center", newIcon.StackText, "center", 0, 0)
+ newIcon.StackTextShadow:SetTextColor(0, 0, 0)
+ newIcon.StackTextShadow:Hide()
+
+ ---@type fontstring
+ newIcon.Desc = newIcon:CreateFontString(nil, "overlay", "GameFontNormal")
+ newIcon.Desc:SetPoint("bottom", newIcon, "top", 0, 2)
+ newIcon.Desc:Hide()
+
+ --create a overlay texture which will indicate the cooldown time
+ newIcon.CooldownTexture = newIcon:CreateTexture(self:GetName() .. "CooldownTexture", "overlay", nil, 6)
+ newIcon.CooldownTexture:SetColorTexture(1, 1, 1, 1)
+ newIcon.CooldownTexture:SetPoint("bottomleft", newIcon.Texture, "bottomleft", 0, 0)
+ newIcon.CooldownTexture:SetPoint("bottomright", newIcon.Texture, "bottomright", 0, 0)
+ newIcon.CooldownTexture:SetHeight(1)
+ newIcon.CooldownTexture:Hide()
+
+ newIcon.CooldownEdge = newIcon:CreateTexture(self:GetName() .. "CooldownEdge", "overlay", nil, 7)
+
+ newIcon.CountdownText = newIcon:CreateFontString(self:GetName() .. "CooldownText", "overlay", "GameFontNormal")
+ newIcon.CountdownText:SetPoint("center", newIcon, "center", 0, 0)
+ newIcon.CountdownText:Hide()
+
+ newIcon.stacks = 0
+ newIcon:SetScript("OnHide", iconFrameOnHideScript)
+
+ return newIcon
+ end,
+
+ ---get an icon frame from the pool
+ ---@param self df_iconrow the parent frame
+ ---@return df_icongeneric
+ GetIcon = function(self)
+ ---@type df_icongeneric
+ local iconFrame = self.IconPool[self.NextIcon]
+
+ if (not iconFrame) then
+ ---@type df_icongeneric
+ iconFrame = self:CreateIcon("$parentIcon" .. self.NextIcon)
+ iconFrame.parentIconRow = self
+
+ iconFrame.Desc:Hide()
+ iconFrame.Texture:SetTexCoord(0.1, 0.9, 0.1, 0.9)
+ iconFrame.Border:ClearAllPoints()
+ iconFrame.Border:SetPoint("topleft", iconFrame, "topleft", -1, 1)
+ iconFrame.Border:SetPoint("bottomright", iconFrame, "bottomright", 1, -1)
+ iconFrame.Border:SetTexture(130759)
+ iconFrame.Border:SetTexCoord(0.296875, 0.5703125, 0, 0.515625)
+ iconFrame.Border:SetDrawLayer("overlay", 7)
+
+ iconFrame.StackText:SetTextColor(detailsFramework:ParseColors(self.options.stack_text_color))
+ detailsFramework:SetFontSize(iconFrame.StackText, self.options.stack_text_size)
+ detailsFramework:SetFontFace(iconFrame.StackText, self.options.stack_text_font)
+ detailsFramework:SetFontOutline(iconFrame.StackText, self.options.stack_text_outline)
+ detailsFramework:SetFontFace(iconFrame.StackTextShadow, self.options.stack_text_font)
+ detailsFramework:SetFontSize(iconFrame.StackTextShadow, self.options.stack_text_size+1)
+
+ iconFrame.StackText:ClearAllPoints()
+ iconFrame.StackText:SetPoint(self.options.stack_text_anchor or "center", iconFrame, self.options.stack_text_rel_anchor or "center", self.options.stack_text_x_offset or 0, self.options.stack_text_y_offset or 0)
+
+ self.IconPool[self.NextIcon] = iconFrame
+ iconFrame = iconFrame
+ end
+
+ self.NextIcon = self.NextIcon + 1
+ return iconFrame
+ end,
+
+ SetStacks = function(self, iconFrame, bIsShown, stacksAmount)
+ if (bIsShown) then
+ iconFrame.StackText:Show()
+ iconFrame.StackTextShadow:Show()
+ iconFrame.StackText:SetText(stacksAmount)
+ iconFrame.StackTextShadow:SetText(stacksAmount)
+ iconFrame.stacks = stacksAmount
+ else
+ iconFrame.StackText:Hide()
+ iconFrame.StackTextShadow:Hide()
+ iconFrame.stacks = 0
+ end
+ end,
+
+ ---adds only if not existing already in the cache
+ ---@param self df_iconrow the parent frame
+ AddSpecificIcon = function(self, identifierKey, spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff, modRate, iconSettings)
+ if (not identifierKey or identifierKey == "") then
+ return
+ end
+
+ if (not self.AuraCache[identifierKey]) then
+ ---@type df_icongeneric
+ local icon = self:SetIcon(spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff or false, modRate, iconSettings)
+ icon.identifierKey = identifierKey
+ self.AuraCache[identifierKey] = true
+ end
+ end,
+
+ AddSpecificIconWithTemplate = function(self, iconTemplateTable)
+ self:AddSpecificIcon(iconTemplateTable.id, iconTemplateTable.id, nil, iconTemplateTable.startTime, iconTemplateTable.duration, nil, nil, iconTemplateTable.count, nil, nil, nil, nil, nil, nil, iconTemplateTable)
+ end,
+
+ ---set an icon frame with a template
+ ---@param self df_iconrow the parent frame
+ ---@param aI aurainfo
+ ---@param iconTemplateTable df_icontemplate
+ SetAuraWithIconTemplate = function(self, aI, iconTemplateTable)
+ local startTime = aI.expirationTime - aI.duration
+ ---@type df_icongeneric
+ self:SetIcon(aI.spellId, nil, startTime, aI.duration, aI.icon, nil, aI.applications, aI.dispelName, aI.sourceUnit, aI.isStealable, aI.name, aI.isHelpful, aI.timeMod, iconTemplateTable, aI.expirationTime)
+ end,
+
+ ---set an icon frame with a template
+ ---@param self df_iconrow the parent frame
+ ---@return df_icongeneric?
+ SetIcon = function(self, spellId, borderColor, startTime, duration, iconTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff, modRate, iconSettings, expirationTime)
+ local actualSpellName, spellIcon = spellNameCache[spellId], spellIconCache[spellId]
+
+ iconSettings = iconSettings or emptyTable
+
+ if (not actualSpellName) then
+ actualSpellName, _, spellIcon = GetSpellInfo(spellId)
+ spellIconCache[spellId] = spellIcon
+ spellNameCache[spellId] = actualSpellName
+ end
+
+ if iconTexture then
+ spellIcon = iconTexture
+ end
+
+ if (not spellIcon) then
+ if (iconSettings.texture) then
+ spellIcon = iconSettings.texture
+ end
+ end
+
+ if (spellIcon) then
+ spellName = spellName or actualSpellName or "unknown_aura"
+ modRate = modRate or 1
+
+ ---@type df_icongeneric
+ local iconFrame = self:GetIcon()
+ self.shownAmount = self.NextIcon - 1
+
+ iconFrame.expirationTime = expirationTime
+
+ local widthFromTexture
+ local heightFromTexture
+
+ if (iconFrame.Texture.texture ~= spellIcon or (iconSettings.coords and iconSettings.coords ~= iconFrame.currentCoords)) then
+ iconFrame.Texture:SetTexture(spellIcon, "CLAMP", "CLAMP", iconSettings.textureFilter or "LINEAR") --"TRILINEAR"
+
+ if (iconSettings.coords) then
+ iconFrame.Texture:SetTexCoord(unpack(iconSettings.coords))
+ iconFrame.currentCoords = iconSettings.coords
+
+ elseif (self.options.texcoord ~= iconFrame.currentCoords) then
+ iconFrame.Texture:SetTexCoord(unpack(self.options.texcoord))
+ iconFrame.currentCoords = self.options.texcoord
+ else
+ iconFrame.Texture:SetTexCoord(0, 1, 0, 1)
+ end
+
+ iconFrame.Texture:ClearAllPoints()
+
+ if (iconSettings.points) then
+ for i = 1, #iconSettings.points do
+ local point = iconSettings.points[i]
+ iconFrame.Texture:SetPoint(point[1], iconFrame, point[2], point[3], point[4])
+ end
+
+ if (iconSettings.width) then
+ iconFrame.Texture:SetWidth(iconSettings.width)
+ widthFromTexture = iconSettings.width
+ else
+ iconFrame.Texture:SetWidth(self.options.icon_width)
+ end
+
+ if (iconSettings.height or iconSettings.width) then
+ iconFrame.Texture:SetHeight(iconSettings.height or iconSettings.width)
+ heightFromTexture = iconSettings.height or iconSettings.width
+ else
+ iconFrame.Texture:SetHeight(self.options.icon_height)
+ end
+ else
+ if (iconSettings.width) then
+ iconFrame.Texture:SetWidth(iconSettings.width)
+ iconFrame.Texture:SetHeight(iconSettings.height or iconSettings.width)
+ widthFromTexture = iconSettings.width
+ heightFromTexture = iconSettings.height or iconSettings.width
+ PixelUtil.SetPoint(iconFrame.Texture, "center", iconFrame, "center", 0, 0)
+ else
+ PixelUtil.SetPoint(iconFrame.Texture, "topleft", iconFrame, "topleft", 1, -1)
+ PixelUtil.SetPoint(iconFrame.Texture, "bottomright", iconFrame, "bottomright", -1, 1)
+ end
+ end
+
+ iconFrame.Texture.texture = spellIcon
+
+ elseif (not iconSettings.coords) then
+ if (self.options.texcoord ~= iconFrame.currentCoords) then
+ iconFrame.Texture:SetTexCoord(unpack(self.options.texcoord))
+ iconFrame.currentCoords = self.options.texcoord
+ else
+ iconFrame.Texture:SetTexCoord(0, 1, 0, 1)
+ end
+ end
+
+ if (borderColor) then
+ iconFrame.Border:Show()
+ iconFrame.Border:SetVertexColor(unpack(borderColor))
+ else
+ if (iconSettings.borderColor) then
+ iconFrame.Border:Show()
+ iconFrame.Border:SetTexture(iconSettings.borderTexture or 130759)
+ iconFrame.Border:SetVertexColor(unpack(iconSettings.borderColor or white))
+ else
+ iconFrame.Border:Hide()
+ end
+ end
+
+ if (count and count > 1 and self.options.stack_text) then
+ self:SetStacks(iconFrame, true, count)
+ else
+ self:SetStacks(iconFrame, false)
+ end
+
+ iconFrame.stacks = count or 0
+
+ if (iconSettings.scale) then
+ iconFrame.Texture:SetScale(iconSettings.scale)
+ if (widthFromTexture) then
+ widthFromTexture = widthFromTexture * iconSettings.scale
+ end
+ if (heightFromTexture) then
+ heightFromTexture = heightFromTexture * iconSettings.scale
+ end
+ else
+ iconFrame.Texture:SetScale(1)
+ end
+
+ if (iconSettings.alpha) then
+ iconFrame.Texture:SetAlpha(iconSettings.alpha)
+ else
+ iconFrame.Texture:SetAlpha(1)
+ end
+
+ iconFrame:Show()
+ iconFrame.textureWidth = iconFrame.Texture:GetWidth()
+ iconFrame.textureHeight = iconFrame.Texture:GetHeight()
+ PixelUtil.SetSize(iconFrame, iconFrame.textureWidth, iconFrame.textureHeight)
+
+ --cache size
+ iconFrame.width = iconFrame.textureWidth
+ iconFrame.height = iconFrame.textureHeight
+
+ --iconFrame.Texture:SetBlendMode("ADD")
+ iconFrame.CooldownBrightnessTexture:SetTexture(iconFrame.Texture:GetTexture())
+ do
+ local left, top, c, bottom, right = iconFrame.Texture:GetTexCoord()
+ iconFrame.CooldownBrightnessTexture:SetTexCoord(left, right, top, bottom)
+ iconFrame.CooldownBrightnessTexture.cords = {left, right, top, bottom}
+ iconFrame.CooldownBrightnessTexture.top = top
+ iconFrame.CooldownBrightnessTexture.bottom = bottom
+ end
+
+ PixelUtil.SetPoint(iconFrame.CooldownBrightnessTexture, "bottomright", iconFrame, "bottomright", -1, 1)
+
+ --make information available
+ iconFrame.spellId = spellId
+ iconFrame.startTime = startTime
+ iconFrame.duration = duration
+ iconFrame.endTime = (startTime and duration and startTime + duration) or 0
+ iconFrame.count = count
+ iconFrame.debuffType = debuffType
+ iconFrame.caster = caster
+ iconFrame.canStealOrPurge = canStealOrPurge
+ iconFrame.isBuff = isBuff
+ iconFrame.spellName = spellName
+ iconFrame.modRate = modRate
+ iconFrame.options = self.options
+
+ if (startTime and duration and duration > 0) then
+ local endTime = startTime + duration
+ local now = GetTime()
+ if (endTime > now) then
+ iconFrame.CooldownTexture:Show()
+ iconFrame.CooldownBrightnessTexture:Show()
+ iconFrame.CooldownTexture:SetHeight(1)
+ self:SetCooldown(iconFrame)
+ end
+ else
+ iconFrame.CooldownBrightnessTexture:Hide()
+ iconFrame.CooldownTexture:Hide()
+ end
+
+ iconFrame.identifierKey = nil -- only used for "specific" add/remove
+
+ --add the spell into the cache
+ self.AuraCache[spellId or -1] = true
+ self.AuraCache[spellName] = true
+ self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or canStealOrPurge
+ self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or debuffType == "" --yes, enrages are empty-string...
+
+ --show the frame
+ self:Show()
+
+ return iconFrame
+ end
+ end,
+
+ ---@param self df_iconrow the parent frame
+ ---@param iconFrame df_icongeneric
+ SetCooldown = function(self, iconFrame)
+ if (iconFrame.cooldownLooper) then
+ iconFrame.cooldownLooper:Cancel()
+ end
+
+ local options = iconFrame.options
+
+ --iconFrame:SetScale(3) --debug
+
+ iconFrame.CooldownEdge:Hide()
+ iconFrame.CooldownEdge.texture = nil
+
+ detailsFramework:SetFontColor(iconFrame.CountdownText, self.options.text_color)
+
+ PixelUtil.SetSize(iconFrame.CooldownEdge, iconFrame.CooldownTexture:GetWidth(), 2)
+ PixelUtil.SetPoint(iconFrame.CooldownEdge, "topleft", iconFrame.CooldownTexture, "topleft", 0, 0)
+ PixelUtil.SetPoint(iconFrame.CooldownEdge, "topright", iconFrame.CooldownTexture, "topright", 0, 0)
+ PixelUtil.SetHeight(iconFrame.CooldownEdge, 2)
+
+ local swipe_brightness = options.swipe_brightness
+ iconFrame.CooldownBrightnessTexture:SetAlpha(swipe_brightness)
+
+ local swipe_darkness = options.swipe_alpha
+ iconFrame.CooldownTexture:SetAlpha(swipe_darkness)
+ iconFrame.CooldownTexture:SetVertexColor(unpack(options.swipe_color))
+
+ iconFrame.CooldownEdge:SetAlpha(0.834)
+
+ self.OnIconTick(iconFrame)
+
+ local amountOfLoops = math.floor(iconFrame.duration / 0.5)
+ local loopEndCallback = nil
+ local checkPointCallback = nil
+
+ local newLooper = detailsFramework.Schedules.NewLooper(0.5, self.OnIconTick, amountOfLoops, loopEndCallback, checkPointCallback, iconFrame)
+ iconFrame.cooldownLooper = newLooper
+ end,
+
+ ---@param iconFrame df_icongeneric
+ OnIconTick = function(iconFrame)
+ local now = GetTime()
+ --local percent = (now - iconFrame.startTime) / iconFrame.duration --no mod rate
+ local percent = ((now - iconFrame.startTime) / (iconFrame.modRate or 1)) / (iconFrame.duration / (iconFrame.modRate or 1))
+ local options = iconFrame.options
+ --percent = abs(percent - 1)
+
+ local newHeight = math.min(iconFrame.textureHeight * percent, iconFrame.textureHeight)
+ iconFrame.CooldownTexture:SetHeight(newHeight)
+
+ PixelUtil.SetPoint(iconFrame.CooldownBrightnessTexture, "bottomright", iconFrame, "bottomright", 0, newHeight) --iconFrame.textureHeight -
+ local left, right, top, bottom = unpack(iconFrame.CooldownBrightnessTexture.cords)
+ local newBottomCord = Lerp(iconFrame.CooldownBrightnessTexture.top, iconFrame.CooldownBrightnessTexture.bottom, abs(percent - 1))
+ iconFrame.CooldownBrightnessTexture:SetTexCoord(left, right, top, newBottomCord)
+
+ if (percent > options.swipe_percent2) then
+ if (options.swipe_red and iconFrame.CooldownEdge.texture ~= options.swipe_red) then
+ iconFrame.CooldownEdge:Show()
+ iconFrame.CooldownEdge:SetTexture(options.swipe_red)
+ iconFrame.CooldownEdge.texture = options.swipe_red
+ end
+
+ elseif (percent > options.swipe_percent1) then
+ if (options.swipe_yellow and iconFrame.CooldownEdge.texture ~= options.swipe_yellow) then
+ iconFrame.CooldownEdge:Show()
+ iconFrame.CooldownEdge:SetTexture(options.swipe_yellow)
+ iconFrame.CooldownEdge.texture = options.swipe_yellow
+ end
+ end
+
+ --iconFrame.CountdownText:SetText(iconFrame.parentIconRow.FormatCooldownTime(iconFrame.duration - (now - iconFrame.startTime))) --no mod rate
+ iconFrame.CountdownText:SetText(iconFrame.parentIconRow.FormatCooldownTime((iconFrame.duration - (now - iconFrame.startTime)) / (iconFrame.modRate or 1)))
+ --self.CountdownText:Show()
+ end,
+
+ FormatCooldownTime = function(thisTime)
+ if (thisTime >= 3600) then
+ thisTime = math.floor(thisTime / 3600) .. "h"
+
+ elseif (thisTime >= 60) then
+ thisTime = math.floor(thisTime / 60) .. "m"
+
+ else
+ thisTime = math.floor(thisTime)
+ end
+ return thisTime
+ end,
+
+ FormatCooldownTimeDecimal = function(formattedTime)
+ if formattedTime < 10 then
+ return ("%.1f"):format(formattedTime)
+
+ elseif formattedTime < 60 then
+ return ("%d"):format(formattedTime)
+
+ elseif formattedTime < 3600 then
+ return ("%d:%02d"):format(formattedTime/60%60, formattedTime%60)
+
+ elseif formattedTime < 86400 then
+ return ("%dh %02dm"):format(formattedTime/(3600), formattedTime/60%60)
+
+ else
+ return ("%dd %02dh"):format(formattedTime/86400, (formattedTime/3600) - (math.floor(formattedTime/86400) * 24))
+ end
+ end,
+
+ ---@param self df_iconrow the parent frame
+ ---@param identifierKey any
+ RemoveSpecificIcon = function(self, identifierKey)
+ if (not identifierKey or identifierKey == "") then
+ return
+ end
+
+ if (not self.AuraCache[identifierKey]) then
+ return
+ end
+ self.AuraCache[identifierKey] = nil
+
+ local iconPool = self.IconPool
+
+ --find and hide the icon frame
+ for i = 1, self.NextIcon -1 do
+ local iconFrame = iconPool[i]
+ if (iconFrame.identifierKey and iconFrame.identifierKey == identifierKey) then
+ iconFrame:Hide()
+ iconFrame:ClearAllPoints()
+ iconFrame.identifierKey = nil
+ else
+ self.AuraCache[iconFrame.spellId] = true
+ self.AuraCache[iconFrame.spellName] = true
+ self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or iconFrame.canStealOrPurge
+ self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or iconFrame.debuffType == "" --yes, enrages are empty-string...
+ end
+ end
+
+ self:AlignAuraIcons()
+ end,
+
+ ---@param self df_iconrow the parent frame
+ ClearIcons = function(self, resetBuffs, resetDebuffs)
+ resetBuffs = resetBuffs ~= false
+ resetDebuffs = resetDebuffs ~= false
+ table.wipe(self.AuraCache)
+
+ local iconPool = self.IconPool
+
+ for i = 1, self.NextIcon -1 do
+ local iconFrame = iconPool[i]
+ if (iconFrame.isBuff == nil) then
+ iconFrame:Hide()
+ iconFrame:ClearAllPoints()
+
+ elseif (resetBuffs and iconFrame.isBuff) then
+ iconFrame:Hide()
+ iconFrame:ClearAllPoints()
+
+ elseif (resetDebuffs and not iconFrame.isBuff) then
+ iconFrame:Hide()
+ iconFrame:ClearAllPoints()
+
+ else
+ self.AuraCache[iconFrame.spellId] = true
+ self.AuraCache[iconFrame.spellName] = true
+ self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or iconFrame.canStealOrPurge
+ self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or iconFrame.debuffType == "" --yes, enrages are empty-string...
+ end
+ end
+
+ self:AlignAuraIcons()
+ end,
+
+ ---@param self df_iconrow the parent frame
+ AlignAuraIcons = function(self)
+ local iconPool = self.IconPool
+ local iconAmount = #iconPool
+ local countStillShown = 0
+
+ if iconAmount == 0 then
+ self:Hide()
+ else
+ table.sort(iconPool, function(i1, i2) return i1:IsShown() and not i2:IsShown() end)
+ local shownAmount = 0
+ for i = 1, iconAmount do
+ if iconPool[i]:IsShown() then
+ shownAmount = shownAmount + 1
+ end
+ end
+
+ local width = 0
+ local growDirection = self:GetIconGrowDirection()
+ local nWhichSide = self.options.anchor.side
+ local bIsCenterAligned = detailsFramework.ShouldCenterAlign[nWhichSide]
+
+ --re-anchor not hidden
+ for i = 1, shownAmount do
+ local bIsFirstIcon = i == 1
+
+ local iconFrame = iconPool[i]
+ local anchorTo = bIsFirstIcon and self or self.IconPool[i - 1]
+ local xPadding
+
+ if (bIsFirstIcon) then
+ xPadding = self.options.left_padding
+ else
+ xPadding = self.options.icon_padding or 1
+ xPadding = xPadding * (growDirection == 2 and -1 or 1)
+ end
+
+ countStillShown = countStillShown + (iconFrame:IsShown() and 1 or 0)
+
+ iconFrame:ClearAllPoints()
+
+ if (growDirection == 1) then --grow to right
+ if (bIsFirstIcon) then
+ local attachSide = (bIsCenterAligned and "center") or (nWhichSide and not detailsFramework.SideIsCorner[nWhichSide] and "left") or "bottomleft"
+ PixelUtil.SetPoint(iconFrame, attachSide, anchorTo, attachSide, 0, 0)
+ else
+ PixelUtil.SetPoint(iconFrame, "left", anchorTo, "right", xPadding, 0)
+ end
+
+ elseif (growDirection == 2) then --grow to left
+ if (bIsFirstIcon) then
+ local attachSide = (bIsCenterAligned and "center") or (nWhichSide and not detailsFramework.SideIsCorner[nWhichSide] and "right") or "bottomright"
+ PixelUtil.SetPoint(iconFrame, attachSide, anchorTo, attachSide, 0, 0)
+ else
+ PixelUtil.SetPoint(iconFrame, "right", anchorTo, "left", xPadding, 0)
+ end
+ end
+
+ width = width + ((iconFrame.width or iconFrame:GetWidth()) * iconFrame:GetScale()) + 1
+ end
+
+ if (bIsCenterAligned) then
+ self:SetWidth(width)
+ end
+
+ self.shownAmount = shownAmount
+ end
+
+ self.NextIcon = countStillShown + 1
+
+ if countStillShown > 0 then
+ self:Show()
+ end
+ end,
+
+ ---@param self df_iconrow the parent frame
+ GetIconGrowDirection = function(self)
+ local side = self.options.anchor.side
+ return detailsFramework.GrowDirectionBySide[side]
+ end,
+
+ ---@param self df_iconrow the parent frame
+ OnOptionChanged = function(self, optionName)
+ if (self.SetBackdropColor) then
+ self:SetBackdropColor(unpack(self.options.backdrop_color))
+ self:SetBackdropBorderColor(unpack(self.options.backdrop_border_color))
+ end
+ end,
+}
+
+local default_icon_row_options = {
+ icon_width = 20,
+ icon_height = 20,
+ texcoord = {.1, .9, .1, .9},
+ show_text = true,
+ text_color = {1, 1, 1, 1},
+ text_size = 12,
+ text_font = "Arial Narrow",
+ text_outline = "NONE",
+ text_anchor = "center",
+ text_rel_anchor = "center",
+ text_x_offset = 0,
+ text_y_offset = 0,
+ desc_text = true,
+ desc_text_color = {1, 1, 1, 1},
+ desc_text_size = 7,
+ desc_text_font = "Arial Narrow",
+ desc_text_outline = "NONE",
+ desc_text_anchor = "bottom",
+ desc_text_rel_anchor = "top",
+ desc_text_x_offset = 0,
+ desc_text_y_offset = 2,
+ stack_text = true,
+ stack_text_color = {1, 1, 1, 1},
+ stack_text_size = 10,
+ stack_text_font = "Arial Narrow",
+ stack_text_outline = "NONE",
+ stack_text_anchor = "center",
+ stack_text_rel_anchor = "bottomright",
+ stack_text_x_offset = 0,
+ stack_text_y_offset = 0,
+ left_padding = 1, --distance between right and left
+ top_padding = 1, --distance between top and bottom
+ icon_padding = 1, --distance between each icon
+ backdrop = {},
+ backdrop_color = {0, 0, 0, 0.5},
+ backdrop_border_color = {0, 0, 0, 1},
+ anchor = {side = 6, x = 2, y = 0},
+ grow_direction = 1, --1 = to right 2 = to left
+ center_alignment = false, --if true if will align the icons with grow_direction and then set the iconRow width to match the length used by all icons
+ surpress_blizzard_cd_timer = false,
+ surpress_tulla_omni_cc = false,
+ on_tick_cooldown_update = true,
+ decimal_timer = false,
+ cooldown_reverse = false,
+ cooldown_swipe_enabled = true,
+ cooldown_edge_texture = "Interface\\Cooldown\\edge",
+
+ swipe_alpha = 0.5,
+ swipe_brightness = 0.5,
+ swipe_color = {0, 0, 0},
+ swipe_yellow = false,
+ swipe_red = false,
+ swipe_percent1 = 0.75,
+ swipe_percent2 = 0.90,
+
+ --first_icon_anchor = "auto",
+}
+
+---@param parent frame
+---@param name string?
+---@param options table?
+---@return df_iconrow
+function detailsFramework:CreateIconRowGeneric(parent, name, options)
+ local newIconRowFrame = CreateFrame("frame", name, parent, "BackdropTemplate")
+ newIconRowFrame.IconPool = {}
+ newIconRowFrame.NextIcon = 1
+ newIconRowFrame.AuraCache = {}
+ newIconRowFrame.shownAmount = 0
+
+ detailsFramework:Mixin(newIconRowFrame, detailsFramework.IconGenericMixin)
+ detailsFramework:Mixin(newIconRowFrame, detailsFramework.OptionsFunctions)
+
+ newIconRowFrame:BuildOptionsTable(default_icon_row_options, options)
+
+ newIconRowFrame:SetSize(1, 1)
+
+ newIconRowFrame:SetBackdrop(newIconRowFrame.options.backdrop)
+ newIconRowFrame:SetBackdropColor(unpack(newIconRowFrame.options.backdrop_color))
+ newIconRowFrame:SetBackdropBorderColor(unpack(newIconRowFrame.options.backdrop_border_color))
+
+ return newIconRowFrame
+end
\ No newline at end of file
diff --git a/Libs/DF/load.xml b/Libs/DF/load.xml
index 1f04f55d..b7674865 100644
--- a/Libs/DF/load.xml
+++ b/Libs/DF/load.xml
@@ -36,6 +36,7 @@
+
diff --git a/classes/class_damage.lua b/classes/class_damage.lua
index 2b29c68b..0e40e645 100644
--- a/classes/class_damage.lua
+++ b/classes/class_damage.lua
@@ -3455,7 +3455,7 @@ function damageClass.PredictedAugSpellsOnEnter(self)
---@type spellcontainer
local receivedBuffs = actorObject.received_buffs_spells
- if (receivedBuffs and actorObject:IsPlayer()) then
+ if (receivedBuffs and actorObject:IsPlayer() and actorObject:IsGroupPlayer()) then
for sourceNameSpellId, spellTable in receivedBuffs:ListSpells() do
local sourceName, spellId = strsplit("@", sourceNameSpellId)
if (sourceName == actorName) then
@@ -3529,6 +3529,8 @@ function damageClass.PredictedAugSpellsOnEnter(self)
end
end
+ GameCooltip:AddLine("cannot disable this bar while the feature is under tests")
+
--GameCooltip:SetOption("LeftBorderSize", -5)
--GameCooltip:SetOption("RightBorderSize", 5)
--GameCooltip:SetOption("RightTextMargin", 0)
diff --git a/core/control.lua b/core/control.lua
index f48caec1..da9390b2 100644
--- a/core/control.lua
+++ b/core/control.lua
@@ -1747,6 +1747,10 @@
end
end
+ ---@param self instance
+ ---@param frame table
+ ---@param whichRowLine number
+ ---@param keydown string
function Details:MontaTooltip(frame, whichRowLine, keydown)
self:BuildInstanceBarTooltip(frame)
@@ -1777,6 +1781,9 @@
if (not object.ToolTip) then
if (object.__destroyed) then
Details:Msg("object:ToolTip() is invalid.", object.__destroyedBy)
+ self:ResetWindow()
+ self:RefreshWindow(true)
+ return
end
end
@@ -1896,7 +1903,7 @@
dumpt(t)
end
- function Details:ForceRefresh()
+ function Details:ForceRefresh() --getting deprecated soon
self:RefreshMainWindow(true)
end
diff --git a/images/spec_icons_normal.jpg b/images/spec_icons_normal.jpg
index 839c32c8..79a2485f 100644
Binary files a/images/spec_icons_normal.jpg and b/images/spec_icons_normal.jpg differ
diff --git a/images/spec_icons_normal.tga b/images/spec_icons_normal.tga
deleted file mode 100644
index 29570a65..00000000
Binary files a/images/spec_icons_normal.tga and /dev/null differ
diff --git a/images/spec_icons_normal_alpha.tga b/images/spec_icons_normal_alpha.tga
index bad97b79..fbe21afd 100644
Binary files a/images/spec_icons_normal_alpha.tga and b/images/spec_icons_normal_alpha.tga differ
diff --git a/plugins/Details_Compare2/Details_Compare2.toc b/plugins/Details_Compare2/Details_Compare2.toc
index 889f631c..70ebc821 100644
--- a/plugins/Details_Compare2/Details_Compare2.toc
+++ b/plugins/Details_Compare2/Details_Compare2.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Compare 2.0
## Notes: Replace the Compare tab in the player breakdown window.
## RequiredDeps: Details
diff --git a/plugins/Details_DataStorage/Details_DataStorage.toc b/plugins/Details_DataStorage/Details_DataStorage.toc
index 1e565ca3..7d8b3656 100644
--- a/plugins/Details_DataStorage/Details_DataStorage.toc
+++ b/plugins/Details_DataStorage/Details_DataStorage.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Storage
## Notes: Stores information for Details! Damage Meter
## DefaultState: Enabled
diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc
index 79dadab9..8df3211b 100644
--- a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc
+++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Encounter Breakdown (plugin)
## Notes: Show detailed information about a boss encounter. Also provide damage per phase, graphic charts, easy weakauras creation.
## RequiredDeps: Details
diff --git a/plugins/Details_RaidCheck/Details_RaidCheck.toc b/plugins/Details_RaidCheck/Details_RaidCheck.toc
index c78eb25f..a35e09bb 100644
--- a/plugins/Details_RaidCheck/Details_RaidCheck.toc
+++ b/plugins/Details_RaidCheck/Details_RaidCheck.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Raid Check (plugin)
## Notes: Show talents and item level for all members in your group, also shows food and flask state.
## RequiredDeps: Details
diff --git a/plugins/Details_Streamer/Details_Streamer.toc b/plugins/Details_Streamer/Details_Streamer.toc
index b9746e28..94f898cb 100644
--- a/plugins/Details_Streamer/Details_Streamer.toc
+++ b/plugins/Details_Streamer/Details_Streamer.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Streamer (plugin)
## Notes: Show which spells you are casting, viewers can see what are you doing and follow your steps.
## RequiredDeps: Details
diff --git a/plugins/Details_TinyThreat/Details_TinyThreat.toc b/plugins/Details_TinyThreat/Details_TinyThreat.toc
index 20f106fb..3d8f7455 100644
--- a/plugins/Details_TinyThreat/Details_TinyThreat.toc
+++ b/plugins/Details_TinyThreat/Details_TinyThreat.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Tiny Threat (plugin)
## Notes: Threat meter plugin, show threat for group members in the window. Select it from the Plugin menu in the Orange Cogwheel.
## RequiredDeps: Details
diff --git a/plugins/Details_Vanguard/Details_Vanguard.toc b/plugins/Details_Vanguard/Details_Vanguard.toc
index b22e197a..161ca021 100644
--- a/plugins/Details_Vanguard/Details_Vanguard.toc
+++ b/plugins/Details_Vanguard/Details_Vanguard.toc
@@ -1,4 +1,4 @@
-## Interface: 100105
+## Interface: 100107
## Title: Details!: Vanguard (plugin)
## Notes: Show the health and debuffs for tanks in your group.
## SavedVariablesPerCharacter: _detalhes_databaseVanguard