gohud

Opacity — the game behind the panel

← Theming

Popups, dialogs, sheets, cards, HUD panels, alerts and snackbars draw their face at 80% opacity. The fight carries on behind a confirm dialog; the map shows under an inventory sheet. In a game this is not decoration — it is what keeps the player oriented. A fully solid panel erases where they were standing the moment a window opens.

Only the face thins out. Text, icons, buttons, badges and quick slots stay sharp, and so do borders and shadows. A translucent panel reads as glass only while its outline is crisp; fade the outline and you cannot tell where the panel ends. Fade the content and the UI cannot be read at all — that is not a transparent window, it is a bug. This is why the value is never applied through modulate.a.

Five layers, most specific first

OrderWhereUnitReach
the argument at that call — surface.alpha, GoStyle.card(…, alpha)ratio 0.0–1.0one window
GoConfig.container_alpha_overrides[kind]ratio 0.0–1.0one kind of panel, project-wide
GoConfig.metric_overrides[<kind>_alpha]percentprojects that keep every measurement in one place
GoConfig.container_alpharatio 0.0–1.0every panel at once
the theme's GoHud/constants/<kind>_alphapercentwhat the look decides — the source of truth

With none of them set the value is 100, so nothing about an older theme changes.

Opacity is a ratio everywhere — except in the theme. Every alpha field and argument takes 0.0–1.0, the same units as Color.a and modulate.a, and a negative value means "not set". The one exception is the theme's constants, because a Theme constant cannot hold a float: those and the channel that overrides them (metric_overrides, which shares the theme's names and integer type) are written as 80. Nothing else is.
# One window only — a confirm dialog that must not hide the fight behind it
surface.alpha = 0.6
sheet.alpha = 0.7
dialogs.alpha = 0.9                          # @export fields are ratios too
drawer.alpha = 0.7
GoPopover.open(slot, body, {"alpha": 0.9})
var glass := GoStyle.card(Color.TRANSPARENT, -1.0, -1.0, -1.0, 0.5)

# Per kind — keep the HUD nearly solid, because its text sits straight over the world
GoUi.config.container_alpha_overrides = {
    GoTheme.BOX_PANEL: 0.7,                   # dialogs and sheets can breathe
    GoTheme.BOX_HUD: 0.95,
}
GoUi.refresh()                               # redraws widgets that are already open

# The whole project — a busy world wants its panels back to solid
GoUi.config.container_alpha = 1.0
GoUi.refresh()

GoUi.surface_alpha(GoTheme.BOX_PANEL)        # the resolved ratio, e.g. 0.8

What follows the value, and what does not

Follows it — containersIgnores it — things you press, and markers
GoSurface (the one shell behind dialogs, sheets and dropdowns) · GoSheet · GoDialogs · GoDrawer · GoPopover · GoNotice · GoSnackbar · GoPromptCard · GoCoachMark · GoConsole every button · GoSlot (quick slots) · GoBadge · segmented controls · choice cells · chips · discs and avatars
GoStyle.card() · hud_panel() · overlay_panel() · alert() · plate() · edge_card_panel() · style_notice_panel() · floating() · box() · surface() all text and icons

A button whose state is washed out no longer says what it is, and a badge exists to make two characters legible — neither is a container, so neither follows the value.

Popup menus stay solid (popup_alpha 100). The engine may host a PopupMenu in its own Window, and there the OS does not composite it with the game: translucency comes out black rather than see-through. Lower it only in projects that embed their subwindows (gui_embed_subwindows).

Three details that come from real screens

Custom faces fade too — and that is the part that silently breaks

The cut-corner panel (GoStyleBoxCut) and the forged frame (GoStyleBoxMedieval) are not StyleBoxFlat; they draw themselves. Put the opacity only in the flat branch and these themes quietly ignore it while every value-based test still passes. Both fade their background and keep glow, rivets, corner engraving and bevels at full strength — and the medieval face's grain and bevel were always proportional to its background alpha, so they thin out along with the panel.

Which is the wider point: bg_color.a == 0.8 is a number. The world shows through and the text is still legible is the requirement. gohud checks the first in its headless suite and the second by drawing panels over diagonal stripes on a virtual monitor (tests/gohud_alpha_shot.gd) — on the flat, the cut and the forged face, in both the dark and the light theme.