--[[----------------------------------------------------------------------- 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 == "WARLOCK" then local BurningEmbers = NewBarGroup(self.Health, 4, 30, config.powerHeight) BurningEmbers[1]:SetPoint("TOPLEFT", self.Health, 3, -3) BurningEmbers.PostUpdate = Stardust.PostUpdateCPoints self.BurningEmbers = BurningEmbers end 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)