diff --git a/EUI__General_Options.lua b/EUI__General_Options.lua index f86a6f18..f173e917 100644 --- a/EUI__General_Options.lua +++ b/EUI__General_Options.lua @@ -1860,8 +1860,15 @@ initFrame:SetScript("OnEvent", function(self) if not EllesmereUIDB then EllesmereUIDB = {} end if v == "default" then EllesmereUIDB.fctFont = nil + EllesmereUIDB.fctFontPath = nil + EllesmereUIDB.fctFontPathFor = nil else EllesmereUIDB.fctFont = v + -- smf: keys cache their resolved path for the next login's + -- early window; see ApplyCombatTextFont in Startup. + local e = v:match("^smf:") and fctFontValues[v] + EllesmereUIDB.fctFontPath = e and e.font + EllesmereUIDB.fctFontPathFor = e and v end EllesmereUI:ShowConfirmPopup({ title = "Logout Required", diff --git a/EllesmereUI_Startup.lua b/EllesmereUI_Startup.lua index 1ea8041a..4aa9a41b 100644 --- a/EllesmereUI_Startup.lua +++ b/EllesmereUI_Startup.lua @@ -216,16 +216,30 @@ end -- Reads EllesmereUIDB.fonts directly rather than going through GetFontsDB(): -- that helper lazy-creates the table, and this can run at the ADDON_LOADED of -- Blizzard_CombatText, before our SavedVariables have been restored. + +-- Probe a font path before it reaches an engine global: SetFont returns a +-- success boolean, so a cached path whose providing addon was uninstalled is +-- detected instead of leaving the engine pointed at a missing file for the +-- whole session (which kills floating text entirely). +local probeFS +local function ProbeFont(path) + if type(path) ~= "string" or path == "" then return false end + probeFS = probeFS or UIParent:CreateFontString() + local ok, success = pcall(probeFS.SetFont, probeFS, path, 12, "") + return ok and success == true +end + local function ApplyUnitNameFont() local fonts = EllesmereUIDB and EllesmereUIDB.fonts local name = fonts and fonts.unitNameFont if not name or name == "" then return end local path = fonts.unitNameFontPath - if (type(path) ~= "string" or path == "") - and EllesmereUI and EllesmereUI.ResolveFontName then + local ok = ProbeFont(path) + if not ok and EllesmereUI and EllesmereUI.ResolveFontName then path = EllesmereUI.ResolveFontName(name) + ok = ProbeFont(path) end - if type(path) == "string" and path ~= "" then + if ok then _G.UNIT_NAME_FONT = path end end @@ -304,19 +318,30 @@ end -- CombatTextFont may not exist yet here, so we also hook ADDON_LOADED -- to catch it as soon as it becomes available. do + -- smf: keys resolve via LSM when the providing pack has loaded, else via + -- the path cached at selection time (external packs load after us, so at + -- our ADDON_LOADED -- the window where the engine caches the global -- + -- the name is never registered yet). noDefault on Fetch: without it an + -- unregistered name silently resolves to the DEFAULT font, not nil. + -- Every candidate is probed, so only a loadable path is ever applied or + -- kept in the cache. local function ApplyCombatTextFont() - local saved = EllesmereUIDB and EllesmereUIDB.fctFont + local db = EllesmereUIDB + local saved = db and db.fctFont if not saved or type(saved) ~= "string" or saved == "" then return end - -- Resolve "smf:" prefixed SharedMedia font keys to actual paths local fontPath = saved local smName = saved:match("^smf:(.+)") if smName then local LSM = LibStub and LibStub("LibSharedMedia-3.0", true) - local fetched = LSM and LSM:Fetch("font", smName) - -- If the SM addon is missing or hasn't loaded yet, skip entirely - -- so Blizzard's default combat text font stays intact. - if not fetched then return end - fontPath = fetched + local fetched = LSM and LSM:Fetch("font", smName, true) + -- The cache only counts if it was written for the currently + -- saved key (fctFontPathFor pairs them). + local cached = (db.fctFontPathFor == saved) and db.fctFontPath or nil + fontPath = (ProbeFont(fetched) and fetched) + or (ProbeFont(cached) and cached) or nil + db.fctFontPath = fontPath + db.fctFontPathFor = fontPath and saved or nil + if not fontPath then return end end _G.DAMAGE_TEXT_FONT = fontPath if _G.CombatTextFont then @@ -348,7 +373,14 @@ do self:UnregisterEvent("PLAYER_LOGIN") elseif event == "PLAYER_ENTERING_WORLD" then self:UnregisterEvent("PLAYER_ENTERING_WORLD") - elseif event == "ADDON_LOADED" then + elseif addonName == "Blizzard_CombatText" + or not (EllesmereUIDB and EllesmereUIDB.fctFont) + or (C_AddOns and C_AddOns.IsAddOnLoaded and C_AddOns.IsAddOnLoaded("Blizzard_CombatText")) then + -- The watch exists to restyle the load-on-demand CombatTextFont + -- object at its actual load (our own addon always fires first, so + -- retiring on the first match missed it). Retire it once that has + -- happened, or when it never can: feature unused (a mid-session + -- pick needs a relog anyway) or the addon already loaded. self:UnregisterEvent("ADDON_LOADED") end end)