from __future__ import annotations # Screen-space (pixel) UI drawing: pure instance-list builders, no wgpu/rendering dependency, # so this is testable without a GPU. Renderer feeds the dicts these functions build into a # second, screen-space camera pass alongside the normal world-space one - see # engine/render/renderer.py::render_frame's `ui_instances` parameter, and engine/ui_assets.py # for how the glyph/panel textures referenced here actually get generated on disk. GLYPH_SIZE = 16.0 # both the source PNG's pixel dimensions and its default on-screen size CHAR_ADVANCE = 10.0 # horizontal spacing between glyph left edges when drawing a string LINE_HEIGHT = 18.0 PRINTABLE_MIN = 32 PRINTABLE_MAX = 126 FALLBACK_CHAR = "?" def glyph_texture_path(ch: str) -> str: code = ord(ch) if not (PRINTABLE_MIN <= code <= PRINTABLE_MAX): ch = FALLBACK_CHAR return f"ui/font/{ord(ch)}.png" def panel_texture_path(name: str) -> str: return f"ui/panel/{name}.png" def text_width(text: str, char_advance: float = CHAR_ADVANCE) -> float: return len(text) * char_advance def draw_text( buckets: dict[str, list[float]], text: str, x: float, y: float, size: float = GLYPH_SIZE, char_advance: float = CHAR_ADVANCE, ) -> float: """Appends one instance per non-space glyph in `text` at (x, y), advancing left to right. Returns the total pixel width advanced, so callers can center/right-align follow-up text. """ for i, ch in enumerate(text): if ch == " ": continue buckets[glyph_texture_path(ch)].extend((x + i * char_advance, y, size, size)) return text_width(text, char_advance) def draw_panel(buckets: dict[str, list[float]], name: str, x: float, y: float, w: float, h: float) -> None: buckets[panel_texture_path(name)].extend((x, y, w, h))