lua_egui (0.3.0)

Published 2026-10-21 15:35:42 -05:00 by tenk

Installation

[registries.forgejo]
index = "sparse+" # Sparse index
# index = "" # Git

[net]
git-fetch-with-cli = true
cargo add lua_egui@0.3.0 --registry forgejo

About 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.2.1
slotmap ^1.1.1
egui-wgpu ^0.36
image ^0.25
pollster ^1.0.1
Details
Cargo
2026-10-21 15:35:42 -05:00
1
36 KiB
Assets (1)
Versions (5) View all
0.3.1 2026-10-21
0.3.0 2026-10-21
0.2.0 2026-10-20
0.1.1 2026-10-18
0.1.0 2026-10-18