diff --git a/docs/hud.md b/docs/hud.md index be83f9d..690302c 100644 --- a/docs/hud.md +++ b/docs/hud.md @@ -115,3 +115,14 @@ game lays them out at creation only). A window anchored `Screen` still counts as the outermost scope for events, so its child buttons (hooked as standalone controls, `Center`) don't shift again. + +## Viewports (cursor in the quest book, 2026-10-17) + +`SetViewport` inside a moved window is shifted like its vertices. The quest +book's map tab ("V") draws the zoomed map view (`0x6cc950`), which sets a +256x256 viewport and, when done, resets it to the full render size +(`DxDriver7` `0x646510`: 0, 0, width x height). Shifted by the window's +offset, that reset reached past the render target, `SetViewport` failed and +the small viewport stayed set: the cursor (drawn after the UI) was only +visible inside it. A viewport at x 0 across the whole render width is now +passed unshifted. diff --git a/src/mods/hud.cpp b/src/mods/hud.cpp index a5ef398..202efc2 100644 --- a/src/mods/hud.cpp +++ b/src/mods/hud.cpp @@ -402,8 +402,13 @@ using ClearFn = HRESULT(__stdcall*)(void* device, DWORD count, Rect7* rects, DWO SetViewportFn g_setViewport = nullptr; ClearFn g_clear = nullptr; +// A viewport across the whole render width is a reset, not one of the window's +// own (e.g. the zoomed map view in the quest book restores it with 0x646510 +// when done): shifted, it would reach past the render target, SetViewport +// fails and the window's small viewport stays set, clipping the cursor. HRESULT __stdcall SetViewportShifted(void* device, Viewport7* viewport) { - if (g_offsetX == 0 || !viewport) { + if (g_offsetX == 0 || !viewport || + (viewport->x == 0 && static_cast(viewport->width) >= mods::widescreen::RenderWidth())) { return g_setViewport(device, viewport); } Viewport7 shifted = *viewport;