# UI System Source: `src/dusk/ui/` The UI system is an immediate-mode layer drawn on top of the game scene each frame. Elements register themselves; `uiUpdate()` ticks all elements and `uiRender()` draws them. All coordinates are in screen pixels. --- ## Lifecycle ``` uiInit() → uiTextboxInit() // init order matters — textbox depends on display being ready uiUpdate() // each frame, before rendering uiRender() // each frame, after scene render uiDispose() uiTextboxDispose() ``` --- ## Element registration (`ui/uielement.h`) Elements are stored in `UI_ELEMENTS[]`. Each has a type and a `draw` callback: ```c typedef struct { uielementtype_t type; errorret_t (*draw)(); } uielement_t; ``` Currently `UI_ELEMENT_TYPE_NATIVE` elements call their `draw` function directly. New debug/HUD elements are registered by adding to this array. --- ## Textbox (`ui/uitextbox.h`) `UI_TEXTBOX` is the global dialogue box. It word-wraps text, paginates it, and plays a typewriter scroll effect. ```c uiTextboxSetText("Long dialogue string..."); // wraps to charsPerLine, paginates uiTextboxUpdate(); // each frame: advance scroll, check input uiTextboxDraw(); // draw box + text // Pagination: uiTextboxPageIsComplete() // true when all chars of current page are visible uiTextboxHasNextPage() uiTextboxNextPage() // Subscibe to page events: eventSubscribe(&UI_TEXTBOX.onPageComplete, cb, user); eventSubscribe(&UI_TEXTBOX.onLastPage, cb, user); ``` `UI_TEXTBOX.advanceAction` defaults to the input action that advances dialogue — set it before calling `uiTextboxInit()` if the default doesn't suit. Layout constants: - `UI_TEXTBOX_TEXT_MAX` — 1024 chars - `UI_TEXTBOX_LINES_MAX` — 64 lines - `UI_TEXTBOX_LINES_PER_PAGE_MAX` — 3 lines visible at once - `UI_TEXTBOX_SCROLL_CHARS_PER_TICK` — 1 char per tick (typewriter speed) The textbox uses `UI_TEXTBOX.frame` (a `uiframe_t`) for its border rendering and `UI_TEXTBOX.font` for text. --- ## UI Frame (`ui/uiframe.h`) 9-slice bordered box rendered with a tileset: ```c uiFrameInit(&frame); uiFrameDraw(&frame, x, y, width, height); uiFrameDispose(&frame); ``` The tileset is loaded from the asset system during `uiFrameInit()`. The 9 slices are arranged in the tileset grid as: top-left corner, top edge, top-right corner, left edge, fill, right edge, bottom-left, bottom edge, bottom-right. --- ## Loading overlay (`ui/uiloading.h`) `UI_LOADING` is a full-screen loading indicator with fade-in/fade-out transitions: ```c uiLoadingShow(onShownCallback, user); // fade in; calls callback when fully opaque uiLoadingHide(onHiddenCallback, user); // fade out; calls callback when fully transparent uiLoadingUpdate(delta); // each frame uiLoadingDraw(); // each frame, over everything ``` `UI_LOADING_FADE_DURATION` is `FIXED(0.5f)` seconds. Subscribe to `UI_LOADING.onTransitionEnd` for completion events. --- ## Full-box overlay (`ui/uifullbox.h`) Two global full-screen color overlays: `UI_FULLBOX_UNDER` (drawn before game content) and `UI_FULLBOX_OVER` (drawn after). Used for scene transitions (fade to black, etc.): ```c uiFullboxTransition( &UI_FULLBOX_OVER, COLOR_TRANSPARENT, COLOR_BLACK, FIXED(0.5f), EASING_IN_OUT_CUBIC ); eventSubscribe(&UI_FULLBOX_OVER.onTransitionEnd, myCallback, NULL); uiFullboxUnderDraw(); // draw under layer uiFullboxOverDraw(); // draw over layer ``` --- ## FPS counter (`ui/uifps.h`) `UIFPS` tracks a rolling average FPS. `uiFPSDraw()` renders it in the corner. Currently drawn as part of the debug HUD (not wired to an element slot). --- ## Player position HUD (`ui/uiplayerpos.h`) `uiplayerpos.c` draws the player's current world tile coordinates. Debug overlay, currently drawn directly in the scene render.