Skip to content

Themed GUIs, HUD elements and appearance pages

Lesson 9.8

Players choose how Celestial looks in Appearance: the Vanilla style (the game’s own widgets) or the Fancy style (the Celestial design), and a colour theme. With the UI kit (API 1.21) your screens, HUD parts and settings follow that choice by themselves.

A themed screen

Add .themed = true (the last field of clight::ScreenSpec) and use the kit widgets:

void open_settings() {
    clight::screen::open({
        .title = "Compass Plus",
        .pause = false,
        .init = [](clight::Screen s) {
            int32_t x = s.width() / 2 - 150, y = 30;
            s.widget_panel(x - 14, y - 14, 328, 210);
            s.widget_heading(x, y, "Compass Plus", 1);
            s.toggle(x, y + 30, 300, 20, "Show the compass bar", true, [](clight::Widget w) {
                bool on = w.value() >= 0.5;
                (void)on;
            });
            s.slider(x, y + 56, 300, 20, "Bar width", 80, 240, 160, 10, [] {});
            s.dropdown(x, y + 86, 300, 20, "Labels", "Letters\nDegrees", 0, [](clight::Widget d) { (void)d.value(); });
            s.button(x + 210, y + 160, 90, 20, "Done", [s] { s.close(); });
        },
        .themed = true,
    });
}

Switch Appearance > Style while the screen is open and it redraws in the other style. With lambdas there are toggle, icon_button, dropdown, tabs, list, card and color_picker; widget_panel and widget_heading need no callback. A list is filled with w.list_add(title, detail, icon). The UI Kit has the table.

Drawing in the right style

In the .render callback of a themed screen, and in HUD elements, the clight::Gui methods panel, ui_text, icon and control draw in the player’s style:

.render = [](clight::Screen, clight::Gui g, int32_t, int32_t, float) {
    g.panel(10, 10, 120, 40);
    g.ui_text("Distance", 18, 16, CL_UI_TEXT_SMALL, 0);   // 0: the style's colour
},

clight::ui::fancy() tells you the style, clight::ui::color("panel") and clight::ui::length("radius.box") give the theme’s values.

A HUD element

clight::HudElement g_bar;
int g_heading = 0;

void setup_hud() {
    cl_hud_element_desc d = CL_HUD_ELEMENT_DESC_INIT;
    d.id = clight::s("compass");
    d.label = clight::s("Compass bar");
    d.icon = clight::s("marker");
    d.width = 160;
    d.height = 14;
    d.anchor = CL_HUD_TOP;
    d.y = 6;
    d.panel = true;
    d.cached = true;
    d.render = [](cl_gui g, int32_t w, int32_t, void*) {
        const std::string text = std::to_string(g_heading);
        clight::Gui(g).ui_text(text, static_cast<float>(w) / 2 - 6, 2, CL_UI_TEXT_SMALL, 0);
    };
    if (auto e = clight::hud::element_register(&d)) g_bar = *e;
}

cached = true keeps your drawing; after g_heading changes, call g_bar.invalidate() and the game draws it once more. The player places the bar in the HUD editor (“From mods”).

An Appearance page

void setup_page() {
    cl_ui_page_desc d = CL_UI_PAGE_DESC_INIT;
    d.id = clight::s("settings");
    d.label = clight::s("Compass Plus");
    d.icon = clight::s("marker");
    auto page = clight::ui::page_register(&d);
    if (!page) return;
    page->option("bar.show", "Show the compass bar", "");
    page->choice("bar.labels", "Labels", "", "Letters\nDegrees");
    page->hud_element(g_bar);
}

The options are those you defined in your client config (define_bool, define_i32, …); the page edits and saves them.

Try it

Add a colour picker for the compass marker. Save the colour as "#RRGGBB" in the client config option bar.marker and show the option on the Appearance page.

Show a solution
// in .init
s.color_picker(x, y + 116, 300, 20, "Marker colour", 0xFFAA00, [](clight::Widget w) {
    char hex[8];
    std::snprintf(hex, sizeof hex, "#%06X", static_cast<unsigned>(w.value()) & 0xFFFFFFu);
    if (auto c = clight::config::open(CL_CONFIG_CLIENT)) {
        c->set_str("bar.marker", hex);
        c->save();
    }
    g_bar.invalidate();
});

// in setup_page
page->color("bar.marker", "Marker colour", "The centre marker");

Recap: .themed = true + kit widgets, g.panel / g.ui_text for your own drawing, clight::hud::element_register for placeable HUD parts, clight::ui::page_register for an Appearance page.