Luau Bindings — gui

The require("gui") script API — a retained, event-driven UI layer over immediate-mode imgui. Create widgets as objects, set their properties, attach event handlers; gui maintains the immediate-mode frame for you. This is the friendly default for scripts and user programs — raw imgui stays for AntOS internals, power users, and dynamic UIs. Every function is [antos]. Design & native core: antos_gui.

Design-stage. gui is a proposed convenience layer built on the (also design-stage) imgui windowing system. The shape below is the intended API.

local gui = require("gui")
local win = gui.window("Counter")
local lbl = win:label("count: 0")
local n = 0
win:button("Add").on_click = function()
  n = n + 1
  lbl.text = "count: " .. n       -- just set a property; the UI updates itself
end
gui.run()                          -- event loop on *this* (your) thread

Your code runs on your own thread — gui marshals widget changes to the render thread and delivers events back to you. You never write a per-frame draw, and a slow handler stalls only your program, not the desktop.

Windows & widgets

Call Returns
gui.window(title [, opts]) A window object. opts.context targets "local" / "remote" / "both" (see below).
win:label(text) · win:button(text) A label / button widget.
win:checkbox(text, value) · win:input(label, value) A checkbox / text field.
win:slider(label, value, min, max) · win:combo(label, items, i) A slider / drop-down.
win:row{...} · win:column{...} · win:group(title) Layout containers.
win:menu(title) → menu:item(label) A window menu bar (see imgui menus).

Properties (retained, mutable, thread-safe)

Set a property and the widget updates on the next frame — no redraw call:

Property On
.text labels, buttons, inputs
.value checkboxes, sliders, inputs, combos
.enabled · .visible any widget

Events

Assign a handler; gui calls it (on your thread) when it fires:

Event Fires
.on_click buttons, menu items
.on_change checkboxes, sliders, inputs, combos
win.on_close the window is closed

The loop

Function Behaviour
gui.run() Run the event loop on your thread — dispatch events to handlers until all windows close.
gui.quit() Stop the loop.

Dialogs

A message box blocks your thread by default and returns the pressed button — the render thread keeps drawing it, so the modal stays live while your code waits, exactly like a normal desktop dialog. This is safe precisely because your code runs on its own thread, not the render thread.

Call Behaviour
gui.message_box(title, text [, buttons]) Show a modal and block until answered → the pressed button.
gui.message_box(title, text, buttons, on_result) Non-blocking — returns at once; on_result(button) fires when answered.
if gui.message_box("Quit?", "Save before quitting?", {"Save","Discard","Cancel"}) == "Save" then
  save()
end

Raw imgui's message_box can't block — its draw is on the render thread — so it polls instead. Blocking is gui's to offer because a gui program has its own thread to block.

Where it renders — local, remote, or both

Like an imgui window, a gui window targets the local desktop, the netImgui context (a connected PC), or both — gui reconciles its widget tree into each active context.

Call Effect
gui.window(title, { context = "local" }) Local desktop only.
gui.window(title, { context = "remote" }) Only on a connected PC over netImgui — nothing locally.
gui.window(title, { context = "both" }) Both — appears on the PC when one connects.
gui.window(title, { context = "panel" }) The keyboard touch panel — a portrait, ~230 PPI, 5-point-touch surface; its surface profile scales and target-floors the same widgets automatically.
gui.context(default) Set the default context for windows created after (state it once per app).
gui.contexts() Which are live — { local = true, panel = <present?>, remote = <connected?> }.
gui.surface(name) A surface's profile — { scale, input = "pointer" or "touch", points, orientation }.

Each surface carries a profile (scale from physical DPI, input mode, touch points, orientation), and gui reconciles the one tree into each through its profile — so a window on "panel" comes out finger-sized, portrait, and target-floored with no different code. On the panel's 5-point surface gui hit-tests each touch against the retained tree and dispatches concurrently, so several pads or faders respond at once (raw imgui's single mouse can't) — see surface profiles.

Because the tree is retained, this is cleaner than immediate mode: one widget, one handler, reconciled into every active context. A button on a "both" window is a single on_click — clicked on the machine or on the PC, gui delivers the one event to your thread once, no per-context bookkeeping.

gui uses imgui underneath, so a gui window docks, floats, and mirrors to netImgui exactly like a raw imgui one — you just don't manage the frame. Reach for raw imgui when you want immediate-mode control (procedural or per-frame-dynamic UIs); reach for gui for a conventional app.

Related

Important: The Ant64 family of home computers are at early design/prototype stage, everything you see here is subject to change.