Screens, widgets and 2d drawing
Status: Partly implemented. 2D drawing in HUD layers and screens (
cl_gui_*), custom screens with vanilla widgets (button, checkbox, slider, text field, label) and their callbacks. Not yet:cl_gui_blitof texture files draws nothing (use GUI atlas sprites),cl_gui_itemdraws the item’s flat icon without the durability bar, text is drawn without formatting codes or styles, and a screen’schar_typedcallback is not called. An immediate-mode widget layer, lists and more widgets are Planned.
Function tables: gui, screen. Client only. HUD layers: HUD layers. Document screens: GUI screens (RmlUi).
2D drawing (cl_gui)
A cl_gui draw context is passed to a HUD layer’s or a screen’s render callback and is valid only during that call. Coordinates are GUI pixels (after the GUI scale), origin top left, like vanilla GuiGraphics. Colours are 0xAARRGGBB; an alpha of 0 counts as opaque, so 0xRRGGBB works like vanilla text colours.
| C | Lua (g:...) |
Does |
|---|---|---|
cl_gui_width(g), cl_gui_height(g), cl_gui_scale_factor(g) |
g:width(), g:height(), g:scale_factor() |
The scaled screen size and the GUI scale |
cl_gui_fill(g, x0, y0, x1, y1, argb) |
g:fill(...) |
A rectangle |
cl_gui_fill_gradient(g, x0, y0, x1, y1, top, bottom) |
g:fill_gradient(...) |
A vertical gradient |
cl_gui_outline(g, x, y, w, h, argb) |
g:outline(...) |
A 1-pixel outline |
cl_gui_text(g, s, x, y, argb, shadow) → end x |
g:text(s, x, y, argb, shadow) |
Text in the vanilla font |
cl_gui_text_component(g, text, x, y, argb, shadow) |
g:text_component(t, ...) |
A text component (its plain text today) |
cl_gui_text_centered(g, s, cx, y, argb, shadow) |
g:text_centered(...) |
Centred on cx |
cl_gui_text_width(s), cl_gui_line_height() |
cl.gui.text_width(s), cl.gui.line_height() |
Measure text |
cl_gui_sprite(g, sprite, x, y, w, h) |
g:sprite(...) |
A GUI atlas sprite: "minecraft:hud/heart/full", or "<modid>:<path>" from assets/<modid>/textures/gui/sprites/<path>.png |
cl_gui_blit(g, texture, x, y, w, h, u0, v0, u1, v1, tint) |
g:blit(...) |
Any texture (draws nothing yet) |
cl_gui_item(g, stack, x, y, decorations), cl_gui_item_by_name(g, id, x, y) |
g:item(stack, x, y, true), g:item_by_name("minecraft:apple", x, y) |
A 16x16 item icon (and its count) |
cl_gui_push_pose, cl_gui_pop_pose, cl_gui_translate(g, x, y), cl_gui_scale(g, x, y) |
g:push_pose(), … |
Move or scale what follows |
cl_gui_push_scissor(g, x0, y0, x1, y1), cl_gui_pop_scissor |
g:push_scissor(...), … |
Clip to a rectangle (nested clips intersect) |
cl_gui_tooltip(g, s, x, y) |
g:tooltip("Line 1\nLine 2", mx, my) |
A vanilla tooltip box |
A pose or scissor you forget to pop is reset after your callback, so the vanilla GUI is never affected.
Custom screens
typedef struct cl_screen_desc {
uint32_t struct_size;
cl_str title; // a translation key or plain text
bool pause, background, close_on_esc; // all true by default
cl_screen_init_fn init; // (s, user): build the widgets; runs again after every resize
cl_screen_render_fn render; // (s, g, mouse_x, mouse_y, partial_tick, user)
cl_screen_tick_fn tick; // (s, user): 20 times a second
cl_screen_key_fn key; // (s, key, scancode, modifiers, user) -> true = used
cl_screen_char_fn char_typed; // not called yet
cl_screen_mouse_fn mouse; // (s, x, y, button, action, user) -> true = used
cl_screen_scroll_fn scroll; // (s, x, y, dx, dy, user) -> true = used
cl_screen_close_fn close; // (s, user)
void* user;
} cl_screen_desc;
/* CL_SCREEN_DESC_INIT */
cl_result cl_screen_open(const cl_screen_desc* desc, cl_screen* out); // replaces the current screen
cl_result cl_screen_close(cl_screen s);
bool cl_screen_is_open(cl_screen s);
int32_t cl_screen_width(cl_screen s); int32_t cl_screen_height(cl_screen s);
Widgets
Widgets are owned by the screen and removed when init runs again and when it closes.
| C | Lua (on the screen s) |
Callback gets |
|---|---|---|
cl_widget_button(s, x, y, w, h, label, on_press, user, &out) |
s:button(x, y, w, h, label, fn) |
the button |
cl_widget_checkbox(s, x, y, label, checked, on_change, user, &out) |
s:checkbox(x, y, label, checked, fn) |
the checkbox (value() 1 or 0) |
cl_widget_slider(s, x, y, w, h, label, min, max, value, step, on_change, user, &out) |
s:slider(...) |
the slider (value()); the label shows "label: value"; step 0 = smooth |
cl_widget_text_field(s, x, y, w, h, hint, max_length, on_change, user, &out) |
s:text_field(...) |
the field (text()) |
cl_widget_label(s, x, y, label, argb, centered, &out) |
s:label(x, y, text, colour, centered) |
Every widget: cl_widget_set_active, set_visible, set_label, set_tooltip, set_bounds, value / set_value, text / set_text, remove (Lua w:set_label(...), …). Labels are literal text.
Bindings
| C | C++ | Lua |
|---|---|---|
cl_screen_open(&d, &s) |
clight::screen::open({.title = "Hello", .init = [](clight::Screen s) { s.button(10, 10, 200, 20, "Done", [s] { s.close(); }); }}) → Expected<Screen> (lambdas freed when it closes) |
cl.screen.open{ title = "Hello", init = function(s) ... end } |
cl_widget_button(...) |
s.button(x, y, w, h, label, fn) |
s:button(...) |
| drawing | clight::Gui(g).text("Hi", 4, 4, 0xFFFFFF, true) |
g:text("Hi", 4, 4, 0xFFFFFF, true) |
Example (Lua)
local volume = 50
local function open_settings()
cl.screen.open{
title = "Settings",
pause = false,
init = function(s)
local cx = s:width() // 2
s:slider(cx - 100, 60, 200, 20, "Volume", 0, 100, volume, 5, function(w) volume = w:value() end)
s:button(cx - 100, s:height() - 40, 200, 20, "Done", function() s:close() end)
end,
render = function(s, g, mx, my)
g:text_centered("My Mod", s:width() // 2, 20, 0xFFFFFF, true)
end,
}
end
Keep the screen’s state outside it (here volume): init runs again after every resize.
Themed screens (API 1.21)
Open a screen with themed = true and it follows the player’s Appearance style: the widgets above draw as the kit’s widgets (vanilla widgets in Vanilla, the design system in Fancy), and new widget kinds (toggles, dropdowns, tabs, lists, cards, a colour picker) are available. See The UI Kit.
Planned
Texture blits, items with durability bars, styled text and formatting codes, char_typed, list and cycle widgets, and an immediate-mode widget layer for tool windows.