From 03dbbfc5e3184167c894951ba9ddce71f0ce5919 Mon Sep 17 00:00:00 2001 From: Torhan Bartel Date: Wed, 14 Oct 2026 04:57:15 +0200 Subject: [PATCH] docs: HUD layout mechanism Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/hud.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/hud.md diff --git a/docs/hud.md b/docs/hud.md new file mode 100644 index 0000000..690d427 --- /dev/null +++ b/docs/hud.md @@ -0,0 +1,44 @@ +# HUD layout in widened views (`src/mods/hud.cpp`) + +The UI is laid out for 1024x768. In a widened render target (e.g. 1835x768) +the windows are moved as a whole, without touching their own coordinates: +the bottom bar and all dialogs are centred, the party panel (portrait, health) +sits at the right edge. Main menu and loading screen keep the classic 1024x768 +frame (see `widescreen.md`). + +## How a window is moved + +A window's render and event methods are hooked (`HUD_RENDER`, `HUD_RENDER3`, +`HUD_EVENT`). While one of them runs on a thread, everything the window sees or +draws is translated by its offset `dx` (outermost window wins, children and +shared base methods are inside the scope): + +| What | Where | Translation | +|---|---|---| +| screen-space vertices (`XYZRHW`) | `IDirect3DDevice7::DrawPrimitive` / `DrawIndexedPrimitive` (vtable 25 / 26) | x + dx | +| 3D items (belt, equipment) | ortho projection centred on the screen | none needed | +| mouse events | `cEvent_mouseMove` x at +4 (previous) and +0xc; button down / up x at +8 | x - dx, restored afterwards | +| mouse cursor object (`*0xcdbadc`) | x at +4, previous x at +0xc (polled for hover, item pick-up `0x6559a0`) | x - dx, restored unless the window thread stored a new position | +| `GetMouseClientPos` (`0x66e500`) | polled position | x - dx | + +## Calls outside a window's scope + +- Tooltips (`cUI_Tooltip::vf14` `0x6e7300`) are separate windows that the + hovered window positions in its own layout: they draw with the offset of the + moved window under the cursor (noted while windows render, expires after + 150 ms). +- Hit tests (`vf1c`: `0x731d40`, taskbar `0x6dfb10`) are also called by the UI + manager with plain render coordinates, e.g. "is UI under the cursor" for + world picking (`0x75a370`). They use the offset the top-level window (parent + chain at +0x50) was last drawn with. +- The item carried by the cursor (`0x6555e0`, drawn by the render loop) and the + manager's status line / message box (`0x75bbf0`, `0x75c200`, laid out around + x = 512) draw with the centre offset. + +## UI events + +`vf04` of an event is its category: 1 mouse move, 2 button down, 3 button up, +4 key (code at +8), 5 UI command (`cEventUI2`: id at +4, vf08 subtype). Only +mouse events carry positions; category 5 events with subtype 0x10 test a point +at +0x48 in `cUI_Window2::vf10`, but commands such as "open ESC menu" (0x11) +keep unrelated data there.