-------------------------------------------------------------------------------- -- Nanami-UI: Central Theme Engine (Theme.lua) -------------------------------------------------------------------------------- SFrames = SFrames or {} SFrames.Theme = {} SFrames.ActiveTheme = {} local function HSVtoRGB(h, s, v) if s <= 0 then return v, v, v end h = h - math.floor(h / 360) * 360 local hh = h / 60 local i = math.floor(hh) local f = hh - i local p = v * (1 - s) local q = v * (1 - s * f) local t = v * (1 - s * (1 - f)) if i == 0 then return v, t, p elseif i == 1 then return q, v, p elseif i == 2 then return p, v, t elseif i == 3 then return p, q, v elseif i == 4 then return t, p, v else return v, p, q end end local function toHexChar(n) if n < 10 then return string.char(48 + n) end return string.char(97 + n - 10) end local function RGBtoHex(r, g, b) local rr = math.floor(r * 255 + 0.5) local gg = math.floor(g * 255 + 0.5) local bb = math.floor(b * 255 + 0.5) return "ff" .. toHexChar(math.floor(rr / 16)) .. toHexChar(rr - math.floor(rr / 16) * 16) .. toHexChar(math.floor(gg / 16)) .. toHexChar(gg - math.floor(gg / 16) * 16) .. toHexChar(math.floor(bb / 16)) .. toHexChar(bb - math.floor(bb / 16) * 16) end SFrames.Theme.Presets = {} SFrames.Theme.Presets["pink"] = { name = "Pink", hue = 330, satMul = 1.00 } SFrames.Theme.Presets["frost"] = { name = "Frost", hue = 210, satMul = 1.00 } SFrames.Theme.Presets["emerald"] = { name = "Emerald", hue = 140, satMul = 0.85 } SFrames.Theme.Presets["flame"] = { name = "Flame", hue = 25, satMul = 0.90 } SFrames.Theme.Presets["shadow"] = { name = "Shadow", hue = 270, satMul = 0.90 } SFrames.Theme.Presets["golden"] = { name = "Golden", hue = 45, satMul = 0.80 } SFrames.Theme.Presets["teal"] = { name = "Teal", hue = 175, satMul = 0.85 } SFrames.Theme.Presets["crimson"] = { name = "Crimson", hue = 355, satMul = 0.90 } SFrames.Theme.Presets["holy"] = { name = "Holy", hue = 220, satMul = 0.15 } SFrames.Theme.PresetOrder = { "pink", "frost", "emerald", "flame", "shadow", "golden", "teal", "crimson", "holy" } SFrames.Theme.ClassMap = {} SFrames.Theme.ClassMap["WARRIOR"] = "crimson" SFrames.Theme.ClassMap["MAGE"] = "frost" SFrames.Theme.ClassMap["ROGUE"] = "teal" SFrames.Theme.ClassMap["DRUID"] = "flame" SFrames.Theme.ClassMap["HUNTER"] = "emerald" SFrames.Theme.ClassMap["SHAMAN"] = "frost" SFrames.Theme.ClassMap["PRIEST"] = "holy" SFrames.Theme.ClassMap["WARLOCK"] = "shadow" SFrames.Theme.ClassMap["PALADIN"] = "golden" local function GenerateTheme(H, satMul) satMul = satMul or 1.0 local function S(s) local v = s * satMul if v > 1 then v = 1 end return v end local function C3(s, v) local r, g, b = HSVtoRGB(H, S(s), v) return { r, g, b } end local function C4(s, v, a) local r, g, b = HSVtoRGB(H, S(s), v) return { r, g, b, a } end local t = {} t.accent = C4(0.40, 0.80, 0.98) t.accentDark = C3(0.45, 0.55) t.accentLight = C3(0.30, 1.00) t.accentHex = RGBtoHex(t.accentLight[1], t.accentLight[2], t.accentLight[3]) t.panelBg = C4(0.50, 0.12, 0.95) t.panelBorder = C4(0.45, 0.55, 0.90) t.headerBg = C4(0.60, 0.10, 0.98) t.sectionBg = C4(0.43, 0.14, 0.82) t.sectionBorder = C4(0.38, 0.45, 0.86) t.bg = t.panelBg t.border = t.panelBorder t.slotBg = C4(0.20, 0.07, 0.90) t.slotBorder = C4(0.10, 0.28, 0.80) t.slotHover = C4(0.38, 0.40, 0.90) t.slotSelected = C4(0.43, 0.70, 1.00) t.buttonBg = C4(0.44, 0.18, 0.94) t.buttonBorder = C4(0.40, 0.50, 0.90) t.buttonHoverBg = C4(0.47, 0.30, 0.96) t.buttonDownBg = C4(0.50, 0.14, 0.96) t.buttonDisabledBg = C4(0.43, 0.14, 0.65) t.buttonActiveBg = C4(0.52, 0.42, 0.98) t.buttonActiveBorder = C4(0.42, 0.90, 1.00) t.buttonText = C3(0.16, 0.90) t.buttonActiveText = C3(0.08, 1.00) t.buttonDisabledText = C4(0.14, 0.55, 0.68) t.btnBg = t.buttonBg t.btnBorder = t.buttonBorder t.btnHoverBg = t.buttonHoverBg t.btnHoverBd = C4(0.40, 0.80, 0.98) t.btnDownBg = t.buttonDownBg t.btnText = t.buttonText t.btnActiveText = t.buttonActiveText t.btnDisabledText = C3(0.14, 0.40) t.btnHover = C4(0.47, 0.30, 0.95) t.btnHoverBorder = t.btnHoverBd t.tabBg = t.buttonBg t.tabBorder = t.buttonBorder t.tabActiveBg = C4(0.50, 0.32, 0.96) t.tabActiveBorder = C4(0.40, 0.80, 0.98) t.tabText = C3(0.21, 0.70) t.tabActiveText = t.buttonActiveText t.checkBg = t.buttonBg t.checkBorder = t.buttonBorder t.checkHoverBorder = C4(0.40, 0.80, 0.95) t.checkFill = C4(0.43, 0.88, 0.98) t.checkOn = C3(0.40, 0.80) t.checkOff = C4(0.40, 0.25, 0.60) t.sliderTrack = C4(0.45, 0.22, 0.90) t.sliderFill = C4(0.35, 0.85, 0.92) t.sliderThumb = C4(0.25, 1.00, 0.95) t.text = C3(0.11, 0.92) t.title = C3(0.30, 1.00) t.gold = t.title t.nameText = C3(0.06, 0.92) t.dimText = C3(0.25, 0.60) t.bodyText = C3(0.05, 0.82) t.sectionTitle = C3(0.24, 0.90) t.catHeader = C3(0.31, 0.80) t.colHeader = C3(0.25, 0.80) t.labelText = C3(0.23, 0.65) t.valueText = t.text t.subText = t.labelText t.pageText = C3(0.19, 0.80) t.objectiveText = C3(0.10, 0.90) t.optionText = t.tabText t.countText = t.tabText t.trackText = C3(0.25, 0.80) t.divider = C4(0.45, 0.55, 0.40) t.sepColor = C4(0.44, 0.45, 0.50) t.scrollThumb = C4(0.45, 0.55, 0.70) t.scrollTrack = C4(0.50, 0.08, 0.50) t.inputBg = C4(0.50, 0.08, 0.95) t.inputBorder = C4(0.38, 0.40, 0.80) t.searchBg = C4(0.50, 0.08, 0.80) t.searchBorder = C4(0.38, 0.40, 0.60) t.progressBg = C4(0.50, 0.08, 0.90) t.progressFill = C4(0.50, 0.70, 1.00) t.modelBg = C4(0.60, 0.08, 0.85) t.modelBorder = C4(0.43, 0.35, 0.70) t.emptySlot = C4(0.40, 0.25, 0.40) t.emptySlotBg = C4(0.50, 0.08, 0.40) t.emptySlotBd = C4(0.40, 0.25, 0.30) t.barBg = C4(0.60, 0.10, 1.00) t.rowNormal = C4(0.50, 0.06, 0.30) t.rowNormalBd = C4(0.22, 0.20, 0.30) t.raidGroup = t.sectionBg t.raidGroupBorder = C4(0.38, 0.40, 0.70) t.raidSlotEmpty = C4(0.50, 0.08, 0.60) t.questSelected = C4(0.70, 0.60, 0.85) t.questSelBorder = C4(0.47, 0.95, 1.00) t.questSelBar = C4(0.45, 1.00, 1.00) t.questHover = C4(0.52, 0.25, 0.50) t.zoneHeader = t.catHeader t.zoneBg = C4(0.50, 0.14, 0.50) t.collapseIcon = C3(0.31, 0.70) t.trackBar = C4(0.53, 0.95, 1.00) t.trackGlow = C4(0.53, 0.95, 0.22) t.rewardBg = C4(0.50, 0.10, 0.85) t.rewardBorder = C4(0.45, 0.40, 0.70) t.listBg = C4(0.50, 0.08, 0.80) t.listBorder = C4(0.43, 0.35, 0.60) t.detailBg = C4(0.50, 0.09, 0.92) t.detailBorder = t.listBorder t.selectedRowBg = C4(0.65, 0.35, 0.60) t.selectedRowBorder = C4(0.50, 0.90, 0.70) t.selectedNameText = { 1, 0.95, 1 } t.overlayBg = C4(0.75, 0.04, 0.55) t.accentLine = C4(0.50, 1.00, 0.90) t.titleColor = t.title t.nameColor = { 1, 1, 1 } t.valueColor = t.text t.labelColor = C3(0.28, 0.58) t.dimColor = C3(0.29, 0.48) t.clockColor = C3(0.18, 1.00) t.timerColor = C3(0.27, 0.75) t.brandColor = C4(0.37, 0.60, 0.70) t.particleColor = C3(0.40, 1.00) t.wbGold = { 1, 0.88, 0.55 } t.wbBorder = { 0.95, 0.75, 0.25 } t.passive = { 0.60, 0.60, 0.65 } return t end function SFrames.Theme.Extend(self, extras) local t = {} local src = SFrames.ActiveTheme if src then for k, v in pairs(src) do t[k] = v end end if extras then for k, v in pairs(extras) do t[k] = v end end return t end function SFrames.Theme.Apply(self, presetKey) local preset = self.Presets[presetKey or "pink"] if not preset then preset = self.Presets["pink"] end local newTheme = GenerateTheme(preset.hue, preset.satMul) local oldKeys = {} for k, v in pairs(SFrames.ActiveTheme) do table.insert(oldKeys, k) end for i = 1, table.getn(oldKeys) do SFrames.ActiveTheme[oldKeys[i]] = nil end for k, v in pairs(newTheme) do SFrames.ActiveTheme[k] = v end if SFrames.Config and SFrames.Config.colors then local a = SFrames.ActiveTheme SFrames.Config.colors.border = { r = a.accent[1], g = a.accent[2], b = a.accent[3], a = 1 } SFrames.Config.colors.backdrop = { r = a.panelBg[1], g = a.panelBg[2], b = a.panelBg[3], a = a.panelBg[4] or 0.8 } end end function SFrames.Theme.GetCurrentPreset(self) if SFramesDB and SFramesDB.Theme then if SFramesDB.Theme.useClassTheme then local _, class = UnitClass("player") if class and self.ClassMap[class] then return self.ClassMap[class] end end if SFramesDB.Theme.preset and self.Presets[SFramesDB.Theme.preset] then return SFramesDB.Theme.preset end end return "pink" end function SFrames.Theme.GetAccentHex(self) return SFrames.ActiveTheme.accentHex or "ffffb3d9" end SFrames.Theme.HSVtoRGB = HSVtoRGB SFrames.Theme.RGBtoHex = RGBtoHex SFrames.Theme:Apply(SFrames.Theme:GetCurrentPreset()) local themeInitFrame = CreateFrame("Frame") themeInitFrame:RegisterEvent("PLAYER_LOGIN") themeInitFrame:SetScript("OnEvent", function() SFrames.Theme:Apply(SFrames.Theme:GetCurrentPreset()) end)