|
|
|
@@ -15,6 +15,26 @@ local module = ShaguTweaks:register({
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
-- Golden UI runs the same recolor pass with a gold palette (like the WoW
|
|
|
|
|
-- Forever client): textures are tinted gold, borders and tooltip edges get a
|
|
|
|
|
-- softer gold, and backgrounds keep their own colors.
|
|
|
|
|
local golden = ShaguTweaks:register({
|
|
|
|
|
title = T["Golden UI"],
|
|
|
|
|
description = T["Turns the borders of the interface, tooltips and dialogs gold, like the WoW Forever client. Darkened UI takes priority when both are enabled."],
|
|
|
|
|
expansions = { ["vanilla"] = true },
|
|
|
|
|
category = T["Interface"],
|
|
|
|
|
enabled = nil,
|
|
|
|
|
config = {
|
|
|
|
|
["goldmode.color"] = { r = 1, g = .78, b = .4, a = 1 },
|
|
|
|
|
["goldmode.border"] = { r = .8, g = .62, b = .32, a = 1 },
|
|
|
|
|
["goldmode.text"] = { r = .84, g = .72, b = .48, a = 1 },
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
-- Active palette, set by whichever of the two modules is enabled:
|
|
|
|
|
-- tint goes on textures, edge on backdrop borders and added button borders.
|
|
|
|
|
local tint, edge
|
|
|
|
|
|
|
|
|
|
local blacklist = {
|
|
|
|
|
["Solid Texture"] = true,
|
|
|
|
|
["WHITE8X8"] = true,
|
|
|
|
@@ -81,6 +101,9 @@ local borders = {
|
|
|
|
|
["ChatFrame(.+)Button"] = -2,
|
|
|
|
|
["PetFrameHappiness"] = 2,
|
|
|
|
|
["MicroButton"] = { -21, 0, 0, 0 },
|
|
|
|
|
-- VCB's buff and weapon-buff buttons, like the Blizzard buff buttons
|
|
|
|
|
["^VCB_BF_BUFF_BUTTON%d+$"] = 3,
|
|
|
|
|
["^VCB_BF_WEAPON_BUTTON%d+$"] = 3,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local addonframes = {
|
|
|
|
@@ -97,6 +120,7 @@ local addonframes = {
|
|
|
|
|
["Blizzard_RaidUI"] = { "ReadyCheckFrame" },
|
|
|
|
|
["Blizzard_TradeSkillUI"] = { "TradeSkillFrame" },
|
|
|
|
|
["Blizzard_TrainerUI"] = { "ClassTrainerFrame" },
|
|
|
|
|
["Artisan"] = { "ArtisanFrame" },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-- Turtle WoW exposes these extra inspect pages. Keep them out of the generic
|
|
|
|
@@ -117,11 +141,34 @@ if GetExpansion() == "tbc" then
|
|
|
|
|
borders["MicroButton"] = { -21, 0, 0, 0 }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Frame art that ships inside an addon (the "AddOns" entry above skips
|
|
|
|
|
-- addon textures, which are mostly icons) but should follow the palette.
|
|
|
|
|
local whitelist = {
|
|
|
|
|
"outfitter\\textures\\outfitterframe",
|
|
|
|
|
"outfitter\\textures\\scrollbartrench",
|
|
|
|
|
-- Artisan swaps in its own lower half of the profession window
|
|
|
|
|
"artisan\\textures\\bottomleft",
|
|
|
|
|
"artisan\\textures\\bottomright",
|
|
|
|
|
-- RollFor's classic loot window
|
|
|
|
|
"rollfor\\assets\\og-loot-frame",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-- Addon windows that build their rows while opening: recolored every time
|
|
|
|
|
-- they are shown (and once more on the next frame, after the rows exist).
|
|
|
|
|
local showframes = {
|
|
|
|
|
["RollForLootFrameHeader"] = true,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local function IsBlacklisted(texture)
|
|
|
|
|
local name = texture:GetName()
|
|
|
|
|
local texture = texture:GetTexture()
|
|
|
|
|
if not texture then return true end
|
|
|
|
|
|
|
|
|
|
local lower = string.lower(texture)
|
|
|
|
|
for i = 1, table.getn(whitelist) do
|
|
|
|
|
if string.find(lower, whitelist[i], 1, true) then return nil end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if name then
|
|
|
|
|
for entry in pairs(blacklist) do
|
|
|
|
|
if string.find(name, entry, 1) then return true end
|
|
|
|
@@ -145,12 +192,12 @@ local function AddSpecialBackground(frame, w, h, x, y)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function DarkenFrame(frame, r, g, b, a)
|
|
|
|
|
-- dont't do anything if disabled
|
|
|
|
|
if not ShaguTweaks.DarkMode then return end
|
|
|
|
|
-- dont't do anything if neither Darkened UI nor Golden UI is enabled
|
|
|
|
|
if not tint then return end
|
|
|
|
|
|
|
|
|
|
-- set defaults
|
|
|
|
|
if not r and not g and not b then
|
|
|
|
|
r, g, b, a = module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, module.config["darkmode.color"].a
|
|
|
|
|
r, g, b, a = tint.r, tint.g, tint.b, tint.a
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- iterate through all subframes
|
|
|
|
@@ -165,8 +212,8 @@ local function DarkenFrame(frame, r, g, b, a)
|
|
|
|
|
-- read name
|
|
|
|
|
local name = frame.GetName and frame:GetName()
|
|
|
|
|
|
|
|
|
|
-- set a dark backdrop border color everywhere
|
|
|
|
|
frame:SetBackdropBorderColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, module.config["darkmode.color"].a)
|
|
|
|
|
-- set the palette's backdrop border color everywhere
|
|
|
|
|
frame:SetBackdropBorderColor(edge.r, edge.g, edge.b, edge.a)
|
|
|
|
|
|
|
|
|
|
-- add special backgrounds to quests and such
|
|
|
|
|
for pattern, inset in pairs(backgrounds) do
|
|
|
|
@@ -175,7 +222,7 @@ local function DarkenFrame(frame, r, g, b, a)
|
|
|
|
|
|
|
|
|
|
-- add black borders around specified buttons
|
|
|
|
|
for pattern, inset in pairs(borders) do
|
|
|
|
|
if name and string.find(name, pattern) then AddBorder(frame, inset, module.config["darkmode.color"]) end
|
|
|
|
|
if name and string.find(name, pattern) then AddBorder(frame, inset, edge) end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- scan through all regions (textures)
|
|
|
|
@@ -201,8 +248,178 @@ end
|
|
|
|
|
-- register darken frame to global
|
|
|
|
|
ShaguTweaks.DarkenFrame = DarkenFrame
|
|
|
|
|
|
|
|
|
|
module.enable = function(self)
|
|
|
|
|
ShaguTweaks.DarkMode = true
|
|
|
|
|
-- Other addons that draw their own tooltip-style borders. Their frames (and
|
|
|
|
|
-- everything inside them) keep following the palette even when the addon
|
|
|
|
|
-- sets its border color again later, or builds a window only when opened.
|
|
|
|
|
local ADDON_PREFIXES = {
|
|
|
|
|
"ShaguDPS", "Bagshui", "Outfitter", "SoulstoneTracker", "SSWarlock",
|
|
|
|
|
"SSTClassic", "SSTracker", "TrinketMenu", "OctoBus", "RollFor", "VCB_",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local function IsAddonFrameName(name)
|
|
|
|
|
if not name then return end
|
|
|
|
|
for i = 1, table.getn(ADDON_PREFIXES) do
|
|
|
|
|
if string.find(name, ADDON_PREFIXES[i], 1, true) == 1 then return true end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Only light grey/white/silver borders follow the palette. Colored borders
|
|
|
|
|
-- (item quality, hover highlights, class or theme colors) and dark ones stay
|
|
|
|
|
-- as the addon set them.
|
|
|
|
|
local function IsLightNeutral(r, g, b)
|
|
|
|
|
r, g, b = tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0
|
|
|
|
|
local hi, lo = math.max(r, g, b), math.min(r, g, b)
|
|
|
|
|
return hi - lo < .1 and hi >= .35
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function LockBorder(frame)
|
|
|
|
|
if not frame or frame.stBorderLock or not frame.SetBackdropBorderColor then return end
|
|
|
|
|
frame.stBorderLock = true
|
|
|
|
|
|
|
|
|
|
local setColor, setBackdrop = frame.SetBackdropBorderColor, frame.SetBackdrop
|
|
|
|
|
|
|
|
|
|
frame.SetBackdropBorderColor = function(self, r, g, b, a)
|
|
|
|
|
if IsLightNeutral(r, g, b) then
|
|
|
|
|
setColor(self, edge.r, edge.g, edge.b, a or 1)
|
|
|
|
|
else
|
|
|
|
|
setColor(self, r, g, b, a)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- a new backdrop starts with a white border
|
|
|
|
|
if setBackdrop then
|
|
|
|
|
frame.SetBackdrop = function(self, backdrop)
|
|
|
|
|
setBackdrop(self, backdrop)
|
|
|
|
|
if backdrop and backdrop.edgeFile then setColor(self, edge.r, edge.g, edge.b, 1) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- run the current color through the filter once
|
|
|
|
|
if frame.GetBackdropBorderColor then
|
|
|
|
|
local ok, r, g, b, a = pcall(frame.GetBackdropBorderColor, frame)
|
|
|
|
|
if ok and r then frame:SetBackdropBorderColor(r, g, b, a) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Border textures (VCB's buff and weapon borders): same rule, on the
|
|
|
|
|
-- texture's vertex color.
|
|
|
|
|
local function LockTextureBorder(texture)
|
|
|
|
|
if texture.stBorderLock or not texture.SetVertexColor then return end
|
|
|
|
|
texture.stBorderLock = true
|
|
|
|
|
|
|
|
|
|
local setColor = texture.SetVertexColor
|
|
|
|
|
texture.SetVertexColor = function(self, r, g, b, a)
|
|
|
|
|
if IsLightNeutral(r, g, b) then
|
|
|
|
|
setColor(self, edge.r, edge.g, edge.b, a or 1)
|
|
|
|
|
else
|
|
|
|
|
setColor(self, r, g, b, a)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if texture.GetVertexColor then
|
|
|
|
|
local ok, r, g, b, a = pcall(texture.GetVertexColor, texture)
|
|
|
|
|
if ok and r then texture:SetVertexColor(r, g, b, a) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function LockTree(frame)
|
|
|
|
|
if not frame then return end
|
|
|
|
|
LockBorder(frame)
|
|
|
|
|
if frame.GetRegions then
|
|
|
|
|
local regions = { frame:GetRegions() }
|
|
|
|
|
for i = 1, table.getn(regions) do
|
|
|
|
|
local region = regions[i]
|
|
|
|
|
local name = region.GetName and region:GetName()
|
|
|
|
|
if name and string.find(name, "Border$") and region.GetObjectType and region:GetObjectType() == "Texture" then
|
|
|
|
|
LockTextureBorder(region)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if frame.GetChildren then
|
|
|
|
|
local children = { frame:GetChildren() }
|
|
|
|
|
for i = 1, table.getn(children) do LockTree(children[i]) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- find the addon frames that exist already, anywhere below UIParent
|
|
|
|
|
local function FindAddonFrames(frame)
|
|
|
|
|
local children = { frame:GetChildren() }
|
|
|
|
|
for i = 1, table.getn(children) do
|
|
|
|
|
local child = children[i]
|
|
|
|
|
if IsAddonFrameName(child.GetName and child:GetName()) then
|
|
|
|
|
LockTree(child)
|
|
|
|
|
else
|
|
|
|
|
FindAddonFrames(child)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- The round border of addon minimap buttons (most use the stock tracking
|
|
|
|
|
-- border texture). Those buttons are often made after login.
|
|
|
|
|
local function TintMinimapButton(frame)
|
|
|
|
|
if not frame or not frame.GetRegions then return end
|
|
|
|
|
local regions = { frame:GetRegions() }
|
|
|
|
|
for i = 1, table.getn(regions) do
|
|
|
|
|
local region = regions[i]
|
|
|
|
|
local texture = region.GetTexture and region:GetTexture()
|
|
|
|
|
if texture and string.find(string.lower(texture), "minimap%-trackingborder") then
|
|
|
|
|
region:SetVertexColor(tint.r, tint.g, tint.b, 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function RecolorOnShow(frame)
|
|
|
|
|
if not frame or frame.stRecolorOnShow then return end
|
|
|
|
|
frame.stRecolorOnShow = true
|
|
|
|
|
ShaguTweaks.HookScript(frame, "OnShow", function()
|
|
|
|
|
DarkenFrame(frame)
|
|
|
|
|
if _G.C_Timer and _G.C_Timer.After then
|
|
|
|
|
_G.C_Timer.After(0, function() DarkenFrame(frame) end)
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
if frame:IsShown() then DarkenFrame(frame) end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function LockAddonFrames()
|
|
|
|
|
FindAddonFrames(UIParent)
|
|
|
|
|
|
|
|
|
|
for name in pairs(showframes) do RecolorOnShow(_G[name]) end
|
|
|
|
|
|
|
|
|
|
if Minimap then
|
|
|
|
|
local buttons = { Minimap:GetChildren() }
|
|
|
|
|
for i = 1, table.getn(buttons) do TintMinimapButton(buttons[i]) end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- frames those addons create later: named after the addon, or created
|
|
|
|
|
-- inside one of their frames (templates bring their children along)
|
|
|
|
|
local create = CreateFrame
|
|
|
|
|
CreateFrame = function(a1, a2, a3, a4, a5, a6)
|
|
|
|
|
local frame = create(a1, a2, a3, a4, a5, a6)
|
|
|
|
|
if frame and (IsAddonFrameName(a2) or (type(a3) == "table" and a3.stBorderLock)) then
|
|
|
|
|
LockTree(frame)
|
|
|
|
|
end
|
|
|
|
|
if frame and type(a2) == "string" and showframes[a2] then RecolorOnShow(frame) end
|
|
|
|
|
-- buttons that get an extra border (VCB buffs made after login)
|
|
|
|
|
if frame and type(a2) == "string" then
|
|
|
|
|
for pattern, inset in pairs(borders) do
|
|
|
|
|
if string.find(a2, pattern) then AddBorder(frame, inset, edge) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
-- minimap buttons get their border texture right after they are made
|
|
|
|
|
if frame and a3 and a3 == Minimap then
|
|
|
|
|
if _G.C_Timer and _G.C_Timer.After then
|
|
|
|
|
_G.C_Timer.After(0, function() TintMinimapButton(frame) end)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return frame
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function Apply(tintColor, edgeColor, darkBackgrounds)
|
|
|
|
|
if tint then return end
|
|
|
|
|
tint, edge = tintColor, edgeColor
|
|
|
|
|
ShaguTweaks.UITint = tint
|
|
|
|
|
ShaguTweaks.UIBorder = edge
|
|
|
|
|
|
|
|
|
|
local name, original, r, g, b
|
|
|
|
|
local hookBuffButton_Update = BuffButton_Update
|
|
|
|
@@ -220,23 +437,32 @@ module.enable = function(self)
|
|
|
|
|
elseif not original and _G[name] then
|
|
|
|
|
-- tbc buff buttons don't have borders, so we
|
|
|
|
|
-- need to manually add a dark one.
|
|
|
|
|
AddBorder(_G[name], 2, module.config["darkmode.color"])
|
|
|
|
|
AddBorder(_G[name], 2, edge)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
TOOLTIP_DEFAULT_COLOR.r = module.config["darkmode.color"].r
|
|
|
|
|
TOOLTIP_DEFAULT_COLOR.g = module.config["darkmode.color"].g
|
|
|
|
|
TOOLTIP_DEFAULT_COLOR.b = module.config["darkmode.color"].b
|
|
|
|
|
TOOLTIP_DEFAULT_COLOR.r = edge.r
|
|
|
|
|
TOOLTIP_DEFAULT_COLOR.g = edge.g
|
|
|
|
|
TOOLTIP_DEFAULT_COLOR.b = edge.b
|
|
|
|
|
|
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.r = module.config["darkmode.color"].r
|
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.g = module.config["darkmode.color"].g
|
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.b = module.config["darkmode.color"].b
|
|
|
|
|
-- Darkened UI also greys the tooltip background; Golden UI keeps it.
|
|
|
|
|
if darkBackgrounds then
|
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.r = tint.r
|
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.g = tint.g
|
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.b = tint.b
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
DarkenFrame(UIParent)
|
|
|
|
|
DarkenFrame(WorldMapFrame)
|
|
|
|
|
DarkenFrame(DropDownList1)
|
|
|
|
|
DarkenFrame(DropDownList2)
|
|
|
|
|
DarkenFrame(DropDownList3)
|
|
|
|
|
LockAddonFrames()
|
|
|
|
|
|
|
|
|
|
-- the loot window gets its art set again when it opens
|
|
|
|
|
if LootFrame then
|
|
|
|
|
ShaguTweaks.HookScript(LootFrame, "OnShow", function() DarkenFrame(LootFrame) end)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- align all actionbutton textures
|
|
|
|
|
local bars = { "Action", "BonusAction", "MultiBarBottomLeft", "MultiBarBottomRight", "MultiBarLeft", "MultiBarRight", "Shapeshift" }
|
|
|
|
@@ -259,7 +485,7 @@ module.enable = function(self)
|
|
|
|
|
if button[func] then
|
|
|
|
|
local tex = button[func](button)
|
|
|
|
|
if tex then
|
|
|
|
|
tex:SetVertexColor(module.config["darkmode.color"].r+.2, module.config["darkmode.color"].g+.2, module.config["darkmode.color"].b+.2, 1)
|
|
|
|
|
tex:SetVertexColor(math.min(tint.r+.2, 1), math.min(tint.g+.2, 1), math.min(tint.b+.2, 1), 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
@@ -268,12 +494,12 @@ module.enable = function(self)
|
|
|
|
|
HookAddonOrVariable("Blizzard_AuctionUI", function()
|
|
|
|
|
for i = 1, 15 do
|
|
|
|
|
local tex = _G["AuctionFilterButton"..i]:GetNormalTexture()
|
|
|
|
|
tex:SetVertexColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, 1)
|
|
|
|
|
tex:SetVertexColor(tint.r, tint.g, tint.b, 1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for i = 1, 8 do
|
|
|
|
|
_G["BrowseButton"..i.."Left"]:SetVertexColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, 1)
|
|
|
|
|
_G["BrowseButton"..i.."Right"]:SetVertexColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, 1)
|
|
|
|
|
_G["BrowseButton"..i.."Left"]:SetVertexColor(tint.r, tint.g, tint.b, 1)
|
|
|
|
|
_G["BrowseButton"..i.."Right"]:SetVertexColor(tint.r, tint.g, tint.b, 1)
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
@@ -413,3 +639,28 @@ module.enable = function(self)
|
|
|
|
|
table.insert(ShaguTweaks.libnameplate.OnShow, ReapplyShaguDarkMode)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module.enable = function(self)
|
|
|
|
|
ShaguTweaks.DarkMode = true
|
|
|
|
|
Apply(module.config["darkmode.color"], module.config["darkmode.color"], true)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
golden.enable = function(self)
|
|
|
|
|
-- Both recolor the same textures; Darkened UI wins when both are ticked.
|
|
|
|
|
if ShaguTweaks_config and ShaguTweaks_config[T["Darkened UI"]] == 1 then return end
|
|
|
|
|
ShaguTweaks.GoldMode = true
|
|
|
|
|
Apply(golden.config["goldmode.color"], golden.config["goldmode.border"], false)
|
|
|
|
|
|
|
|
|
|
-- the softer, browner gold of WoW Forever's titles and labels instead of
|
|
|
|
|
-- the stock bright yellow (every text that uses the "normal" gold font)
|
|
|
|
|
local text = golden.config["goldmode.text"]
|
|
|
|
|
local r, g, b = tonumber(text.r) or .84, tonumber(text.g) or .72, tonumber(text.b) or .48
|
|
|
|
|
if NORMAL_FONT_COLOR then
|
|
|
|
|
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b = r, g, b
|
|
|
|
|
end
|
|
|
|
|
local fonts = { "GameFontNormal", "GameFontNormalSmall", "GameFontNormalLarge", "GameFontNormalHuge" }
|
|
|
|
|
for i = 1, table.getn(fonts) do
|
|
|
|
|
local font = _G[fonts[i]]
|
|
|
|
|
if font and font.SetTextColor then font:SetTextColor(r, g, b) end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|