ui
The ui package provides a robust Immediate Mode GUI
for in-engine tooling, editors, and debug overlays.
Features:
- Comprehensive Widgets: Includes interactable controls like
button,checkbox,slider,inputText,colorPicker, and debug tools likeplot. - Layouts: Organize your interfaces using draggable
windows, collapsibleheaders,beginTabBarsystems, and horizontalbeginRows. - State Tracking: Utilizes an internal
_Statetracker and an ID stack (pushId/popId) to safely handle overlapping windows, focus states, and dynamically generated UI elements inside loops. - Styling: Easily tweak colors, sizing, fonts, and padding via
the
Stylestruct and theDEFAULT_STYLEconfiguration.
The overall lifecycle (start, draw, and end)
is managed automatically by the engine’s main loop.
During the frame, calling a widget function (like button)
will immediately return true if interacted with, allowing instant logic execution.
Visually, the UI commands are queued into a Command buffer and deferred until draw
is called. This deferred rendering guarantees proper Z-indexing, clipping (scissoring),
and overlapping of popup menus and tooltips.
Command
Section titled “Command”Command :: union { LineCommand, RectangleCommand, TriangleCommand, TextCommand, ScissorCommand, PopScissorCommand,}Union of all possible drawing commands recorded by the UI system.
These are executed in draw at the end of the frame.
DEFAULT_STYLE
Section titled “DEFAULT_STYLE”DEFAULT_STYLE :: Style { backgroundColor = gmath.Color{0.2, 0.2, 0.2, 0.9}, hotColor = gmath.Color{0.6, 0.6, 0.6, 1.0}, activeColor = gmath.Color{0.4, 0.4, 0.4, 1.0}, textColor = gmath.Color{1.0, 1.0, 1.0, 1.0}, buttonColor = gmath.Color{0.3, 0.3, 0.3, 1.0}, titleColor = gmath.Color{0.0, 0.0, 0.0, 1.0}, rounding = 2.0, padding = 2.0, outlineThickness = 0.5, itemHeight = 7.0, titleHeight = 8.0, titleButtonSize = 6.0, resizeSize = 6.0, scrollbarWidth = 2.0, scrollSpeed = 10.0, minimumScrollbarHeight = 20.0, separatorHeight = 0.5, plotHeight = 40.0, colorPreviewWidth = 30.0, fontSize = 6, font = .PixelCode,}Default style configuration (Dark theme).
Style :: struct { backgroundColor: gmath.Color, hotColor: gmath.Color, activeColor: gmath.Color, textColor: gmath.Color, buttonColor: gmath.Color, titleColor: gmath.Color, rounding: f32, padding: f32, outlineThickness: f32, itemHeight: f32, titleHeight: f32, titleButtonSize: f32, resizeSize: f32, scrollbarWidth: f32, scrollSpeed: f32, minimumScrollbarHeight: f32, separatorHeight: f32, plotHeight: f32, colorPreviewWidth: f32, fontSize: uint, font: generated.FontName,}Configuration struct defining the visual appearence of the UI.
WindowState
Section titled “WindowState”WindowState :: struct { position: gmath.Vector2, size: gmath.Vector2, isCollapsed: bool, scrollY: f32, contentHeight: f32, commands: [dynamic]Command, zIndex: f32, lastFrameSeen: u64, scissorRectangle: gmath.Rectangle,}Persistent state for a draggable window.
_State
Section titled “_State”@(private)_State :: struct { hotId: u64, // widget currently hovered activeId: u64, // widget currently clicked cursor: gmath.Vector2, // current layout position startX: f32, // where the current column started indentation: f32, // current x offset maxWidth: f32, // widest item in the current column windows: map[u64]WindowState, // state storage headers: map[u64]bool, // id -> is open inputBuffers: map[u64]strings.Builder, // id -> text buffer tabBars: map[u64]u64, // tab id -> active tab id idStack: [dynamic]u64, // id stack for loops and scopes currentWindowId: u64, // track if we are currently inside window focusedWindowId: u64, // track the last clicked window hoveredWindowId: u64, nextFocusedWindowId: u64, // candidate for focus next frame clickClaimedZ: f32, // z index of window claiming the click inRow: bool, rowStartX: f32, rowMaxHeight: f32, currentZIndex: f32, nextZIndex: f32, tooltipText: string, // if not empty drawn at the end of frame lastWidgetRectangle: gmath.Rectangle, // rect of the widget just drawn currentTabBarId: u64, tabSavedCursor: gmath.Vector2, tabContentHeight: f32, openComboId: u64, // id of currently open combo comboWidth: f32, // width of currently open combo isRecordingPopup: bool, // true if inside uiBeginCombo popupCursor: gmath.Vector2, // layout cursor for the popup popupCommands: [dynamic]Command, // draw list for popup mousePosition: gmath.Vector2, // store it to avoid unneeded matrix inverses
}Internal global state for the Immediate mode UI. Stores layout cursors, input state, and widget persistence maps.
beginCombo
Section titled “beginCombo”beginCombo :: proc (label: string, preview: string, width: f32 = 50.0) -> boolStarts a dropdown menu (combo box).
preview: The text to display on the closed button. Returnstrueif the dropdown is open and items should be rendered. Must be ended withendCombo.
beginRow
Section titled “beginRow”beginRow :: proc ()Starts a horizontal layout row.
Subsequent widgets will be placed side-by-side until endRow is called.
beginTabBar
Section titled “beginTabBar”beginTabBar :: proc (idString: string) -> boolStarts a tab bar container.
Must be followed by tabItem
calls and ended with endTabBar.
beginTabItem
Section titled “beginTabItem”beginTabItem :: proc (label: string) -> boolDraws a tab button.
Returns true if this tab is currently selected.
button
Section titled “button”button :: proc (text: string, width: f32 = 60.0) -> boolDraws a clickable button.
Returns true if clicked.
checkbox
Section titled “checkbox”checkbox :: proc (label: string, value: ^bool) -> boolDraws a checkbox.
Modifies value directly via a pointer.
Returns true if the value was toggled this frame.
colorPicker
Section titled “colorPicker”colorPicker :: proc (label: string, color: ^gmath.Color, alpha: bool = true) -> boolDraws a color picker (preview box + RGB(A) sliders).
Returns true if the color changed.
comboEnum
Section titled “comboEnum”comboEnum :: proc ( label: string, value: ^$T, width: f32 = 50.0,) -> bool where intrinsics.type_is_enum(T)Draws a combo box for any enum.
Automatically extracts enum names.
value: Pointer to the enum variable.
comboString
Section titled “comboString”comboString :: proc ( label: string, currentItemIndex: ^int, items: []string, width: f32 = 50.0,) -> boolDraws a combo box that selects an index from a list of strings.
currentItemIndex: Pointer to the index of the selected itemitems: Slice of strings to display. Returnstrueif the selection changed.
draw :: proc ()Executes all deferred UI commands. Sorts windows by Z-index, renders them back-to-front, then renders popups and tooltips on top. Called internally at the end of the frame.
end :: proc ()Finalizes the UI frame state. Commits focus changes and resets active widget state on mouse release. Called internally at the end of each frame.
endCombo
Section titled “endCombo”endCombo :: proc ()Ends the dropdown menu block.
Must be called if beginCombo returns true.
endRow
Section titled “endRow”endRow :: proc ()Ends the current horizontal layout row. Moves the cursor down by the height of the tallest item in the row.
endTabBar
Section titled “endTabBar”endTabBar :: proc ()Ends the tab bar container.
endTabItem
Section titled “endTabItem”endTabItem :: proc ()Ends the current tab item content block.
Must be called if beginTabItem returns true.
endWindow
Section titled “endWindow”endWindow :: proc ()Ends the current window block.
Calculates content height, draws scrollbar, and cleans up window state.
Must be called if window returns true.
getAvailableWidth
Section titled “getAvailableWidth”getAvailableWidth :: proc () -> f32Returns the available width in the current window/column. Automatically subtracts scrollbar width if active.
header
Section titled “header”header :: proc (text: string, width: f32 = 60.0) -> boolDraws a collapsible header.
Returns true if open.
indent
Section titled “indent”indent :: proc (amount: f32 = 5.0)Increases the layout indentation (shifts cursor right). Useful for hierarchical data or grouping.
inputText
Section titled “inputText”inputText :: proc (text: ^string, label: string = "", width: f32 = 60.0) -> boolDraws a text input field that modifies a string directly.
Manages a temporary builder internally.
Updates text only when enter is pressed or focus is lost.
Returns true if the user pressed enter.
inputTextBuilder
Section titled “inputTextBuilder”inputTextBuilder :: proc ( label: string, builder: ^strings.Builder, width: f32 = 60.0, idOverride: u64 = 0,) -> boolLow-level builder for text input.
Handles the core interaction and rendering logic for inputText
isRectangleVisible
Section titled “isRectangleVisible”isRectangleVisible :: proc (rectangle: gmath.Rectangle) -> boolChecks if rectangle is visible within the current window’s scissor area.
Useful for culling optimization.
label :: proc (text: string)Draws a static text label.
plot :: proc ( label: string, values: []f32, minimumValue: f32 = 0.0, maximumValue: f32 = 0.0, height: f32 = 0.0,)Draws a simple line plot for a slice of numbers. Useful for FPS counters or physics debugging.
popId :: proc ()Pops the last identifier from the stack.
pushId
Section titled “pushId”pushId :: proc { pushIdInt, pushIdString, pushIdPointer,}Generic overload for functions used to pushing variable based identifiers onto the ID stack.
pushIdInt
Section titled “pushIdInt”pushIdInt :: proc (value: int)Pushes an integer identifier onto the ID stack.
pushIdPointer
Section titled “pushIdPointer”pushIdPointer :: proc (pointer: rawptr)Pushes a pointer identifier onto the ID stack.
pushIdString
Section titled “pushIdString”pushIdString :: proc (value: string)Pushes a string identifier onto the ID stack.
selectable
Section titled “selectable”selectable :: proc (text: string, selected: bool) -> boolDraws a selectable item inside a dropdown menu.
Returns true if clicked.
separator
Section titled “separator”separator :: proc ()Draws a horizontal separator line. Spans the full available width of the current window or column.
slider
Section titled “slider”slider :: proc { sliderFloat, sliderInteger,}Draws a slider.
Modifies value directly via a pointer.
Returns true if the value was changed this frame.
Function overload for sliderFloat/sliderInteger
sliderFloat
Section titled “sliderFloat”sliderFloat :: proc ( value: ^f32, minimumValue: f32, maximumValue: f32, label: string = "", width: f32 = 60.0, step: f32 = 0.0,) -> boolDraws a float slider.
sliderInteger
Section titled “sliderInteger”sliderInteger :: proc ( value: ^int, minimumValue: int, maximumValue: int, label: string = "", width: f32 = 60.0, step: int = 1,) -> boolDraws a integer slider.
start :: proc ()Initializes the UI state for the new frame. Resets per-frame counters, clears command buffers, and performs window hit-testing. Called internally at the start of each frame.
tooltip
Section titled “tooltip”tooltip :: proc (text: string)Shows a tooltip if the previous widget is hovered. Call this immediately after the widget you want to describe.
unindent
Section titled “unindent”unindent :: proc (amount: f32 = 5.0)Decreases the layout indentation (shifts cursor left).
Clamps indentation to 0.
window
Section titled “window”window :: proc ( title: string, rectangle: gmath.Rectangle, isOpen: ^bool = nil, idSuffix: string = "",) -> boolBegins a draggable window.
Returns true if the window is visible (not collapsed).
Accepts an optional isOpen pointer. If provided, an ‘X’
button is drawn. If clicked, isOpen^ becomes false
and the window stops rendering.