-- Aura Icons indicator local Grid2 = Grid2 local min, wipe, format = math.min, wipe, string.format local pairs, ipairs = pairs, ipairs local function Icon_Create(self, parent) local f = self:CreateFrame("Frame", parent) f.myIndicator = self f.myFrame = parent f.auras = f.auras or {} f.visibleCount = 0 end -- Warning: This is an overrided indicator:Update() NOT the standard indicator:OnUpdate() local function Icon_OnFrameUpdate(f) local unit = f.myFrame.unit if not unit then return end local self = f.myIndicator local max = self.maxIcons local auras = f.auras local showStack = self.showStack local showCool = self.showCooldown local useStatus = self.useStatusColor local i = 1 for _, status in ipairs(self.statuses) do if status:IsActive(unit) then if status.GetIcons then local k, textures, counts, expirations, durations, colors = status:GetIcons(unit, max) for j = 1, k do local aura = auras[i] aura.icon:SetTexture(textures[j]) if showStack then local count = counts[j] aura.text:SetText(count > 1 and count or "") end if showCool then local expiration, duration = expirations[j], durations[j] aura.cooldown:SetCooldown(expiration - duration, duration) end if useStatus then local c = colors[j] aura:SetBackdropBorderColor(c.r, c.g, c.b, min(c.a, self.borderOpacity)) end aura:Show() i = i + 1 end max = max - k else local aura = auras[i] aura.icon:SetTexture(status:GetIcon(unit)) aura.icon:SetTexCoord(status:GetTexCoord(unit)) aura.icon:SetVertexColor(status:GetVertexColor(unit)) if showStack then local count = status:GetCount(unit) aura.text:SetText(count > 1 and count or "") end if showCool then local expiration, duration = status:GetExpirationTime(unit) or 0, status:GetDuration(unit) or 0 aura.cooldown:SetCooldown(expiration - duration, duration) end if useStatus then local r, g, b, a = status:GetColor(unit) aura:SetBackdropBorderColor(r, g, b, min(a or 1, self.borderOpacity)) end aura:Show() i = i + 1 max = max - 1 end if max <= 0 then break end end end for j = i, f.visibleCount do auras[j]:Hide() end f.visibleCount = i - 1 if i > 1 then f:Show() else f:Hide() end end -- Delayed updates local updates = {} local EnableDelayedUpdates EnableDelayedUpdates = function() CreateFrame("Frame", nil, Grid2LayoutFrame):SetScript("OnUpdate", function() for i = 1, #updates do Icon_OnFrameUpdate(updates[i]) end wipe(updates) end) EnableDelayedUpdates = Grid2.Dummy end local function Icon_Update(self, parent) updates[#updates + 1] = parent[self.name] end local function Icon_Layout(self, parent) local f = parent[self.name] local x, y = 0, 0 local ux, uy = self.ux, self.uy local vx, vy = self.vx, self.vy local borderSize = self.borderSize local iconSize = self.iconSize > 1 and self.iconSize or self.iconSize * parent:GetHeight() local size = iconSize + self.iconSpacing local frameName if not self.dbx.disableOmniCC then local i, j = parent:GetName():match("Grid2LayoutHeader(%d+)UnitButton(%d+)") frameName = format("Grid2Icons%s%02d%02d", self.name:gsub("%-", ""), i, j) end f:SetParent(parent) f:ClearAllPoints() f:SetPoint(self.anchor, parent.container, self.anchorRel, self.offsetx, self.offsety) f:SetFrameLevel(parent:GetFrameLevel() + self.frameLevel) f:SetSize(size * self.pw, size * self.ph) local auras = f.auras for i = 1, self.maxIcons do local frame = auras[i] if not frame then frame = CreateFrame("Frame", nil, f) frame.icon = frame:CreateTexture(nil, "ARTWORK") auras[i] = frame end frame:SetSize(iconSize, iconSize) -- frame container Grid2:SetFrameBackdrop(frame, self.backdrop) if borderSize > 0 then local c = self.colorBorder frame:SetBackdropBorderColor(c.r, c.g, c.b, c.a) end frame:ClearAllPoints() frame:SetPoint(self.anchorIcon, f, self.anchorIcon, (x * ux + y * vx) * size, (x * uy + y * vy) * size) -- stack count text if self.showStack then local c = self.colorStack frame.text = frame.text or frame:CreateFontString(nil, "OVERLAY") frame.text:SetFontObject(GameFontHighlightSmall) frame.text:SetFont(self.font, self.fontSize, self.fontFlags) frame.text:SetTextColor(c.r, c.g, c.b, c.a) frame.text:ClearAllPoints() frame.text:SetPoint(self.fontPoint, self.fontOffsetX, self.fontOffsetY) frame.text:Show() elseif frame.text then frame.text:Hide() end -- cooldown animation if self.showCooldown then frame.cooldown = frame.cooldown or CreateFrame("Cooldown", frameName and frameName .. i or nil, frame, "CooldownFrameTemplate") frame.cooldown:SetAllPoints() frame.cooldown.noCooldownCount = self.dbx.disableOmniCC frame.cooldown:SetDrawEdge(self.dbx.disableOmniCC ~= nil) frame.cooldown:SetReverse(self.dbx.reverseCooldown) frame.cooldown:Show() elseif frame.cooldown then frame.cooldown:Hide() end -- icon texture frame.icon:SetPoint("TOPLEFT", frame, "TOPLEFT", borderSize, -borderSize) frame.icon:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -borderSize, borderSize) frame.icon:SetTexCoord(0.05, 0.95, 0.05, 0.95) -- frame:Hide() -- TODO: Why this? x = x + 1 if x >= self.maxIconsPerRow then x = 0 y = y + 1 end end end local function Icon_Disable(self, parent) local f = parent[self.name] f:Hide() f:SetParent(nil) f:ClearAllPoints() end local pointsX = {TOPLEFT = 1, TOPRIGHT = -1, BOTTOMLEFT = 1, BOTTOMRIGHT = -1} local pointsY = {TOPLEFT = -1, TOPRIGHT = -1, BOTTOMLEFT = 1, BOTTOMRIGHT = 1} local function Icon_UpdateDB(self, dbx) dbx = dbx or self.dbx local theme = Grid2Frame.db.profile -- location local l = dbx.location self.anchor = l.point self.anchorRel = l.relPoint self.offsetx = l.x self.offsety = l.y self.anchorIcon = (pointsX[self.anchor] and self.anchor) or (self.anchor == "BOTTOM" and "BOTTOMLEFT") or (self.anchor == "RIGHT" and "TOPRIGHT") or "TOPLEFT" -- misc variables self.borderSize = dbx.borderSize or 0 self.orientation = dbx.orientation or "HORIZONTAL" self.frameLevel = dbx.level or 1 self.iconSize = dbx.iconSize or theme.iconSize or 14 self.iconSpacing = dbx.iconSpacing or 1 self.maxIcons = dbx.maxIcons or 3 self.maxIconsPerRow = dbx.maxIconsPerRow or 3 self.iconTotSize = self.iconSize + self.iconSpacing self.maxRows = math.floor(self.maxIcons / self.maxIconsPerRow) + (self.maxIcons % self.maxIconsPerRow == 0 and 0 or 1) self.uy = 0 self.vx = 0 self.ux = pointsX[self.anchorIcon] self.vy = pointsY[self.anchorIcon] self.pw = math.abs(self.ux) * self.maxIconsPerRow self.ph = math.abs(self.vy) * self.maxRows if self.orientation == "VERTICAL" then self.ux, self.vx = self.vx, self.ux self.uy, self.vy = self.vy, self.uy self.pw, self.ph = self.ph, self.pw end self.showCooldown = not dbx.disableCooldown self.showStack = not dbx.disableStack self.useStatusColor = dbx.useStatusColor self.borderOpacity = dbx.borderOpacity or 1 self.colorBorder = Grid2:MakeColor(dbx.color1, "WHITE") self.colorStack = Grid2:MakeColor(dbx.colorStack, "WHITE") -- stacks text local jV, jH = dbx.fontJustifyV or "MIDDLE", dbx.fontJustifyH or "CENTER" self.fontPoint = (jV == "MIDDLE" and jH) or (jH == "CENTER" and jV) or jV .. jH self.fontOffsetX = dbx.fontOffsetX or 0 self.fontOffsetY = dbx.fontOffsetY or 0 self.fontFlags = dbx.fontFlags or "OUTLINE" self.fontSize = dbx.fontSize or 9 self.font = Grid2:MediaFetch("font", dbx.font or theme.font) or STANDARD_TEXT_FONT -- backdrop self.backdrop = self.borderSize > 0 and Grid2:GetBackdropTable("Interface\\Addons\\Grid2\\media\\white16x16", self.borderSize) or nil self.dbx = dbx end Grid2.setupFunc["icons"] = function(indicatorKey, dbx) local indicator = Grid2.indicators[indicatorKey] or Grid2.indicatorPrototype:new(indicatorKey) indicator.Create = Icon_Create indicator.Layout = Icon_Layout indicator.Disable = Icon_Disable indicator.Update = Icon_Update indicator.UpdateDB = Icon_UpdateDB Icon_UpdateDB(indicator, dbx) EnableDelayedUpdates() Grid2:RegisterIndicator(indicator, {"icon", "icons"}) return indicator end