GUI
Displaying a gui
The gui module
This module exposes the gui function
The gui function is used to present the queued gui layout.
gui() returns Promise and therefore an await should be used to allow the gui to run.
gui_text("Hello, World")
await gui()
Example
To insert a blank part of the layout just call gui_blank::
gui_blank()
Proving a count will allow inserting multiple blanks::
gui_blank(4)
One use of blanks it to help center an element but also adding space::
gui_blank()
gui_icon(...)
gui_blank()
await_gui_sites_clear()
Per-mission reset -- see handlerhooks.reset_mission_state.
gui(buttons=None, timeout=None)
Present the GUI layout that has been queued up for the current client.
Suspends execution until the player presses a button or the timeout fires.
GUI elements (text, images, sections, etc.) must be queued with gui_*
calls before await gui(); they are rendered when the promise activates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
buttons
|
dict
|
Extra buttons to add, mapping label text to
jump target label name. e.g. |
None
|
timeout
|
Promise
|
A promise (e.g. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Promise |
Resolves when a button is pressed or timeout fires. |
Example
gui_text("Choose your mission") await gui(): + "Patrol": jump patrol_mission + "Escort": jump escort_mission
gui_client_id()
Return the client ID for the currently executing GUI task.
Shortcut for FrameContext.client_id. Returns 0 when running on
the server.
Returns:
| Name | Type | Description |
|---|---|---|
int |
Current client ID, or |
Example
id = gui_client_id() gui_text("Your client ID is {id}")
gui_hide_choice()
Hide the button that was just pressed during its handler block.
Call this from inside a button's handler block to remove the button
from the layout immediately after it is clicked, without waiting for
the await gui() to complete. Has no effect if called outside of
a running button handler.
Example
await gui(): + "Launch Missile": gui_hide_choice() ~~ fire_torpedo(SHIP_ID) ~~
gui_page_for_client(client_id)
Return the active GUI page for a client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client to look up. |
required |
Returns:
| Type | Description |
|---|---|
|
Page | None: The client's current page, or |
Example
page = gui_page_for_client(CLIENT_ID) if page is not None: ~~ page.dirty() ~~
gui_percent_from_ems(client_id, ems, font)
Convert an em-based size to GUI percentage coordinates for a client's screen.
An em is the width/height of the character "X" in the given font. Use this to size layout elements relative to text size rather than fixed pixels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client whose screen resolution to use. |
required |
ems
|
float
|
The number of em units to convert. |
required |
font
|
str
|
Font name used to measure one em (e.g. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Vec3 |
Percentage values (x=horizontal %, y=vertical %, z=0). |
Example
pct = gui_percent_from_ems(CLIENT_ID, 2, "hud_font") gui_section(style="width:{pct.x}%;")
gui_percent_from_pixels(client_id, pixels)
Convert a pixel size to GUI percentage coordinates for a client's screen.
GUI layout positions are expressed as percentages (0–100) of the screen dimensions. Use this to convert a fixed pixel measurement to the equivalent percentage for a specific client's resolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client whose screen resolution to use. |
required |
pixels
|
float
|
The pixel size to convert. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Vec3 |
Percentage values (x=horizontal %, y=vertical %, z=0). |
Example
pct = gui_percent_from_pixels(CLIENT_ID, 40) gui_section(style="height:{pct.y}%;")
gui_properties_change(var, label)
Watch a MAST variable and run an inline block when its value changes.
Registers a per-tick change detector on the current client's GUI task.
When var changes value, the block at label is pushed and executed
immediately within the current tick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
var
|
str
|
Name of the MAST variable to watch. |
required |
label
|
The inline label or block to execute on change. |
required |
Example
gui_properties_change("shield_level", shield_changed) ///shield_changed gui_text("Shields: {shield_level}")
gui_screen_size(client_id)
Return the pixel dimensions of a client's screen.
CAUTION: when the client has not reported its size yet, this returns a
1024x768 PLACEHOLDER with z == 99 rather than a real measurement, and a
client that reconnects goes back to the placeholder until its next resize
event. Branching on the width without checking validity silently builds the
small-screen layout on a large display:
ss = gui_screen_size(client_id)
if ss.x < 1600: # WRONG - 1024 placeholder also lands here
...
Use gui_screen_size_known to tell "small" from "unknown".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client whose screen to query. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Vec3 |
Screen dimensions in pixels (x=width, y=height); z is |
|
|
|
Example
size = gui_screen_size(CLIENT_ID) ~~ print(size.x, size.y) ~~
gui_screen_size_known(client_id)
True when the client has actually reported its screen size.
Pair with gui_screen_size before branching on the dimensions, so an
unknown size can be handled deliberately (usually: assume the LARGER layout,
which degrades better than cramming a wide screen into the narrow one).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client whose screen to query. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
False while the size is still the 1024x768 placeholder. |
Example
ss = gui_screen_size(client_id) if not gui_screen_size_known(client_id) or ss.x >= 1600: gui_row("row-height: 35px;col-width:45px;") else: gui_row("row-height: 35px;col-width:25px;")
gui_task_for_client(client_id)
Return the GUI task currently running for a client.
Each connected client has a dedicated GUI task that drives its page layout.
Returns None if the client has no active page.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client to look up. |
required |
Returns:
| Type | Description |
|---|---|
|
MastAsyncTask | None: The client's GUI task, or |
Example
task = gui_task_for_client(CLIENT_ID) if task is not None: ~~ task.set_variable("score", 10) ~~
promote_await_gui(page, task, gui_task)
await gui() reached on a task that is not the console's GUI task.
A handler runs on whatever task built the widget, which is very often not
the GUI task (LM #714). When such a handler paints a screen and awaits, the
console has to follow it -- but the GUI task's in-flight GuiPromise must NOT
resolve, or the GUI task falls through past its own await gui() into
whatever comes next, leaving a screen nobody asked to leave. So this is a
JUMP on the GUI task, not a handover of the promise.
The GUI task is sent to the very command the handler is standing on -- the
await gui() itself -- so it re-evaluates gui() as the GUI task and takes
the normal swap_gui_promise path. Nothing is re-executed: the widgets the
handler already queued stay exactly as it left them.
The old promise is neither resolved nor cancelled here. do_jump does not call leave(), so it is simply abandoned; swap_gui_promise cancels it a moment later, once the GUI task has already jumped off that node.
Returns one of PROMOTED / STEERED_ALREADY / NOT_PROMOTED. The first two
both end the calling task and neither warrants a warning; only the last
leaves an await gui() that nothing will ever resolve.
warn_await_gui_off_gui_task(task)
Report an await gui() that will never resolve.
Without promotion this hangs the calling task silently and permanently: the promise is returned and awaited, but the page never adopted it, so nothing will ever resolve it. It used to be a bare print(), which in the engine goes nowhere a scripter will look.
Layout related
This module exposes the gui_blank function
The gui_blank function is used to insert a black space in a layout. Blanks are useful to add space.
Example
To insert a blank part of the layout just call gui_blank::
gui_blank()
Proving a count will allow inserting multiple blanks::
gui_blank(4)
One use of blanks it to help center an element but also adding space::
gui_blank()
gui_icon(...)
gui_blank()
gui_blank(count=1, style=None)
Add one or more empty columns to the current layout row.
Blanks occupy column space without rendering anything visible. Use them to push elements right, add padding, or center icons.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
int
|
Number of blank columns to insert. Defaults to 1. |
1
|
style
|
str
|
CSS-like style overrides applied to each blank. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Blank |
The last blank layout item created. |
Example
gui_blank() gui_icon("icons/shield") gui_blank()
gui_hole(count=1, style=None)
Reserve empty column space that the next layout item expands to fill.
Unlike gui_blank, a hole is consumed by the following item as extra
width. Use it to make a single element span multiple column slots.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
int
|
Number of extra column slots to reserve. Defaults to 1. |
1
|
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Hole |
The last hole layout item created. |
Example
gui_hole(2) gui_text("This text spans 3 columns")
gui_row(style=None)
Start a new layout row, pushing subsequent items to the next line.
Call before adding items that should appear on a fresh row. Without explicit rows, items flow left-to-right across the current row.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
style
|
str
|
CSS-like style overrides for the row container. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Row |
The row layout object. |
Example
gui_text("Name:") gui_row() gui_input("", var="ship_name")
PageRegion
A re-drawable area. REBUILDING ONE REUSES ITS TAGS.
ENGINE-SEEN 2026-09-29 (xESS Act): a text area or listbox is its OWN engine
sub-region, and clearing the parent region does not take old child sub-regions with
it. Every rebuild made new ones under the next build-order tags, so the old ones
stayed on screen underneath - the transcript was drawn once per rebuild, stacked, at
whatever scroll each had. So after rebuild(), the next fill hands out tags derived
from this region's own (stable) tag: each rebuild reuses the same sub-regions, which
clear themselves before drawing. One the new fill no longer uses is blanked.
rebuild()
Empty the region for a fresh fill - which reuses the last fill's tags.
PageSubSection
is_message_for(event)
Used by MessageTrigger i.e. gui_message to know if message is for this object
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
EVENT
|
the engine event |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
if the gui_message MessageTrigger should be True |
gui_region(style=None)
Create a re-representable GUI region pinned to an absolute screen area.
Unlike gui_sub_section, a region uses absolute positioning (the area
style property) and can be redrawn independently with region.represent().
Use it for UI panels that update without redrawing the entire page.
Also a context manager — content inside the with block is placed in
the region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
style
|
str
|
CSS-like style string. The |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
PageRegion |
Context manager object with |
Example
hud = gui_region(style="area:0,0,100,10;") with hud: gui_text("HUD content here") ~~ hud.represent(event) ~~ # refresh just this region later
gui_section(style=None)
Create a top-level GUI layout section at a specific screen area.
Sections are the primary way to position content on screen. The area
style property sets the region (left, top, right, bottom as percentages).
Content added after this call is placed inside the section until the next
gui_section or the frame ends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
style
|
str
|
CSS-like style string. Use |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Layout |
The layout object for this section. |
Example
gui_section(style="area:5,5,95,50;") gui_text("Top half of screen") gui_section(style="area:5,50,95,95;") gui_text("Bottom half of screen")
gui_sub_section(style=None)
Create a nested layout sub-section, used as a context manager.
Sub-sections let you group and style a subset of content within the current
section. Use with Python's with statement in MAST via the with
keyword. The sub-section is added to the current layout when the with
block exits.
The returned object can be hidden and restored after it is built, with
gui_hide / gui_show or its own show(). Hiding takes the whole
sub-tree off screen, and its siblings reclaim the space on the next layout
pass. Hold on to the object to do that - hiding one before its with
block has run is a no-op, since the layout it stands for does not exist yet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
style
|
str
|
CSS-like style string controlling the column width, row height, background, etc. of the sub-section. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
PageSubSection |
Context manager object with |
Example
gui_row(style="row-height:3em;") with gui_sub_section(style="col-width:30%;"): gui_text("Left column") right = gui_sub_section() with right: gui_text("Right column") gui_hide(right) # and gui_show(right) to bring it back
Responding to gui interactions
dead_handler_sites_clear()
Per-mission reset -- see handlerhooks.reset_mission_state.
gui_host_task(task)
The page's live GUI task -- who can tick a handler this task registered.
gui_message(layout_item, label=None)
Register a MAST label to run when a layout element receives a GUI event.
Attaches a MessageTrigger to the current task so that when the engine
fires a gui_message event matching layout_item's tag, the given
label is pushed and executed inline. Used to respond to clicks on custom
layout items (sections, regions, etc.) that are not plain buttons.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
The layout object whose tag to watch. Must expose
|
required | |
label
|
optional
|
MAST label or inline block to run on the event. Defaults to the current active label. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
MessageTrigger |
The registered trigger object. |
Example
region = gui_region(style="area:10,10,50,50;") gui_message(region, on_region_click) ///on_region_click gui_text("Region clicked!")
gui_message_callback(layout_item, cb)
Set a Python callable to invoke when a layout element receives a GUI event.
Attaches a callback directly to the layout item's on_message_cb
attribute. The callback is called with the event and the layout item when
the engine fires a gui_message event matching the item's tag.
Use this for pure-Python handlers; use gui_message for MAST label
handlers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
The layout object to attach the callback to. |
required | |
cb
|
callable
|
Function called as |
required |
Example
btn = gui_button("Fire!", on_press=None) gui_message_callback(btn, lambda e, item: fire_torpedo(SHIP_ID))
gui_message_clear(layout_item)
Drop EVERY gui_message handler attached to a widget, on both channels.
Handlers accumulate now (LM #614), so replacing rather than adding takes an explicit step: clear, then register. Before #614 a plain re-registration did this implicitly, by throwing the previous handler away.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
the widget to detach every handler from. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
how many registrations were removed. |
gui_message_label(layout_item, label)
Schedule a MAST label as a sub-task when a layout element receives a GUI event.
Similar to gui_message_callback but wraps the label in a
gui_sub_task_schedule call, running it as an independent sub-task
rather than inline in the current task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
The layout object to attach the handler to. |
required | |
label
|
MAST label to schedule as a sub-task on event. |
required |
Example
section = gui_sub_section(style="col-width:30%;") gui_message_label(section, handle_section_click)
gui_signal(layout_item, name, data=None)
Emit a signal whenever a control is used.
The control does not run anything itself; the signal's routes do. That keeps
the widget free of handler plumbing, and lets the SAME control drive a
//shared/signal route (state, once on the server) and a //signal
route (a repaint, on each console) - see SIGNAL_ROUTING.md for which is which.
Works on any control: button, icon button, cycle button, checkbox, dropdown,
slider and listbox (on a row click). It is added alongside the widget's other
handlers (on_press, on gui_message), never in place of them.
The route gets these variables:
- every key of
data, when it is a dict (anything else isSIGNAL_DATA) SIGNAL_CLIENT_ID: the console that used the controlSIGNAL_ITEM: the control itselfSIGNAL_VALUE: its value after the click - the checkbox state, the dropdown text, the slider value, the listbox selection, the cycle button's state; None for a plain button
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
the control, as returned by its |
required | |
name
|
str
|
the signal to emit. |
required |
data
|
dict
|
extra variables for the route. Defaults to None. |
None
|
Returns:
| Type | Description |
|---|---|
|
the layout item, so the call can wrap the builder. |
Example
gui_signal(gui_checkbox("Shields", var="shields_on"), "shields_toggled")
//shared/signal/shields_toggled set_shields(SIGNAL_CLIENT_ID, SIGNAL_VALUE)
host_handler_sub_task(builder, sub_task)
Give a handler sub-task a LIVE ticking parent when its builder has ended.
A gui_message(widget, label) handler runs as a sub-task of the task that
built the widget, and sub-tasks are only ever ticked by their parent's
tick(). On a finished builder that is exactly one tick -- the
tick_in_context() at the call site -- after which the handler stalls
wherever it happens to be. Single-line handlers looked like they worked;
anything that awaited did not.
The page's gui_task takes over the TICKING only. root_task is deliberately left pointing at the builder, so the handler's variable scope is exactly what it is when the builder is alive.
Returns True when the sub-task was re-hosted.
signal_control_value(layout_item)
What a control holds right now, as a signal payload's SIGNAL_VALUE.
The value AFTER the click: the widget's own on_message has already run (a
checkbox has toggled, a cycle button advanced) by the time a callback fires.
A plain button has no value - its .value is its props string - so None.
signal_emit_from_gui(name, data, client_id, item, **extra)
Emit a signal for a GUI interaction.
The payload is the author's data (a dict is copied, anything else is
passed as SIGNAL_DATA) plus SIGNAL_CLIENT_ID and SIGNAL_ITEM and
any extra keys.
The sender task is whichever task is current when the click arrives, unless
it has ended, in which case there is no sender. Mast.signal_emit drops a
signal whose sender is finished, and a widget's builder is often finished by
the time anyone clicks (a //gui route body, a scheduled builder).
warn_dead_handler(task, label, loc, kind)
Report a click that landed on a task which has already finished.
Without this the failure is completely silent: the widget draws, the click dispatches, the handler is discarded, and nothing is logged anywhere. That silence is most of what made LM issue #707 hard to place.
Gui control formatting
gui_set_style_def(name, style)
Parse a style string and register it under a named class.
After registering, the name can be used as a CSS class reference in any
style string (e.g. ".my_style").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Class name to register (conventionally prefixed with
|
required |
style
|
str
|
CSS-like style string to associate with the name. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
StyleDefinition |
The parsed and registered style object. |
Example
gui_set_style_def(".alert", "color:red;background:#400;") gui_text("Warning!", style=".alert")
gui_style_def(style)
Parse a CSS-like style string into a StyleDefinition object.
Useful when you want to pre-parse a style string and inspect or reuse it without re-parsing each time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
style
|
str
|
CSS-like style string, e.g. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
StyleDefinition |
Parsed style object. |
Example
s = gui_style_def("color:green;font:hud_font;")
GUI Controls
MessageHandler
is_inert()
True when this handler has nothing to run.
gui_button() builds one of these even with no on_press, because the click also sets ITEM and unpacks the widget's data. With no handler it falls through to start_sub_task(None, ...), so it must not become a link in a chain -- see message_chain.compose_handler. (LM #614)
runs_as_sub_task()
Whether this click starts a sub-task or jumps the builder.
Explicit wins in both directions. Unspecified follows
MastAsyncTask.handler_defaults_to_sub_task(), which is the #714 pair --
sub-task default + await gui() promotion -- and is all-or-nothing on
purpose.
call_press_handler(handler, layout_item, event)
Call a Python on_press, giving it the widget's data when it asks for it.
gui_button(props, style=None, data=None, on_press=None, is_sub_task=None, signal=None)
Add a button to the current GUI layout outside of an await gui() block.
Unlike buttons declared with * or + inside await gui(), this
button is placed directly in the layout at the current position and fires
its handler without ending the surrounding await gui(). Use it for
action buttons embedded in panels, listboxes, or info panels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Button label text, optionally as a property string
(e.g. |
required |
style
|
str
|
Additional CSS-like style overrides.
End each property with a semicolon, e.g. |
None
|
data
|
object
|
Arbitrary data passed to the handler.
Available as |
None
|
on_press
|
label | callable | Promise
|
What to do when the button is pressed. A label is jumped to; a callable is called; a Promise has its result set. Defaults to None. A callable is called with NOTHING unless it asks. Declare a
REQUIRED parameter and it is handed
|
None
|
is_sub_task
|
bool
|
How an |
None
|
signal
|
str
|
A signal to emit on each press, as
|
None
|
Valid Styles
area:
Format as top, left, bottom, right.
Just numbers indicates percentage of the section or page to cover.
Can also use px (pixels) or em (1em = height of text font).
Can combine different units, e.g. 5+5px, 3em, 100-10em, 50px; is a valid area.
color:
The color of the text
background-color:
The background color of the button
padding:
A gap inside the element (makes the button smaller, but the background still is there.)
margin:
The gap outside the element (makes the button smaller).
col-width:
The width of the button
justify:
Where the text is placed inside the button. left, center, or right
font:
The font to use. Overrides the font in prefernces.json
Returns:
| Type | Description |
|---|---|
|
layout object: The Layout object created |
handler_inputs(data)
A widget's data= as the dict start_sub_task wants.
The two dispatch paths disagreed about non-dict data: the jump path bound it
to a variable called data, while the sub-task path handed it straight to
start_sub_task, whose for k in inputs then walked a string or a list.
A dict was always fine on both. This makes them agree. (LM #714)
press_handler_arity(handler)
How many arguments to hand this handler: 0, 1 or 2.
NOT CACHED, and that is deliberate. The first version memoised this on id(handler),
which is wrong for the exact objects it is asked about: a handler is usually a
lambda built during a GUI build, and once one is freed CPython REUSES ITS ADDRESS -
so the next lambda at that address inherited the previous one's arity. It showed up
immediately as bound-default closures being handed an event. A press happens at
human speed; inspect.signature costs microseconds and no cache is worth that
class of bug.
Anything unintrospectable - a C callable, an odd functools.partial - answers 0,
which is the behaviour every caller had before this existed. A handler that cannot
be read is never a reason to change how it is called.
gui_checkbox(msg, style=None, var=None, data=None, signal=None)
Add a checkbox to the current GUI layout.
The current value of var (expected to be a bool) sets the initial
checked state. When the player toggles the checkbox, var is updated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msg
|
str
|
Label text or property string shown next to the checkbox,
e.g. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to read the initial checked state from and update on toggle. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
signal
|
str
|
A signal to emit on each toggle, with the new
state as |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Checkbox |
The layout item created. |
Example
gui_checkbox("Enable auto-fire", var="auto_fire_on")
gui_cinematic_auto(client_id)
Switch a client to cinematic view, automatically tracking its assigned ship.
Sets the client's view mode to "3dview/front/cinematic" with automatic
camera control. The tracked ship must expose excitement values; player ships
have these set automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client to switch to cinematic view. |
required |
Example
gui_cinematic_auto(CLIENT_ID)
gui_cinematic_full_control(client_id, camera_id, camera_offset, tracked_id, tracked_offset)
Switch a client to cinematic view with explicit camera and target control.
Sets the view mode to "3dview/front/cinematic" and hands full camera
control to the caller. Both offset vectors are converted to engine
vec3 objects before being passed to cinematic_control.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client to switch to cinematic view. |
required |
camera_id
|
int
|
Object ID to use as the camera position anchor. |
required |
camera_offset
|
Vec3 | None
|
Offset from |
required |
tracked_id
|
int
|
Object ID for the camera to look at. |
required |
tracked_offset
|
Vec3 | None
|
Offset from |
required |
Example
gui_cinematic_full_control(CLIENT_ID, camera_ship_id, Vec3(0,50,0), target_id, None)
gui_content(content, style=None, var=None)
Place a Python widget object into the layout system.
Wraps a pre-built Python widget (e.g. a ship picker, custom control) in a
GuiControl so it participates in the normal layout flow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content
|
widget
|
A Python GUI widget object. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to bind the widget's value to.
The current value of |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
GuiControl |
The layout wrapper object. |
Example
picker = ShipPicker(0, 0, "mast", "Your Ship") gui_content(picker, var="selected_ship")
gui_drop_down(props, style=None, var=None, data=None, signal=None)
Add a drop-down list to the current GUI layout.
When the player selects an item, var is updated. var is written, not
read: the INITIAL selection comes from text: in props, so interpolate
the variable there yourself -- f"text:{speed};list:Slow,Medium,Fast;" --
or set it afterwards with .value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Semicolon-separated properties. The options go in |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to write the selection to when it changes. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
signal
|
str
|
A signal to emit on each selection, with the
selected text as |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Dropdown |
The layout item created. |
Example
speed = gui_drop_down("text:Medium;list:Slow,Medium,Fast;", var="speed_setting") speed.value = "Fast" # move the selection from script
gui_face(face, style=None)
Add a character face portrait to the current GUI layout.
Renders the named face asset, typically used in comms panels to show the speaker's portrait.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
face
|
str
|
Face asset name or property string, e.g. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Face |
The layout item created. |
Example
gui_face("crew/captain")
gui_icon(props, style=None, data=None)
Add an icon image to the current GUI layout.
Renders an icon from the atlas or media path. It is not clickable on its
own, but a click_tag: in the style makes it so - which is why it can
carry data like any other widget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Icon key, atlas name, or image property string, e.g.
|
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
data
|
object
|
Arbitrary data carried by the widget, read
back in a handler as |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Icon |
The layout item created. |
Example
gui_icon("icons/shield") gui_text("{shield_pct}%")
gui_icon_add_atlas(name, image, left=None, top=None, right=None, bottom=None, color=None)
Claim an icon NAME for a cell of your own sheet.
gui_icon_add_atlas("wanted", media_shared("icons/quest-sheet"), 0, 0, 64, 64)
From then on every gui_icon_name("quest.job") draws your art - the meaning points
at the look wanted, and this claims that look. Nothing that draws it changes.
This is gui_image_add_atlas(..., domain="icon"). The domain is what separates a
deliberate re-skin from an image that happens to be called square.
gui_icon_add_atlas_grid(image, cols, rows=None, names=None, cell=None, color=None, start=0)
Claim a whole sheet of icon names at once - gui_image_add_atlas_grid in the icon
domain. Names are laid out row-major; a None entry skips a cell.
gui_icon_button(props, style=None, data=None, on_press=None, is_sub_task=None, signal=None)
Add a clickable icon button to the current GUI layout.
Like gui_icon but the rendered item accepts click events. Takes
data and on_press exactly as gui_button does, so a row of icon
buttons built in a loop can each say which row they belong to (LM #708).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Icon key, atlas name, or image property string, e.g.
|
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
data
|
object
|
Arbitrary data carried by the widget. The
handler reads it as |
None
|
on_press
|
label | callable | Promise
|
What to do when the
icon is pressed. A label is jumped to; a callable is called; a
Promise has its result set. Defaults to None - attach the handler
with |
None
|
is_sub_task
|
bool
|
How an |
None
|
signal
|
str
|
A signal to emit on each press (see
|
None
|
Returns:
| Name | Type | Description |
|---|---|---|
IconButton |
The layout item created. |
Example
btn = gui_icon_button("icons/fire", data={"slot": i}) gui_message(btn, on_fire_clicked) ///on_fire_clicked fire_torpedo(SHIP_ID, slot)
gui_icon_name(name, color=None, style=None, props=None)
Draw an icon by NAME rather than by sheet index.
gui_icon_name("quest.job", color="#cc0")
The name is resolved by icon_names.icon_resolve: a meaning (quest.job) follows
its alias to a look, and a look is either a cell of the built-in sheet or - when a
mission has registered that name with gui_image_add_atlas - a cell of its own
sheet. The caller says what it wants; where the art comes from is not its business,
which is what lets a consumer be written before the art exists and lets a mission
re-skin every screen that draws it.
An unknown name draws NOTHING and says so once, rather than falling back to some arbitrary glyph: a wrong icon is worse than a missing one, because it looks deliberate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
a meaning or a look - see |
required |
color
|
str
|
tint. The built-in glyphs are white on transparent, so one glyph serves every state. |
None
|
style
|
str
|
layout style, as for |
None
|
props
|
str
|
extra icon properties appended verbatim. |
None
|
Returns:
| Type | Description |
|---|---|
|
Icon | Image | None |
gui_icon_name_button(name, color=None, style=None, props=None, data=None, on_press=None, is_sub_task=None)
gui_icon_name, but clickable - the button form of drawing an icon BY NAME.
Without this a caller that wanted a named icon it could press had to resolve the
sheet index itself and hand it to gui_icon_button, which is exactly the bare
index the name indirection exists to remove: a mission that re-skins the sheet
then moves every icon on the screen EXCEPT the ones you can click.
data/on_press behave as on gui_button, so a row of these built in a plain
for loop each knows which row it belongs to - the documented escape from the
for-loop handler trap.
An unknown name draws NOTHING and says so once, same as gui_icon_name: a wrong
icon is worse than a missing one because it looks deliberate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
a meaning or a look - see |
required |
color
|
str
|
tint. |
None
|
style
|
str
|
layout style. |
None
|
props
|
str
|
extra icon properties appended verbatim. |
None
|
data
|
object
|
carried by the widget; a dict is unpacked into the handler's variables. |
None
|
on_press
|
label | callable | Promise
|
what a press does. |
None
|
is_sub_task
|
bool
|
how an |
None
|
Returns:
| Type | Description |
|---|---|
|
IconButton | None |
gui_icon_recolor(widget, color)
Tint an icon that is already on screen, whatever gui_icon_name gave back.
That function returns an Icon for a built-in glyph and an Image for a name a mission has re-skinned, and the two carry their color in different places - so a caller that recolored by hand would work until someone registered their own sheet, which is the one thing the name indirection exists to survive. Recolor, never rebuild: the widget keeps its tag, so the engine re-sends one glyph instead of the console rebuilding a row that may be under the pilot's cursor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
widget
|
the layout item from |
required | |
color
|
str
|
the new tint. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
whether the tint was applied. |
gui_icon_rename(widget, name, color=None)
Show a different NAMED icon in a widget already on screen - a toggle's two
states, say - whatever kind of widget gui_icon_name / gui_icon_name_button
gave back. Same tag, so only that one glyph is re-sent.
Both names must be the same kind: two built-in glyphs, or two atlas cells. A built-in icon cannot become an image in place (they are different engine widgets); that is refused with a warning rather than drawn wrong.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
widget
|
the layout item (None is a no-op). |
required | |
name
|
str
|
the icon name to show now. |
required |
color
|
str
|
a new tint; None keeps the current one. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
whether the widget was changed. |
Names for the built-in icon sheet, and one lookup that takes a NAME.
data/graphics/grid-icon-sheet.png is a 2560x2560 sheet of 128px cells, 20 across -
400 slots of which 0..175 are drawn (the rest are free for custom art). The glyphs are
white on transparent, which is why color: in the style string does all the work: one
glyph serves every state.
Until now every caller wrote a bare number - gui_icon("icon_index:101;...") - so the
quest log's state square, the list box's fold arrows and a mission's own icons were all
magic constants, and nothing could be re-skinned without editing the code that draws it.
gui_icon_name("square") -> the built-in glyph
gui_icon_name("quest.job") -> whatever a mission says a job looks like
WHY A NAME AND NOT A NUMBER. It is the same move the image atlas already makes
(gui_image_add_atlas maps a key onto a file + sub-rect): the caller says WHAT it wants
and the library decides where that comes from. A name can be backed by a built-in index
today and a cell of a custom sheet tomorrow, without the drawing code changing - so
consumers can be written before any art exists, and a mission can re-point
quest.job at its own sheet and re-skin every quest log in the game.
The identifications come from the sheet itself (most of these are from game-icons.net); a few are best-guess and marked. Adding or correcting a name is a line here.
icon_names()
Every name that resolves - the built-ins plus the meanings. For lint, for a picker, and for anyone wondering what they may ask for.
icon_props(name, color=None, extra=None)
(kind, props) for a DIRECT engine send: kind is "icon" or "image", props the style string to hand it.
Widget code goes through gui_icon_name, but the low-level renderers call
send_gui_icon themselves with a hand-written property string - which is where the
remaining magic numbers live. This lets them name what they draw without giving up
the direct send, and an atlas-backed name comes back as an IMAGE because the engine
has no icon concept for art it did not ship.
Never raises and never returns nothing: an unknown name falls back to the built-in look, because a renderer mid-frame is the worst place to discover a typo.
icon_resolve(name)
A name -> (icon_index, atlas_key). Exactly one of the two is set.
Follows aliases first, so quest.job lands on whatever look it currently points at.
An unknown name resolves to (None, None) and the caller draws nothing rather than
guessing a glyph - a wrong icon is worse than a missing one.
The atlas branch is what makes a custom sheet a drop-in later: register the look in
the ICON DOMAIN (gui_icon_add_atlas, or Kind: icon in AMD) and it wins, with no
change to anything that draws it.
The domain is a GUARD, not ceremony. ImageAtlas.all is one process-wide dict, so
without it any mission registering an image called square or flag - words no one
would think twice about - would silently re-skin every icon meaning pointing there.
Overriding a look has to be something you meant.
gui_input(props, style=None, var=None, data=None)
Add a text input field to the current GUI layout.
The current value of var is pre-filled as the input text. When the
player edits and submits, var is updated with the new value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Property string for input configuration, e.g.
|
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to pre-fill and update on submit. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
TextInput |
The layout item created. |
Example
gui_input("", var="ship_name", style="col-width:50%;")
ImageAtlas
local_file()
self.file as a path THIS process can open.
self.file is what the ENGINE is handed - engine_file shape, relative to the
Cosmos root (or absolute, when the art lives outside the install; os.path.join
passes that through). So the base to resolve it against is the root, and the one
rule lives here rather than being spelled out at each reader.
It used to be resolved against data/graphics, which was right while self.file
was relpath(file, graphics) and became wrong the moment it stopped being - so
every mission image answered is_valid() == False and drew "IMAGE NOT FOUND",
and get_size() measured nothing.
qualify(key, domain=None)
staticmethod
The key a registration is stored under. ImageAtlas.all is one process-wide
dict, so without a domain two addons can claim the same word and the last one
loaded silently wins. A domain makes the claim explicit and scoped.
gui_image(props, style=None, fit=0, color=None)
Add an image to the current GUI layout.
Resolves the image via the atlas, mission directory, and engine graphics
path in that order. Prefer the named wrappers (gui_image_stretch,
gui_image_absolute, etc.) over calling this directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Image filename (without extension), a registered atlas
key (see |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
fit
|
int
|
Scaling mode — 0=stretch, 1=absolute pixels, 2=keep aspect ratio (top-left), 3=keep aspect ratio (centered). |
0
|
color
|
str
|
Tint for this use only, overriding the atlas's own color. Lets one registered cell serve every state. Defaults to 0. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Image |
The layout item created. |
gui_image_absolute(props, style=None)
Add an image to the layout at its native pixel dimensions.
The image is drawn at 1:1 pixel size relative to the client's screen resolution, anchored at the top-left of the layout area.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Image filename (without extension), atlas key, or image property string. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Image |
The layout item created. |
Example
gui_image_absolute("media/icons/torpedo")
gui_image_add_atlas(key, image, left=None, top=None, right=None, bottom=None, color=None, domain=None)
The image atlas allows a key name to be used to assign to a set of image properties. This key can be used instead of image properties in any command that expect image properties.
The image file passed will be used to search for the file. It will first check the mission directory followed by data/graphics folder. In the future this could be modified to account for mods, e.g. a common media folders. The image atlas takes care of supplying the correct path for the engine to use.
By specifying the rect (left,top, right, bottom) the image key can reference a part of an image.
Add a key to reference a full image
MAST / python
gui_image_add_atlas("test", "media/LegendaryMissions/operator")
Add a key to reference a full image
MAST / python
gui_image_add_atlas("test2", "media/LegendaryMissions/operator", 645,570, 950,820)
Once the atlas is added the key can be used anywhere images can be used.
MAST / python
gui_image("test")
MAST / python
# Text area also use the image atlas for images
gui_text_area("")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
the key to define in the image atlas |
required |
image
|
str
|
The file of the image. This can also be a image property string do not include the extension. Only PNG files are valid. |
required |
left
|
float
|
The pixel location of the left. Defaults to None. |
None
|
top
|
float
|
The pixel location of the top. Defaults to None. |
None
|
right
|
float
|
The pixel location of the right. Defaults to None. |
None
|
bottom
|
float
|
The pixel location of the bottom. Defaults to None. |
None
|
color
|
str
|
default tint for this key. A drawing call may override it. |
None
|
domain
|
str
|
a namespace for the key. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
ImageAtlas |
The image Atlas object. This is a low level object typically used by the system |
gui_image_add_atlas_grid(image, cols, rows=None, names=None, cell=None, color=None, domain=None, start=0)
Register a whole sheet of evenly spaced cells in one call.
Cutting a sheet up by hand is the same four lines of arithmetic every time, and
getting one of them wrong shows up as art that is off by a cell rather than as an
error (casino_media.py hand-loops exactly this).
gui_image_add_atlas_grid("media/icons/quest-sheet", 8, 8,
["job", "beat", "arc"], cell=64, domain="icon")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
str
|
the sheet, without the extension. |
required |
cols
|
int
|
cells across. |
required |
rows
|
int
|
cells down. Needed only to measure a cell from the file. |
None
|
names
|
list | dict
|
a list is laid out ROW-MAJOR from |
None
|
cell
|
int | tuple
|
cell size in PIXELS. Measured from the file
( |
None
|
color
|
str
|
default tint for every cell. |
None
|
domain
|
str
|
namespace for the keys - see |
None
|
start
|
int
|
index of the first name in row-major order. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
{name: ImageAtlas} for everything registered. |
gui_image_button(props, style=None, data=None, on_press=None, is_sub_task=None, fit=3, color=None)
Add a clickable image - a portrait, a card, a map tile, a custom icon.
The engine has no image-button command, so this is an image with a transparent
click region laid over it. It behaves like gui_button: data and
on_press work the same way, and on gui_message(widget) fires on a click.
Change the picture in place with widget.update(props) (or gui_icon_rename
for a named icon) - same tag, so only that image is re-sent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Image filename (without extension), atlas key, or image
property string, exactly as |
required |
style
|
str
|
Layout style. A |
None
|
data
|
object
|
Carried by the widget; a dict is unpacked into the handler's variables. Defaults to None. |
None
|
on_press
|
label | callable | Promise
|
What a click does, as
on |
None
|
is_sub_task
|
bool
|
How an |
None
|
fit
|
int
|
Scaling mode, as |
3
|
color
|
str
|
Tint for this use. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Image |
The layout item created. |
Example
card = gui_image_button("card_ter_hearts_7", on_press=play_card, data={"card": 7})
gui_image_get_atlas(text, domain=None)
The atlas registered under a key, or one built from the text as a file name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
a registered key, or an image path / property string. |
required |
domain
|
str
|
look only in this domain (see |
None
|
gui_image_keep_aspect_ratio(props, style=None)
Add an image scaled to fit the area while preserving aspect ratio.
Scales the image as large as possible without cropping, anchored top-left. Leaves empty space if the area's aspect ratio differs from the image's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Image filename (without extension), atlas key, or image property string. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Image |
The layout item created. |
Example
gui_image_keep_aspect_ratio("media/ship/artemis")
gui_image_keep_aspect_ratio_center(props, style=None)
Add an image scaled to fit the area while preserving aspect ratio, centered.
Like gui_image_keep_aspect_ratio but centers the image in the
remaining space when the aspect ratios differ.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Image filename (without extension), atlas key, or image property string. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Image |
The layout item created. |
Example
gui_image_keep_aspect_ratio_center("media/crew/captain")
gui_image_size(file)
Return the pixel dimensions of an image file or atlas entry.
Checks the atlas first, then reads the PNG header directly. Results are cached so repeated calls are free after the first read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
str
|
Atlas key or image path (without |
required |
Returns:
| Type | Description |
|---|---|
|
tuple[int, int]: |
Example
w, h = gui_image_size("media/backgrounds/nebula")
gui_image_stretch(props, style=None)
Add an image to the layout, stretched to fill its area.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Image filename (without extension), atlas key, or image
property string e.g. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Image |
The layout item created. |
Example
gui_image_stretch("media/backgrounds/nebula")
gui_radio(msg, style=None, var=None, data=None, vertical=False)
Add a radio button group to the current GUI layout.
The current value of var sets the initially selected option. When the
player selects a button, var is updated to the selected label.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msg
|
str
|
Comma-separated button labels or property string, e.g.
|
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to read the initial selection from and update on selection. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
vertical
|
bool
|
Stack buttons vertically. Defaults to
|
False
|
Returns:
| Name | Type | Description |
|---|---|---|
RadioButtonGroup |
The layout item created. |
Example
gui_radio("Beam,Missile,Mine", var="weapon_type")
gui_vradio(msg, style=None, var=None, data=None)
Add a vertical radio button group to the current GUI layout.
Convenience wrapper for gui_radio(..., vertical=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msg
|
str
|
Comma-separated button labels or property string. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to read the initial selection from and update on selection. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
RadioButtonGroup |
The layout item created. |
Example
gui_vradio("Alpha,Beta,Gamma", var="choice")
gui_ship(props, style=None)
Render a 3D ship model in the current GUI layout.
Displays a real-time 3D render of the named ship type within the layout area. The ship type key must match one defined in the game data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Ship type key or property string, e.g. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Ship |
The layout item created. |
Example
gui_ship("battleship", style="area:20,0,80,60;")
gui_int_slider(msg, style=None, var=None, data=None, signal=None)
Add an integer-only slider control to the current GUI layout.
Convenience wrapper for gui_slider(..., is_int=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msg
|
str
|
Property string defining the slider range and label, e.g.
|
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to read the initial value from and update on change. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
signal
|
str
|
As |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Slider |
The layout item created. |
Example
gui_int_slider("low:1;high:5;text:int;", var="torp_count")
gui_slider(msg, style=None, var=None, data=None, is_int=False, signal=None)
Add a slider control to the current GUI layout.
The current value of var is used as the initial slider position. When
the player adjusts the slider, var is updated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msg
|
str
|
Property string defining the slider range and label, e.g.
|
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
var
|
str
|
Variable name to read the initial value from and update on change. Defaults to None. |
None
|
data
|
object
|
Arbitrary data passed to the event handler. Defaults to None. |
None
|
is_int
|
bool
|
Restrict values to integers. Defaults to
|
False
|
signal
|
str
|
A signal to emit on each change, with the new
value as |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Slider |
The layout item created. |
Example
gui_slider("low:0;high:100;text:float;", var="speed_pct")
gui_text(props, style=None)
Add a text label to the current GUI layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Text content or property string, e.g. |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Text |
The layout item created. |
Example
gui_text("Hull: {hull_pct}%") gui_text("$text:WARNING;color:red;")
gui_text_area(props, style=None, markdown=True, line_styles=None, on_link=None, link_resolver=None)
Add a rich text area to the current GUI layout.
Supports Markdown-style formatting: headings (##+/##- fold), lists,
pipe tables, gauges ([Energy](gauge://946?max=1000)), links
([Text](ref://key)) and pictures. A picture ALONE on its line
(, face://, ship://) is drawn full size;
followed by text it LEADS the line - a square size=N text lines tall with
the text beside it, and at the start of a - item it is the bullet. Use for
multi-line or formatted text blocks.
Choices. A line that is only [Display](signal://name?key=value) is a
button. Lines of them next to each other are one group, drawn as flat buttons
that share a row while they fit and wrap when they do not. Clicking one
replaces the whole group with the choice made (so the document reads as the
story so far) and emits name with the query as variables, plus
SIGNAL_CHOICE (the words), SIGNAL_CLIENT_ID and SIGNAL_ITEM (this
area). Continue the story from the route with
gui_text_area_append(SIGNAL_ITEM, text). A line
[](choices://?layout=stack&fill=#234) above a group restyles the groups
after it (fill, text, chosen_fill, chosen_text, font,
pad_x, pad_y, gap, layout = flow | stack).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
props
|
str
|
Text content or Markdown string. Supports |
required |
style
|
str
|
CSS-like style overrides. Defaults to None. |
None
|
markdown
|
bool
|
Parse the mini-markdown. Pass |
True
|
line_styles
|
list
|
One style key per line, applied in order -
how you colorize text that is no longer being parsed. Pairs with
|
None
|
on_link
|
callable
|
|
None
|
link_resolver
|
callable | dict
|
what a link NAVIGATES to -
|
None
|
Returns:
| Name | Type | Description |
|---|---|---|
TextArea |
The layout item created. |
Example
gui_text_area("## Status\nAll systems nominal.")
gui_text_area("")
gui_text_area("
Mission active")
gui_text_area(source, markdown=False, line_styles=per_line_keys)
gui_text_area_append(text_area, text, sep='\n\n')
Add text to the end of a text area - how a story continues after a choice.
The area repaints itself and, when the reader is at the bottom, stays there.
Use this rather than area.value += text: value reads back as a list of
lines. The text is not {var}-formatted here; format it before passing it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text_area
|
TextArea
|
the area, e.g. |
required |
text
|
str
|
markdown to add, choices included. |
required |
sep
|
str
|
what goes between. A blank line by default, so the new text starts a paragraph. |
'\n\n'
|
Returns:
| Name | Type | Description |
|---|---|---|
TextArea |
the area. |
Example
//shared/signal/lp_pick gui_text_area_append(SIGNAL_ITEM, next_scene_text(pick))
gui_text_escape(s)
Quote a dynamic value for safe inclusion as a $text: style value.
Wraps s in backticks so any : or ; it contains is treated as
literal text by the style parser rather than a style property (issue #569).
A literal backtick -- the quoting delimiter itself -- is stripped. An empty
or None value returns "" so the caller emits $text:; with no
stray backtick in the box (issue #641).
Use this ONLY on the dynamic value, e.g. f"$text:{gui_text_escape(name)};color:red;"
-- never on a whole authored props string, so the author's own :/;
styling is left untouched.
List boxes
gui_list_box(items, style, item_template=None, title_template=None, section_style=None, title_section_style=None, select=False, multi=False, carousel=False, collapsible=False, read_only=False, reveal=False, hint=None, signal=None, data=None)
Add a listbox to the current GUI layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
list
|
Items to display. Plain strings render as text rows;
|
required |
style
|
str
|
CSS-like style overrides for the listbox container.
Declare neither and an item is exactly as tall as its template's rows, with items flush - unchanged from before either key existed. |
required |
item_template
|
callable | None
|
Called per item to build its row layout. Defaults to None (built-in text row). |
None
|
title_template
|
str | callable | None
|
Title for the listbox. A string is used as-is; a callable is invoked to build the title row. Defaults to None. |
None
|
section_style
|
str | None
|
Style overrides applied to each item row section. Defaults to None. |
None
|
title_section_style
|
str | None
|
Style overrides applied to the title section. Defaults to None. |
None
|
select
|
bool
|
Allow item selection. Defaults to |
False
|
multi
|
bool
|
Allow multiple simultaneous selections. Only
used when |
False
|
carousel
|
bool
|
Use carousel styling (e.g. ship-type
selection). Defaults to |
False
|
collapsible
|
bool
|
Clicking a header collapses items until
the next header. Defaults to |
False
|
read_only
|
bool
|
Prevent item modification. Defaults to
|
False
|
reveal
|
bool
|
Scroll so the selected row is visible. A
repaint rebuilds the listbox and the view starts at the top, so a
restored selection can be held but off screen. Opt-in: this widget
is load-bearing, and defaulting it on would move every list in every
mission. Defaults to |
False
|
hint
|
object
|
An opaque token from the previous listbox's
|
None
|
signal
|
str
|
A signal to emit on each row click, with the
selection as |
None
|
data
|
dict
|
Extra variables for the |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
LayoutListbox |
The layout object created. |
Example
gui_list_box(items, style="area:0,0,100,100;", select=True)
gui_list_box_header(label, collapse=False, indent=0, selectable=False, data=None, visual_indent=None)
Create a collapsible section header for use in a listbox.
When collapsible=True is set on the listbox, clicking a header toggles
the visibility of items that follow it until the next header.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
Header label text. |
required |
collapse
|
bool
|
Start in collapsed state. Defaults to
|
False
|
indent
|
int
|
Logical indent level for tree structures. Defaults to 0. |
0
|
selectable
|
bool
|
Whether clicking the header fires a
selection event in addition to toggling collapse. Defaults to
|
False
|
data
|
object
|
Arbitrary data attached to the header item. Defaults to None. |
None
|
visual_indent
|
int | None
|
Override indent level for
rendering only. Defaults to None (uses |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
LayoutListBoxHeader |
The header item. |
gui_list_box_is_header(item)
Return whether a listbox item is a collapsible header.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
Any item from a listbox items list. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
|
Example
for item in items: if gui_list_box_is_header(item): ~~ print("header:", item.label) ~~
gui_listbox_items_convert_headers(items)
Convert a flat string list into a listbox-ready list with collapsible headers.
Items prefixed with >> become LayoutListBoxHeader objects; all
others pass through as plain strings. Pass the result to gui_list_box
with collapsible=True to enable collapse on header click.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
list[str]
|
Flat list of strings. Prefix a string with |
required |
Returns:
| Type | Description |
|---|---|
|
list[str | LayoutListBoxHeader]: Mixed list ready for |
Example
items = gui_listbox_items_convert_headers( [">>Section A", "Item 1", "Item 2", ">>Section B", "Item 3"] ) gui_list_box(items, style="", select=True, collapsible=True)
gui_properties_set(p=None, tag=None)
Update the data displayed in a property list box.
Parses p (a dict or YAML string) into a flat list of label/control
pairs and refreshes the list box stored under tag in the GUI task.
Call this whenever the underlying data changes to redraw the panel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
dict | str
|
Property data as a Python dict or a YAML string. Dict keys become labels; values are Python expressions evaluated to produce the control widget. Nested dicts become collapsible sections. Defaults to None (clears the list). |
None
|
tag
|
str
|
Task inventory key holding the list box widget.
Defaults to |
None
|
Example
gui_properties_set({"Speed": "gui_text(str(ship_speed))", "Shields": "gui_slider(shield_pct)"})
gui_property_list_box(name=None, tag=None, temp=_property_lb_item_template_one_line, hide_when_empty=False)
Create a property list box with single-line label/control layout.
Each property is rendered as a label on the left and its control widget
on the right of the same row. Suitable for compact property panels.
The widget is stored in the GUI task under tag so gui_properties_set
can refresh it later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Title shown in the list box header.
Defaults to |
None
|
tag
|
str
|
Task inventory key used to store and retrieve
the list box widget. Defaults to |
None
|
temp
|
callable
|
Item template function used to render each row. Defaults to the built-in one-line template. |
_property_lb_item_template_one_line
|
hide_when_empty
|
bool
|
Hide the ROW the panel sits in while it
has no properties, so the rows below it take the space. Give the panel
a row of its own ( |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
LayoutListBox |
The list box widget. |
Example
gui_property_list_box("Navigation") gui_properties_set({"Heading": "gui_text(str(heading))", "Speed": "gui_text(str(speed))"})
gui_property_list_box_stacked(name=None, tag=None)
Create a property list box with two-line stacked label/control layout.
Each property is rendered as a label on one line and its control widget
on the line below. Useful when controls are wide and need their own row.
The widget is stored in the GUI task under tag so gui_properties_set
can refresh it later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Title shown in the list box header.
Defaults to |
None
|
tag
|
str
|
Task inventory key used to store and retrieve
the list box widget. Defaults to |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
LayoutListBox |
The list box widget. |
Example
gui_property_list_box_stacked("Ship Systems") gui_properties_set({"Warp Core": "gui_slider(warp_pct)"})
Cosmos consoles
gui_activate_console(console)
Set the current page's active console name.
Marks the page as running a specific console type, which affects which console-specific routes and widgets respond to this client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
str
|
Console name, e.g. |
required |
Example
gui_activate_console("helm")
gui_console(console, is_jump=False)
Activate a standard console with its default engine widget layout.
Sets the engine widget list for the named console using the built-in
configuration. Supported values: "helm", "weapons",
"science", "engineering", "comms", "cinematic",
"mainscreen", "cockpit".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
str
|
Console name (case-insensitive). |
required |
is_jump
|
bool
|
For |
False
|
Example
gui_console("helm") gui_console("helm", is_jump=True)
gui_console_clients(path, for_ships=None)
Return the set of client IDs that have a specific console type.
Searches all player ships (or the given ship set) for linked console
clients whose role matches console,{path}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Console path to match, e.g. |
required |
for_ships
|
object | None
|
Agent ID, object, or set of ships
to search. Defaults to all |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
set |
Client IDs that have a console matching |
Example
helm_clients = gui_console_clients("helm")
gui_console_enter(client_id, console_type, ship=None)
THE ONE DOOR. Call this FIRST whenever a console becomes something else.
A console that arrives somewhere carrying the last screen's furniture is the single most common transition bug in this codebase, and every mission used to have to remember seven separate pieces of trivia to avoid it. This is those seven, in the order that works.
It fires on a CHANGE of console type, not on a repaint. A screen is re-entered every time it repaints - LegendaryMissions' main screen jumps back to itself on the viewscreen signal - so clearing on every reroute would tear down the furniture the screen just raised. Passing the type it already is is a no-op, so putting this at the top of a console label costs nothing.
In order, and each step is here because it bit somebody:
- Overlays. They belong to the CONSOLE, not the page, and the page object
survives a reroute - so
present_allre-draws whatever the slots still hold, and the catch-up ticker re-delivers any live record it finds an empty slot for.overlay_clear_consoledefeats both. - The viewscreen claim. A console that was driving its ship's main screen gives it back rather than holding it from a station that no longer has the control. Leaving a story claim held by a console nobody is sitting at parks every later crew request forever.
- The camera. A shot ASSIGNS its console to the object the lens rides, so a console leaving mid-shot is still riding an enemy ship.
- Every console role, stripped - or a screen that used to be a main screen keeps answering as one.
- The role AND
CONSOLE_TYPE, both. Role withoutCONSOLE_TYPEmeans main-screen view routes never find it;CONSOLE_TYPEwithout the role means overlays,announce()and comms drop the message in SILENCE, because every audience narrows throughany_role. - The crew seat. A seat is believed only while the client's own
CONSOLE_TYPEstill agrees with it, so changing console frees it as a side effect and the player's name and face vanish. Re-asserted with an explicit pick, which is deterministic where letting it re-resolve is not. - The engine widget list. A console leaves its native widgets behind and the page underneath draws through them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
the console. |
required |
console_type
|
str
|
what it is becoming - |
required |
ship
|
optional
|
the ship it belongs to. Defaults to its home ship. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True if the console actually changed, False if it already was this. |
gui_screen_revision(client_id=None, band=GUI_SCREEN_BAND_PX)
What an on change watches to rebuild a console after a RESIZE.
A console that decides anything from the screen - how many rows a box shows, how
wide a column is - reads it while BUILDING, so the answer is baked into the page.
screen_size updates the aspect ratio and re-presents, which recomputes
percentages but does not re-run the builder, so those decisions stay as they were.
Watching this and jumping back to the console's label rebuilds them.
COARSE ON PURPOSE. The raw size is reported many times while a window is dragged, and a console rebuild per distinct value would thrash. A band rebuilds at most once per band crossed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
defaults to the current frame's client. |
None
|
band
|
int
|
band size in pixels. Defaults to
:data: |
GUI_SCREEN_BAND_PX
|
Returns:
| Type | Description |
|---|---|
|
tuple[int, int]: the banded (width, height). Compare, do not read as pixels. |
Example
on change gui_screen_revision(client_id): jump my_console_label
Console tabs:
The console tab system allows for creating a page tabbing system that allows the user to switch between pages quickly.
Tabs are defined with a //gui/tab label. This label defines what happens when that tab is press.
Example:
# Allow the debug tab to be shown
# at the top level
gui_tab_add_top("debug")
//gui/tab/debug
jump show_debug_page
//gui/tab/brain
jump show_brain_page
=== show_debug_page
# Set the return page
gui_tab_back(CONSOLE_SELECT)
# Add the brain as a tab of the debug page
gui_tab_enable("brain")
# Set the back button to the last selected standard console
# Rest of code to show page
=== show_brain_page
# Set the back button to the last selected standard console
gui_tab_back("debug")
# Rest of code to show page
gui_app_activate(app_name)
Records which ePADD app this client is on. Injected by every //gui/app label.
DELIBERATELY DOES NOT TOUCH __active_tab__. That asymmetry with
gui_tab_activate is the whole return-point mechanism: an app never overwrites the
tab you were on, so the PADD's single Back knows where to send you with nothing
having to capture it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app_name
|
str
|
The path of a //gui/app |
required |
gui_app_get_active(client_id=None)
The ePADD app this client is on, or "" when they are not in the PADD.
Takes an explicit client because the PAGE asks this question while drawing, and
_tab_client_id answers with the ambient page - which during a strip build is not
reliably the page being built. The same distinction epadd._client_id documents.
gui_tab_activate(tab_name)
Sets the back tab (left most) tab for the console tabs. This is general called automatically by //gui/tab and //console labels
ALSO ENDS THE PADD. Arriving at a tab is how you leave the ePADD, so this clears
__active_app__ - otherwise the strip would go on drawing the PADD's bar over a
console. Doing it here rather than in each tab means nothing has to remember to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
The path of a //gui/tab |
required |
gui_tab_add_top(tab_name)
Specify a tab by default to shown when the page is shown for standard consoles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
A comma separated list of paths of a //gui//tab e.g. helm,weapons |
required |
gui_tab_back(tab_name)
Sets the back tab (left most) tab for the console tabs. The back tag is set by //gui/tab and //console labels This allows overriding
A console that is currently BOARDED goes back to the crew console instead, whatever the caller asked for - see the comment above. Nothing to do at the call sites.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
The path of a //gui/tab |
required |
gui_tab_back_override(client_id, tab_name)
Send this console's Back to tab_name, whatever a screen asks for.
For a console that is somewhere other than the console it picked - a pilot in the
cockpit picked the Hangar, so every ePADD screen's gui_tab_back(CONSOLE_SELECT)
said "hangar", and Back pulled them out of their craft mid-flight. The mission sets
this when the pilot takes the seat and clears it when they leave; no call site
changes. A boarded or EVA console's own swap still wins.
gui_tab_back_override_clear(client_id)
Forget a Back target set by gui_tab_back_override.
gui_tab_back_while_boarded(tab_name=None, kind=BOARDED_KIND_GRID)
Name the tab a BOARDED console's Back should go to, or clear it with None.
Called once by the addon that declares that tab::
gui_tab_back_while_boarded("boarding_crew")
gui_tab_back_while_boarded("eva_crew", kind="eva")
//gui/tab/boarding_crew
jump boarding_crew_console
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
the |
None
|
kind
|
str
|
which kind of boarded console this tab is for - |
BOARDED_KIND_GRID
|
Returns:
| Type | Description |
|---|---|
|
str | None: the name now installed for that kind. |
gui_tab_boarded_back_clear()
Drop every substitution (called by reset_mission_state).
A LATCH, not a container: an addon installs it at its top level, so one left behind would point the next mission's Back at a tab whose route no longer exists.
gui_tab_boarded_back_tab(kind=BOARDED_KIND_GRID)
The tab a boarded console's Back goes to, or None when nothing installed one.
gui_tab_boarded_back_tabs()
Every installed substitution, as {kind: tab}. For tools and the reset ledger.
gui_tab_clear_top()
Specify a tab by default to shown when the page is shown for standard consoles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
A comma separated list of paths of a //gui//tab e.g. helm,weapons |
required |
gui_tab_enable(tab_name)
Enable a tab on the console tabs
A NAME THAT IS NOT A STRING IS IGNORED, not a crash. Callers pass a variable -
gui_tab_back(CONSOLE_SELECT) is the shipped shape - and a task variable that was
never set arrives as None, which used to reach None.split(",") and raise INSIDE a
GUI build. A screen that cannot draw is a far worse outcome than a screen with no
back tab, and the missing tab is reported where it is noticed rather than here.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
A comma separated list of paths of a //gui//tab e.g. helm,weapons |
required |
gui_tab_get_active()
returns the active tab
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
The path of a //gui/tab |
required |
gui_tab_is_top(tab_name)
Specify a tab by default to shown when the page is shown for standard consoles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
A comma separated list of paths of a //gui//tab e.g. helm,weapons |
required |
gui_tab_remove_top(tab_name)
Specify a tab by default to shown when the page is shown for standard consoles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab_name
|
str
|
A comma separated list of paths of a //gui//tab e.g. helm,weapons |
required |
gui_add_console_type(path, display_name, description, label)
adds a tab definition
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id_or_obj
|
agent
|
agent id or object |
required |
console
|
str
|
Console name |
required |
tab_name
|
str
|
Tab name |
required |
label
|
label
|
Label to run when tab selected |
required |
gui_get_console_type(key)
Get the list of consoles defined by @console decorator labels
gui_get_console_type_list()
Get the list of consoles defined by @console decorator labels path is added as a value
gui_get_console_types()
Get the list of consoles defined by @console decorator labels
gui_remove_console_type(path, display_name, label)
adds a tab definition
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Console path |
required |
display_name
|
str
|
Display name |
required |
label
|
label
|
Label to run when tab selected |
required |
gui_layout_widget(widget, style=None, alt=None)
Place a specific engine widget at a fixed position in the layout.
Adds the named engine widget to the console widget list AND places a
ConsoleWidget placeholder in the layout at the current position so the
engine widget renders inside the defined area.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
widget
|
str
|
Engine widget name, e.g. |
required |
style
|
str
|
Layout style for the PLACEHOLDER, as for any other
widget - most usefully |
None
|
alt
|
str | sequence
|
the SECOND rect, |
None
|
DO NOT SHARE A ROW WITH MAST CONTROLS. The placeholder lays out correctly - measured:
red_alert beside three checkboxes computes four clean quarters, and every rect is
sent - but the ENGINE draws its widget at its own size, over the top of whatever MAST
put beside it, so the controls simply vanish. Give an engine widget its own row (or
its own section). col-width still shapes the rect the engine is GIVEN, which is
worth having on its own; it just cannot stop the engine painting outside it.
Returns:
| Name | Type | Description |
|---|---|---|
ConsoleWidget |
The layout placeholder item. |
Example
gui_section(style="area:0,0,70,100;") gui_layout_widget("2dview")
sharing one row with a checkbox:
gui_checkbox("Follow", "col-width:90px;", var="follow_tag") gui_layout_widget("red_alert", "col-width:1fr;")
a stock widget kept exactly where the engine had it (guiboxdata.txt
normal_helm throttle):
gui_section(style="area:0,62,10,100;") gui_layout_widget("throttle", alt="0,61,5,99")
gui_update_widget_list(add_widgets=None, remove_widgets=None)
Add or remove widgets from the current client's active widget list.
Modifies the live widget list by taking the union of add_widgets and
the current list, then subtracting remove_widgets. View widgets
(2dview, 3dview, etc.) are always placed first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
add_widgets
|
str | None
|
|
None
|
remove_widgets
|
str | None
|
|
None
|
Example
gui_update_widget_list(add_widgets="shield_control", remove_widgets="radar_zoom_ctrl")
gui_update_widgets(add_widgets, remove_widgets)
Stage widget list changes on the pending widget list without sending.
Modifies page.pending_widgets rather than the live widget list. Changes
are committed when the pending list is flushed to the engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
add_widgets
|
str
|
|
required |
remove_widgets
|
str
|
|
required |
Example
gui_update_widgets("shield_control", "radar_zoom_ctrl")
gui_widget_list(console, widgets)
Set the engine console widget list for the current client.
Sends a widget list string directly to the engine, replacing the current
widget layout. Widgets are ^-separated engine widget names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
str
|
Console type name, e.g. |
required |
widgets
|
str
|
|
required |
Example
gui_widget_list("normal_helm", "2dview^helm_movement^throttle")
gui_widget_list_clear()
Clear all engine widgets from the current client's console.
Sends an empty widget list to the engine, removing all engine controls. The MAST GUI layout (sections, regions, etc.) is not affected.
Example
gui_widget_list_clear()
gui_widget_offscreen(widget, client_id=None)
Push an engine widget out of view.
The ONLY reliable way to be rid of an engine widget. It cannot be un-declared: the
console's widget list is what the engine draws from, and the engine keeps what it has
been given, so simply not asking for it is not always enough on a console that has
already shown it. gui_hide() does even less - it clears _show on the layout
placeholder while the engine carries on rendering.
So this does what gui_panel_widget_hide has always quietly done: sends the widget a
rect at 100,100, off the visible area. Named, because "hide the waterfall" was
attempted three different wrong ways before anyone found the one that works.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
widget
|
str
|
engine widget name, e.g. |
required |
client_id
|
int
|
defaults to the current client. |
None
|
Tab panels
gui_info_panel(tab=0, tab_location=0, icon_size=0, var=None)
Create the standard info panel with a built-in ship-data tab.
Initialises a TabbedPanel pre-loaded with a "hide" tab (icon 121) and
a "ship_data" tab (icon 140). Additional tabs can be appended with
gui_info_panel_add. The panel object is stored in the GUI task under
var so it can be retrieved and updated later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab
|
int
|
Initially active tab index. Defaults to 0. |
0
|
tab_location
|
int
|
Edge where tabs appear (0=left). Defaults to 0. |
0
|
icon_size
|
int
|
Icon size in pixels. Defaults to 0 (auto). |
0
|
var
|
str
|
Task variable name used to store the panel.
Defaults to |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
TabbedPanel |
The info panel layout object. |
Example
tp = gui_info_panel() gui_info_panel_add("comms", 130, show_comms_tab)
gui_info_panel_add(path, icon_index, show, hide=None, tick=None, var=None)
Add a tab to an existing info panel.
If the panel is currently displayed, it is re-represented immediately.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Route name for this tab, used to switch to it programmatically. |
required |
icon_index
|
int
|
Icon index displayed on the tab button. |
required |
show
|
callable
|
|
required |
hide
|
callable
|
Called when the tab is deactivated. Defaults to None. |
None
|
tick
|
callable
|
Called each tick while the tab is active. Defaults to None. |
None
|
var
|
str
|
Task variable holding the panel (set by
|
None
|
Returns:
| Type | Description |
|---|---|
|
TabbedPanel | None: The panel, or |
Example
gui_info_panel_add("crew", 155, show_crew_tab, hide_crew_tab)
gui_info_panel_remove(path, var=None)
Remove a tab from an info panel by its path name.
If the panel is currently displayed and the tab was actually present, the panel is re-represented immediately.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Route name of the tab to remove (as passed to
|
required |
var
|
str
|
Task variable holding the panel. Defaults to
|
None
|
Returns:
| Type | Description |
|---|---|
|
TabbedPanel | None: The panel, or |
Example
gui_info_panel_remove("crew")
gui_info_panel_send_message(client_id, message=None, message_color=None, path=None, title=None, title_color=None, banner=None, banner_color=None, face=None, icon_index=None, icon_color=None, button=None, history=True, time=-1, notify=None)
Send a message card to a client's info panel.
Every card is filed in the tab's log (readable any time on the log tab)
unless history=False. A card only interrupts - taking over the panel's
tab and auto-dismissing - when it needs an answer or the caller asks:
- a card with a
buttonALWAYS interrupts. It is a progression gate: a mission awaiting the press deadlocks if the player never sees it. - otherwise pass
notify=Trueto interrupt. The default isFalse: the card goes to the log and does not steal the tab, because the attention half of a notification belongs to an overlay now (seeannounce).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int | set
|
Client(s) to receive the message. |
required |
message
|
str
|
Main body text. |
None
|
message_color
|
str
|
CSS color for the body text. |
None
|
path
|
str
|
Tab path to place the message in. Defaults to
|
None
|
title
|
str
|
Bold header line above the message. |
None
|
title_color
|
str
|
CSS color for the title. |
None
|
banner
|
str
|
Larger banner text shown above the title. |
None
|
banner_color
|
str
|
CSS color for the banner. |
None
|
face
|
str
|
Face/portrait key to display alongside the message. |
None
|
icon_index
|
int
|
Icon index to display alongside the message. |
None
|
icon_color
|
str
|
CSS color for the icon. |
None
|
button
|
str | list
|
Button label(s) to show. When set the function returns an awaitable Promise that resolves on button press. |
None
|
history
|
bool
|
File the card in the tab's log. Defaults to True. |
True
|
time
|
int
|
Auto-dismiss after this many seconds if no button is configured. Defaults to -1 (use panel default of 10 s). |
-1
|
notify
|
bool
|
Interrupt - show the card live and switch the panel to its tab. Defaults to None, meaning "only if it has a button". Pass True for a card that must be seen now. |
None
|
Returns:
| Type | Description |
|---|---|
|
Promise | None: Resolves when the button is pressed, or None if no button was specified. |
Example
await gui_info_panel_send_message(CLIENT_ID, title="New Orders", message="Report to DS1 immediately.", face="captain")
gui_panel_ship_data_hide(cid, left, top, width, height)
Push ship data off screen when the tab is deactivated.
No longer moves text_waterfall with it - that widget is gone; see the note on
gui_panel_ship_data_show.
gui_panel_ship_data_show(cid, left, top, width, height)
Ship data filling the panel.
It used to give the bottom four lines to text_waterfall and shrink ship_data to
suit. That widget is gone (mkdocs build/messages.md) - it could not be styled from script -
and positioning it here brought it BACK on any console showing this tab, whatever the
console's widget list said. ship_data now gets the whole panel.
gui_tabbed_panel(items=None, style=None, tab=0, tab_location=0, icon_size=0)
Create a tabbed panel widget with icon-based tab navigation.
Each tab is defined by a dict with path, icon, show, and
optionally hide and tick keys. The panel calls show when a tab
is activated and hide when it is deactivated. Prefer gui_info_panel
for the standard info panel; use this directly only when building a custom
panel layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
list[dict]
|
Tab descriptors. Each dict has:
|
None
|
style
|
str
|
CSS-like style string for the panel. Defaults to None. |
None
|
tab
|
int
|
Index of the initially active tab. Defaults to 0. |
0
|
tab_location
|
int
|
Edge where tabs appear (0=left). Defaults to 0. |
0
|
icon_size
|
int
|
Icon size in pixels. Defaults to 0 (auto). |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
TabbedPanel |
The panel layout object. |
Example
panels = [ {"path": "status", "icon": 140, "show": show_status, "hide": hide_status}, {"path": "map", "icon": 121, "show": show_map}, ] tp = gui_tabbed_panel(panels, tab=0)
Update and refreshing the GUI
gui_hide(layout_item)
Hide a visible layout item.
For sections, recalculates the layout after hiding. For individual items
or rows, hides the element but does not re-layout — pair with
gui_represent on the parent section if the layout needs updating.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
The layout object to hide. No-op if already hidden or
|
required |
Example
gui_hide(warning_row) gui_represent(my_section)
gui_rebuild(region)
Mark a section or region to rebuild its layout on the next present.
Clears the region's sub-layout so it is reconstructed from scratch the next time the region is rendered.
USE THIS ON A REGION, NOT ON A PLAIN SUB-SECTION. A region brackets its own
drawing region and sends send_gui_clear for it before redrawing
(Layout.region_begin), so its old children genuinely go. A plain
gui_sub_section has no region to clear and the engine offers no "delete
this widget", so a refill allocates NEW tags and every earlier fill stays
painted underneath - which is how the ePADD inbox came to draw three
messages on top of each other. A pane that is refilled out of band has to be
a region, or a Control that owns its region (a text area, a listbox),
updated in place.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
region
|
A section or region layout item. |
required |
Returns:
| Type | Description |
|---|---|
|
The same |
Example
gui_rebuild(my_region) gui_represent(my_region)
gui_refresh(label)
Re-run an await gui() block at a given label on the current task.
Causes any scheduler running label to rebuild its GUI from scratch on
the next tick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
MAST label whose |
required |
Example
gui_refresh(status_panel)
gui_represent(layout_item)
Redraw a layout item on the client screen.
For sections and regions, recalculates the entire sub-layout and redraws all children. For individual items or rows, redraws that element only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
The layout object to redraw. |
required |
Example
gui_represent(my_section)
gui_show(layout_item)
Make a hidden layout item visible.
For sections, recalculates the layout after showing. For individual items
or rows, shows the element but does not re-layout — pair with
gui_represent on the parent section if the layout needs updating.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layout_item
|
The layout object to show. No-op if already visible or
|
required |
Example
gui_show(warning_row) gui_represent(my_section)
gui_update(tag, props, shared=False, test=None)
Update the property string of an existing GUI element by tag.
Finds the element with the given tag on the current page (or all pages if
shared=True) and updates its properties in-place without rebuilding the
full layout.
The tag is a SCRIPT-SIDE name, not the string the engine knows the widget by.
Set it with a tag: style (gui_text("hi", style="tag:status;")) and the
page records it beside the engine's own tag, so naming a widget never disturbs
the tag the engine, a listbox, or a click region depends on.
A name set inside a listbox item_template resolves too, but note two things:
only rows that are currently ON SCREEN exist, so a tag naming a scrolled-away row
finds nothing; and the name must be unique per row (put the item in it, e.g.
f"tag:row-{item};") or only the last row drawn is reachable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tag
|
str
|
The element name to find and update. |
required |
props
|
str
|
New property string for the element, e.g.
|
required |
shared
|
bool
|
Apply the update to all client pages, not just
the current one. Defaults to |
False
|
test
|
dict | None
|
Only apply the update when any variable
in |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True when a widget was found and updated. False is not an error -- |
|
|
an off-screen listbox row is the ordinary case -- but it lets a caller tell |
||
|
a miss from a hit. Always False for |
Example
gui_update(status_tag, "$text:OK;color:green;")
gui_update_shared(tag, props, test=None)
Update a GUI element by tag on all client pages.
Convenience wrapper for gui_update(tag, props, shared=True, test=test).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tag
|
str
|
The element tag to find and update. |
required |
props
|
str
|
New property string for the element. |
required |
test
|
dict | None
|
Only update when any variable in
|
None
|
Example
gui_update_shared(alert_tag, "$text:ALERT;color:red;")
gui_history_back()
Jump back to the previous navigation history entry.
Restores any variables stored with the entry and jumps to its label. No-op if there is no history.
Example
- "Back" gui_history_back()
gui_history_clear()
Clear the navigation history for the current page.
Removes all back and forward history entries. Call this when entering a top-level screen where back-navigation should not be available.
Example
gui_history_clear()
gui_history_forward()
Jump forward to the next navigation history entry.
Restores any variables stored with the entry and jumps to its label. No-op if there is no forward history.
Example
- "Forward" gui_history_forward()
gui_history_jump(to_label, back_name=None, back_label=None, back_data=None)
Jump to a new GUI label and record the current position in navigation history.
Appends the current position to the back-stack (clearing any forward
history) then jumps to to_label. Call gui_history_back to return.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
to_label
|
label
|
Label to navigate to. |
required |
back_name
|
str | None
|
Display name for the back entry.
Defaults to |
None
|
back_label
|
label | None
|
Label to return to. Defaults to the currently active label. |
None
|
back_data
|
dict | None
|
Variables to restore when returning back. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
PollResults |
Result of the jump. |
Example
gui_history_jump(ship_detail_screen, back_name="Ship List")
gui_history_redirect(back_name=None, back_label=None, back_data=None)
Append to navigation history without jumping forward.
Adds a history entry so the current location can be returned to via
gui_history_back, but does not change the active label. Use when you
need to update the back-stack from within a label that was jumped to
externally (e.g. from a route).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
back_name
|
str | None
|
Display name for the history entry.
Defaults to |
None
|
back_label
|
label | None
|
Label to return to. Defaults to the currently active label. |
None
|
back_data
|
dict | None
|
Variables to restore when returning back. Defaults to None. |
None
|
gui_history_store(back_text, back_label=None)
Record the current label as a history entry (back destination).
Stores the active label (or back_label) so that gui_history_back
can return to it later. Use gui_history_jump instead when also
navigating forward.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
back_text
|
str
|
Display name for this history entry (shown in back buttons or breadcrumbs). |
required |
back_label
|
label
|
Label to return to. Defaults to the currently active label. |
None
|
gui_reroute_client(client_id, label, data=None)
Jump a specific client's GUI task to a new label immediately.
Finds the client's active page, optionally sets variables from data,
then jumps the page's GUI task to label and ticks it in the current
frame context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
The client to reroute. |
required |
label
|
MAST label to jump to. |
required | |
data
|
dict | None
|
Variables to set on the task before jumping. Defaults to None. |
None
|
Example
gui_reroute_client(CLIENT_ID, briefing_screen)
gui_reroute_clients(label, data=None, exclude=None)
Jump all connected client GUI tasks to a new label.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
MAST label to jump to. |
required | |
data
|
dict | None
|
Variables to set on each task before jumping. Defaults to None. |
None
|
exclude
|
set | None
|
Set of client IDs to skip. Defaults to None (no exclusions). |
None
|
Example
gui_reroute_clients(mission_end_screen, exclude={spectator_id})
gui_reroute_server(label, data=None)
Jump the server GUI task to a new label.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
MAST label to jump to. |
required | |
data
|
dict | None
|
Variables to set on the task before jumping. Defaults to None. |
None
|
Example
gui_reroute_server(server_status_page)
page_gui_task_jump(page, label, activate_cmd=0, tick=False)
Queue a jump on a page's GUI task. The one place that does this.
Three callers steer a console's GUI task from outside it -- gui_task_jump,
gui_reroute_client, and the await gui() promotion in gui.py (LM #714) --
and they used to each spell it out. They differ only in whether the jump
runs in the CURRENT frame:
tick=False queue it; the next scheduler tick picks it up. tick=True run it now, under a FrameContextOverride, the way a repaint triggered by a click has to.
Returns True when the jump was queued.
Windows clipboard
gui_screenshot(image_path)
Capture the full desktop and save it as a BMP file.
Windows-only. Captures the entire desktop window (not just the Cosmos window) using GDI BitBlt. Useful for automated testing or recording mission state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_path
|
str
|
Absolute path to write the |
required |
Example
~~ gui_screenshot("C:/missions/debug/frame001.bmp") ~~
gui_clipboard_get()
Read the current text content of the Windows clipboard.
Windows-only. Returns None if the clipboard is empty or contains
non-text data.
Returns:
| Type | Description |
|---|---|
|
str | None: The clipboard text, or |
Example
text = gui_clipboard_get() if text is not None: gui_text("Pasted: {text}")
gui_clipboard_put(s)
Write a text string to the Windows clipboard.
Windows-only. Replaces whatever is currently on the clipboard.
gui_clipboard_copy is an alias for this function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s
|
str
|
The text to place on the clipboard. |
required |
Example
gui_clipboard_put("TSN Artemis — Mission Report")
Interacting with client side data
gui_request_client_string(client_id, key, timeout=None)
Request a text string from the player via a native OS input dialog.
Sends a request_client_string call to the engine for the given client.
The engine shows an OS-level text input and returns the typed value as a
client_string event. Suspends until the player submits or the timeout
fires.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_id
|
int
|
Client to prompt. |
required |
key
|
str
|
Tag used to identify the response event ( |
required |
timeout
|
Promise
|
A promise that cancels the request if it resolves first. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Promise |
Resolves with the typed string as its result. |
Example
result = await gui_request_client_string(CLIENT_ID, "ship_name") ~~ player_name = result.result ~~
The ePADD
ePADD - one console tab that holds the apps.
The console tab strip is a junk drawer. A bridge console carries help, library,
upgrade, quest and (in a dev build) debug before Engineering adds fabricate
and cargo - seven of the eight slots TAB_MAX_VISIBLE allows, after which the rest
roll into a More (n) dropdown. And the strip cannot be ordered: position is .mast
load order, reversed by add_front, and the button label is the raw lowercase route
path, so every tab reads fabricate, upgrade, cargo.
ePADD replaces the strip with ONE button. Opening it gives a home screen of app tiles,
grouped and scoped to the station that should see them. An app IS a tab - the same
//gui/tab/<name> route, unchanged - plus the presentation the route grammar has no
room for ([\w]+ and an optional if is the whole of it).
//gui/tab/cargo # untouched
jump cargo_screen
gui_app_register("cargo", title="Cargo", icon="cargo",
consoles="engineering", group="Ship", sort=10)
ALWAYS ON. It used to be opt-in, with gui_app_mode() per client and an
EPADD_ENABLED setting behind it. That went when apps became their own route kind: an
app is no longer a tab, so switching the PADD off does not fall back to the classic
strip - it leaves the apps with no way in at all. Nothing about the declare-every-build
contract changes: the page still consumes console_tabs and __back_tab__ every build.
AN APP IS ITS OWN ROUTE KIND. A screen on the PADD is //gui/app/<name>, not
//gui/tab/<name>, because the two answer different questions: a tab's if says
whether it may be OFFERED ON THE BAR, an app's says whether the app is AVAILABLE. One
route kind doing both is what let //gui/tab/boarding_party if not gui_app_mode_is_on() hide the
boarding tab correctly and delete the way back to the crew console with it.
There used to be an ADOPTION bridge here: a tab nobody registered showed up under
"Other" so an addon that had never heard of ePADD kept working. It was removed when
apps got their own route kind - a name can no longer be both - so an app that names a
route no .mast declares is now REPORTED rather than silently left off the PADD.
epadd_console_allowed(console)
Whether the PADD belongs on this console (any name the engine or a script uses).
epadd_console_name(console)
The name a script would use for a console, whatever the engine calls it.
gui_app_badge(app)
An app's live badge, as text.
Never raises: a provider that throws costs its own tile a badge and nothing else.
RE-ENTRANT PROVIDERS ARE ANSWERED, NOT RE-ENTERED. A provider is free to ask what
the other apps are reporting - LM's Status tile does exactly that, counting the apps
with something to say - and status_rows computes a badge for EVERY app, the asking
one included. That is a cycle: the provider was entered 332 times for one badge
(measured), unwound only when Python's own recursion limit tripped, and the
RecursionError caught below was logged as "status provider for 'status' raised" on
every badge computation, several times a second. The badge still came out right,
which is why it read as noise rather than as a bug.
gui_app_chrome(title, subtitle=None)
An app's title bar. OPTIONAL - an app draws it when a title helps orient.
ITS OWN BAND, 45px..109px, from design/epadd/Spec.src. It used to be a bare
gui_row with no section of its own, so it landed in the ambient full-screen section
at y=0 and painted over the engine's Options button. Every caller already reserved
area: 0, 109px, 100, 100 for its body, so the bar was always MEANT to own this
band - it just never claimed it.
45px is the console body top, the LM convention every tab body already follows, so this clears the tab strip as well as Options.
NO HOME BUTTON. The strip's status region opens the PADD home already; a HOME here
was a second control for the same thing. And no back: the one Back in the game is
the console's, on the tab bar, declared by every PADD screen with
gui_tab_back(CONSOLE_SELECT).
NOT EVERY APP WANTS ONE. Upgrades and the other list/detail screens use their whole sheet and read better for it, so this is opt-in rather than something every screen must remember to draw.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
the screen's name. |
required |
subtitle
|
str
|
a second, dimmer line. Leave it out unless it says something the screen below does not - a board captioned with the count of what it is already listing says nothing. Pass "" rather than None for a line that is EMPTY NOW but will have text later: the widget is created either way, so a live screen can update it in place instead of rebuilding the page to make one appear. |
None
|
Returns:
| Type | Description |
|---|---|
|
Text | None: the subtitle widget, so a caller can keep it and update it. |
gui_app_get_registered()
Every registration, unfiltered - the raw table, for tools and tests.
gui_app_groups(console=None, client_id=None)
gui_app_list folded into (heading, apps) pairs, in drawing order.
An empty group is not returned at all, which is why Helm - registering no ship apps - draws no "Ship" heading rather than an empty one.
gui_app_home(ship_name=None, columns=None, title='ePADD')
Draw the PADD home screen for this console.
Called from the //gui/tab/epadd route's screen label, which then sits in
await gui() - so the tile handlers belong to a task that stays alive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ship_name
|
str
|
shown beside the wordmark. |
None
|
columns
|
int
|
tiles per row. Defaults to 4, or 6 once the console carries more than twelve apps, where the descriptions are dropped too. |
None
|
title
|
str
|
the wordmark. |
'ePADD'
|
gui_app_home_tick()
Move the mission clock on, without rebuilding the home sheet.
The screen calls this from an on change mission_elapsed_text() block, so it
runs once a second - which means it has to be cheap, and it has to not care
about being called when the home screen is no longer up:
gui_app_home()
on change mission_elapsed_text():
gui_app_home_tick()
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True when the clock was changed, False when there was nothing to do - no home screen on this page, or the same second again. |
gui_app_identity_text(client_id=None, console=None)
What the badge says: who you are, and how much is waiting.
None when there is nothing worth a line - then no badge is drawn at all, rather than an empty box on every console of a mission that uses none of this.
gui_app_list(console=None, client_id=None)
The apps this console should offer, in the order they should be drawn.
Registered apps scoped to console. An entry whose //gui/app/ route does not
exist, or whose route condition is false right now, is left out - the route's own
if is still the authority on whether a panel is available. A MISSING route is
reported by name; it is almost always a typo or an unmigrated //gui/tab.
Returns:
| Type | Description |
|---|---|
|
list[dict]: each with tab, title, icon, group, sort, description, label. |
gui_app_open(tab)
Open an app: send the GUI task to that app's label.
The same two lines TabControl.on_message runs when a tab button is clicked, so
an app opened from the PADD arrives exactly as a tab would have.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
False when the app has no route or there is no GUI task to send. |
gui_app_register(tab, title=None, icon=None, consoles='*', group=None, sort=100, description=None, status=None, boarding=False)
Present an existing //gui/tab/<tab> route as an ePADD app.
The route is not touched and keeps its own if condition, which is still what
decides whether the app is offered at all.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab
|
str
|
the |
required |
title
|
str
|
the tile's name. Defaults to the tab path, title-cased. |
None
|
status
|
callable | str
|
a short live value for the tile's badge - "3 unread", "2 building", "42/60". A callable is called at build time and anything it raises is swallowed, because a badge must never be able to take the home screen down with it. This is what the crew read WITHOUT opening anything, and it is why the apps that carry live state do not each need a panel of their own. |
None
|
icon
|
str
|
an icon NAME for |
None
|
consoles
|
str
|
comma list of console names, or "" for every SHIP
console. Matched after |
'*'
|
boarding
|
bool
|
also offer this app to the crew console. |
False
|
group
|
str
|
heading to file the tile under. Defaults to "Mission". |
None
|
sort
|
int
|
order within the group, low first. Ties break on title. |
100
|
description
|
str
|
the tile's second line. |
None
|
gui_app_revision(console=None, client_id=None)
What the HOME screen watches to know it must repaint.
A signal does not wake await gui(), so the home screen polls - the same shape
the inbox and the crew console use. Two things change under it: a badge (mail
arrives, a build finishes) and the app LIST itself, because a route condition can
turn an app on or off while the PADD is open. Without this the home screen was
frozen at whatever it said when it was opened.
Cheap: the badges are computed for the tiles anyway.
gui_app_subnav(apps)
The screens THIS app can reach, on the bar's own line.
Called straight after gui_app_chrome, and deliberately opens NO row of its own -
it appends to the bar's, so the sub-apps sit to the right of the title in the same
45..109px band instead of eating a second one:
gui_app_chrome("Debug")
gui_app_subnav(["brain", "mast"])
[ Debug ..................... [Brain] [MAST] ]
The chrome's trailing blank is what puts them on the right: it takes the slack, so everything after it is pushed to the far end of the row.
Its own call rather than a parameter on the bar, because exactly one app has sub-apps and folding that into the component every screen draws is how the bar accumulated the special cases that made it wrong.
Replaces gui_tab_enable("brain,mast"), which put an app's sub-screens on the
CONSOLE'S tab bar - the last place the PADD and the tab system still met.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
apps
|
list[str]
|
app names. A sub-app has no registration, so a name with no registered title falls back to its own name. |
required |
gui_app_unregister(tab)
Drop an app registration. The //gui/app/ route is untouched - it simply stops
being offered on the PADD.
gui_app_waiting(console=None, client_id=None)
How many apps have something to say - the count the badge carries.
Apps, not messages. Unread mail is only one of the things a badge reports, and the number a crew member cannot get any other way is "how many of these should I open".
gui_app_why(tab, console=None, client_id=None)
Why a tile is, or is not, on this console's PADD. One line, in plain words.
A missing tile has four causes and three of them are SILENT by design - the whole point of a route condition is that it hides things quietly - so "the app is just not there" has been costing a full archaeology session each time it is reported. Ask this instead, from a debug console or a comms route::
log(gui_app_why("boarding_party"))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tab
|
str
|
the app, as |
required |
console
|
str
|
the console to ask about. Defaults to this client's. |
None
|
client_id
|
optional
|
the console's client. Defaults to the page's own. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
str |
the reason, naming the thing to go and look at. |