The ui namespace contains the widgets of sshook's custom front-end screens: one to three billboards on a podium, painted by Dear ImGui and opened with F9 from the main menu. The widgets are drawn from a handler of the ui event, which runs once a frame while one of the screens is on stage and passes the number of billboards and the index of the screen. The widgets are immediate-mode: a widget is drawn by calling it, and the call returns the widget's state for that frame.

Static members#

These elements are static to the class itself and can be accessed like so:

ss.ui.panel(0, function() ss.ui.text("Hello") end)

Panels#

FunctionReturn ValuesDescription
ss.ui.panel( integer index, function draw ) nil Draws the widgets of the given function inside the billboard at the given index (0-based). The panel is closed whatever the function does, an error included.
ss.ui.begin_panel(integer index) nil Opens the billboard at the given index for the widgets that follow. This is the raw pair behind panel.
ss.ui.end_panel() nil Closes the billboard opened by begin_panel.
ss.ui.open(integer panels) nil Opens the screen with the given number of billboards, from the main or More menu or from another sshook screen. Can be called at any time, not only from the handler.
ss.ui.close() nil Pops the screen on stage. Can be called at any time.

Text#

FunctionReturn ValuesDescription
ss.ui.heading( string title, [string subtitle] ) nil Draws a heading, with a smaller line under it when a subtitle is given.
ss.ui.text(string text) nil Draws a line of text.
ss.ui.text_disabled(string text) nil Draws a greyed line of text.
ss.ui.text_wrapped(string text) nil Draws text wrapped to the width of the panel.
ss.ui.text_colored( number r, number g, number b, number a, string text ) nil Draws text in a colour. Each component is in the range 0 to 1, as ImGui takes them.

Buttons#

These return true on the frame they are activated.

FunctionReturn ValuesDescription
ss.ui.button( string label, [number width, number height] ) boolean activated Draws a button, sized to its label unless a size is given.
ss.ui.small_button(string label) boolean activated Draws a button with no vertical padding, for a row of buttons.
ss.ui.selectable( string label, boolean selected ) boolean activated Draws a list-style row, highlighted while selected is true.
ss.ui.radio( string label, boolean active ) boolean activated Draws a radio button, filled while active is true.

Values#

Each of these takes the current value and returns the new one, with a second return value of whether it changed this frame. The value is kept by the script, in a local or in ss.data, and the result is assigned back every frame, as the example does.

FunctionReturn ValuesDescription
ss.ui.checkbox( string label, boolean value ) boolean value, boolean changed Draws a checkbox.
ss.ui.slider( string label, number value, number min, number max, [string format] ) number value, boolean changed Draws a slider over a number. The optional format is a printf format for the readout, such as %.2f.
ss.ui.slider_int( string label, integer value, integer min, integer max ) integer value, boolean changed Draws a slider over whole numbers.
ss.ui.input_text( string label, string value ) string value, boolean changed Draws a text field. See Navigation for how it is typed into.
ss.ui.combo( string label, integer index, table items ) integer index, boolean changed Draws a drop-down over the strings in items. Takes and returns a 1-based index into the table.
ss.ui.listbox( string label, integer index, table items, [integer rows] ) integer index, boolean changed Draws a list over the strings in items, the given number of rows tall. Takes and returns a 1-based index into the table.

Layout and feedback#

FunctionReturn ValuesDescription
ss.ui.progress( number fraction, [string text] ) nil Draws a progress bar filled to the given fraction, 0 to 1, with an optional label over it.
ss.ui.separator() nil Draws a horizontal rule.
ss.ui.same_line([number x]) nil Places the next widget on the same line as the previous one, at the given x position when one is given.
ss.ui.spacing() nil Adds a small amount of vertical space.
ss.ui.new_line() nil Adds a whole empty line.
ss.ui.indent([number width]) nil Indents the widgets that follow by the given number of pixels, or by the style's default indent.
ss.ui.unindent([number width]) nil Removes an indent added by indent.
ss.ui.set_next_width(number width) nil Sets the width of the next widget.
ss.ui.tooltip(string text) nil Attaches a tooltip to the previous widget, shown while it is hovered.
ss.ui.is_hovered() boolean hovered Returns whether the previous widget is hovered, which on the billboards means focused by the navigation.
ss.ui.begin_disabled([boolean disabled]) nil Greys out and deactivates the widgets that follow, until end_disabled. When disabled is false the widgets are left alone, so the pair can stay in place.
ss.ui.end_disabled() nil Ends the stretch started by begin_disabled.

Static fields#

TypeFieldRead-only?Description
integer ss.ui.active Yes The index of the screen on stage. nil when none is.
integer ss.ui.panels Yes The number of billboards of the screen on stage.
number ss.ui.fps Yes The ImGui frame rate.

The navigation is the front end's. Up and Down move the focus and Enter activates the focused widget; the pad's D-pad and A do the same, and Esc or B pops the screen. While a text field is being edited the keyboard is read directly, through the current layout, with Backspace, Delete, Home, End and the arrow keys, so input_text can be typed into. There is no mouse on the billboards, as the cursor has no simple mapping onto the texture of a 3D model.

Limits#

A widget call outside the ui handler results in an error; open and close are the exceptions. The built-in demo panels are drawn when no mod has a ui handler. The translated builds (Linux, macOS, Android, iOS and the lifted Windows build) run the lite hook DLL, which has no ImGui, so every widget results in an error there. A mod that runs on every build keeps its menu code behind pcall, or behind a check of the build it is running on.

Example#

local enabled, laps, name = true, 3, "Holly"

ss.on("ui", function(ev)
	ss.ui.panel(0, function()                        -- billboard 0
		ss.ui.heading("My mod", "settings")
		enabled = ss.ui.checkbox("Enabled", enabled)   -- a widget returns the new value
		laps = ss.ui.slider_int("Laps", laps, 1, 10)
		name = ss.ui.input_text("Name", name)
		if ss.ui.button("Apply") then ss.params["RaceSetup/Logic/Laps/Number of Laps"] = laps end
		if ss.ui.button("Back") then ss.ui.close() end
	end)
	if ev.panels > 1 then
		ss.ui.panel(1, function() ss.ui.text_wrapped("A second billboard.") end)
	end
end)