HUD elements
Status: Implemented (API 1.21). Parts of the HUD the player moves, scales, hides and styles in the HUD editor and in Appearance > HUD, with an optional cached drawing.
Function table: hud. Related: HUD (layers), The UI Kit, Appearance Pages.
Layers or elements
HUD layer (cl_hud_layer_register, API 1.0) |
HUD element (cl_hud_element_register, API 1.21) |
|
|---|---|---|
| Where it draws | Anywhere on the screen, you decide | In its own box; the player places the box |
| HUD editor, Appearance > HUD | No | Yes: drag, scale, hide, Vanilla / Fancy style |
| Saved placement | No | Yes, anchored, survives window and GUI-scale changes |
| Cost per frame | Your render callback every frame | Every frame, or only when it changed (cached) |
Use an element for anything the player looks at while playing (a compass, a counter, a timer). Use a layer for things that are not boxes (a full-screen tint, markers over the world).
Registering
local bar = cl.hud.element_register{
id = "compass", label = "Compass bar", icon = "marker",
width = 160, height = 14,
anchor = "top", x = 0, y = 6,
panel = true, -- Fancy draws the HUD panel behind it
cached = true, -- drawn again only after bar:invalidate()
visible = function() return cl.entity.client_player() ~= nil end,
render = function(g, w, h)
g:ui_text("N", w / 2 - 3, 2, "small", 0)
end,
}
| Field | Meaning |
|---|---|
id |
Unique in your mod: a-z, 0-9, _, -, .. The player’s placement is saved under mod.<mod id>.<id>; registering the same id again (a hot reload) replaces the element and keeps the placement. |
label, icon |
The name and icon in the HUD editor and in Appearance > HUD. |
width, height |
The box in GUI pixels. Change it later with e:set_size(w, h). |
anchor, x, y |
The default position: one of the 9 screen points (top_left, top, top_right, left, center, right, bottom_left, bottom, bottom_right) and an offset inward from it. |
panel |
In the Fancy style the HUD panel (with the opacity the player set) is drawn behind the element. |
cached |
See below. |
visible |
Optional; false skips the element this frame (and the editor shows a placeholder). |
render(g, w, h) |
Draw in the element’s own box: (0, 0) is its top left. The player’s position and scale are applied around it. |
Functions on the element: e:set_size(w, h), e:invalidate(), e:shown() (false while the player has hidden it), e:remove().
Cached elements
With cached = true the engine records what render drew and replays it every frame without calling your mod. Call e:invalidate() when what it shows changes:
cl.on("tick.client_post", function()
local yaw = math.floor(cl.entity.client_player():rotation().yaw)
if yaw ~= last_yaw then last_yaw = yaw; bar:invalidate() end
end)
The recording is also redrawn when the style, the theme, the fonts, the GUI scale or the placement change. A cached element costs well under a microsecond per frame; drawing that is not plain shapes and text (items, scissors) is drawn directly every frame.
The style
Inside render, g:panel, g:hud_panel, g:ui_text and g:icon follow the element’s own style (the player can set it per element in Appearance > HUD). cl.ui.hud_fancy() tells the HUD’s style for your own decisions.
C
static void draw_bar(cl_gui g, int32_t w, int32_t h, void* user) {
cl_gui_ui_text(g, CL_STR("N"), (float)w / 2 - 3, 2, CL_UI_TEXT_SMALL, 0);
}
void setup_hud(void) {
cl_hud_element_desc d = CL_HUD_ELEMENT_DESC_INIT;
d.id = CL_STR("compass");
d.label = CL_STR("Compass bar");
d.width = 160;
d.height = 14;
d.anchor = CL_HUD_TOP;
d.y = 6;
d.panel = true;
d.cached = true;
d.render = draw_bar;
cl_hud_element bar;
cl_hud_element_register(&d, &bar);
}
C++: clight::hud::element_register(&d) returns Expected<clight::HudElement> with invalidate(), set_size(), shown(), remove().
Elements are client-only (CL_E_WRONG_SIDE on a dedicated server). Register them in lifecycle.client_setup. At most 64 per game, and the HUD layout holds 18 mod elements at a time.