From e610f6b7963f97f0550caef4a967be33032badda Mon Sep 17 00:00:00 2001 From: Eddoursul Date: Thu, 30 Jul 2026 22:11:28 +0200 Subject: [PATCH] Do not crop kNoBorder menus on widescreen --- .../src/Patches/MenuAspectRatioFix.h | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/source/Enderal DLL/src/Patches/MenuAspectRatioFix.h b/source/Enderal DLL/src/Patches/MenuAspectRatioFix.h index f4ff1341a..c5187571a 100644 --- a/source/Enderal DLL/src/Patches/MenuAspectRatioFix.h +++ b/source/Enderal DLL/src/Patches/MenuAspectRatioFix.h @@ -1,15 +1,17 @@ #pragma once -// Restores the Scaleform scale modes menus were loaded with before Skyrim 1.6.1130. +// Restores the Scaleform scale modes menus were loaded with before Skyrim 1.6.1130, and stops +// kNoBorder from cropping them on displays wider than 16:9. // // 1.6.1130 switched nearly every menu to kExactFit, which stretches the movie across the whole // viewport instead of preserving its aspect ratio. Enderal's menus - including the SkyUI-derived // widescreen versions shipped with them - are authored for the old modes, so on anything that is // not 16:9 they come out distorted. // -// The table below is what 1.6.640 passes to BSScaleformManager::LoadMovie. Menus the update left -// alone (Book, BookMenu, Console, CreditsMenu, CursorMenu, FaderMenu, GiftMenu, StartMenu) are -// deliberately absent and keep whatever the caller asked for. +// The table below is what 1.6.640 passes to BSScaleformManager::LoadMovie, plus BookMenu and +// GiftMenu, which 1.6.1130 left on kNoBorder and which need the same clamp. Menus that want no +// help (Book, Console, CreditsMenu, CursorMenu, FaderMenu, StartMenu) are absent and keep +// whatever the caller asked for. // // Based on Widescreen Scale Removed by SkyHorizon (GPL-3.0) // https://www.nexusmods.com/skyrimspecialedition/mods/136793 @@ -34,9 +36,11 @@ namespace MenuAspectRatioFix { "TweenMenu"sv, ScaleModeType::kShowAll }, { "BarterMenu"sv, ScaleModeType::kNoBorder }, + { "BookMenu"sv, ScaleModeType::kNoBorder }, { "ContainerMenu"sv, ScaleModeType::kNoBorder }, { "CraftingMenu"sv, ScaleModeType::kNoBorder }, { "DialogueMenu"sv, ScaleModeType::kNoBorder }, + { "GiftMenu"sv, ScaleModeType::kNoBorder }, { "InventoryMenu"sv, ScaleModeType::kNoBorder }, { "LockpickingMenu"sv, ScaleModeType::kNoBorder }, { "MagicMenu"sv, ScaleModeType::kNoBorder }, @@ -53,13 +57,38 @@ namespace MenuAspectRatioFix return it != modes.end() ? std::optional{ it->second } : std::nullopt; } + // The movie gets the whole framebuffer as its viewport, so kNoBorder scales a 1280x720 menu + // until it covers the full width and crops whatever no longer fits: at 32:9 that is a 2x zoom + // with half the menu off screen. Past 16:9 it can only ever crop, so hand out kShowAll instead - + // that keeps the 16:9 scale and merely leaves more of the stage surroundings visible, which is + // exactly what SkyUI's widescreen menus stretch their bars over (they cover up to 32:9). + // Narrower than 16:9 kNoBorder is still the better answer: it hides the strips above and below + // the stage that kShowAll would expose. + ScaleModeType ClampToViewport(ScaleModeType a_mode) + { + if (a_mode != ScaleModeType::kNoBorder) { + return a_mode; + } + + const auto state = RE::BSGraphics::State::GetSingleton(); + if (!state || state->screenHeight == 0) { + return a_mode; + } + + // Every vanilla menu is authored on a 1280x720 stage + constexpr float stageAspect = 1280.0f / 720.0f; + const float viewportAspect = static_cast(state->screenWidth) / static_cast(state->screenHeight); + + return viewportAspect > stageAspect ? ScaleModeType::kShowAll : a_mode; + } + struct LoadMovie { static bool thunk(RE::BSScaleformManager* a_scaleformManager, RE::IMenu* a_menu, RE::GPtr& a_viewOut, const char* a_fileName, ScaleModeType a_mode, float a_backgroundAlpha) { if (a_fileName && a_fileName[0]) { if (const auto mode = GetScaleMode(a_fileName); mode) { - a_mode = *mode; + a_mode = ClampToViewport(*mode); } }