Working with Fonts in Nexus
Updated 21 October, 2026
ImGui draws text from a single font atlas, a texture that contains every glyph of every loaded font. Nexus owns that atlas and rebuilds it whenever fonts change, for example when the user picks a different font or the game's interface size changes. The font API lets your addon add fonts to the atlas and keeps you informed when they change. This guide covers using the game's fonts, adding your own, and handling atlas rebuilds safely.
Fonts arrive through a receiver
You never get a font pointer once and keep it forever. Whenever the atlas is rebuilt, every ImFont* becomes invalid and a new one is created. Nexus therefore delivers fonts through a receiver function that you provide:
static ImFont* s_HeaderFont = nullptr;
void ReceiveFont(const char* aIdentifier, void* aFont)
{
if (strcmp(aIdentifier, "FONT_MYADDON_HEADER") == 0)
{
s_HeaderFont = (ImFont*)aFont;
}
}
Before the atlas is rebuilt, Nexus calls the receiver with nullptr. After the rebuild, it calls it again with the new pointer. Both happen on the render thread, between frames. Always check for nullptr before using a font:
if (s_HeaderFont)
{
ImGui::PushFont(s_HeaderFont);
ImGui::Text("Boss timers");
ImGui::PopFont();
}
else
{
ImGui::Text("Boss timers");
}
Adding your own font
Add a font from a file, an embedded resource or memory. The size is in pixels. The receiver is called once the font is ready:
/* From a file. */
std::string path = APIDefs->Paths_GetAddonDirectory("MyAddon/fonts/Header.ttf");
APIDefs->Fonts_AddFromFile("FONT_MYADDON_HEADER", 22.0f, path.c_str(), ReceiveFont, nullptr);
/* From a resource of type FONT. */
APIDefs->Fonts_AddFromResource("FONT_MYADDON_HEADER", 22.0f, IDR_FONT_HEADER, s_Module, ReceiveFont, nullptr);
/* From memory. Nexus copies the data. */
APIDefs->Fonts_AddFromMemory("FONT_MYADDON_HEADER", 22.0f, data, size, ReceiveFont, nullptr);
To embed a font, add it to your resource file with the type FONT, for example IDR_FONT_HEADER FONT "fonts/Header.ttf".
- Font identifiers are global. If a font with the identifier already exists, your receiver is subscribed to it and no new font is added, even if you asked for a different file or size. Prefix identifiers with your addon's name.
- The last parameter is an optional
ImFontConfig*, for options such as oversampling or merging icon fonts. Nexus copies it, so a local variable is fine. - Every font makes the atlas bigger and every change rebuilds it, which costs a moment of rendering time. Add the fonts you need once, in your load function, rather than at different sizes on the fly.
Character coverage
To keep the atlas small, fonts added by addons contain the basic Latin and Latin Extended characters, plus every character that appears in the loaded translations. Other characters, for example from text the user types, may show as placeholders. The user's main interface font additionally contains Cyrillic and Chinese characters, so use it for user-provided text.
Using the game's fonts
Nexus loads the fonts of the game's interface, so your addon can match its look. The easiest way to use them is through NexusLinkData_t, which always holds the variant matching the user's interface size:
NexusLinkData_t* nexusLink = (NexusLinkData_t*)APIDefs->DataLink_Get(DL_NEXUS_LINK);
/* In your render callback: */
ImFont* font = (ImFont*)nexusLink->Font; /* Read it every frame, it changes. */
if (font) { ImGui::PushFont(font); }
ImGui::Text("Looks like the game.");
if (font) { ImGui::PopFont(); }
| Field | Font | Typical use |
|---|---|---|
Font |
Menomonia | Body text in the game's style. |
FontBig |
Menomonia, larger | Headlines and titles. |
FontUI |
Trebuchet MS | Interface labels, like the game's own small text. |
These fonts are also available by identifier for a fixed interface size, as MENOMONIA_S, MENOMONIA_BIG_S and TREBUCHET_S, with the suffixes _S, _N, _L and _XL for the game's Small, Normal, Large and Larger interface sizes. The user's chosen interface font is FONT_DEFAULT, which is also ImGui's default font, so you never need to push it.
Subscribing to an existing font
Fonts_Get subscribes your receiver to a font that already exists, and calls it immediately with the current pointer:
APIDefs->Fonts_Get("MENOMONIA_BIG_N", ReceiveFont);
If the font does not exist at that moment, your receiver is called once with nullptr and is not subscribed, so it will not be notified if the font is added later. To share a font between addons regardless of load order, have every addon add it with the same identifier and the same file instead.
Resizing
Fonts_Resize(identifier, size) changes the size of a font and rebuilds the atlas. Every subscriber receives the new pointer through its receiver. Use this for a font size setting in your addon, and only resize fonts you added yourself.
Releasing fonts
In your unload function, release every font you added or subscribed to, using the same receiver:
void AddonUnload()
{
APIDefs->Fonts_Release("FONT_MYADDON_HEADER", ReceiveFont);
s_HeaderFont = nullptr;
}
Once the last subscriber has released a font, Nexus removes it from the atlas. A receiver you forget to release would point into your unloaded DLL, which is one of the references Nexus cleans up and warns about after unloading.