diff --git a/LunaDll/LuaMain/LuaProxyFFI.cpp b/LunaDll/LuaMain/LuaProxyFFI.cpp index e9c53a78..2be301cc 100644 --- a/LunaDll/LuaMain/LuaProxyFFI.cpp +++ b/LunaDll/LuaMain/LuaProxyFFI.cpp @@ -12,6 +12,7 @@ #include "../Rendering/LunaImage.h" #include "../Rendering/FrameCapture.h" #include "../Rendering/GL/GLTextureStore.h" +#include "../Rendering/WindowSizeHandler.h" #include "../SMBXInternal/NPCs.h" #include "../SMBXInternal/Blocks.h" #include "../SMBXInternal/Layer.h" @@ -807,6 +808,29 @@ typedef struct ExtendedBlockFields_\ ShowWindow(gMainWindowHwnd, SW_MAXIMIZE); } } + + FFI_EXPORT(void) LunaLuaSetWindowScale(double scale) + { + if (LunaLuaIsFullscreen()) return; + + gWindowSizeHandler.SetNewWindowScale(scale); + gWindowSizeHandler.Recalculate(); + } + + struct WindowSize + { + int w; + int h; + }; + FFI_EXPORT(WindowSize) LunaLuaGetWindowSize() + { + int w; + int h; + + gWindowSizeHandler.GetDPIScaledWindowSize(w, h); + + return {w, h}; + } } void CachedReadFile::clearData() diff --git a/LunaDll/Rendering/WindowSizeHandler.cpp b/LunaDll/Rendering/WindowSizeHandler.cpp index c88a307e..bf82bb24 100644 --- a/LunaDll/Rendering/WindowSizeHandler.cpp +++ b/LunaDll/Rendering/WindowSizeHandler.cpp @@ -253,3 +253,65 @@ int WindowSizeHandler::SetInitialWindowSize() return dpi; } + +void WindowSizeHandler::SetNewWindowScale(double scale) +{ + // Get current window/client area + RECT windowRect; + RECT clientRect; + + GetWindowRect(gMainWindowHwnd, &windowRect); + GetClientRect(gMainWindowHwnd, &clientRect); + + // Find the new scale to use, given the provided scale argument and the DPI scale + double dpiScale = static_cast(GetDpi_impl()) / 96.0; + + clientRect.left = 0; + clientRect.top = 0; + clientRect.right = static_cast(::round(g_GLContextManager.GetMainFBWidth() * scale * dpiScale)); + clientRect.bottom = static_cast(::round(g_GLContextManager.GetMainFBHeight() * scale * dpiScale)); + + AdjustWindowRectEx(&clientRect, GetWindowLong(gMainWindowHwnd, GWL_STYLE), + GetMenu(gMainWindowHwnd) != 0, GetWindowLong(gMainWindowHwnd, GWL_EXSTYLE)); + + // Find new position for the window + int newW = (clientRect.right - clientRect.left); + int newH = (clientRect.bottom - clientRect.top); + int newX = (windowRect.left + windowRect.right - newW) / 2; + int newY = (windowRect.top + windowRect.bottom - newH) / 2; + + // Clamp it based on monitor size + MONITORINFO monitorInfo; + monitorInfo.cbSize = sizeof(monitorInfo); + GetMonitorInfo(MonitorFromWindow(gMainWindowHwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo); + RECT& workRect = monitorInfo.rcWork; + + if (newX < workRect.left) + { + newX = workRect.left; + } + else if ((newX + newW) > workRect.right) + { + newX = workRect.right - newW; + } + + if (newY < workRect.top) + { + newY = workRect.top; + } + else if ((newY + newH) > workRect.bottom) + { + newY = workRect.bottom - newH; + } + + SetWindowPos(gMainWindowHwnd, nullptr, newX, newY, newW, newH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOREDRAW); +} + +void WindowSizeHandler::GetDPIScaledWindowSize(int& w, int& h) +{ + // Take the window's current size, scaling down using the DPI scale + double dpiScale = static_cast(GetDpi_impl()) / 96.0; + + w = static_cast(::round(mState.windowSize.x / dpiScale)); + h = static_cast(::round(mState.windowSize.y / dpiScale)); +} diff --git a/LunaDll/Rendering/WindowSizeHandler.h b/LunaDll/Rendering/WindowSizeHandler.h index 9e151b66..2904ba36 100644 --- a/LunaDll/Rendering/WindowSizeHandler.h +++ b/LunaDll/Rendering/WindowSizeHandler.h @@ -55,6 +55,10 @@ class WindowSizeHandler // Copy whole state (thread safe) inline State getStateThreadSafe() { std::lock_guard lock(mMutex); return mState; } + // Window size setting for FFI + void SetNewWindowScale(double scale); + void GetDPIScaledWindowSize(int& w, int& h); + // Functions to set window (thread safe) void SetWindowSize(int w, int h); void Recalculate();