raygui
Add buttons, sliders, text fields, lists and dialogs to a raylib window with immediate-mode controls.
import "std:raygui"std:raygui draws controls inside a raylib window: buttons, checkboxes, sliders, text fields, lists, dropdowns, dialogs and more. It is immediate mode. There are no widget objects. Every frame you call raygui.button(bounds, "Click"), which draws the button and tells you whether it was clicked right now.
Reach for it for tools, editors and debug panels in a game or visualisation. For a full application interface, use ui with window.
Controls need an open raylib window, so these examples compile but don't run here, except for the small ones near the end.
A button#
A control takes its bounds, a rectangle {x, y, width, height}, and returns its answer. A button returns true on the frame it is clicked:
import "std:raylib"
import "std:raygui"
int clicks = 0
raylib.runWindow(def(ms) (
if raygui.button({x: 20, y: 20, width: 140, height: 36}, "Click me") (
clicks += 1
)
raygui.label({x: 20, y: 70, width: 200, height: 24}, "clicks: " ++ clicks)
), {width: 320, height: 160, title: "Button", background: "#f5f5f5"})Move the button, change its label, and click it ten times.
You keep the state#
The control doesn't remember anything. A checkbox gets its current value and returns the new one after this frame's input, and you store it:
import "std:raylib"
import "std:raygui"
boolean sound = true
number volume = 0.5
raylib.runWindow(def(ms) (
sound = raygui.checkBox({x: 20, y: 20, width: 24, height: 24}, "Sound", sound)
volume = raygui.valueSlider(
{x: 20, y: 60, width: 200, height: 24},
volume,
{min: 0, max: 1, textLeft: "Vol"}
)
raygui.progress({x: 20, y: 100, width: 200, height: 16}, volume)
), {width: 300, height: 160, title: "State", background: "#f5f5f5"})The pattern is always value = control(bounds, ..., value). Forget the assignment and the control snaps back every frame.
raygui.checkBox(bounds, "Sound", sound) is called without storing the result. What happens when you click it?
Text and numbers#
textField takes and returns {text, editing}. Clicking it starts editing, and Enter or clicking elsewhere stops. spinBox and valueField do the same for whole numbers:
import "std:raylib"
import "std:raygui"
auto name = {text: "Ada", editing: false}
auto age = {value: 36, editing: false}
raylib.runWindow(def(ms) (
name = raygui.textField({x: 20, y: 20, width: 200, height: 28}, name)
age = raygui.spinBox({x: 20, y: 60, width: 200, height: 28}, age, {min: 0, max: 120})
raygui.label({x: 20, y: 100, width: 300, height: 24}, name.text ++ " is " ++ age.value)
), {width: 300, height: 160, title: "Fields", background: "#f5f5f5"})Lists and choices#
list takes {selected, scroll}, and dropdown takes {selected, open}. buttonGroup, cycleButton, toggleSwitch and tabs take and return a 1-based selected item. A dropdown covers what is below it, so draw it last:
import "std:raylib"
import "std:raygui"
string[] fruit = ["Apple", "Banana", "Cherry", "Date"]
auto chosen = {selected: 1, scroll: 1}
auto menu = {selected: 1, open: false}
raylib.runWindow(def(ms) (
chosen = raygui.list({x: 20, y: 20, width: 140, height: 100}, fruit, chosen)
raygui.label({x: 180, y: 20, width: 140, height: 24}, "list: " ++ fruit[chosen.selected])
menu = raygui.dropdown({x: 180, y: 60, width: 140, height: 28}, fruit, menu)
), {width: 340, height: 180, title: "Choices", background: "#f5f5f5"})Dialogs#
messageDialog returns the 1-based button clicked this frame (0 for its close button, null for nothing yet). inputDialog returns {text, button} and wants its own state passed back:
import "std:raylib"
import "std:raygui"
boolean asking = true
string answer = ""
raylib.runWindow(def(ms) (
raygui.label({x: 20, y: 20, width: 300, height: 24}, "answer: " ++ answer)
if asking (
auto reply = raygui.messageDialog(
{x: 40, y: 50, width: 240, height: 100},
"Delete everything?",
{title: "Careful", buttons: ["Yes", "No"]}
)
if reply != null (
answer = if reply == 1 then "yes" else "no"
asking = false
)
)
), {width: 320, height: 200, title: "Dialog", background: "#f5f5f5"})Laying controls out#
Controls are positioned by hand, so put the sums in a helper. A function that returns the next row keeps a form tidy:
import "std:raylib"
import "std:raygui"
def row(int n) object -> {x: 20, y: 20 + (n * 40), width: 200, height: 30}
raylib.runWindow(def(ms) (
raygui.button(row(0), "One")
raygui.button(row(1), "Two")
raygui.button(row(2), "Three")
), {width: 260, height: 160, title: "Rows", background: "#f5f5f5"})Styles, locking and icons#
raygui.setStyle("default", "text_size", 20) changes a property of every control, and "button" or "textbox" of only that kind. Colours take any colour value (raygui.setStyle("button", "base_color_normal", "#89b4fa")). loadStyle(path) loads a .rgs style file. lock() and disable() make the controls drawn after them ignore input, until unlock() and enable().
A few helpers don't need a window, so you can try them here. raygui.iconText(icon, text) puts one of raygui's numbered icons in front of a label:
import "std:raygui"
log raygui.iconText(1, "Open")
log raygui.state()
raygui.lock()
log raygui.isLocked()
raygui.unlock()
log raygui.isLocked()Try other icon numbers. The text it returns is what you pass as a control's label.
An icon label
Build the label for a save button. Icon 2 followed by the text Save, using iconText, and print it.
#002#Save
API reference#
53 members, generated from the std:raygui source of OSL 9.3.0.
Functions
raygui.button(any bounds, string text) booleanbutton draws a button and returns true when it was clicked this frame.
raygui.buttonGroup(any bounds, any items, int selected) intbuttonGroup draws a row of toggle buttons, one per item, and returns the 1-based selected item after this frame's input. Throws ValueError when selected is out of range.
raygui.checkBox(any bounds, string text, boolean checked) booleancheckBox draws a check box and returns whether it is checked after this frame's input.
raygui.colorBarAlpha(any bounds, string text, number alpha) numbercolorBarAlpha draws an alpha bar and returns the alpha, 0 to 1, after this frame's input.
raygui.colorBarHue(any bounds, string text, number hue) numbercolorBarHue draws a hue bar and returns the hue, 0 to 360, after this frame's input.
raygui.colorPanel(any bounds, string text, any color) {a: int, b: int, g: int, r: int}colorPanel draws a saturation/value color square and returns the color {r, g, b, a} after this frame's input.
raygui.colorPicker(any bounds, string text, any color) {a: int, b: int, g: int, r: int}colorPicker draws a color picker and returns the color {r, g, b, a} after this frame's input.
raygui.cycleButton(any bounds, any items, int selected) intcycleButton draws a button that steps through items when clicked and returns the 1-based selected item after this frame's input. Throws ValueError when selected is out of range.
raygui.disable()disable greys out controls drawn afterwards and makes them ignore input.
raygui.disableTooltip()disableTooltip stops showing tooltips.
raygui.dropdown(any bounds, any items, object state) {open: boolean, selected: int}dropdown draws a dropdown list of items. state is {selected, open} (the 1-based selected item, default 1, and whether the list is open, default false); pass the returned state back in next frame. Draw open dropdowns last so their list covers other controls. Throws ValueError when selected is out of range.
raygui.enable()enable makes controls respond to input again after disable.
raygui.enableTooltip()enableTooltip shows the text set with setTooltip when the mouse rests on controls drawn afterwards.
raygui.getStyle(any control, any property) intDeprecated. Deprecated: use raygui.style(control, property) instead.
getStyle returns a style property, treating unknown names as the default control's first property.
raygui.gridCell(any bounds, number spacing, object? options) {column: int, row: int}?gridCell draws a grid of lines spacing apart and returns the 1-based {column, row} under the mouse, or null when the mouse is outside it. Options: subdivisions (lines between main lines, default 2) and text.
raygui.groupBox(any bounds, string text)groupBox draws a titled frame around a group of controls.
raygui.icon(int id, any position, object? options)icon draws one of raygui's icons (by number) with its top-left corner at a point {x, y}. Options: scale (pixels per icon pixel, default 1) and color (default "#000000"). Throws StateError when no window is open.
raygui.iconText(int icon, string text) stringiconText returns text prefixed with one of raygui's icons (by number), for use as a control's label.
raygui.inputDialog(any bounds, object state, object? options) {button: int?, text: string}inputDialog draws a dialog with a text field. state is {text} (the returned {text, button} works too); it returns {text, button}, where button is the 1-based button clicked this frame, 0 for the close button, or null. Options: title, message, buttons (default ["OK"]), maxLength (default 256) and secret (hide the text, default false).
raygui.isLocked() booleanisLocked reports whether controls are locked.
raygui.label(any bounds, string text)label draws text.
raygui.labelButton(any bounds, string text) booleanlabelButton draws text that acts as a button and returns true when it was clicked this frame.
raygui.line(any bounds, string text)line draws a separator line with optional text.
raygui.list(any bounds, any items, object state) {scroll: int, selected: int?}list draws a scrollable list of items. state is {selected, scroll} (the 1-based selected item or null for none, and the 1-based first visible item, default 1); pass the returned state back in next frame. Throws ValueError when selected or scroll is out of range.
raygui.loadStyle(string path) result<unit, error>loadStyle loads a raygui style file (.rgs). Fails with StateError when no window is open and NotFoundError or IOError when the file can't be read.
raygui.loadStyleDefault()loadStyleDefault restores raygui's default style. Throws StateError when no window is open.
raygui.lock()lock makes controls ignore input while still drawing normally.
raygui.locked() booleanDeprecated. Deprecated: use raygui.isLocked() instead.
locked reports whether controls are locked.
raygui.messageDialog(any bounds, string message, object? options) int?messageDialog draws a message box and returns the 1-based button clicked this frame, 0 for its close button, or null when nothing was clicked. Options: title and buttons (an array of labels, default ["OK"]).
raygui.panel(any bounds, string text)panel draws a background panel with an optional title.
raygui.progress(any bounds, number value, object? options)progress draws a progress bar filled up to value. Takes valueSlider's options.
raygui.scrollSlider(any bounds, int value, object? options) intscrollSlider draws a scroll bar and returns its value after this frame's input. Options: min (default 0) and max (default 100).
raygui.scrollView(any bounds, any content, object? options) {scroll: {x: number, y: number}, view: {height: number, width: number, x: number, y: number}}scrollView draws a scrollable panel over content {x, y, width, height} and returns {scroll, view}: the scroll offset {x, y} to pass back in next frame and draw the content shifted by, and the visible area {x, y, width, height}, x, y its top-left corner as for bounds. Options: title and scroll (default {x: 0, y: 0}, a distance rather than a position).
raygui.setAlpha(number alpha)setAlpha sets the opacity controls are drawn with, from 0 to 1. Throws ValueError outside that range.
raygui.setIconScale(int scale)setIconScale sets how many pixels each icon pixel takes in controls.
raygui.setState(any state)setState sets the state controls are drawn in: "normal", "focused", "pressed" or "disabled" (older scripts passed 0 to 3). Throws ValueError for anything else.
raygui.setStyle(any control, any property, any value)setStyle sets one style property of a control: control is a name such as "default" (all controls), "button", "textbox" or "listview", property a name such as "text_size", "border_width" or "base_color_normal", and value a number or, for color properties, a color. Throws ValueError for unknown names and StateError when no window is open.
raygui.setTooltip(string text)setTooltip sets the tooltip for controls drawn afterwards.
raygui.spinBox(any bounds, object state, object? options) {editing: boolean, value: int}spinBox draws a whole-number field with - and + buttons. state is {value, editing}; pass the returned state back in next frame. Options: min (default 0), max (default 100) and text (a label beside it).
raygui.state() stringstate returns the state controls are drawn in: "normal", "focused", "pressed" or "disabled".
raygui.statusBar(any bounds, string text)statusBar draws a status bar with text.
raygui.style(any control, any property) intstyle returns a control's style property as a number, naming them as setStyle does. Throws ValueError for unknown names and StateError when no window is open.
raygui.styleColor(any control, any property) {a: int, b: int, g: int, r: int}styleColor returns a control's color style property as {r, g, b, a}. Throws ValueError for unknown names and StateError when no window is open.
raygui.tabs(any bounds, any items, int selected) {closed: int?, selected: int}tabs draws a tab bar of items and returns {selected, closed}: the 1-based selected tab after this frame's input, and the tab whose close button was clicked (null for none). Throws ValueError when selected is out of range.
raygui.textField(any bounds, object state, object? options) {editing: boolean, text: string}textField draws a single-line text field. state is {text, editing} (the text, and whether it has keyboard focus; clicking it starts editing and Enter or clicking elsewhere stops); pass the returned state back in next frame. Options: maxLength (characters, default 256).
raygui.textWidth(string text) inttextWidth returns how wide text is in the current style, in pixels. Throws StateError when no window is open.
raygui.toggle(any bounds, string text, boolean active) booleantoggle draws a toggle button and returns whether it is on after this frame's input; pass the result back in next frame.
raygui.toggleSwitch(any bounds, any items, int selected) inttoggleSwitch draws a sliding switch between items and returns the 1-based selected item after this frame's input. Throws ValueError when selected is out of range.
raygui.unlock()unlock makes controls respond to input again after lock.
raygui.valueBar(any bounds, number value, object? options) numbervalueBar draws a slider that fills up to its value and returns the value after this frame's input. Takes valueSlider's options.
raygui.valueField(any bounds, object state, object? options) {editing: boolean, value: int}valueField draws a whole-number field to type into. state is {value, editing}; pass the returned state back in next frame. Options: min (default 0), max (default 100) and text (a label beside it).
raygui.valueSlider(any bounds, number value, object? options) numbervalueSlider draws a slider with a handle and returns its value after this frame's input. Options: min (default 0), max (default 1), textLeft and textRight (labels on either side).
raygui.windowBox(any bounds, string title) booleanwindowBox draws a window panel with a title bar and returns true when its close button was clicked.