lua_egui (0.2.0)
Installation
[registries.forgejo]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add lua_egui@0.2.0 --registry forgejoAbout this package
lua_egui
Declarative GUI trees written in Lua. Elements are added as plain tables and rendered every frame; user interaction is delivered back to Lua through hook callbacks.
The Lua side uses a generic widget vocabulary (colors, fills, spacing, enabled, min/max/round...). Backend specifics live in Rust, so the Lua API does not have to change if the backend is swapped.
local win = gui:add({
type = "window",
title = "demo",
pos = "center",
size = { x = 420, y = 260 },
})
win:add({ type = "label", text = "Hello", font_size = 20, color = { r = 96, g = 40, b = 160 } })
local button = win:add({ type = "button", text = "Click" })
button:on(function() print("clicked") end)
Host integration
Wire the tree into the Lua state, then render each frame:
lua.set_app_data(lua_hook::HookRegistry::new());
lua.set_app_data(lua_egui::GuiTree::new(&lua));
lua.globals().set("gui", lua.create_userdata(lua_egui::LuaGui))?;
// per frame
let output = ctx.run_ui(input, |ui| {
let mut ctx = ui.ctx().clone();
lua_egui::GuiTree::from_lua(&lua).render(&mut ctx, &lua);
});
lua_hook::LuaQueue::run(&lua); // deliver queued hooks
A full headless render to PNG lives in examples/screenshot.rs.
Elements
Added with gui:add(tbl) or node:add(tbl). Every element takes type
and no_close; containers listed as such accept children.
Display
| type | options |
|---|---|
label |
text, font_size?, color?, bold?, italic?, wrap? |
image |
path (file), size? = {x, y} (exact, keeps aspect by default) |
progress |
value (0..=1, settable), text? |
separator |
orientation? = "horizontal" | "vertical" |
Input
Stateful widgets keep their value in the node. The on callback receives
the new value; value (or selected for combo/tabs) can also be read
and written from Lua for two-way sync.
| type | options | on receives |
|---|---|---|
button |
text, color? (fill), enabled?, rounding? |
none |
checkbox |
text, value?, enabled? |
the new bool |
radio |
text, value?, enabled? |
the new bool (group exclusivity is Lua's job) |
slider |
text?, value?, min, max, round?, enabled? |
the new number |
text |
value?, hint?, rows? (>1 for multiline), enabled? |
the new string |
combo |
text, options = { ... }, selected? (1-based), width?, enabled? |
(index, text), index 1-based |
Containers
| type | options |
|---|---|
window |
title, pos = "center" | {x, y}?, size?, movable?, resizable?, collapsible?, title_bar? |
layout |
main_dir? = "left_to_right" | "right_to_left" | "top_down" | "bottom_up", main_wrap?, main_align?, main_justify?, cross_align?, cross_justify? ("min" | "center" | "max"), spacing? = {x, y} |
frame |
fill?, stroke?, stroke_width?, rounding?, margin? (number or {x, y}) |
columns |
columns? (n, children fill left-to-right then top-to-bottom) |
scroll |
direction? = "vertical" | "horizontal" | "both" |
tabs |
children provide title; selected is readable/writable (1-based) |
align |
x?, y? ("min" | "center" | "max") |
spacer |
size? = {x, y} |
target |
target (host-resolved screen anchor), offset? = {x, y} — see GuiTree::update_targets |
Shared options
| option | meaning |
|---|---|
color |
text/widget color, { r, g, b, a? } each 0..=255 |
fill |
background color, same shape as color |
stroke + stroke_width |
border (width defaults to 1) |
rounding |
corner radius in pixels |
margin |
padding inside a frame (number or {x, y}) |
spacing |
item spacing inside a layout ({x, y}) |
enabled |
interactive widgets, defaults to true |
no_close |
node refuses to close implicitly |
Every node supports close(), on_close hook, and (for containers) add.
Dependencies
| ID | Version |
|---|---|
| as-any | ^0.3.2 |
| egui | ^0.36 |
| lua_bundle | ^0.1.1 |
| lua_hook | ^0.1.1 |
| slotmap | ^1.1.1 |
| egui-wgpu | ^0.36 |
| image | ^0.25 |
| pollster | ^1.0.1 |