52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
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))
|