local _, Cell = ... local L = Cell.L local F = Cell.funcs local I = Cell.iFuncs local P = Cell.pixelPerfectFuncs local LCG = LibStub("LibCustomGlow-1.0") CELL_BORDER_SIZE = 1 CELL_BORDER_COLOR = {0, 0, 0, 1} ------------------------------------------------- -- SetFont ------------------------------------------------- function I:SetFont(fs, anchorTo, font, size, flags, anchor, xOffset, yOffset, color) font = F:GetFont(font) if flags == "Shadow" then fs:SetFont(font, size, "") fs:SetShadowOffset(1, -1) fs:SetShadowColor(0, 0, 0, 1) else if flags == "None" then flags = "" elseif flags == "Outline" then flags = "OUTLINE" else flags = "OUTLINE,MONOCHROME" end fs:SetFont(font, size, flags) fs:SetShadowOffset(0, 0) fs:SetShadowColor(0, 0, 0, 0) end P:ClearPoints(fs) P:Point(fs, anchor, anchorTo, anchor, xOffset, yOffset) if color then fs.r = color[1] fs.g = color[2] fs.b = color[3] fs:SetTextColor(fs.r, fs.g, fs.b) else fs.r, fs.g, fs.b = 1, 1, 1 end end ------------------------------------------------- -- CreateAura_BorderIcon ------------------------------------------------- local function BorderIcon_SetFont(frame, font1, font2) I:SetFont(frame.stack, frame.textFrame, unpack(font1)) I:SetFont(frame.duration, frame.textFrame, unpack(font2)) end local function BorderIcon_SetCooldown(frame, start, duration, debuffType, texture, count, refreshing) local r, g, b if debuffType then r, g, b = I:GetDebuffTypeColor(debuffType) else r, g, b = 0, 0, 0 end if duration == 0 then frame.border:Show() frame.border:SetColorTexture(r, g, b) frame.cooldown:Hide() frame.duration:Hide() frame:SetScript("OnUpdate", nil) else frame.border:Hide() frame.cooldown:Show() frame.cooldown:SetSwipeColor(r, g, b) frame.cooldown:_SetCooldown(start, duration) frame.duration:Show() local fmt frame.elapsed = 0.1 -- update immediately frame:SetScript("OnUpdate", function(self, elapsed) local remain = duration-(GetTime()-start) if remain < 0 then remain = 0 end self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 -- color if Cell.vars.iconDurationColors then if remain < Cell.vars.iconDurationColors[3][4] then frame.duration:SetTextColor(Cell.vars.iconDurationColors[3][1], Cell.vars.iconDurationColors[3][2], Cell.vars.iconDurationColors[3][3]) elseif remain < (Cell.vars.iconDurationColors[2][4] * duration) then frame.duration:SetTextColor(Cell.vars.iconDurationColors[2][1], Cell.vars.iconDurationColors[2][2], Cell.vars.iconDurationColors[2][3]) else frame.duration:SetTextColor(Cell.vars.iconDurationColors[1][1], Cell.vars.iconDurationColors[1][2], Cell.vars.iconDurationColors[1][3]) end else frame.duration:SetTextColor(frame.duration.r, frame.duration.g, frame.duration.b) end end -- format if remain > 60 then fmt, remain = "%dm", remain/60 else if Cell.vars.iconDurationRoundUp then fmt, remain = "%d", ceil(remain) else if remain < Cell.vars.iconDurationDecimal then fmt = "%.1f" else fmt = "%d" end end end frame.duration:SetFormattedText(fmt, remain) end) end frame.icon:SetTexture(texture) frame.stack:SetText((count == 0 or count == 1) and "" or count) frame:Show() if refreshing then frame.ag:Play() end end function I:CreateAura_BorderIcon(name, parent, borderSize) local frame = CreateFrame("Frame", name, parent, "BackdropTemplate") frame:Hide() -- frame:SetSize(11, 11) frame:SetBackdrop({bgFile = "Interface\\Buttons\\WHITE8x8"}) frame:SetBackdropColor(0, 0, 0, 0.85) local border = frame:CreateTexture(name.."Border", "BORDER") frame.border = border border:SetAllPoints(frame) border:Hide() local cooldown = CreateFrame("Cooldown", name.."Cooldown", frame) frame.cooldown = cooldown cooldown:SetAllPoints(frame) cooldown:SetSwipeTexture("Interface\\Buttons\\WHITE8x8") cooldown:SetSwipeColor(1, 1, 1) cooldown:SetHideCountdownNumbers(true) -- disable omnicc cooldown.noCooldownCount = true -- prevent some addons from adding cooldown text cooldown._SetCooldown = cooldown.SetCooldown cooldown.SetCooldown = nil local iconFrame = CreateFrame("Frame", name.."IconFrame", frame) P:Point(iconFrame, "TOPLEFT", frame, "TOPLEFT", borderSize, -borderSize) P:Point(iconFrame, "BOTTOMRIGHT", frame, "BOTTOMRIGHT", -borderSize, borderSize) iconFrame:SetFrameLevel(cooldown:GetFrameLevel()+1) local icon = iconFrame:CreateTexture(name.."Icon", "ARTWORK") frame.icon = icon icon:SetTexCoord(0.12, 0.88, 0.12, 0.88) icon:SetAllPoints(iconFrame) local textFrame = CreateFrame("Frame", nil, iconFrame) textFrame:SetAllPoints(frame) frame.textFrame = textFrame local stack = textFrame:CreateFontString(nil, "OVERLAY", "CELL_FONT_STATUS") frame.stack = stack stack:SetJustifyH("RIGHT") P:Point(stack, "TOPRIGHT", textFrame, "TOPRIGHT", 2, 1) local duration = textFrame:CreateFontString(nil, "OVERLAY", "CELL_FONT_STATUS") frame.duration = duration duration:SetJustifyH("RIGHT") P:Point(duration, "BOTTOMRIGHT", textFrame, "BOTTOMRIGHT", 2, -1) function frame:SetBorder(thickness) P:ClearPoints(iconFrame) P:Point(iconFrame, "TOPLEFT", frame, "TOPLEFT", thickness, -thickness) P:Point(iconFrame, "BOTTOMRIGHT", frame, "BOTTOMRIGHT", -thickness, thickness) end frame.SetFont = BorderIcon_SetFont local ag = frame:CreateAnimationGroup() frame.ag = ag local t1 = ag:CreateAnimation("Translation") t1:SetOffset(0, 5) t1:SetDuration(0.1) t1:SetOrder(1) t1:SetSmoothing("OUT") local t2 = ag:CreateAnimation("Translation") t2:SetOffset(0, -5) t2:SetDuration(0.1) t2:SetOrder(2) t2:SetSmoothing("IN") frame.SetCooldown = BorderIcon_SetCooldown function frame:UpdatePixelPerfect() P:Resize(frame) P:Repoint(frame) P:Repoint(iconFrame) P:Repoint(stack) P:Repoint(duration) end return frame end ------------------------------------------------- -- CreateAura_BarIcon ------------------------------------------------- local function BarIcon_SetFont(frame, font1, font2) I:SetFont(frame.stack, frame.textFrame, unpack(font1)) I:SetFont(frame.duration, frame.textFrame, unpack(font2)) end local function BarIcon_SetCooldown(frame, start, duration, debuffType, texture, count, refreshing) if duration == 0 then frame.cooldown:Hide() frame.duration:Hide() frame:SetScript("OnUpdate", nil) else if frame.showAnimation then -- init bar values frame.cooldown.elapsed = 0.1 -- update immediately frame.cooldown:SetMinMaxValues(0, duration) frame.cooldown:SetValue(GetTime()-start) frame.cooldown:Show() else frame.cooldown:Hide() end local threshold if not frame.showDuration then frame.duration:Hide() else if frame.showDuration == true then threshold = duration elseif frame.showDuration >= 1 then threshold = frame.showDuration else -- < 1 threshold = frame.showDuration * duration end frame.duration:Show() end if frame.showDuration then local fmt frame.elapsed = 0.1 -- update immediately frame:SetScript("OnUpdate", function(self, elapsed) local remain = duration-(GetTime()-start) if remain < 0 then remain = 0 end if remain > threshold then frame.duration:SetText("") return end self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 -- color if Cell.vars.iconDurationColors then if remain < Cell.vars.iconDurationColors[3][4] then frame.duration:SetTextColor(Cell.vars.iconDurationColors[3][1], Cell.vars.iconDurationColors[3][2], Cell.vars.iconDurationColors[3][3]) elseif remain < (Cell.vars.iconDurationColors[2][4] * duration) then frame.duration:SetTextColor(Cell.vars.iconDurationColors[2][1], Cell.vars.iconDurationColors[2][2], Cell.vars.iconDurationColors[2][3]) else frame.duration:SetTextColor(Cell.vars.iconDurationColors[1][1], Cell.vars.iconDurationColors[1][2], Cell.vars.iconDurationColors[1][3]) end else frame.duration:SetTextColor(frame.duration.r, frame.duration.g, frame.duration.b) end end -- format if remain > 60 then fmt, remain = "%dm", remain/60 else if Cell.vars.iconDurationRoundUp then fmt, remain = "%d", ceil(remain) else if remain < Cell.vars.iconDurationDecimal then fmt = "%.1f" else fmt = "%d" end end end frame.duration:SetFormattedText(fmt, remain) end) end end local r, g, b if debuffType then r, g, b = I:GetDebuffTypeColor(debuffType) frame.spark:SetColorTexture(r, g, b, 1) else r, g, b = 0, 0, 0 frame.spark:SetColorTexture(0.5, 0.5, 0.5, 1) end frame:SetBackdropColor(r, g, b, 1) frame.icon:SetTexture(texture) frame.maskIcon:SetTexture(texture) frame.stack:SetText((count == 0 or count == 1) and "" or count) frame:Show() if refreshing then frame.ag:Play() end end function I:CreateAura_BarIcon(name, parent) local frame = CreateFrame("Frame", name, parent, "BackdropTemplate") frame:Hide() -- frame:SetSize(11, 11) frame:SetBackdrop({bgFile = "Interface\\Buttons\\WHITE8x8"}) frame:SetBackdropColor(0, 0, 0, 1) local icon = frame:CreateTexture(name.."Icon", "ARTWORK") frame.icon = icon icon:SetTexCoord(0.12, 0.88, 0.12, 0.88) P:Point(icon, "TOPLEFT", frame, "TOPLEFT", CELL_BORDER_SIZE, -CELL_BORDER_SIZE) P:Point(icon, "BOTTOMRIGHT", frame, "BOTTOMRIGHT", -CELL_BORDER_SIZE, CELL_BORDER_SIZE) -- icon:SetDrawLayer("ARTWORK", 1) local cooldown = CreateFrame("StatusBar", name.."CooldownBar", frame) frame.cooldown = cooldown cooldown:SetPoint("TOPLEFT", icon) cooldown:SetPoint("BOTTOMRIGHT", icon) cooldown:SetOrientation("VERTICAL") cooldown:SetReverseFill(true) -- cooldown:SetFillStyle("REVERSE") cooldown:SetStatusBarTexture("Interface\\Buttons\\WHITE8x8") cooldown:GetStatusBarTexture():SetAlpha(0) cooldown.elapsed = 0.1 -- update immediately cooldown:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then cooldown:SetValue(cooldown:GetValue() + self.elapsed) self.elapsed = 0 end end) -- for LCG.ButtonGlow_Start function cooldown:GetCooldownDuration() return 0 end local spark = cooldown:CreateTexture(nil, "OVERLAY") frame.spark = spark P:Height(spark, CELL_BORDER_SIZE) spark:SetBlendMode("ADD") spark:SetPoint("TOPLEFT", cooldown:GetStatusBarTexture(), "BOTTOMLEFT") spark:SetPoint("TOPRIGHT", cooldown:GetStatusBarTexture(), "BOTTOMRIGHT") local mask = frame:CreateMaskTexture() mask:SetTexture("Interface\\Buttons\\WHITE8x8", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE") mask:SetPoint("TOPLEFT") mask:SetPoint("BOTTOMRIGHT", cooldown:GetStatusBarTexture()) local maskIcon = cooldown:CreateTexture(name.."MaskIcon", "ARTWORK") frame.maskIcon = maskIcon maskIcon:SetTexCoord(0.12, 0.88, 0.12, 0.88) maskIcon:SetDesaturated(true) maskIcon:SetAllPoints(icon) -- maskIcon:SetDrawLayer("ARTWORK", 0) maskIcon:SetVertexColor(0.5, 0.5, 0.5, 1) maskIcon:AddMaskTexture(mask) frame:SetScript("OnSizeChanged", function(self, width, height) -- keep aspect ratio icon:SetTexCoord(unpack(F:GetTexCoord(width, height))) maskIcon:SetTexCoord(unpack(F:GetTexCoord(width, height))) end) local textFrame = CreateFrame("Frame", nil, frame) frame.textFrame = textFrame textFrame:SetAllPoints(frame) textFrame:SetFrameLevel(cooldown:GetFrameLevel()+1) local stack = textFrame:CreateFontString(nil, "OVERLAY", "CELL_FONT_STATUS") frame.stack = stack stack:SetJustifyH("RIGHT") P:Point(stack, "TOPRIGHT", textFrame, "TOPRIGHT", 2, 0) local duration = textFrame:CreateFontString(nil, "OVERLAY", "CELL_FONT_STATUS") frame.duration = duration duration:SetJustifyH("RIGHT") P:Point(duration, "BOTTOMRIGHT", textFrame, "BOTTOMRIGHT", 2, 0) duration:Hide() frame.SetFont = BarIcon_SetFont local ag = frame:CreateAnimationGroup() frame.ag = ag local t1 = ag:CreateAnimation("Translation") t1:SetOffset(0, 5) t1:SetDuration(0.1) t1:SetOrder(1) t1:SetSmoothing("OUT") local t2 = ag:CreateAnimation("Translation") t2:SetOffset(0, -5) t2:SetDuration(0.1) t2:SetOrder(2) t2:SetSmoothing("IN") frame.SetCooldown = BarIcon_SetCooldown -- frame:SetScript("OnEnter", function() -- local f = frame -- repeat -- f = f:GetParent() -- until f:IsObjectType("button") -- f:GetScript("OnEnter")(f) -- end) function frame:ShowDuration(show) frame.showDuration = show if show then duration:Show() else duration:Hide() end end function frame:ShowAnimation(show) frame.showAnimation = show if show then cooldown:Show() else cooldown:Hide() end end function frame:ShowStack(show) if show then stack:Show() else stack:Hide() end end function frame:UpdatePixelPerfect() P:Resize(frame) P:Repoint(frame) P:Repoint(icon) P:Repoint(cooldown) P:Resize(spark) P:Repoint(stack) P:Repoint(duration) end return frame end ------------------------------------------------- -- CreateAura_Text ------------------------------------------------- local function Text_SetFont(frame, font, size, flags) font = F:GetFont(font) if flags == "Shadow" then frame.text:SetFont(font, size, "") frame.text:SetShadowOffset(1, -1) frame.text:SetShadowColor(0, 0, 0, 1) else if flags == "None" then flags = "" elseif flags == "Outline" then flags = "OUTLINE" else flags = "OUTLINE,MONOCHROME" end frame.text:SetFont(font, size, flags) frame.text:SetShadowOffset(0, 0) frame.text:SetShadowColor(0, 0, 0, 0) end local point = frame:GetPoint(1) frame.text:ClearAllPoints() if string.find(point, "LEFT") then frame.text:SetPoint("LEFT") elseif string.find(point, "RIGHT") then frame.text:SetPoint("RIGHT") else frame.text:SetPoint("CENTER") end frame:SetSize(size+3, size+3) end local circled = {"①","②","③","④","⑤","⑥","⑦","⑧","⑨","⑩","⑪","⑫","⑬","⑭","⑮","⑯","⑰","⑱","⑲","⑳","㉑","㉒","㉓","㉔","㉕","㉖","㉗","㉘","㉙","㉚","㉛","㉜","㉝","㉞","㉟","㊱","㊲","㊳","㊴","㊵","㊶","㊷","㊸","㊹","㊺","㊻","㊼","㊽","㊾","㊿"} local function Text_SetCooldown(frame, start, duration, debuffType, texture, count) if duration == 0 then count = count == 0 and 1 or count count = frame.circledStackNums and circled[count] or count frame.text:SetText(count) frame:SetScript("OnUpdate", nil) else local fmt if frame.durationTbl[1] then if count == 0 then fmt, count = "%s", "" elseif frame.circledStackNums then fmt, count = "%s ", circled[count] .. " " else fmt = "%d " end frame.elapsed = 0.1 -- update immediately frame:SetScript("OnUpdate", function(self, elapsed) local remain = duration-(GetTime()-start) if remain < 0 then remain = 0 end self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 -- color if frame.colors[3][1] and remain <= frame.colors[3][5] then frame.text:SetTextColor(frame.colors[3][2], frame.colors[3][3], frame.colors[3][4]) elseif frame.colors[2][1] and remain <= duration * frame.colors[2][5] then frame.text:SetTextColor(frame.colors[2][2], frame.colors[2][3], frame.colors[2][4]) else frame.text:SetTextColor(frame.colors[1][1], frame.colors[1][2], frame.colors[1][3]) end end -- format local fmt2 if remain > 60 then fmt2, remain = fmt .. "%dm", remain/60 else if frame.durationTbl[2] then fmt2, remain = fmt .. "%d", ceil(remain) else if remain < frame.durationTbl[3] then fmt2 = fmt .. "%.1f" else fmt2 = fmt .. "%d" end end end frame.text:SetFormattedText(fmt2, count, remain) end) else count = count == 0 and 1 or count if frame.circledStackNums then fmt = circled[count] count = nil else fmt = "%d" end -- update count frame.text:SetFormattedText(fmt, count) frame.elapsed = 0.1 -- update immediately frame:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 local remain = duration-(GetTime()-start) -- update color if frame.colors[3][1] and remain <= frame.colors[3][5] then frame.text:SetTextColor(frame.colors[3][2], frame.colors[3][3], frame.colors[3][4]) elseif frame.colors[2][1] and remain <= duration * frame.colors[2][5] then frame.text:SetTextColor(frame.colors[2][2], frame.colors[2][3], frame.colors[2][4]) else frame.text:SetTextColor(frame.colors[1][1], frame.colors[1][2], frame.colors[1][3]) end end end) end end frame:Show() end function I:CreateAura_Text(name, parent) local frame = CreateFrame("Frame", name, parent) frame:SetSize(11, 11) frame:Hide() frame.indicatorType = "text" local text = frame:CreateFontString(nil, "OVERLAY", "CELL_FONT_STATUS") frame.text = text -- stack:SetJustifyH("RIGHT") text:SetPoint("CENTER", 1, 0) frame.SetFont = Text_SetFont frame._SetPoint = frame.SetPoint function frame:SetPoint(point, relativeTo, relativePoint, x, y) text:ClearAllPoints() if string.find(point, "LEFT") then text:SetPoint("LEFT") elseif string.find(point, "RIGHT") then text:SetPoint("RIGHT") else text:SetPoint("CENTER") end frame:_SetPoint(point, relativeTo, relativePoint, x, y) end frame.SetCooldown = Text_SetCooldown function frame:SetDuration(durationTbl) frame.durationTbl = durationTbl end function frame:SetCircledStackNums(circled) frame.circledStackNums = circled end function frame:SetColors(colors) frame.colors = colors end return frame end ------------------------------------------------- -- CreateAura_Rect ------------------------------------------------- local function Rect_SetFont(frame, font, size, flags, anchor, xOffset, yOffset, color) I:SetFont(frame.stack, frame, font, size, flags, anchor, xOffset, yOffset, color) end local function Rect_SetCooldown(frame, start, duration, debuffType, texture, count) if duration == 0 then frame.tex:SetColorTexture(unpack(frame.colors[1])) frame:SetScript("OnUpdate", nil) else frame.elapsed = 0.1 -- update immediately frame:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 local remain = duration-(GetTime()-start) -- update color if frame.colors[3][1] and remain <= frame.colors[3][5] then frame.tex:SetColorTexture(frame.colors[3][2], frame.colors[3][3], frame.colors[3][4]) elseif frame.colors[2][1] and remain <= duration * frame.colors[2][5] then frame.tex:SetColorTexture(frame.colors[2][2], frame.colors[2][3], frame.colors[2][4]) else frame.tex:SetColorTexture(frame.colors[1][1], frame.colors[1][2], frame.colors[1][3]) end end end) end frame.stack:SetText((count == 0 or count == 1) and "" or count) frame:Show() end function I:CreateAura_Rect(name, parent) local frame = CreateFrame("Frame", name, parent, "BackdropTemplate") -- frame:SetSize(11, 4) frame:Hide() frame.indicatorType = "rect" frame:SetBackdrop({bgFile = "Interface\\Buttons\\WHITE8x8"}) frame:SetBackdropColor(0, 0, 0, 1) local tex = frame:CreateTexture(nil, "ARTWORK") frame.tex = tex P:Point(tex, "TOPLEFT", frame, "TOPLEFT", 1, -1) P:Point(tex, "BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1) frame.stack = frame:CreateFontString(nil, "OVERLAY") frame.SetFont = Rect_SetFont frame.SetCooldown = Rect_SetCooldown function frame:SetColors(colors) frame.colors = colors end function frame:ShowStack(show) if show then frame.stack:Show() else frame.stack:Hide() end end function frame:UpdatePixelPerfect() P:Resize(frame) P:Repoint(frame) P:Repoint(tex) end return frame end ------------------------------------------------- -- CreateAura_Bar ------------------------------------------------- local function Bar_SetFont(frame, font, size, flags, anchor, xOffset, yOffset, color) I:SetFont(frame.stack, frame, font, size, flags, anchor, xOffset, yOffset, color) end local function Bar_SetCooldown(bar, start, duration, debuffType, texture, count) if duration == 0 then bar:SetScript("OnUpdate", nil) bar:SetMinMaxValues(0, 1) bar:SetValue(1) bar:SetStatusBarColor(unpack(bar.colors[1])) bar:SetBackdropColor(unpack(bar.colors[4])) else bar:SetMinMaxValues(0, duration) bar.elapsed = 0.1 -- update immediately bar:SetScript("OnUpdate", function(self, elapsed) local remain = duration-(GetTime()-start) if remain < 0 then remain = 0 end bar:SetValue(remain) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 -- update color if bar.colors[3][1] and remain <= bar.colors[3][5] then bar:SetStatusBarColor(bar.colors[3][2], bar.colors[3][3], bar.colors[3][4]) elseif bar.colors[2][1] and remain <= duration * bar.colors[2][5] then bar:SetStatusBarColor(bar.colors[2][2], bar.colors[2][3], bar.colors[2][4]) else bar:SetStatusBarColor(bar.colors[1][1], bar.colors[1][2], bar.colors[1][3]) end bar:SetBackdropColor(bar.colors[4][1], bar.colors[4][2], bar.colors[4][3], bar.colors[4][4]) end end) end bar.stack:SetText((count == 0 or count == 1) and "" or count) bar:Show() end function I:CreateAura_Bar(name, parent) local bar = Cell:CreateStatusBar(name, parent, 18, 4, 100) bar:Hide() bar.indicatorType = "bar" bar.stack = bar:CreateFontString(nil, "OVERLAY") bar.SetFont = Bar_SetFont bar.SetCooldown = Bar_SetCooldown function bar:SetColors(colors) bar.colors = colors end function bar:ShowStack(show) if show then bar.stack:Show() else bar.stack:Hide() end end return bar end ------------------------------------------------- -- CreateAura_Color ------------------------------------------------- local function Color_SetCooldown(color, start, duration, debuffType) if color.type == "change-over-time" then if duration == 0 then color.solidTex:SetVertexColor(unpack(color.colors[4])) color:SetScript("OnUpdate", nil) else color.elapsed = 0.1 -- update immediately color:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 local remain = duration-(GetTime()-start) -- update color if remain <= color.colors[6][4] then color.solidTex:SetVertexColor(color.colors[6][1], color.colors[6][2], color.colors[6][3]) elseif remain <= duration * color.colors[5][4] then color.solidTex:SetVertexColor(color.colors[5][1], color.colors[5][2], color.colors[5][3]) else color.solidTex:SetVertexColor(color.colors[4][1], color.colors[4][2], color.colors[4][3]) end end end) end elseif color.type == "debuff-type" and debuffType then solidTex:SetVertexColor(CellDB["debuffTypeColor"][debuffType]["r"], CellDB["debuffTypeColor"][debuffType]["g"], CellDB["debuffTypeColor"][debuffType]["b"], 1) end color:Show() end function I:CreateAura_Color(name, parent) local color = CreateFrame("Frame", name, parent) color:Hide() color.indicatorType = "color" local solidTex = color:CreateTexture(nil, "OVERLAY", nil, -5) color.solidTex = solidTex solidTex:SetTexture(Cell.vars.texture) solidTex:SetAllPoints(color) solidTex:Hide() solidTex:SetScript("OnShow", function() -- update texture solidTex:SetTexture(Cell.vars.texture) end) local gradientTex = color:CreateTexture(nil, "OVERLAY", nil, -5) gradientTex:SetTexture("Interface\\Buttons\\WHITE8x8") gradientTex:SetAllPoints(color) gradientTex:Hide() color.SetCooldown = Color_SetCooldown function color:SetAnchor(anchorTo) color:ClearAllPoints() if anchorTo == "healthbar-current" then -- current hp texture color:SetAllPoints(parent.widget.healthBar:GetStatusBarTexture()) color:SetFrameLevel(parent:GetFrameLevel()+5) elseif anchorTo == "healthbar-entire" then -- entire hp bar color:SetAllPoints(parent.widget.healthBar) color:SetFrameLevel(parent:GetFrameLevel()+5) else -- unitbutton P:Point(color, "TOPLEFT", parent.widget.overlayFrame, "TOPLEFT", 1, -1) P:Point(color, "BOTTOMRIGHT", parent.widget.overlayFrame, "BOTTOMRIGHT", -1, 1) color:SetFrameLevel(parent:GetFrameLevel()+6) end end function color:SetColors(colors) color.type = colors[1] color.colors = colors if colors[1] == "solid" then color:SetScript("OnUpdate", nil) solidTex:SetVertexColor(colors[2][1], colors[2][2], colors[2][3], colors[2][4]) solidTex:Show() gradientTex:Hide() elseif colors[1] == "gradient-vertical" then color:SetScript("OnUpdate", nil) gradientTex:SetGradient("VERTICAL", CreateColor(colors[2][1], colors[2][2], colors[2][3], colors[2][4]), CreateColor(colors[3][1], colors[3][2], colors[3][3], colors[3][4])) gradientTex:Show() solidTex:Hide() elseif colors[1] == "gradient-horizontal" then color:SetScript("OnUpdate", nil) gradientTex:SetGradient("HORIZONTAL", CreateColor(colors[2][1], colors[2][2], colors[2][3], colors[2][4]), CreateColor(colors[3][1], colors[3][2], colors[3][3], colors[3][4])) gradientTex:Show() solidTex:Hide() elseif colors[1] == "debuff-type" then color:SetScript("OnUpdate", nil) solidTex:SetVertexColor(colors[2][1], colors[2][2], colors[2][3], colors[2][4]) solidTex:Show() gradientTex:Hide() elseif colors[1] == "change-over-time" then solidTex:SetVertexColor(colors[4][1], colors[4][2], colors[4][3], colors[4][4]) solidTex:Show() gradientTex:Hide() end end return color end ------------------------------------------------- -- CreateAura_Texture ------------------------------------------------- function I:CreateAura_Texture(name, parent) local texture = CreateFrame("Frame", name, parent) texture:Hide() texture.indicatorType = "texture" local tex = texture:CreateTexture(name, "OVERLAY") tex:SetAllPoints(texture) function texture:SetCooldown(start, duration) if texture.fadeOut then texture.elapsed = 0.1 -- update immediately texture:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 local remain = duration - (GetTime() - start) if remain <= 0 then tex:SetAlpha(0.2) elseif remain >= duration then tex:SetAlpha(1) else tex:SetAlpha(remain / duration * 0.8 + 0.2) end end end) else texture:SetScript("OnUpdate", nil) tex:SetAlpha(texture.colorAlpha) end texture:Show() end function texture:SetFadeOut(fadeOut) texture.fadeOut = fadeOut end function texture:SetTexture(texTbl) -- texture, rotation, color if strfind(strlower(texTbl[1]), "^interface") then tex:SetTexture(texTbl[1]) else tex:SetAtlas(texTbl[1]) end tex:SetRotation(texTbl[2] * math.pi / 180) tex:SetVertexColor(unpack(texTbl[3])) texture.colorAlpha = texTbl[3][4] end return texture end ------------------------------------------------- -- CreateAura_Icons ------------------------------------------------- local function Icons_UpdateFrameSize(icons, iconsShown) local lines = ceil(iconsShown / icons.numPerLine) if icons.isHorizontal then if lines > 1 then icons:_SetSize(icons.width*icons.numPerLine, icons.height*lines) else icons:_SetSize(icons.width*iconsShown, icons.height) end else if lines > 1 then icons:_SetSize(icons.width*lines, icons.height*icons.numPerLine) else icons:_SetSize(icons.width, icons.height*iconsShown) end end end local function Icons_UpdateSize(icons, iconsShown) if not (icons.width and icons.height and icons.orientation) then return end -- not init if iconsShown then -- call from I:CheckCustomIndicators or preview for i = iconsShown + 1, icons.maxNum do icons[i]:Hide() end if iconsShown ~= 0 then Icons_UpdateFrameSize(icons, iconsShown) end else for i = 1, icons.maxNum do if icons[i]:IsShown() then Icons_UpdateFrameSize(icons, i) end end end end local function Icons_SetNumPerLine(icons, numPerLine) icons.numPerLine = min(numPerLine, icons.maxNum) if icons.orientation then icons:SetOrientation(icons.orientation) end icons:UpdateSize() end local function Icons_SetOrientation(icons, orientation) icons.orientation = orientation local anchor = icons:GetPoint() assert(anchor, "[indicator] SetPoint must be called before SetOrientation") icons.isHorizontal = not strfind(orientation, "top") local point1, point2, newLinePoint2 if orientation == "left-to-right" then if strfind(anchor, "^BOTTOM") then point1 = "BOTTOMLEFT" point2 = "BOTTOMRIGHT" newLinePoint2 = "TOPLEFT" else point1 = "TOPLEFT" point2 = "TOPRIGHT" newLinePoint2 = "BOTTOMLEFT" end elseif orientation == "right-to-left" then if strfind(anchor, "^BOTTOM") then point1 = "BOTTOMRIGHT" point2 = "BOTTOMLEFT" newLinePoint2 = "TOPRIGHT" else point1 = "TOPRIGHT" point2 = "TOPLEFT" newLinePoint2 = "BOTTOMRIGHT" end elseif orientation == "top-to-bottom" then if strfind(anchor, "RIGHT$") then point1 = "TOPRIGHT" point2 = "BOTTOMRIGHT" newLinePoint2 = "TOPLEFT" else point1 = "TOPLEFT" point2 = "BOTTOMLEFT" newLinePoint2 = "TOPRIGHT" end elseif orientation == "bottom-to-top" then if strfind(anchor, "RIGHT$") then point1 = "BOTTOMRIGHT" point2 = "TOPRIGHT" newLinePoint2 = "BOTTOMLEFT" else point1 = "BOTTOMLEFT" point2 = "TOPLEFT" newLinePoint2 = "BOTTOMRIGHT" end end for i = 1, icons.maxNum do P:ClearPoints(icons[i]) if i == 1 then P:Point(icons[i], point1) elseif i % icons.numPerLine == 1 then P:Point(icons[i], point1, icons[i-icons.numPerLine], newLinePoint2) else P:Point(icons[i], point1, icons[i-1], point2) end end icons:UpdateSize() end local function Icons_SetSize(icons, width, height) icons.width = width icons.height = height for i = 1, icons.maxNum do icons[i]:SetSize(width, height) end icons:UpdateSize() end local function Icons_Hide(icons, hideAll) icons:_Hide() if hideAll then for i = 1, icons.maxNum do icons[i]:Hide() end end end local function Icons_SetFont(icons, ...) for i = 1, icons.maxNum do icons[i]:SetFont(...) end end local function Icons_ShowDuration(icons, show) for i = 1, icons.maxNum do icons[i]:ShowDuration(show) end end local function Icons_ShowStack(icons, show) for i = 1, icons.maxNum do icons[i]:ShowStack(show) end end local function Icons_ShowAnimation(icons, show) for i = 1, icons.maxNum do icons[i]:ShowAnimation(show) end end local function Icons_UpdatePixelPerfect(icons) P:Repoint(icons) for i = 1, icons.maxNum do icons[i]:UpdatePixelPerfect() end end function I:CreateAura_Icons(name, parent, num) local icons = CreateFrame("Frame", name, parent) icons:Hide() icons.indicatorType = "icons" icons.maxNum = num icons.numPerLine = num icons._SetSize = icons.SetSize icons.SetSize = Icons_SetSize icons._Hide = icons.Hide icons.Hide = Icons_Hide icons.SetFont = Icons_SetFont icons.UpdateSize = Icons_UpdateSize icons.SetOrientation = Icons_SetOrientation icons.SetNumPerLine = Icons_SetNumPerLine icons.ShowDuration = Icons_ShowDuration icons.ShowStack = Icons_ShowStack icons.ShowAnimation = Icons_ShowAnimation icons.UpdatePixelPerfect = Icons_UpdatePixelPerfect for i = 1, num do local name = name.."Icons"..i local frame = I:CreateAura_BarIcon(name, icons) icons[i] = frame end return icons end ------------------------------------------------- -- CreateAura_Glow ------------------------------------------------- local function Glow_SetCooldown(glow, start, duration) if glow.fadeOut then glow.elapsed = 0.1 -- update immediately glow:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 local remain = duration-(GetTime()-start) if remain <= 0 then glow:SetAlpha(0.2) elseif remain >= duration then glow:SetAlpha(1) else glow:SetAlpha(remain / duration * 0.8 + 0.2) end end end) else glow:SetScript("OnUpdate", nil) glow:SetAlpha(1) end glow:Show() local glowOptions = glow.glowOptions local glowType = glowOptions[1] if glowType == "Normal" then LCG.PixelGlow_Stop(glow) LCG.AutoCastGlow_Stop(glow) LCG.ProcGlow_Stop(glow) LCG.ButtonGlow_Start(glow, glowOptions[2]) elseif glowType == "Pixel" then LCG.ButtonGlow_Stop(glow) LCG.AutoCastGlow_Stop(glow) LCG.ProcGlow_Stop(glow) -- color, N, frequency, length, thickness LCG.PixelGlow_Start(glow, glowOptions[2], glowOptions[3], glowOptions[4], glowOptions[5], glowOptions[6]) elseif glowType == "Shine" then LCG.ButtonGlow_Stop(glow) LCG.PixelGlow_Stop(glow) LCG.ProcGlow_Stop(glow) -- color, N, frequency, scale LCG.AutoCastGlow_Start(glow, glowOptions[2], glowOptions[3], glowOptions[4], glowOptions[5]) elseif glowType == "Proc" then LCG.ButtonGlow_Stop(glow) LCG.PixelGlow_Stop(glow) LCG.AutoCastGlow_Stop(glow) -- color, duration LCG.ProcGlow_Start(glow, {color=glowOptions[2], duration=glowOptions[3], startAnim=false}) else LCG.ButtonGlow_Stop(glow) LCG.PixelGlow_Stop(glow) LCG.AutoCastGlow_Stop(glow) LCG.ProcGlow_Stop(glow) glow:Hide() end end function I:CreateAura_Glow(name, parent) local glow = CreateFrame("Frame", name, parent) glow:SetAllPoints(parent) glow:Hide() glow.indicatorType = "glow" glow.SetCooldown = Glow_SetCooldown function glow:SetFadeOut(fadeOut) glow.fadeOut = fadeOut end function glow:UpdateGlowOptions(options) glow.glowOptions = options end glow:SetScript("OnHide", function() LCG.ButtonGlow_Stop(glow) LCG.PixelGlow_Stop(glow) LCG.AutoCastGlow_Stop(glow) LCG.ProcGlow_Stop(glow) end) return glow end ------------------------------------------------- -- CreateAura_Bars ------------------------------------------------- local function Bars_SetCooldown(bar, start, duration, color) if duration == 0 then bar:SetScript("OnUpdate", nil) bar:SetMinMaxValues(0, 1) bar:SetValue(1) else bar:SetMinMaxValues(0, duration) bar:SetScript("OnUpdate", function(self, elapsed) local remain = duration-(GetTime()-start) if remain < 0 then remain = 0 end bar:SetValue(remain) end) end bar:SetStatusBarColor(color[1], color[2], color[3], 1) bar:Show() end function I:CreateAura_Bars(name, parent, num) local bars = CreateFrame("Frame", name, parent) bars:Hide() bars.indicatorType = "bars" bars._SetSize = bars.SetSize function bars:UpdateSize(barsShown) if not (bars.width and bars.height) then return end -- not init if barsShown then -- call from I:CheckCustomIndicators or preview for i = barsShown + 1, num do bars[i]:Hide() end if barsShown ~= 0 then bars:_SetSize(bars.width, bars.height*barsShown-P:Scale(1)*(barsShown-1)) end else for i = 1, num do if bars[i]:IsShown() then bars:_SetSize(bars.width, bars.height*i-P:Scale(1)*(i-1)) else break end end end end function bars:SetSize(width, height) bars.width = width bars.height = height for i = 1, num do bars[i]:SetSize(width, height) end bars:UpdateSize() end function bars:SetOrientation(orientation) local point1, point2, offset if orientation == "top-to-bottom" then point1 = "TOPLEFT" point2 = "BOTTOMLEFT" offset = 1 elseif orientation == "bottom-to-top" then point1 = "BOTTOMLEFT" point2 = "TOPLEFT" offset = -1 end for i = 1, num do P:ClearPoints(bars[i]) if i == 1 then P:Point(bars[i], point1) else P:Point(bars[i], point1, bars[i-1], point2, 0, offset) end end bars:UpdateSize() end for i = 1, num do local name = name.."Bar"..i local bar = I:CreateAura_Bar(name, bars) bars[i] = bar bar.stack:Hide() bar.SetCooldown = Bars_SetCooldown end bars._Hide = bars.Hide function bars:Hide(hideAll) bars:_Hide() if hideAll then for i = 1, num do bars[i]:Hide() end end end function bars:UpdatePixelPerfect() -- P:Resize(bars) P:Repoint(bars) for i = 1, num do bars[i]:UpdatePixelPerfect() end end return bars end ------------------------------------------------- -- CreateAura_Overlay ------------------------------------------------- local function Overlay_SetCooldown(overlay, start, duration, debuffType, texture, count) if duration == 0 then overlay:SetScript("OnUpdate", nil) overlay:_SetMinMaxValues(0, 1) overlay:_SetValue(1) overlay:SetStatusBarColor(unpack(overlay.colors[1])) else overlay:_SetMinMaxValues(0, duration) overlay.elapsed = 0.1 -- update immediately overlay:SetScript("OnUpdate", function(self, elapsed) local remain = duration-(GetTime()-start) if remain < 0 then remain = 0 end overlay:_SetValue(remain) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then self.elapsed = 0 -- update color if overlay.colors[3][1] and remain <= overlay.colors[3][6] then overlay:SetStatusBarColor(overlay.colors[3][2], overlay.colors[3][3], overlay.colors[3][4], overlay.colors[3][5]) elseif overlay.colors[2][1] and remain <= duration * overlay.colors[2][6] then overlay:SetStatusBarColor(overlay.colors[2][2], overlay.colors[2][3], overlay.colors[2][4], overlay.colors[2][5]) else overlay:SetStatusBarColor(overlay.colors[1][1], overlay.colors[1][2], overlay.colors[1][3], overlay.colors[1][4]) end end end) end overlay:Show() end function I:CreateAura_Overlay(name, parent) local overlay = CreateFrame("StatusBar", name, parent.widget.healthBar) overlay:SetStatusBarTexture("Interface\\Buttons\\WHITE8x8") overlay:Hide() overlay.indicatorType = "overlay" Mixin(overlay, SmoothStatusBarMixin) overlay:SetAllPoints() -- overlay:SetBackdropColor(0, 0, 0, 0) overlay.SetCooldown = Overlay_SetCooldown overlay._SetMinMaxValues = overlay.SetMinMaxValues overlay._SetValue = overlay.SetValue function overlay:EnableSmooth(smooth) if smooth then overlay._SetMinMaxValues = overlay.SetMinMaxSmoothedValue overlay._SetValue = overlay.SetSmoothedValue else overlay._SetMinMaxValues = overlay.SetMinMaxValues overlay._SetValue = overlay.SetValue end end function overlay:SetColors(colors) overlay.colors = colors end return overlay end