--[[-----------------------------------------------------------------------
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)