HUD: stretch full-screen layers of moved windows across the render width

Primitives covering the whole 1024x768 layout inside a moved window, such as
the dimming behind the exit confirmation, were shifted with the window and
left both sides undimmed; they are stretched to the render width instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-14 09:08:52 +02:00
1 parent d39f12ab4b
commit 09f7dcc0f4
2 files changed
+20 -1

No files matched your search

+6
View File
@@ -52,3 +52,9 @@ sample a position ~400 px off now and then (jerky hold-to-move). Every user of
the cursor goes through the accessor `0x6550f0`, so inside a moved window it the cursor goes through the accessor `0x6550f0`, so inside a moved window it
returns a thread-local copy instead (with its own CRITICAL_SECTION at +0x24; returns a thread-local copy instead (with its own CRITICAL_SECTION at +0x24;
copying and writing back hold the real object's lock). copying and writing back hold the real object's lock).
## Full-screen layers
A primitive drawn inside a moved window that covers the whole 1024x768 layout
(e.g. the dimming behind the exit confirmation) is stretched across the render
width instead of shifted.
+14 -1
View File
@@ -20,6 +20,7 @@
// [hud] // [hud]
// Enabled=1 // Enabled=1
#include <algorithm>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <vector> #include <vector>
@@ -324,6 +325,8 @@ size_t VertexSize(DWORD fvf) {
} }
// Returns vertices shifted by g_offsetX, or the input when nothing to do. // Returns vertices shifted by g_offsetX, or the input when nothing to do.
// Primitives covering the whole 1024x768 layout (e.g. the dimming behind
// modal dialogs) are stretched across the render width instead.
void* ShiftVertices(DWORD fvf, void* vertices, DWORD count) { void* ShiftVertices(DWORD fvf, void* vertices, DWORD count) {
if (g_offsetX == 0 || (fvf & kFvfPositionMask) != kFvfXyzRhw || !vertices || count == 0) { if (g_offsetX == 0 || (fvf & kFvfPositionMask) != kFvfXyzRhw || !vertices || count == 0) {
return vertices; return vertices;
@@ -331,9 +334,19 @@ void* ShiftVertices(DWORD fvf, void* vertices, DWORD count) {
thread_local std::vector<uint8_t> buffer; thread_local std::vector<uint8_t> buffer;
const size_t stride = VertexSize(fvf); const size_t stride = VertexSize(fvf);
buffer.assign(static_cast<uint8_t*>(vertices), static_cast<uint8_t*>(vertices) + stride * count); buffer.assign(static_cast<uint8_t*>(vertices), static_cast<uint8_t*>(vertices) + stride * count);
float minX = 1e9f, maxX = -1e9f, minY = 1e9f, maxY = -1e9f;
for (DWORD i = 0; i < count; ++i) {
const auto* position = reinterpret_cast<const float*>(buffer.data() + stride * i);
minX = std::min(minX, position[0]);
maxX = std::max(maxX, position[0]);
minY = std::min(minY, position[1]);
maxY = std::max(maxY, position[1]);
}
const bool fullLayout = minX <= 0.5f && maxX >= kLayoutWidth - 0.5f && minY <= 0.5f && maxY >= 767.5f;
const float scale = static_cast<float>(mods::widescreen::RenderWidth()) / kLayoutWidth;
for (DWORD i = 0; i < count; ++i) { for (DWORD i = 0; i < count; ++i) {
auto* x = reinterpret_cast<float*>(buffer.data() + stride * i); auto* x = reinterpret_cast<float*>(buffer.data() + stride * i);
*x += static_cast<float>(g_offsetX); *x = fullLayout ? *x * scale : *x + static_cast<float>(g_offsetX);
} }
return buffer.data(); return buffer.data();
} }