factoriax.playground.ui.panels#
Reusable drawing primitives for Factoriax menus.
All components read sizes and colors from factoriax.playground.ui.theme so the
look stays consistent across menus. Each function is a stateless drawing
operation. Menus own the layout and event loop.
- class factoriax.playground.ui.panels.DecorationStrip(surfaces: tuple[Surface, ...], ore_surface: Surface, icon_size: int, icon_gap: int, anim_targets: tuple[int, ...], anim_step_ms: int = 700, anim_cycle_len: int = 6)#
Horizontal row of game icons with a periodic “ore on belt” animation.
Stateless:
drawderives the animation phase fromtime_ms(typicallypygame.time.get_ticks()). Build one with thefactoriax_default()factory or by populating the fields manually.- draw(surf: Surface, x: int, y: int, time_ms: int) None#
Blit every icon left-to-right at
(x, y)and overlay the ore.
- classmethod factoriax_default(icon_size: int, icon_gap: int = 10) DecorationStrip#
Build the standard 8-slot strip: player, miner, 4×belt, arm, pallet.
Ore travels across the four belt slots (indices 2-5) and onto the arm (index 6). The player and miner slots stay clear.
- class factoriax.playground.ui.panels.InputSourceTracker#
Record which input device moved the selection last.
A menu takes the mouse hover only while
mouse_activeisTrue. That flag becomesTruewhen the cursor moves between two calls totick().The caller calls
mark_keyboard()for each keyboard action. A cursor that does not move therefore leaves the selection where the keyboard put it.
- class factoriax.playground.ui.panels.LabelValueSection(title: str, labels: tuple[str, ...])#
A titled group of
(label, value)rows for read-only / non-numeric display.Companion to
SettingSection: same visual layout, but values are arbitrary strings the caller pre-formats (key bindings, toggle state, enum-style choices). The active row gets the gold-fill highlight but no chevron decoration. There are no arrow-adjust semantics to advertise.
- class factoriax.playground.ui.panels.SettingField(key: str, label: str, is_float: bool, step: float, min_value: float, max_value: float)#
One editable numeric setting in a settings menu.
- class factoriax.playground.ui.panels.SettingSection(title: str, fields: tuple[SettingField, ...])#
A titled group of related
SettingFieldrows.Used by
draw_setting_sections()to render an editable settings list with elegant headings and dividers between groups.
- factoriax.playground.ui.panels.draw_button(surf: Surface, rect: Rect, label: str, font: Font, *, focused: bool = False, hovered: bool = False) None#
Draw a button with round corners, in the style of a panel.
- Parameters:
surf – Surface to draw on.
rect – Area of the button.
label – Text at the center of the button.
font – Font for the label.
focused –
Truedraws the button as the selected one.hovered –
Truedraws the button under the mouse.
- factoriax.playground.ui.panels.draw_description(surf: Surface, rect: Rect, text: str, scroll: int, font: Font) int#
Render wrapped scrollable text in
rect. Returns the clamped scroll.
- factoriax.playground.ui.panels.draw_hint_bar(surf: Surface, sw: int, y: int, text: str, font: Font) None#
Centered hint text in
theme.HINT_COLOR.
- factoriax.playground.ui.panels.draw_label_value_sections(surf: Surface, rect: Rect, sections: tuple[LabelValueSection, ...] | list[LabelValueSection], values: list[str], selected_idx: int, focused: bool, font: Font, heading_font: Font) tuple[list[Rect], int]#
Render sectioned label/value rows for bindings, toggles, choices.
The rows look the same as the rows of
draw_setting_sections(). The caller gives each value as text, and the selected row gets no chevron.- Parameters:
surf – Surface to draw on.
rect – Area that holds the rows.
sections – Sections to draw, in order. Each one has a heading and its rows.
values – Value of every row, as one flat list. It follows the order of the rows of every section, one section after the other.
selected_idx – Index into
valuesof the selected row.focused –
Truedraws the selected row as active.font – Font for a row.
heading_font – Font for a heading.
- factoriax.playground.ui.panels.draw_list_rows(surf: Surface, rect: Rect, rows: list[str], selected_idx: int, font: Font) None#
Render a vertically-stacked selectable list inside
rect.
- factoriax.playground.ui.panels.draw_panel(surf: Surface, rect: Rect, title: str | None = None, title_font: Font | None = None, *, focused: bool = True) None#
Draw a panel with round corners.
A title sits in a gap in the top border line.
- Parameters:
surf – Surface to draw on.
rect – Area of the panel.
title – Text for the top border line.
Nonedraws no title.title_font – Font for the title.
Nonedraws no title.focused –
Truedraws the border in the color of the active panel.
- factoriax.playground.ui.panels.draw_setting_rows(surf: Surface, rect: Rect, fields: tuple[SettingField, ...] | list[SettingField], values: list[float], selected_idx: int, focused: bool, font: Font) list[Rect]#
Render
label … valuerows for an editable settings list.The selected row gets a gold fill, and chevrons around the value. The chevrons tell the user that Left and Right change this value.
- Parameters:
surf – Surface to draw on.
rect – Area that holds the rows.
fields – Setting of each row, in order.
values – Value of each row, in the same order as
fields.selected_idx – Index of the selected row.
focused –
Truedraws the selected row as active.font – Font for a row.
- Returns:
The rectangle of each row, so a caller can test a mouse position.
- Return type:
list[pygame.Rect]
- factoriax.playground.ui.panels.draw_setting_sections(surf: Surface, rect: Rect, sections: tuple[SettingSection, ...] | list[SettingSection], values: list[float], selected_idx: int, focused: bool, font: Font, heading_font: Font) tuple[list[Rect], int]#
Render sectioned setting rows with headings and dividers.
- Parameters:
surf – Surface to draw on.
rect – Area that holds the rows.
sections – Sections to draw, in order. Each one has a heading and its rows.
values – Value of every row, as one flat list. It follows the order of the rows of every section, one section after the other.
selected_idx – Index into
valuesof the selected row.focused –
Truedraws the selected row as active.font – Font for a row.
heading_font – Font for a heading.
- Returns:
(row_rects, bottom_y), for hit-testing and for positioning contentbelow the rendered block.
- factoriax.playground.ui.panels.label_value_section_layout(rect: Rect, sections: tuple[LabelValueSection, ...] | list[LabelValueSection], heading_h: int) tuple[list[Rect], list[tuple[int, int]], int]#
Return the layout of a block of label and value sections.
- Parameters:
rect – Area that holds the sections.
sections – Sections to lay out, in order.
heading_h – Height of one heading in pixels.
- Returns:
The rectangle of each row, the position of each heading, and the row under the last section.
- Return type:
- factoriax.playground.ui.panels.list_row_rects(rect: Rect, n_rows: int) list[Rect]#
Return the rectangle of each row of a list.
draw_list_rows()draws into these same rectangles. A caller that tests a mouse position therefore reads the layout from one place.
- factoriax.playground.ui.panels.rgba_to_surface(rgba: ndarray) Surface#
Convert an RGBA uint8 array of shape
(H, W, 4)to a Surface.
- factoriax.playground.ui.panels.setting_section_layout(rect: Rect, sections: tuple[SettingSection, ...] | list[SettingSection], heading_h: int) tuple[list[Rect], list[tuple[int, int]], int]#
Compute per-field row rects, per-section heading positions, and bottom y.
The drawer and every caller read the layout from this one function. A caller can therefore put a button under the block, or test a mouse position, against the same coordinates.
- Parameters:
rect – Area that holds the sections.
sections – Sections to lay out, in order.
heading_h – Height of one heading in pixels.
- Returns:
The rectangle of each row, the position of each heading, and the row under the last section.
- Return type:
- factoriax.playground.ui.panels.wrap_text(text: str, font: Font, max_width: int) list[str]#
Word-wrap
textto fitmax_widthusingfont.Newlines become explicit breaks. Empty paragraphs become empty lines so the line breaks of the source stay. A word longer than
max_widthare kept on their own line (no character-level splitting).