Call an icon by its name
Widgets never hold a picture. They ask for a name, and the icon set in use decides what is drawn — swap the set and every icon changes without touching a line of code.
GoStyle.icon_button(GoIconSet.SETTINGS, open_settings) # a button
slot.icon_name = GoGameIcons.BACKPACK # a quick slot
var mark := GoUi.icons().node(&"cloud_rain", 24) # a bare Control, any size
GoUi.icons() is the set in use. A name it cannot draw becomes an empty box that keeps its space, with a warning in debug builds, so a missing icon never shifts a row.
Find an icon
Every drawing gohud ships. Search by name or by what it shows, narrow it to a set or a group, and pick an icon to copy its name.
Names and search words stay English in every language — they are what you type in code.
Four sets, one lookup
Every set answers the same call. The big ones are added on top of the set in use.
| Set | Names | Constants | Turn it on |
|---|---|---|---|
| Default | 84 | GoIconSet | Always on |
| Medieval | 16 engraved | — | GoUi.use_preset(GoThemePresets.MEDIEVAL_DARK) |
| Game | 187 | GoGameIcons | GoUi.add_icons(GoGameIcons.icon_set()) |
| Library | 1,000 | GoIconLibrary | GoUi.add_icons(GoIconLibrary.icon_set()) |
GoUi.add_icons(GoIconLibrary.icon_set()) # the library — and the game set under it
GoUi.add_icons(GoGameIcons.icon_set()) # or the game set alone
The library falls back to the game set and the game set to the default set, so one line makes 1,271 names drawable. A set lists its drawings as paths and reads a file only the first time its name is drawn: adding the library reads a table of paths (about 30 ms on a desktop), not 1,000 textures.
addons/gohud/icons/; the default “export all resources” needs nothing.How a name is found
One order for every set, so you can tell which drawing wins.
- Every set's own drawings first — the set in use, then each extra set, then their fallbacks, level by level. A set's own drawing is a texture, a path or an icon-font glyph.
- If nothing drew it, an alias is tried:
gearleads tosettings,xtoclose. One hop only. - Still nothing: an empty box that keeps its space.
That order is why the medieval preset's engraved sword stays on top when you add the library — its own drawing is found before anyone's fallback.
GoUi.use_preset(GoThemePresets.MEDIEVAL_DARK)
GoUi.add_icons(GoIconLibrary.icon_set())
GoUi.icons().texture(&"sword") # the medieval engraving — its own drawing comes first
GoUi.icons().texture(&"rocket") # from the game set
GoUi.icons().canonical(&"gear") # &"settings" — an alias
Presets, your set and extra sets
Three places decide what is drawn.
| Call | What it does |
|---|---|
GoUi.use_preset(…) | Theme, skin and icon set in one go. Clears config.icons, keeps config.extra_icons. |
GoUi.config.icons = my_set | Replaces the preset's icon set with yours. |
GoUi.add_icons(set) | Adds a set that is looked in after the one in use. It survives preset changes. |
Your own drawings
Override a few names, add a whole folder, or plug in an icon font — the calling code stays the same.
# Override a few names — everything else still comes from the set in use
var mine := GoIconSet.new()
mine.fallback = GoUi.icons()
mine.textures = {GoIconSet.CLOSE: preload("res://art/close.svg")}
GoUi.config.icons = mine
# A folder of drawings — file name = icon name, each read when first drawn
GoUi.config.icons = GoIconSet.from_folder("res://art/icons", GoUi.icons())
- Draw on a 24×24 grid with a white stroke. Color comes from
modulate, which can only darken — a black drawing stays black on every theme. - Import SVGs as
DPITextureso they stay sharp in a 64 dp inventory slot. - Icons never mirror in right-to-left languages. Only
backandforwardchange direction, and you choose those by name. - An icon font works too: fill
fontandcodepoints. Nothing else changes.
Names, groups and search
The rules the bundled sets follow, and the calls that find a name.
- lower_snake_case, the thing drawn first and its state last:
volume_off,battery_charging,arrow_bar_left. - No group prefixes. Groups are data, so a name stays the same wherever it is filed.
- Library names are Tabler's names with underscores:
cloud-rainon tabler.io iscloud_rainhere. Tabler's names for drawings gohud already had lead there as aliases (shopping_cart→cart). - A synonym is an alias, never a second drawing.
search()
var icons := GoUi.icons()
icons.search("arrow left", 5) # best matches first: back, arrow_bar_left …
icons.search("rain") # cloud_rain, then drawings tagged "rain"
group_names() · names_in_group()
icons.group_names() # every group key, in lookup order
icons.names_in_group(&"weather") # one group, in display order — every set's share of it
icons.group_title(&"weather") # "Weather & sky"
canonical() · has_icon()
icons.canonical(&"gear") # &"settings"
icons.canonical(&"treasure_chest") # &"chest" — Tabler's name for a game drawing
icons.has_icon(&"cloud_rain") # true once the library is added — nothing is loaded to answer
Where the drawings come from
Everything is MIT. The notices travel in the ZIP as THIRD_PARTY_NOTICES.md.
| Set | Source | License |
|---|---|---|
| Default | Drawn for gohud | MIT |
| Medieval | Drawn for gohud | MIT |
| Game | 171 from Tabler Icons 3.46.0, 16 drawn for gohud | MIT |
| Library | Tabler Icons 3.46.0 | MIT |
If you plug in someone else's icons, write their source in GoIconSet.attribution — and keep commercial icon fonts inside your game, not in a fork you publish.