diff --git a/Config.lua b/Config.lua
new file mode 100644
index 0000000..dd368dd
--- /dev/null
+++ b/Config.lua
@@ -0,0 +1,58 @@
+--[[-----------------------------------------------------------------------
+ oUF: Stardust - a layout for the oUF framework
+ Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
+ This code is released under the zlib license; see LICENSE for details.
+-------------------------------------------------------------------------]]
+
+local _, Stardust = ...
+
+Stardust.config = {
+ -- Style
+ barTexture = "Qulight",
+ bgMultiplier = 0.35,
+ numberFont = "Blizzard Bold",
+ textFont = "Blizzard",
+
+ -- Layout
+ width = 220,
+ height = 32,
+ power = true,
+ powerHeight = 5,
+
+ -- Unit Specific
+ units = {
+ pet = {
+ width = 0.5
+ },
+ targettarget = {
+ width = 0.5,
+ power = false
+ },
+ focustarget = {
+ width = 0.5,
+ power = false
+ },
+ party = {
+ width = 0.5
+ },
+ partypet = {
+ width = 0.25,
+ power = false
+ }
+ }
+}
+
+Stardust.colors = {
+ power = {
+ MANA = { 0, 0.8, 1 }
+ },
+ totems = {
+ [1] = { 0.6, 1, 0.2 }, -- Earth
+ [2] = { 1, 0.6, 0.2 }, -- Fire
+ [3] = { 0.2, 0.8, 1 }, -- Water
+ [4] = { 0.8, 0.4, 1 }, -- Air
+ }
+}
+
+setmetatable(Stardust.colors, oUF.colors)
+setmetatable(Stardust.colors.power, oUF.colors.power)
diff --git a/Elements/BurningEmbers.lua b/Elements/BurningEmbers.lua
new file mode 100644
index 0000000..395dfe2
--- /dev/null
+++ b/Elements/BurningEmbers.lua
@@ -0,0 +1,173 @@
+--[[--------------------------------------------------------------------
+ oUF_Phanx
+ Fully-featured PVE-oriented layout for oUF.
+ Copyright (c) 2008-2015 Phanx <addons@phanx.net>. All rights reserved.
+ http://www.wowinterface.com/downloads/info13993-oUF_Phanx.html
+ http://www.curse.com/addons/wow/ouf-phanx
+ https://github.com/Phanx/oUF_Phanx
+------------------------------------------------------------------------
+ Element to display burning embers on oUF frames.
+
+ You may embed this module in your own layout, but please do not
+ distribute it as a standalone plugin.
+----------------------------------------------------------------------]]
+
+local _, ns = ...
+local oUF = ns.oUF or oUF
+assert(oUF, "BurningEmbers element requires oUF")
+
+local MAX_POWER_PER_EMBER = MAX_POWER_PER_EMBER
+local SPEC_WARLOCK_DESTRUCTION = SPEC_WARLOCK_DESTRUCTION
+local SPELL_POWER_BURNING_EMBERS = SPELL_POWER_BURNING_EMBERS
+local WARLOCK_BURNING_EMBERS = WARLOCK_BURNING_EMBERS
+
+local UpdateVisibility, Update, Path, ForceUpdate, Enable, Disable
+
+function UpdateVisibility(self, event)
+ local element = self.BurningEmbers
+
+ if UnitHasVehicleUI("player") or GetSpecialization() ~= SPEC_WARLOCK_DESTRUCTION or not IsPlayerSpell(WARLOCK_BURNING_EMBERS) then
+ self:UnregisterEvent("UNIT_DISPLAYPOWER", Path)
+ self:UnregisterEvent("UNIT_POWER", Path)
+
+ element.__disabled = true
+
+ for i = 1, #element do
+ element[i]:Hide()
+ end
+ if element.Hide then
+ element:Hide()
+ end
+
+ return
+ end
+
+ element.__disabled = nil
+
+ if element.Show then
+ element:Show()
+ end
+
+ self:RegisterEvent("UNIT_DISPLAYPOWER", Path)
+ self:RegisterEvent("UNIT_POWER", Path)
+
+ Update(self, "UpdateVisibility", "player")
+end
+
+function Update(self, event, unit, powerType)
+ if powerType and powerType ~= "BURNING_EMBERS" then return end
+ local element = self.BurningEmbers
+ if element.__disabled then return end
+
+ if element.PreUpdate then
+ element:PreUpdate()
+ end
+
+ local embers = UnitPower("player", SPELL_POWER_BURNING_EMBERS, true)
+ local embersMax = UnitPowerMax("player", SPELL_POWER_BURNING_EMBERS, true)
+
+ local whole = floor(embers / MAX_POWER_PER_EMBER)
+ local wholeMax = floor(embersMax / MAX_POWER_PER_EMBER)
+ local parts = embers % MAX_POWER_PER_EMBER
+
+ if element.SetValue then
+ element:SetMinMaxValues(0, embersMax)
+ element:SetValue(embers)
+ else
+ local rest = embers
+ for i = 1, #element do
+ local ember = element[i]
+ ember.activated = false
+ if i > wholeMax then
+ --print(i, "Unused")
+ ember:Hide()
+ elseif rest >= MAX_POWER_PER_EMBER then
+ --print(i, "Full")
+ if ember.SetValue then
+ ember:SetMinMaxValues(0, MAX_POWER_PER_EMBER)
+ ember:SetValue(MAX_POWER_PER_EMBER)
+ else
+ ember:SetAlpha(1)
+ end
+ ember.activated = true
+ ember:Show()
+ rest = rest - MAX_POWER_PER_EMBER
+ elseif rest > 0 then
+ --print(i, "Partial", rest, parts)
+ if ember.SetValue then
+ ember:SetMinMaxValues(0, MAX_POWER_PER_EMBER)
+ ember:SetValue(rest)
+ else
+ ember:SetAlpha(1 - (0.75 * (rest / MAX_POWER_PER_EMBER)))
+ end
+ ember:Show()
+ rest = 0
+ else
+ --print(i, "Empty")
+ if ember.SetValue then
+ ember:SetMinMaxValues(0, MAX_POWER_PER_EMBER)
+ ember:SetValue(0)
+ else
+ ember:SetAlpha(0.25)
+ end
+ ember:Show()
+ end
+ end
+ end
+
+ if element.PostUpdate then
+ element:PostUpdate(embers, embersMax, SPELL_POWER_BURNING_EMBERS)
+ end
+end
+
+function Path(self, ...)
+ return (self.BurningEmbers.Override or Update)(self, ...)
+end
+
+function ForceUpdate(element)
+ return Path(element.__owner, "ForceUpdate", element.__owner.unit)
+end
+
+function Enable(self)
+ local element = self.BurningEmbers
+ if not element or self.unit ~= "player" then return end
+
+ element.__name = "BurningEmbers"
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ for i = 1, #element do
+ local ember = element[i]
+ if ember.GetStatusBarTexture and not ember:GetStatusBarTexture() then
+ ember:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
+ end
+ end
+
+ self:RegisterEvent("PLAYER_TALENT_UPDATE", UpdateVisibility, true)
+ self:RegisterEvent("UNIT_ENTERING_VEHICLE", UpdateVisibility)
+ self:RegisterEvent("UNIT_EXITED_VEHICLE", UpdateVisibility)
+
+ UpdateVisibility(self, "Enable")
+ return true
+end
+
+function Disable(self)
+ local element = self.BurningEmbers
+ if not element then return end
+
+ self:UnregisterEvent("UNIT_DISPLAYPOWER", Path)
+ self:UnregisterEvent("UNIT_POWER", Path)
+
+ self:UnregisterEvent("PLAYER_TALENT_UPDATE", UpdateVisibility)
+ self:UnregisterEvent("UNIT_ENTERING_VEHICLE", UpdateVisibility)
+ self:UnregisterEvent("UNIT_EXITED_VEHICLE", UpdateVisibility)
+
+ for i = 1, #element do
+ element[i]:Hide()
+ end
+ if element.Hide then
+ element:Hide()
+ end
+end
+
+oUF:AddElement("BurningEmbers", Path, Enable, Disable)
diff --git a/Elements/DemonicFury.lua b/Elements/DemonicFury.lua
new file mode 100644
index 0000000..ef8c32a
--- /dev/null
+++ b/Elements/DemonicFury.lua
@@ -0,0 +1,116 @@
+--[[--------------------------------------------------------------------
+ oUF_Phanx
+ Fully-featured PVE-oriented layout for oUF.
+ Copyright (c) 2008-2015 Phanx <addons@phanx.net>. All rights reserved.
+ http://www.wowinterface.com/downloads/info13993-oUF_Phanx.html
+ http://www.curse.com/addons/wow/ouf-phanx
+ https://github.com/Phanx/oUF_Phanx
+------------------------------------------------------------------------
+ Element to display demonic fury on oUF frames.
+
+ You may embed this module in your own layout, but please do not
+ distribute it as a standalone plugin.
+----------------------------------------------------------------------]]
+
+local _, ns = ...
+local oUF = ns.oUF or oUF
+assert(oUF, "DemonicFury element requires oUF")
+
+local METAMORPHOSIS_FORM = 22
+local SPEC_WARLOCK_DEMONOLOGY = SPEC_WARLOCK_DEMONOLOGY
+local SPELL_POWER_DEMONIC_FURY = SPELL_POWER_DEMONIC_FURY
+
+oUF.colors.power.DEMONIC_FURY = { 132/255, 41/255, 235/255 }
+oUF.colors.power.METAMORPHOSIS = { 132/255, 235/255, 41/255 }
+
+local UpdateVisibility, Update, Path, ForceUpdate, Enable, Disable
+
+function UpdateVisibility(self, event, unit)
+ local element = self.DemonicFury
+
+ if UnitHasVehicleUI("player") or GetSpecialization() ~= SPEC_WARLOCK_DEMONOLOGY then
+ self:UnregisterEvent("SHAPESHIFT_FORM_CHANGED", Path)
+ self:UnregisterEvent("UNIT_POWER", Path)
+ element:Hide()
+ return
+ end
+
+ element:Show()
+ self:RegisterEvent("SHAPESHIFT_FORM_CHANGED", Path, true)
+ self:RegisterEvent("UNIT_POWER", Path)
+
+ Update(self, "UpdateVisibility", "player")
+end
+
+function Update(self, event, unit, powerType)
+ if powerType and powerType ~= "DEMONIC_FURY" then return end
+ local element = self.DemonicFury
+ if not element:IsShown() then return end
+
+ if element.PreUpdate then
+ element:PreUpdate()
+ end
+
+ local fury = UnitPower("player", SPELL_POWER_DEMONIC_FURY)
+ local maxFury = UnitPowerMax("player", SPELL_POWER_DEMONIC_FURY)
+ local inMetamorphosis = GetShapeshiftFormID() == METAMORPHOSIS_FORM
+ local color = oUF.colors.power[inMetamorphosis and "METAMORPHOSIS" or "DEMONIC_FURY"]
+ local r, g, b = color[1], color[2], color[3]
+
+ element:SetMinMaxValues(0, maxFury)
+ element:SetValue(fury)
+ element:SetStatusBarColor(r, g, b)
+
+ local bg = element.bg
+ if bg then
+ local mu = bg.multiplier or 1
+ bg:SetVertexColor(r * mu, g * mu, b * mu)
+ end
+
+ if element.PostUpdate then
+ element:PostUpdate(fury, maxFury, inMetamorphosis)
+ end
+end
+
+function Path(self, ...)
+ return (self.DemonicFury.Override or Update)(self, ...)
+end
+
+function ForceUpdate(element)
+ return Path(element.__owner, "ForceUpdate", element.__owner.unit)
+end
+
+function Enable(self, unit)
+ local element = self.DemonicFury
+ if not element or self.unit ~= "player" then return end
+
+ element.__owner = self
+ element.ForceUpdate = ForceUpdate
+
+ if element.GetStatusBarTexture and not element:GetStatusBarTexture() then
+ element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
+ end
+
+ self:RegisterEvent("PLAYER_TALENT_UPDATE", UpdateVisibility, true)
+ self:RegisterEvent("UNIT_ENTERING_VEHICLE", UpdateVisibility)
+ self:RegisterEvent("UNIT_EXITED_VEHICLE", UpdateVisibility)
+
+ UpdateVisibility(self, "Enable", "player")
+ return true
+end
+
+function Disable(self)
+ local element = self.DemonicFury
+ if not element then return end
+
+ self:UnregisterEvent("SHAPESHIFT_FORM_CHANGED", Path)
+ self:UnregisterEvent("UNIT_POWER", Path)
+
+ self:UnregisterEvent("PLAYER_TALENT_UPDATE", UpdateVisibility)
+ self:UnregisterEvent("UNIT_ENTERING_VEHICLE", UpdateVisibility)
+ self:UnregisterEvent("UNIT_EXITED_VEHICLE", UpdateVisibility)
+
+ element:Hide()
+end
+
+oUF:AddElement("DemonicFury", Path, Enable, Disable)
diff --git a/Functions.lua b/Functions.lua
new file mode 100644
index 0000000..224e4f1
--- /dev/null
+++ b/Functions.lua
@@ -0,0 +1,212 @@
+--[[-----------------------------------------------------------------------
+ oUF: Stardust - a layout for the oUF framework
+ Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
+ This code is released under the zlib license; see LICENSE for details.
+-------------------------------------------------------------------------]]
+
+local _, Stardust = ...
+
+---------------------------
+-- Health
+---------------------------
+
+function Stardust.PostUpdateHealth(self, unit, cur, max)
+ self:SetValue(max - cur)
+ self.text:SetText(cur < max and -max + cur or "")
+ self.bg:SetVertexColor(0.15, 0.15, 0.15)
+end
+
+---------------------------
+-- Power
+-- DruidMana
+-- DemonicFury
+---------------------------
+
+function Stardust.PostUpdatePower(self, unit, cur, max)
+ self:SetShown(max > 0)
+ self.text:SetText(cur)
+end
+
+---------------------------
+-- ClassIcons
+---------------------------
+
+function Stardust.ResizeClassIcons(element)
+ local COUNT = element.__max
+ local SPACING = 3
+ local widthTotal = ((Stardust.config.width - SPACING - SPACING) * 0.6) - (COUNT * SPACING)
+ local widthEach = floor(widthTotal / COUNT + 0.5)
+ for i = 1, COUNT do
+ element[i]:SetWidth(widthEach)
+ end
+end
+
+function Stardust.PostUpdateClassIcons(element, cur, max, maxChanged, event)
+ if maxChanged then
+ Stardust.ResizeClassIcons(element)
+ end
+end
+
+---------------------------
+-- Combo points
+---------------------------
+
+function Stardust.PostUpdateCPoints(element, cur)
+ -- The number of combo points isn't dynamic, so they only need to be resized once per frame.
+ element.PreUpdate = nil
+ Stardust.ResizeClassIcons(element)
+end
+
+---------------------------
+-- Runes
+---------------------------
+
+function Stardust.PostUpdateRuneType(element, rune, index, alt)
+ local r, g, b = rune:GetStatusBarColor()
+ rune.bg:SetVertexColor(r * 0.35, g * 0.35, b * 0.35)
+end
+
+function Stardust.PostUpdateRune(element, rune, index, start, duration, ready)
+ -- The number of runes isn't dynamic, so they only need to be resized once per frame.
+ element.PostUpdateRune = nil
+ Stardust.ResizeClassIcons(element)
+end
+
+---------------------------
+-- Totems
+-- Partly adapted from oUF_Phanx
+---------------------------
+
+local function OnUpdateTotem(bar, elapsed)
+ local t = bar.duration - elapsed
+ if t > 0 then
+ bar.duration = t
+ bar:SetValue(t)
+ else
+ bar:SetValue(0)
+ end
+end
+
+function Stardust.PostUpdateTotem(element, index, _, name, start, duration)
+ local bar = element[index]
+ bar.duration, bar.max = duration, duration
+ if duration > 0 then
+ bar:SetMinMaxValues(0, duration)
+ bar:SetScript("OnUpdate", OnUpdateTotem)
+ else
+ bar:SetScript("OnUpdate", nil)
+ bar:SetValue(0)
+ end
+end
+
+function Stardust.PreUpdateTotems(element, index)
+ -- The number of totems isn't dynamic, so they only need to be resized once per frame.
+ element.PreUpdate = nil
+ Stardust.ResizeClassIcons(element)
+end
+
+---------------------------
+-- Status icons
+---------------------------
+
+function Stardust.PostUpdateStatusIcon(self)
+ if not self:IsShown() then return end
+ local icons, last = self.__owner.StatusIcons
+ for i = 1, #icons do
+ local icon = icons[i]
+ if icon == self then
+ break
+ elseif icon:IsShown() then
+ last = icon
+ end
+ end
+ if last then
+ self:SetPoint("LEFT", last, "RIGHT", 0, 0)
+ else
+ self:SetPoint("LEFT", self.__owner.Health, "TOPLEFT", 3, 0)
+ end
+end
+
+function Stardust.PostUpdateCombat(self)
+ self.__owner.Resting:ForceUpdate()
+end
+
+function Stardust.PostUpdateResting(self)
+ self.__owner.Combat:ForceUpdate()
+end
+
+---------------------------
+-- Glow
+---------------------------
+
+local GLOW_SEGMENTS = {
+ { "TOPLEFT", 0, 1/3, 0, 1/3, -1, 1 },
+ { "TOPRIGHT", 2/3, 1, 0, 1/3, 1, 1 },
+ { "BOTTOMRIGHT", 2/3, 1, 2/3, 1, 1, -1 },
+ { "BOTTOMLEFT", 0, 1/3, 2/3, 1, -1, -1 },
+ { "TOP", 1/3, 2/3, 0, 1/3, 0, 1 },
+ { "RIGHT", 2/3, 1, 1/3, 2/3, 1, 0 },
+ { "BOTTOM", 1/3, 2/3, 2/3, 1, 0, -1 },
+ { "LEFT", 0, 1/3, 1/3, 2/3, -1, 0 },
+}
+
+function Stardust.SetGlowColor(self, r, g, b, a)
+ for i = 1, #self.Glow do
+ self.Glow[i]:SetVertexColor(r, g, b, a)
+ end
+end
+
+function Stardust.SetGlowSize(self, size, offset)
+ local Glow = self.Glow
+ for i = 1, #Glow do
+ Glow[i]:SetSize(size, size)
+ end
+
+ local d = d or floor(size * 2 / 3 + 0.5)
+ Glow[1]:SetPoint("TOPLEFT", -d, d)
+ Glow[2]:SetPoint("TOPRIGHT", d, d)
+ Glow[3]:SetPoint("BOTTOMRIGHT", d, -d)
+ Glow[4]:SetPoint("BOTTOMLEFT", -d, -d)
+
+ Glow[5]:SetShown(Glow[2]:GetLeft() > Glow[1]:GetRight())
+ Glow[6]:SetShown(Glow[2]:GetBottom() > Glow[3]:GetTop())
+ Glow[7]:SetShown(Glow[3]:GetLeft() > Glow[4]:GetLeft())
+ Glow[8]:SetShown(Glow[1]:GetBottom() > Glow[4]:GetTop())
+end
+
+function Stardust.CreateGlow(self)
+ local Glow = {}
+ for i = 1, #GLOW_SEGMENTS do
+ local seg = GLOW_SEGMENTS[i]
+ local tex = self:CreateTexture(nil, "BACKGROUND")
+ tex:SetTexture("Interface\\AddOns\\oUF_Stardust\\textures\\glow")
+ tex:SetTexCoord(seg[2], seg[3], seg[4], seg[5])
+ tex:SetVertexColor(0, 0, 0)
+ Glow[i] = tex
+ end
+
+ -- TOP
+ Glow[5]:SetPoint("LEFT", Glow[1], "RIGHT")
+ Glow[5]:SetPoint("RIGHT", Glow[2], "LEFT")
+
+ -- RIGHT
+ Glow[6]:SetPoint("TOP", Glow[2], "BOTTOM")
+ Glow[6]:SetPoint("BOTTOM", Glow[3], "TOP")
+
+ -- BOTTOM
+ Glow[7]:SetPoint("LEFT", Glow[4], "RIGHT")
+ Glow[7]:SetPoint("RIGHT", Glow[3], "LEFT")
+
+ -- LEFT
+ Glow[8]:SetPoint("TOP", Glow[1], "BOTTOM")
+ Glow[8]:SetPoint("BOTTOM", Glow[4], "TOP")
+
+ SetGlowSize(self, 12)
+
+ self.Glow = Glow
+ self.SetBackdropBorderColor = SetGlowColor
+ self.SetGlowColor = SetGlowColor
+ self.SetGlowSize = SetGlowSize
+ return Glow
+end
+
diff --git a/Layout.lua b/Layout.lua
new file mode 100644
index 0000000..8de2d1a
--- /dev/null
+++ b/Layout.lua
@@ -0,0 +1,380 @@
+--[[-----------------------------------------------------------------------
+ oUF: Stardust - a layout for the oUF framework
+ Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
+ This code is released under the zlib license; see LICENSE for details.
+-------------------------------------------------------------------------]]
+
+local _, Stardust = ...
+local config = Stardust.config
+local colors = Stardust.colors
+
+local _, class = UnitClass("player")
+local LibSharedMedia = LibStub("LibSharedMedia-3.0")
+
+---------------------------
+-- Widget creation
+---------------------------
+
+local function NewStatusBar(parent, textFont, textSize, noBG, noBackdrop)
+ local TEXTURE = LibSharedMedia:Fetch("statusbar", config.barTexture)
+
+ local bar = CreateFrame("StatusBar", nil, parent)
+ bar:SetStatusBarTexture(TEXTURE)
+
+ if textFont and textSize then
+ bar.value = bar:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
+ bar.value:SetFont(LibSharedMedia:Fetch("font", textSize))
+ bar.value:SetPoint("CENTER")
+ end
+
+ if not noBG then
+ bar.bg = bar:CreateTexture(nil, "BORDER")
+ bar.bg:SetAllPoints()
+ bar.bg:SetTexture(TEXTURE)
+ bar.bg.multiplier = config.bgMultiplier
+ end
+
+ if not noBackdrop then
+ bar.backdrop = Health:CreateTexture(nil, "BACKDROP")
+ bar.backdrop:SetPoint("BOTTOMLEFT", -1, -1)
+ bar.backdrop:SetPoint("TOPRIGHT", 1, 1)
+ bar.backdrop:SetTexture(0, 0, 0)
+ end
+
+ return bar
+end
+
+local function NewBarGroup(parent, count, width, height)
+ local group = { __max = count }
+
+ local color = Stardust.colors.class[class]
+ local r, g, b = color[1], color[2], color[3]
+
+ for i = 1, count do
+ local bar = NewStatusBar(parent)
+ bar:SetSize(width, height)
+ bar:SetMinMaxValues(0, 1)
+ bar:SetValue(1)
+
+ if not noColor then
+ local mu = bar.bg.multiplier
+ bar:SetStatusBarColor(r, g, b)
+ bar.bg:SetVertexColor(r * mu, g * mu, b * mu)
+ end
+
+ -- ClassIcons expects texture objects
+ bar.SetVertexColor = bar.SetStatusBarColor
+
+ if i > 1 then
+ bar:SetPoint("LEFT", group[i-1], "RIGHT", 3, 0)
+ end
+
+ group[i] = bar
+ end
+
+ return group
+end
+
+local function AddStatusIcon(self, element, size)
+ local icon = self.Health:CreateTexture(nil, "OVERLAY")
+ icon:SetPoint("LEFT", self.Health, "TOPLEFT", 3, 0)
+ icon:SetSize(size or 16, size or 16)
+
+ self.StatusIcons = self.StatusIcons or {}
+ tinsert(self.StatusIcons, icon)
+
+ icon.PostUpdate = Stardust.PostUpdateStatusIcon
+ self[element] = icon
+ return icon
+end
+
+---------------------------
+-- Frame setup
+---------------------------
+
+local function ApplyStyle(self, unit, isSingle)
+ unit = unit:gsub("%d+", "")
+
+ local uconfig = config.units[unit]
+
+ ---------------------------
+ -- Frame
+ ---------------------------
+
+ self:SetScript("OnEnter", UnitFrame_OnEnter)
+ self:SetScript("OnLeave", UnitFrame_OnLeave)
+
+ self:RegisterForClicks("AnyUp")
+
+ if (isSingle) then
+ self:SetSize(config.width * (uconfig and uconfig.width or 1), config.height * (uconfig and uconfig.height or 1))
+ end
+
+ ---------------------------
+ -- Outer glow
+ ---------------------------
+
+ self.Glow = CreateGlow(self)
+
+ ---------------------------
+ -- Health bar
+ ---------------------------
+
+ local Health = NewStatusBar(self, config.numberFont, 25)
+ Health:SetPoint("BOTTOMLEFT")
+ Health:SetPoint("TOPRIGHT")
+ Health:SetReverseFill(true)
+
+ Health.value:ClearAllPoints()
+ Health.value:SetPoint("RIGHT", Health, "TOPRIGHT", 0, 3)
+
+ Health.colorClass = true
+ Health.colorDisconnected = true
+ Health.colorReaction = true
+ Health.colorTapping = true
+ Health.frequentUpdates = true
+ Health.PostUpdate = Stardust.PostUpdateHealth
+ self.Health = Health
+
+ ---------------------------
+ -- Power bar
+ ---------------------------
+
+ local Power = NewStatusBar(Health, config.numberFont, 15)
+ Power:SetPoint("BOTTOMLEFT", 3, 3)
+ Power:SetPoint("BOTTOMRIGHT", -3, 3)
+ Power:SetHeight(config.powerHeight)
+
+ Power.colorDisconnected = true
+ Power.colorPower = true
+ Power.PostUpdate = Stardust.PostUpdatePower
+ self.Power = Power
+
+ ---------------------------
+ -- Secondary resources
+ ---------------------------
+
+ if class == "PALADIN" or class == "PRIEST" or class == "WARLOCK" then
+ local ClassIcons = NewBarGroup(self.Health, 6, 30, config.powerHeight)
+ ClassIcons[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
+ ClassIcons.PostUpdate = Stardust.PostUpdateClassIcons
+ self.ClassIcons = ClassIcons
+ end
+
+ if class == "DRUID" or class == "ROGUE" then
+ local CPoints = NewBarGroup(self.Health, 5, 30, config.powerHeight)
+ CPoints[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
+ CPoints.PostUpdate = Stardust.PostUpdateCPoints
+ self.CPoints = CPoints
+ end
+
+ if class == "DEATHKNIGHT" then
+ local Runes = NewBarGroup(self.Health, 6, 30, config.powerHeight)
+ Runes[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
+ Runes.PostUpdateRune = Stardust.PostUpdateRune
+ Runes.PostUpdateRuneType = Stardust.PostUpdateRuneType
+ self.Runes = Runes
+ end
+
+ if class == "DRUID" or class == "SHAMAN" then
+ -- TODO: This can also show death knight ghouls.
+ -- How do these work? Are they important?
+ -- How to show them at the same time as runes?
+ local Totems = NewBarGroup(self.Health, 4, 30, config.powerHeight)
+ Totems[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
+ if class == "SHAMAN" then
+ local mu = config.bgMultiplier
+ for i = 1, 4 do
+ local totem = Totems[i]
+ totem:EnableMouse(true)
+
+ local color = Stardust.colors.totems[i]
+ local r, g, b = color[1], color[2], color[3]
+ totem:SetStatusBarColor(r, g, b)
+ totem.bg:SetVertexColor(r * mu, b * mu, g * mu)
+
+ local value = totem:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
+ value:SetFont(LibSharedMedia:Fetch("font", config.numberFont), 15)
+ value:SetPoint("CENTER")
+ end
+ end
+ Totems.PreUpdate = Stardust.PreUpdateTotems
+ self.Totems = Totems
+ end
+
+ -- TODO: burning embers
+
+ ---------------------------
+ -- Druid mana
+ -- Warlock demonic fury
+ ---------------------------
+
+ if class == "DRUID" or class == "WARLOCK" then
+ local bar = NewStatusBar(Health)
+ bar:SetPoint("TOPLEFT", 3, -3)
+ bar:SetPoint("TOPRIGHT", -3, -3)
+ bar:SetHeight(config.powerHeight)
+ if class == "DRUID" then
+ bar:SetPoint("TOPLEFT", self.Totems[4], 3, 0)
+ bar.colorPower = true
+ bar.PostUpdate = PostUpdatePower
+ self.DruidMana = bar
+ else
+ bar.colorPower = true
+ bar.PostUpdate = PostUpdatePower
+ self.DemonicFury = bar
+ end
+ end
+
+ ---------------------------
+ -- TODO
+ ---------------------------
+
+ -- AltPowerBar
+ -- EclipseBar
+ -- HealPrediction
+ -- Stagger
+
+ -- Castbar
+
+ -- Auras
+
+ ---------------------------
+ -- Name text
+ ---------------------------
+
+ local Name = self:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+ Name:SetPoint("BOTTOMLEFT", Power, "TOPLEFT", 0, 3)
+ Name:SetFont(LibSharedMedia:Fetch("font", config.valueFont), 14)
+ self:Tag(Name, "[unitcolor][name]")
+ self.Name = Name
+
+ ---------------------------
+ -- Group status icons
+ ---------------------------
+
+ AddStatusIcon("LFDRole")
+ AddStatusIcon("RaidRole") -- maintank, mainassist
+ AddStatusIcon("Leader")
+ AddStatusIcon("Assistant")
+ AddStatusIcon("MasterLooter")
+ AddStatusIcon("PvP")
+
+ ---------------------------
+ -- Combat icon
+ ---------------------------
+
+ if unit == "player" then
+ local Combat = self.Health:CreateTexture(nil, "OVERLAY")
+ Combat:SetSize(16, 16)
+ Combat:SetPoint("RIGHT", self.Health, "TOPRIGHT", -3, 0)
+ Combat.PostUpdate = Stardust.PostUpdateCombat
+ self.Combat = Combat
+
+ local Resting = self.Health:CreateTexture(nil, "OVERLAY")
+ Resting:SetSize(16, 16)
+ Resting:SetPoint("RIGHT", self.Health, "TOPRIGHT", -3, 0)
+ Resting.PostUpdate = Stardust.PostUpdateResting
+ self.Resting = Resting
+ end
+
+ ---------------------------
+ -- Phasing icon
+ ---------------------------
+
+ if not unit:match(".+target$") and not unit:match(".+pet") then
+ local PhaseIcon = self.Health:CreateTexture(nil, "OVERLAY")
+ PhaseIcon:SetPoint("TOP")
+ PhaseIcon:SetPoint("BOTTOM")
+ PhaseIcon:SetWidth(config.height * 2.5)
+ PhaseIcon:SetTexture("Interface\\Icons\\Spell_Frost_Stun")
+ PhaseIcon:SetTexCoord(0.05, 0.95, 0.5 - 0.25 * 0.9, 0.5 + 0.25 * 0.9)
+ PhaseIcon:SetAlpha(0.5)
+ PhaseIcon:SetBlendMode("ADD")
+ PhaseIcon:SetDesaturated(true)
+ PhaseIcon:SetVertexColor(0.4, 0.8, 1)
+ self.PhaseIcon = PhaseIcon
+ end
+
+ ---------------------------
+ -- Quest mob icon
+ ---------------------------
+
+ if unit == "target" then
+ local QuestIcon = self.Health:CreateTexture(nil, "OVERLAY")
+ QuestIcon:SetSize(16, 16)
+ QuestIcon:SetPoint("RIGHT", self.Health, "TOPRIGHT", -3, 0)
+ self.QuestIcon = QuestIcon
+ end
+
+ ---------------------------
+ -- Raid target icon
+ ---------------------------
+
+ if unit == "player" or unit == "target" or unit == "party" then
+ local RaidIcon = self.Health:CreateTexture(nil, "OVERLAY")
+ RaidIcon:SetSize(24, 24)
+ RaidIcon:SetPoint("CENTER", 0, 3) -- TODO
+ self.RaidIcon = RaidIcon
+ end
+
+ ---------------------------
+ -- Ready Check icon
+ ---------------------------
+
+ if unit == "player" or unit == "target" or unit == "party" then
+ local ReadyCheck = self.Health:CreateTexture(nil, "OVERLAY")
+ ReadyCheck:SetSize(24, 24)
+ ReadyCheck:SetPoint("CENTER", 0, 3) -- TODO
+ self.ReadyCheck = ReadyCheck
+ end
+
+ ---------------------------
+ -- Resurrection icon
+ ---------------------------
+
+ if not unit:match(".+target$") and not unit:match("pet") then
+ local ResurrectIcon = self.Health:CreateTexture(nil, "OVERLAY")
+ ResurrectIcon:SetSize(24, 24)
+ ResurrectIcon:SetPoint("CENTER", 0, 3) -- TODO
+ self.ResurrectIcon = ResurrectIcon
+ end
+
+ ---------------------------
+ -- Threat level icon
+ ---------------------------
+
+ if unit == "target" or unit == "focus" then
+ local Threat = self.Health:CreateTexture(nil, "OVERLAY")
+ Threat:SetSize(16, 16)
+ Threat:SetPoint("CENTER", 0, 3) -- TODO
+ self.Threat = Threat
+ end
+
+ ---------------------------
+ -- Range
+ ---------------------------
+
+ self.Range = {
+ insideAlpha = 1,
+ outsideAlpha = 0.5
+ }
+end
+
+oUF:Factory(function(self)
+ self:RegisterStyle("Stardust", ApplyStyle)
+ self:SetActiveStyle("Stardust")
+
+ local player = self:Spawn("player")
+ player:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOM", -175, 235)
+
+ local pet = self:Spawn("pet")
+ pet:SetPoint("TOPRIGHT", player, "BOTTOMRIGHT", 0, -6)
+
+ local target = self:Spawn("target")
+ target:SetPoint("BOTTOMLEFT", UIParent, "BOTTOM", 175, 235)
+
+ local targettarget = self:Spawn("targettarget")
+ targettarget:SetPoint("TOPLEFT", target, "BOTTOMLEFT", 0, -6)
+end)
+
diff --git a/Tags.lua b/Tags.lua
new file mode 100644
index 0000000..329b254
--- /dev/null
+++ b/Tags.lua
@@ -0,0 +1,51 @@
+--[[-----------------------------------------------------------------------
+ oUF: Stardust - a layout for the oUF framework
+ Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
+ This code is released under the zlib license; see LICENSE for details.
+-------------------------------------------------------------------------]]
+
+local _, Stardust = ...
+
+oUF.Tags.Events["unitcolor"] = "UNIT_HEALTH UNIT_CLASSIFICATION_CHANGED UNIT_CONNECTION UNIT_FACTION UNIT_REACTION"
+oUF.Tags.Methods["unitcolor"] = function(unit)
+ local color
+ if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
+ color = oUF.colors.disconnected
+ elseif UnitIsPlayer(unit) then
+ local _, class = UnitClass(unit)
+ color = oUF.colors.class[class]
+ elseif UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) and not UnitIsTappedByAllThreatList(unit) then
+ color = oUF.colors.tapped
+ elseif UnitIsEnemy(unit, "player") then
+ color = oUF.colors.reaction[1]
+ else
+ color = oUF.colors.reaction[UnitReaction(unit, "player") or 5]
+ end
+ return color and ("|cff%02x%02x%02x"):format(color[1] * 255, color[2] * 255, color[3] * 255) or "|cffffffff"
+end
+
+oUF.Tags.Events["powercolor"] = "UNIT_DISPLAYPOWER"
+oUF.Tags.Methods["powercolor"] = function(unit)
+ local _, type = UnitPowerType(unit)
+ local color = ns.colors.power[type] or ns.colors.power.FUEL
+ return format("|cff%02x%02x%02x", color[1] * 255, color[2] * 255, color[3] * 255)
+end
+
+local threatcolors = {
+ [0] = "|cffffffff",
+ [1] = "|cffffff33",
+ [2] = "|cffff9933",
+ [3] = "|cffff3333",
+}
+oUF.Tags.Events["threatpct"] = "UNIT_THREAT_LIST_UPDATE"
+oUF.Tags.Methods["threatpct"] = function(unit)
+ local isTanking, status, percentage, rawPercentage = UnitDetailedThreatSituation("player", unit)
+ local pct = rawPercentage
+ if isTanking then
+ pct = UnitThreatPercentageOfLead("player", unit)
+ end
+ if pct and pct > 0 and pct < 200 then
+ return format("%s%d%%", threatcolors[status] or threatcolors[0], pct + 0.5)
+ end
+end
+
diff --git a/config.lua b/config.lua
deleted file mode 100644
index dd368dd..0000000
--- a/config.lua
+++ /dev/null
@@ -1,58 +0,0 @@
---[[-----------------------------------------------------------------------
- oUF: Stardust - a layout for the oUF framework
- Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
- This code is released under the zlib license; see LICENSE for details.
--------------------------------------------------------------------------]]
-
-local _, Stardust = ...
-
-Stardust.config = {
- -- Style
- barTexture = "Qulight",
- bgMultiplier = 0.35,
- numberFont = "Blizzard Bold",
- textFont = "Blizzard",
-
- -- Layout
- width = 220,
- height = 32,
- power = true,
- powerHeight = 5,
-
- -- Unit Specific
- units = {
- pet = {
- width = 0.5
- },
- targettarget = {
- width = 0.5,
- power = false
- },
- focustarget = {
- width = 0.5,
- power = false
- },
- party = {
- width = 0.5
- },
- partypet = {
- width = 0.25,
- power = false
- }
- }
-}
-
-Stardust.colors = {
- power = {
- MANA = { 0, 0.8, 1 }
- },
- totems = {
- [1] = { 0.6, 1, 0.2 }, -- Earth
- [2] = { 1, 0.6, 0.2 }, -- Fire
- [3] = { 0.2, 0.8, 1 }, -- Water
- [4] = { 0.8, 0.4, 1 }, -- Air
- }
-}
-
-setmetatable(Stardust.colors, oUF.colors)
-setmetatable(Stardust.colors.power, oUF.colors.power)
diff --git a/functions.lua b/functions.lua
deleted file mode 100644
index 224e4f1..0000000
--- a/functions.lua
+++ /dev/null
@@ -1,212 +0,0 @@
---[[-----------------------------------------------------------------------
- oUF: Stardust - a layout for the oUF framework
- Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
- This code is released under the zlib license; see LICENSE for details.
--------------------------------------------------------------------------]]
-
-local _, Stardust = ...
-
----------------------------
--- Health
----------------------------
-
-function Stardust.PostUpdateHealth(self, unit, cur, max)
- self:SetValue(max - cur)
- self.text:SetText(cur < max and -max + cur or "")
- self.bg:SetVertexColor(0.15, 0.15, 0.15)
-end
-
----------------------------
--- Power
--- DruidMana
--- DemonicFury
----------------------------
-
-function Stardust.PostUpdatePower(self, unit, cur, max)
- self:SetShown(max > 0)
- self.text:SetText(cur)
-end
-
----------------------------
--- ClassIcons
----------------------------
-
-function Stardust.ResizeClassIcons(element)
- local COUNT = element.__max
- local SPACING = 3
- local widthTotal = ((Stardust.config.width - SPACING - SPACING) * 0.6) - (COUNT * SPACING)
- local widthEach = floor(widthTotal / COUNT + 0.5)
- for i = 1, COUNT do
- element[i]:SetWidth(widthEach)
- end
-end
-
-function Stardust.PostUpdateClassIcons(element, cur, max, maxChanged, event)
- if maxChanged then
- Stardust.ResizeClassIcons(element)
- end
-end
-
----------------------------
--- Combo points
----------------------------
-
-function Stardust.PostUpdateCPoints(element, cur)
- -- The number of combo points isn't dynamic, so they only need to be resized once per frame.
- element.PreUpdate = nil
- Stardust.ResizeClassIcons(element)
-end
-
----------------------------
--- Runes
----------------------------
-
-function Stardust.PostUpdateRuneType(element, rune, index, alt)
- local r, g, b = rune:GetStatusBarColor()
- rune.bg:SetVertexColor(r * 0.35, g * 0.35, b * 0.35)
-end
-
-function Stardust.PostUpdateRune(element, rune, index, start, duration, ready)
- -- The number of runes isn't dynamic, so they only need to be resized once per frame.
- element.PostUpdateRune = nil
- Stardust.ResizeClassIcons(element)
-end
-
----------------------------
--- Totems
--- Partly adapted from oUF_Phanx
----------------------------
-
-local function OnUpdateTotem(bar, elapsed)
- local t = bar.duration - elapsed
- if t > 0 then
- bar.duration = t
- bar:SetValue(t)
- else
- bar:SetValue(0)
- end
-end
-
-function Stardust.PostUpdateTotem(element, index, _, name, start, duration)
- local bar = element[index]
- bar.duration, bar.max = duration, duration
- if duration > 0 then
- bar:SetMinMaxValues(0, duration)
- bar:SetScript("OnUpdate", OnUpdateTotem)
- else
- bar:SetScript("OnUpdate", nil)
- bar:SetValue(0)
- end
-end
-
-function Stardust.PreUpdateTotems(element, index)
- -- The number of totems isn't dynamic, so they only need to be resized once per frame.
- element.PreUpdate = nil
- Stardust.ResizeClassIcons(element)
-end
-
----------------------------
--- Status icons
----------------------------
-
-function Stardust.PostUpdateStatusIcon(self)
- if not self:IsShown() then return end
- local icons, last = self.__owner.StatusIcons
- for i = 1, #icons do
- local icon = icons[i]
- if icon == self then
- break
- elseif icon:IsShown() then
- last = icon
- end
- end
- if last then
- self:SetPoint("LEFT", last, "RIGHT", 0, 0)
- else
- self:SetPoint("LEFT", self.__owner.Health, "TOPLEFT", 3, 0)
- end
-end
-
-function Stardust.PostUpdateCombat(self)
- self.__owner.Resting:ForceUpdate()
-end
-
-function Stardust.PostUpdateResting(self)
- self.__owner.Combat:ForceUpdate()
-end
-
----------------------------
--- Glow
----------------------------
-
-local GLOW_SEGMENTS = {
- { "TOPLEFT", 0, 1/3, 0, 1/3, -1, 1 },
- { "TOPRIGHT", 2/3, 1, 0, 1/3, 1, 1 },
- { "BOTTOMRIGHT", 2/3, 1, 2/3, 1, 1, -1 },
- { "BOTTOMLEFT", 0, 1/3, 2/3, 1, -1, -1 },
- { "TOP", 1/3, 2/3, 0, 1/3, 0, 1 },
- { "RIGHT", 2/3, 1, 1/3, 2/3, 1, 0 },
- { "BOTTOM", 1/3, 2/3, 2/3, 1, 0, -1 },
- { "LEFT", 0, 1/3, 1/3, 2/3, -1, 0 },
-}
-
-function Stardust.SetGlowColor(self, r, g, b, a)
- for i = 1, #self.Glow do
- self.Glow[i]:SetVertexColor(r, g, b, a)
- end
-end
-
-function Stardust.SetGlowSize(self, size, offset)
- local Glow = self.Glow
- for i = 1, #Glow do
- Glow[i]:SetSize(size, size)
- end
-
- local d = d or floor(size * 2 / 3 + 0.5)
- Glow[1]:SetPoint("TOPLEFT", -d, d)
- Glow[2]:SetPoint("TOPRIGHT", d, d)
- Glow[3]:SetPoint("BOTTOMRIGHT", d, -d)
- Glow[4]:SetPoint("BOTTOMLEFT", -d, -d)
-
- Glow[5]:SetShown(Glow[2]:GetLeft() > Glow[1]:GetRight())
- Glow[6]:SetShown(Glow[2]:GetBottom() > Glow[3]:GetTop())
- Glow[7]:SetShown(Glow[3]:GetLeft() > Glow[4]:GetLeft())
- Glow[8]:SetShown(Glow[1]:GetBottom() > Glow[4]:GetTop())
-end
-
-function Stardust.CreateGlow(self)
- local Glow = {}
- for i = 1, #GLOW_SEGMENTS do
- local seg = GLOW_SEGMENTS[i]
- local tex = self:CreateTexture(nil, "BACKGROUND")
- tex:SetTexture("Interface\\AddOns\\oUF_Stardust\\textures\\glow")
- tex:SetTexCoord(seg[2], seg[3], seg[4], seg[5])
- tex:SetVertexColor(0, 0, 0)
- Glow[i] = tex
- end
-
- -- TOP
- Glow[5]:SetPoint("LEFT", Glow[1], "RIGHT")
- Glow[5]:SetPoint("RIGHT", Glow[2], "LEFT")
-
- -- RIGHT
- Glow[6]:SetPoint("TOP", Glow[2], "BOTTOM")
- Glow[6]:SetPoint("BOTTOM", Glow[3], "TOP")
-
- -- BOTTOM
- Glow[7]:SetPoint("LEFT", Glow[4], "RIGHT")
- Glow[7]:SetPoint("RIGHT", Glow[3], "LEFT")
-
- -- LEFT
- Glow[8]:SetPoint("TOP", Glow[1], "BOTTOM")
- Glow[8]:SetPoint("BOTTOM", Glow[4], "TOP")
-
- SetGlowSize(self, 12)
-
- self.Glow = Glow
- self.SetBackdropBorderColor = SetGlowColor
- self.SetGlowColor = SetGlowColor
- self.SetGlowSize = SetGlowSize
- return Glow
-end
-
diff --git a/includes/DemonicFury.lua b/includes/DemonicFury.lua
deleted file mode 100644
index ef8c32a..0000000
--- a/includes/DemonicFury.lua
+++ /dev/null
@@ -1,116 +0,0 @@
---[[--------------------------------------------------------------------
- oUF_Phanx
- Fully-featured PVE-oriented layout for oUF.
- Copyright (c) 2008-2015 Phanx <addons@phanx.net>. All rights reserved.
- http://www.wowinterface.com/downloads/info13993-oUF_Phanx.html
- http://www.curse.com/addons/wow/ouf-phanx
- https://github.com/Phanx/oUF_Phanx
-------------------------------------------------------------------------
- Element to display demonic fury on oUF frames.
-
- You may embed this module in your own layout, but please do not
- distribute it as a standalone plugin.
-----------------------------------------------------------------------]]
-
-local _, ns = ...
-local oUF = ns.oUF or oUF
-assert(oUF, "DemonicFury element requires oUF")
-
-local METAMORPHOSIS_FORM = 22
-local SPEC_WARLOCK_DEMONOLOGY = SPEC_WARLOCK_DEMONOLOGY
-local SPELL_POWER_DEMONIC_FURY = SPELL_POWER_DEMONIC_FURY
-
-oUF.colors.power.DEMONIC_FURY = { 132/255, 41/255, 235/255 }
-oUF.colors.power.METAMORPHOSIS = { 132/255, 235/255, 41/255 }
-
-local UpdateVisibility, Update, Path, ForceUpdate, Enable, Disable
-
-function UpdateVisibility(self, event, unit)
- local element = self.DemonicFury
-
- if UnitHasVehicleUI("player") or GetSpecialization() ~= SPEC_WARLOCK_DEMONOLOGY then
- self:UnregisterEvent("SHAPESHIFT_FORM_CHANGED", Path)
- self:UnregisterEvent("UNIT_POWER", Path)
- element:Hide()
- return
- end
-
- element:Show()
- self:RegisterEvent("SHAPESHIFT_FORM_CHANGED", Path, true)
- self:RegisterEvent("UNIT_POWER", Path)
-
- Update(self, "UpdateVisibility", "player")
-end
-
-function Update(self, event, unit, powerType)
- if powerType and powerType ~= "DEMONIC_FURY" then return end
- local element = self.DemonicFury
- if not element:IsShown() then return end
-
- if element.PreUpdate then
- element:PreUpdate()
- end
-
- local fury = UnitPower("player", SPELL_POWER_DEMONIC_FURY)
- local maxFury = UnitPowerMax("player", SPELL_POWER_DEMONIC_FURY)
- local inMetamorphosis = GetShapeshiftFormID() == METAMORPHOSIS_FORM
- local color = oUF.colors.power[inMetamorphosis and "METAMORPHOSIS" or "DEMONIC_FURY"]
- local r, g, b = color[1], color[2], color[3]
-
- element:SetMinMaxValues(0, maxFury)
- element:SetValue(fury)
- element:SetStatusBarColor(r, g, b)
-
- local bg = element.bg
- if bg then
- local mu = bg.multiplier or 1
- bg:SetVertexColor(r * mu, g * mu, b * mu)
- end
-
- if element.PostUpdate then
- element:PostUpdate(fury, maxFury, inMetamorphosis)
- end
-end
-
-function Path(self, ...)
- return (self.DemonicFury.Override or Update)(self, ...)
-end
-
-function ForceUpdate(element)
- return Path(element.__owner, "ForceUpdate", element.__owner.unit)
-end
-
-function Enable(self, unit)
- local element = self.DemonicFury
- if not element or self.unit ~= "player" then return end
-
- element.__owner = self
- element.ForceUpdate = ForceUpdate
-
- if element.GetStatusBarTexture and not element:GetStatusBarTexture() then
- element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
- end
-
- self:RegisterEvent("PLAYER_TALENT_UPDATE", UpdateVisibility, true)
- self:RegisterEvent("UNIT_ENTERING_VEHICLE", UpdateVisibility)
- self:RegisterEvent("UNIT_EXITED_VEHICLE", UpdateVisibility)
-
- UpdateVisibility(self, "Enable", "player")
- return true
-end
-
-function Disable(self)
- local element = self.DemonicFury
- if not element then return end
-
- self:UnregisterEvent("SHAPESHIFT_FORM_CHANGED", Path)
- self:UnregisterEvent("UNIT_POWER", Path)
-
- self:UnregisterEvent("PLAYER_TALENT_UPDATE", UpdateVisibility)
- self:UnregisterEvent("UNIT_ENTERING_VEHICLE", UpdateVisibility)
- self:UnregisterEvent("UNIT_EXITED_VEHICLE", UpdateVisibility)
-
- element:Hide()
-end
-
-oUF:AddElement("DemonicFury", Path, Enable, Disable)
diff --git a/layout.lua b/layout.lua
deleted file mode 100644
index 8de2d1a..0000000
--- a/layout.lua
+++ /dev/null
@@ -1,380 +0,0 @@
---[[-----------------------------------------------------------------------
- oUF: Stardust - a layout for the oUF framework
- Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
- This code is released under the zlib license; see LICENSE for details.
--------------------------------------------------------------------------]]
-
-local _, Stardust = ...
-local config = Stardust.config
-local colors = Stardust.colors
-
-local _, class = UnitClass("player")
-local LibSharedMedia = LibStub("LibSharedMedia-3.0")
-
----------------------------
--- Widget creation
----------------------------
-
-local function NewStatusBar(parent, textFont, textSize, noBG, noBackdrop)
- local TEXTURE = LibSharedMedia:Fetch("statusbar", config.barTexture)
-
- local bar = CreateFrame("StatusBar", nil, parent)
- bar:SetStatusBarTexture(TEXTURE)
-
- if textFont and textSize then
- bar.value = bar:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
- bar.value:SetFont(LibSharedMedia:Fetch("font", textSize))
- bar.value:SetPoint("CENTER")
- end
-
- if not noBG then
- bar.bg = bar:CreateTexture(nil, "BORDER")
- bar.bg:SetAllPoints()
- bar.bg:SetTexture(TEXTURE)
- bar.bg.multiplier = config.bgMultiplier
- end
-
- if not noBackdrop then
- bar.backdrop = Health:CreateTexture(nil, "BACKDROP")
- bar.backdrop:SetPoint("BOTTOMLEFT", -1, -1)
- bar.backdrop:SetPoint("TOPRIGHT", 1, 1)
- bar.backdrop:SetTexture(0, 0, 0)
- end
-
- return bar
-end
-
-local function NewBarGroup(parent, count, width, height)
- local group = { __max = count }
-
- local color = Stardust.colors.class[class]
- local r, g, b = color[1], color[2], color[3]
-
- for i = 1, count do
- local bar = NewStatusBar(parent)
- bar:SetSize(width, height)
- bar:SetMinMaxValues(0, 1)
- bar:SetValue(1)
-
- if not noColor then
- local mu = bar.bg.multiplier
- bar:SetStatusBarColor(r, g, b)
- bar.bg:SetVertexColor(r * mu, g * mu, b * mu)
- end
-
- -- ClassIcons expects texture objects
- bar.SetVertexColor = bar.SetStatusBarColor
-
- if i > 1 then
- bar:SetPoint("LEFT", group[i-1], "RIGHT", 3, 0)
- end
-
- group[i] = bar
- end
-
- return group
-end
-
-local function AddStatusIcon(self, element, size)
- local icon = self.Health:CreateTexture(nil, "OVERLAY")
- icon:SetPoint("LEFT", self.Health, "TOPLEFT", 3, 0)
- icon:SetSize(size or 16, size or 16)
-
- self.StatusIcons = self.StatusIcons or {}
- tinsert(self.StatusIcons, icon)
-
- icon.PostUpdate = Stardust.PostUpdateStatusIcon
- self[element] = icon
- return icon
-end
-
----------------------------
--- Frame setup
----------------------------
-
-local function ApplyStyle(self, unit, isSingle)
- unit = unit:gsub("%d+", "")
-
- local uconfig = config.units[unit]
-
- ---------------------------
- -- Frame
- ---------------------------
-
- self:SetScript("OnEnter", UnitFrame_OnEnter)
- self:SetScript("OnLeave", UnitFrame_OnLeave)
-
- self:RegisterForClicks("AnyUp")
-
- if (isSingle) then
- self:SetSize(config.width * (uconfig and uconfig.width or 1), config.height * (uconfig and uconfig.height or 1))
- end
-
- ---------------------------
- -- Outer glow
- ---------------------------
-
- self.Glow = CreateGlow(self)
-
- ---------------------------
- -- Health bar
- ---------------------------
-
- local Health = NewStatusBar(self, config.numberFont, 25)
- Health:SetPoint("BOTTOMLEFT")
- Health:SetPoint("TOPRIGHT")
- Health:SetReverseFill(true)
-
- Health.value:ClearAllPoints()
- Health.value:SetPoint("RIGHT", Health, "TOPRIGHT", 0, 3)
-
- Health.colorClass = true
- Health.colorDisconnected = true
- Health.colorReaction = true
- Health.colorTapping = true
- Health.frequentUpdates = true
- Health.PostUpdate = Stardust.PostUpdateHealth
- self.Health = Health
-
- ---------------------------
- -- Power bar
- ---------------------------
-
- local Power = NewStatusBar(Health, config.numberFont, 15)
- Power:SetPoint("BOTTOMLEFT", 3, 3)
- Power:SetPoint("BOTTOMRIGHT", -3, 3)
- Power:SetHeight(config.powerHeight)
-
- Power.colorDisconnected = true
- Power.colorPower = true
- Power.PostUpdate = Stardust.PostUpdatePower
- self.Power = Power
-
- ---------------------------
- -- Secondary resources
- ---------------------------
-
- if class == "PALADIN" or class == "PRIEST" or class == "WARLOCK" then
- local ClassIcons = NewBarGroup(self.Health, 6, 30, config.powerHeight)
- ClassIcons[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
- ClassIcons.PostUpdate = Stardust.PostUpdateClassIcons
- self.ClassIcons = ClassIcons
- end
-
- if class == "DRUID" or class == "ROGUE" then
- local CPoints = NewBarGroup(self.Health, 5, 30, config.powerHeight)
- CPoints[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
- CPoints.PostUpdate = Stardust.PostUpdateCPoints
- self.CPoints = CPoints
- end
-
- if class == "DEATHKNIGHT" then
- local Runes = NewBarGroup(self.Health, 6, 30, config.powerHeight)
- Runes[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
- Runes.PostUpdateRune = Stardust.PostUpdateRune
- Runes.PostUpdateRuneType = Stardust.PostUpdateRuneType
- self.Runes = Runes
- end
-
- if class == "DRUID" or class == "SHAMAN" then
- -- TODO: This can also show death knight ghouls.
- -- How do these work? Are they important?
- -- How to show them at the same time as runes?
- local Totems = NewBarGroup(self.Health, 4, 30, config.powerHeight)
- Totems[1]:SetPoint("TOPLEFT", self.Health, 3, -3)
- if class == "SHAMAN" then
- local mu = config.bgMultiplier
- for i = 1, 4 do
- local totem = Totems[i]
- totem:EnableMouse(true)
-
- local color = Stardust.colors.totems[i]
- local r, g, b = color[1], color[2], color[3]
- totem:SetStatusBarColor(r, g, b)
- totem.bg:SetVertexColor(r * mu, b * mu, g * mu)
-
- local value = totem:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
- value:SetFont(LibSharedMedia:Fetch("font", config.numberFont), 15)
- value:SetPoint("CENTER")
- end
- end
- Totems.PreUpdate = Stardust.PreUpdateTotems
- self.Totems = Totems
- end
-
- -- TODO: burning embers
-
- ---------------------------
- -- Druid mana
- -- Warlock demonic fury
- ---------------------------
-
- if class == "DRUID" or class == "WARLOCK" then
- local bar = NewStatusBar(Health)
- bar:SetPoint("TOPLEFT", 3, -3)
- bar:SetPoint("TOPRIGHT", -3, -3)
- bar:SetHeight(config.powerHeight)
- if class == "DRUID" then
- bar:SetPoint("TOPLEFT", self.Totems[4], 3, 0)
- bar.colorPower = true
- bar.PostUpdate = PostUpdatePower
- self.DruidMana = bar
- else
- bar.colorPower = true
- bar.PostUpdate = PostUpdatePower
- self.DemonicFury = bar
- end
- end
-
- ---------------------------
- -- TODO
- ---------------------------
-
- -- AltPowerBar
- -- EclipseBar
- -- HealPrediction
- -- Stagger
-
- -- Castbar
-
- -- Auras
-
- ---------------------------
- -- Name text
- ---------------------------
-
- local Name = self:CreateFontString(nil, "OVERLAY", "GameFontNormal")
- Name:SetPoint("BOTTOMLEFT", Power, "TOPLEFT", 0, 3)
- Name:SetFont(LibSharedMedia:Fetch("font", config.valueFont), 14)
- self:Tag(Name, "[unitcolor][name]")
- self.Name = Name
-
- ---------------------------
- -- Group status icons
- ---------------------------
-
- AddStatusIcon("LFDRole")
- AddStatusIcon("RaidRole") -- maintank, mainassist
- AddStatusIcon("Leader")
- AddStatusIcon("Assistant")
- AddStatusIcon("MasterLooter")
- AddStatusIcon("PvP")
-
- ---------------------------
- -- Combat icon
- ---------------------------
-
- if unit == "player" then
- local Combat = self.Health:CreateTexture(nil, "OVERLAY")
- Combat:SetSize(16, 16)
- Combat:SetPoint("RIGHT", self.Health, "TOPRIGHT", -3, 0)
- Combat.PostUpdate = Stardust.PostUpdateCombat
- self.Combat = Combat
-
- local Resting = self.Health:CreateTexture(nil, "OVERLAY")
- Resting:SetSize(16, 16)
- Resting:SetPoint("RIGHT", self.Health, "TOPRIGHT", -3, 0)
- Resting.PostUpdate = Stardust.PostUpdateResting
- self.Resting = Resting
- end
-
- ---------------------------
- -- Phasing icon
- ---------------------------
-
- if not unit:match(".+target$") and not unit:match(".+pet") then
- local PhaseIcon = self.Health:CreateTexture(nil, "OVERLAY")
- PhaseIcon:SetPoint("TOP")
- PhaseIcon:SetPoint("BOTTOM")
- PhaseIcon:SetWidth(config.height * 2.5)
- PhaseIcon:SetTexture("Interface\\Icons\\Spell_Frost_Stun")
- PhaseIcon:SetTexCoord(0.05, 0.95, 0.5 - 0.25 * 0.9, 0.5 + 0.25 * 0.9)
- PhaseIcon:SetAlpha(0.5)
- PhaseIcon:SetBlendMode("ADD")
- PhaseIcon:SetDesaturated(true)
- PhaseIcon:SetVertexColor(0.4, 0.8, 1)
- self.PhaseIcon = PhaseIcon
- end
-
- ---------------------------
- -- Quest mob icon
- ---------------------------
-
- if unit == "target" then
- local QuestIcon = self.Health:CreateTexture(nil, "OVERLAY")
- QuestIcon:SetSize(16, 16)
- QuestIcon:SetPoint("RIGHT", self.Health, "TOPRIGHT", -3, 0)
- self.QuestIcon = QuestIcon
- end
-
- ---------------------------
- -- Raid target icon
- ---------------------------
-
- if unit == "player" or unit == "target" or unit == "party" then
- local RaidIcon = self.Health:CreateTexture(nil, "OVERLAY")
- RaidIcon:SetSize(24, 24)
- RaidIcon:SetPoint("CENTER", 0, 3) -- TODO
- self.RaidIcon = RaidIcon
- end
-
- ---------------------------
- -- Ready Check icon
- ---------------------------
-
- if unit == "player" or unit == "target" or unit == "party" then
- local ReadyCheck = self.Health:CreateTexture(nil, "OVERLAY")
- ReadyCheck:SetSize(24, 24)
- ReadyCheck:SetPoint("CENTER", 0, 3) -- TODO
- self.ReadyCheck = ReadyCheck
- end
-
- ---------------------------
- -- Resurrection icon
- ---------------------------
-
- if not unit:match(".+target$") and not unit:match("pet") then
- local ResurrectIcon = self.Health:CreateTexture(nil, "OVERLAY")
- ResurrectIcon:SetSize(24, 24)
- ResurrectIcon:SetPoint("CENTER", 0, 3) -- TODO
- self.ResurrectIcon = ResurrectIcon
- end
-
- ---------------------------
- -- Threat level icon
- ---------------------------
-
- if unit == "target" or unit == "focus" then
- local Threat = self.Health:CreateTexture(nil, "OVERLAY")
- Threat:SetSize(16, 16)
- Threat:SetPoint("CENTER", 0, 3) -- TODO
- self.Threat = Threat
- end
-
- ---------------------------
- -- Range
- ---------------------------
-
- self.Range = {
- insideAlpha = 1,
- outsideAlpha = 0.5
- }
-end
-
-oUF:Factory(function(self)
- self:RegisterStyle("Stardust", ApplyStyle)
- self:SetActiveStyle("Stardust")
-
- local player = self:Spawn("player")
- player:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOM", -175, 235)
-
- local pet = self:Spawn("pet")
- pet:SetPoint("TOPRIGHT", player, "BOTTOMRIGHT", 0, -6)
-
- local target = self:Spawn("target")
- target:SetPoint("BOTTOMLEFT", UIParent, "BOTTOM", 175, 235)
-
- local targettarget = self:Spawn("targettarget")
- targettarget:SetPoint("TOPLEFT", target, "BOTTOMLEFT", 0, -6)
-end)
-
diff --git a/oUF_Stardust.toc b/oUF_Stardust.toc
index 0e3b336..0848834 100644
--- a/oUF_Stardust.toc
+++ b/oUF_Stardust.toc
@@ -7,14 +7,15 @@
## X-Email: armordecai@protonmail.ch
## X-License: zlib/libpng License
-libs/LibStub.lua
-libs/CallbackHandler-1.0.lua
-libs/LibSharedMedia-3.0.lua
+Libs/LibStub.lua
+Libs/CallbackHandler-1.0.lua
+Libs/LibSharedMedia-3.0.lua
-includes/DemonicFury.lua
+Elements/BurningEmbers.lua
+Elements/DemonicFury.lua
-config.lua
-functions.lua
-tags.lua
+Config.lua
+Functions.lua
+Tags.lua
-layout.lua
+Layout.lua
diff --git a/tags.lua b/tags.lua
deleted file mode 100644
index 329b254..0000000
--- a/tags.lua
+++ /dev/null
@@ -1,51 +0,0 @@
---[[-----------------------------------------------------------------------
- oUF: Stardust - a layout for the oUF framework
- Copyright (c) 2016 Andrew Mordecai <armordecai@protonmail.ch>
- This code is released under the zlib license; see LICENSE for details.
--------------------------------------------------------------------------]]
-
-local _, Stardust = ...
-
-oUF.Tags.Events["unitcolor"] = "UNIT_HEALTH UNIT_CLASSIFICATION_CHANGED UNIT_CONNECTION UNIT_FACTION UNIT_REACTION"
-oUF.Tags.Methods["unitcolor"] = function(unit)
- local color
- if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
- color = oUF.colors.disconnected
- elseif UnitIsPlayer(unit) then
- local _, class = UnitClass(unit)
- color = oUF.colors.class[class]
- elseif UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) and not UnitIsTappedByAllThreatList(unit) then
- color = oUF.colors.tapped
- elseif UnitIsEnemy(unit, "player") then
- color = oUF.colors.reaction[1]
- else
- color = oUF.colors.reaction[UnitReaction(unit, "player") or 5]
- end
- return color and ("|cff%02x%02x%02x"):format(color[1] * 255, color[2] * 255, color[3] * 255) or "|cffffffff"
-end
-
-oUF.Tags.Events["powercolor"] = "UNIT_DISPLAYPOWER"
-oUF.Tags.Methods["powercolor"] = function(unit)
- local _, type = UnitPowerType(unit)
- local color = ns.colors.power[type] or ns.colors.power.FUEL
- return format("|cff%02x%02x%02x", color[1] * 255, color[2] * 255, color[3] * 255)
-end
-
-local threatcolors = {
- [0] = "|cffffffff",
- [1] = "|cffffff33",
- [2] = "|cffff9933",
- [3] = "|cffff3333",
-}
-oUF.Tags.Events["threatpct"] = "UNIT_THREAT_LIST_UPDATE"
-oUF.Tags.Methods["threatpct"] = function(unit)
- local isTanking, status, percentage, rawPercentage = UnitDetailedThreatSituation("player", unit)
- local pct = rawPercentage
- if isTanking then
- pct = UnitThreatPercentageOfLead("player", unit)
- end
- if pct and pct > 0 and pct < 200 then
- return format("%s%d%%", threatcolors[status] or threatcolors[0], pct + 0.5)
- end
-end
-