Fix graphics settings

This commit is contained in:
Oleg Petruny 2025-06-29 22:48:53 +02:00
parent 20654327c0
commit a21bb37dcd
8 changed files with 122 additions and 24 deletions

Binary file not shown.

Binary file not shown.

View File

@ -117,7 +117,9 @@ public:
static TArray<int32> GetRandomIntArray(int32 size = 16, int32 min = 0, int32 max = 16);
template<typename T>
static TArray<T> ArrayDiff(const TArray<T>& a, const TArray<T>& b);
static TArray<T> ArraySymmetricDiff(const TArray<T>& a, const TArray<T>& b);
template<typename T>
static TArray<T> ArrayIntersection(const TArray<T>& a, const TArray<T>& b);
template<typename T>
static void ArrayRemoveFirstFromEnd(TArray<T>& array, T element);
@ -134,15 +136,15 @@ namespace SlowMotion
}
template<typename T>
inline TArray<T> UCommonFunctions::ArrayDiff(const TArray<T>& a, const TArray<T>& b)
inline TArray<T> UCommonFunctions::ArraySymmetricDiff(const TArray<T>& a, const TArray<T>& b)
{
TSet<T> result;
if(a.Num() == 0)
return b;
else if(b.Num() == 0)
return a;
TSet<T> result;
for(auto& i : a)
if(!b.Contains(i))
result.Add(i);
@ -154,6 +156,32 @@ inline TArray<T> UCommonFunctions::ArrayDiff(const TArray<T>& a, const TArray<T>
return result.Array();
}
template<typename T>
inline TArray<T> UCommonFunctions::ArrayIntersection(const TArray<T>& a, const TArray<T>& b)
{
if(a.Num() == 0)
return {};
else if(b.Num() == 0)
return {};
TSet<T> result;
if(a.Num() < b.Num())
{
for(auto& i : a)
if(b.Contains(i))
result.Add(i);
}
else
{
for(auto& i : b)
if(a.Contains(i))
result.Add(i);
}
return result.Array();
}
template<typename T>
inline void UCommonFunctions::ArrayRemoveFirstFromEnd(TArray<T>& array, T element)
{

View File

@ -8,10 +8,14 @@
#include "CommonTexts.h"
#include "CustomGameSettings.h"
#include <Kismet/KismetSystemLibrary.h>
#include <optional>
namespace
{
// some 16:9 resolutions (eg. 1366x768) are nonmathematical bullshit, therefore we try parse them with tolerance
constexpr float aspectRatioTolerance = 0.01f;
const FIntPoint ipDefaultWindowPosition = { 0, 0 };
std::optional<FIntPoint> ipPreviousWindowPosition;
constexpr int32 iDefaultMonitorId = 0;
@ -19,7 +23,7 @@ namespace
std::optional<FIntPoint> ipPreviousResolution;
constexpr float fDefaultResolutionScale = 100.0f;
constexpr int32 iDefaultFrameRateLimit = 120;
constexpr EDisplayMode eDefaultDisplayMode = EDisplayMode::Fullscreen;
constexpr EDisplayMode eDefaultDisplayMode = EDisplayMode::Borderless;
std::optional<EDisplayMode> ePreviousDisplayMode;
constexpr bool bDefaultVSyncEnabled = false;
constexpr int32 eDefaultAntiAliasingMethod = static_cast<int32>(ELostEdgeAntiAliasingMethod::FXAA);
@ -54,7 +58,7 @@ void UGraphicsSettingsHelper::SetDefaults(UCustomGameSettings* settings)
settings->ResolutionSizeX = res.X;
settings->ResolutionSizeY = res.Y;
}
settings->bUseDynamicResolution = true;
settings->SetDynamicResolutionEnabled(true);
settings->FrameRateLimit = GetDefaultFrameRateLimit(settings);
settings->SetResolutionScaleValueEx(fDefaultResolutionScale);
settings->FullscreenMode = DisplayToWindowMode(GetDefaultDisplayMode(settings));
@ -66,6 +70,7 @@ void UGraphicsSettingsHelper::ApplySettings(UCustomGameSettings* settings)
if(!settings)
return;
CenterWindowPosition(settings);
if(GEngine && GEngine->GameViewport)
if(auto window = GEngine->GameViewport->GetWindow())
window->MoveWindowTo(settings->GetWindowPosition());
@ -94,15 +99,41 @@ FIntPoint UGraphicsSettingsHelper::GetWindowPosition([[maybe_unused]] UCustomGam
void UGraphicsSettingsHelper::SetWindowPosition(UCustomGameSettings* settings, const FIntPoint& pos)
{
if(settings)
{
if(ipPreviousWindowPosition == pos)
ipPreviousWindowPosition.reset();
else
ipPreviousWindowPosition = GetWindowPosition(settings);
if(!settings)
return;
settings->SetWindowPosition(pos.X, pos.Y);
if(ipPreviousWindowPosition == pos)
ipPreviousWindowPosition.reset();
else
ipPreviousWindowPosition = GetWindowPosition(settings);
settings->SetWindowPosition(std::max(0, pos.X), std::max(0, pos.Y));
}
void UGraphicsSettingsHelper::CenterWindowPosition(UCustomGameSettings* settings)
{
if(!settings)
return;
FIntPoint position;
if(GetDisplayMode(settings) == EDisplayMode::Fullscreen)
{
position = { 0, 0 };
}
else
{
auto monitors = GetAvailableMonitors();
int32 monitorId = GetMonitorId(settings);
int32 offset = 0.0f;
for(int32 i = 0; i < monitorId; ++i)
offset += monitors[i].NativeWidth;
FIntPoint monitor = GetNativeResolutionByMonitorId(monitorId);
FIntPoint window = GetResolution(settings);
position = { offset + (monitor.X - window.X) / 2, (monitor.Y - window.Y) / 2 };
}
SetWindowPosition(settings, position);
}
void UGraphicsSettingsHelper::RestoreWindowPosition(UCustomGameSettings* settings)
@ -278,6 +309,10 @@ TArray<FIntPoint> UGraphicsSettingsHelper::GetAllAvailableResolutions()
TArray<FIntPoint> UGraphicsSettingsHelper::GetAvailableResolutionsByMonitorId(const int32 id)
{
if(auto settings = UCustomGameSettings::Get())
if(GetDisplayMode(settings) == EDisplayMode::Fullscreen)
return { GetNativeResolutionByMonitorId(GetMonitorId(settings)) };
auto resolutions = GetAllAvailableResolutions();
FIntPoint nativeRes = GetNativeResolutionByMonitorId(id);
TArray<FIntPoint> result;
@ -306,13 +341,37 @@ TArray<FIntPoint> UGraphicsSettingsHelper::FilterResolutionsViaAspectRatio(const
{
float resRatio = static_cast<float>(i.X) / i.Y;
float aspRatio = static_cast<float>(aspectRatio.X) / aspectRatio.Y;
if(UCommonFunctions::FloatIsZero(resRatio - aspRatio))
if(std::abs(resRatio - aspRatio) < aspectRatioTolerance)
result.Add(i);
}
return MoveTemp(result);
}
FIntPoint UGraphicsSettingsHelper::FilterClosestResolution(const TArray<FIntPoint>& resolutions, const FIntPoint& target)
{
if(resolutions.IsEmpty() || target.X == 0)
return {};
int32 resultId = 0;
float coefficient = resolutions[resultId].X / (float)target.X;
if(UCommonFunctions::FloatIsZero(coefficient - 1))
return resultId;
for(int32 i = 1; i < resolutions.Num(); ++i)
{
float c = resolutions[i].X / (float)target.X;
if((coefficient > 1 && c < coefficient)
|| (coefficient < 1 && c > coefficient && c < 1))
{
coefficient = c;
resultId = i;
}
}
return resolutions[resultId];
}
void UGraphicsSettingsHelper::SetResolution(UCustomGameSettings* settings, const FIntPoint& resolution)
{
if(!settings)
@ -382,6 +441,9 @@ FIntPoint UGraphicsSettingsHelper::GetAspectRatio([[maybe_unused]] UCustomGameSe
FIntPoint UGraphicsSettingsHelper::GetAspectRatioFromResolution(const FIntPoint& resolution)
{
if(std::abs(resolution.X / (float)resolution.Y - 16 / 9.0f) < aspectRatioTolerance)
return { 16, 9 };
int32 gcd = UCommonFunctions::GreatestCommonDivisor(resolution.X, resolution.Y);
return { resolution.X / gcd, resolution.Y / gcd };
}
@ -393,6 +455,10 @@ FIntPoint UGraphicsSettingsHelper::GetAspectRatioOfMonitor(const int32 monitor)
TArray<FIntPoint> UGraphicsSettingsHelper::GetAvailableAspectRatiousOfMonitor(const int32 monitor)
{
if(auto settings = UCustomGameSettings::Get())
if(GetMonitorId(settings) == monitor && GetDisplayMode(settings) == EDisplayMode::Fullscreen)
return { GetAspectRatioFromResolution(GetNativeResolutionByMonitorId(monitor)) };
TArray<FIntPoint> resolutions = GetAvailableResolutionsByMonitorId(monitor);
if(resolutions.Num() == 0)
return { GetAspectRatio(nullptr) };

View File

@ -65,6 +65,8 @@ protected: // Window position setting is on the thin edge of user safeness, ther
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Window")
static void SetWindowPosition(class UCustomGameSettings* settings, const FIntPoint& pos);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Window")
static void CenterWindowPosition(class UCustomGameSettings* settings);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Window")
static void RestoreWindowPosition(class UCustomGameSettings* settings);
public:
@ -96,6 +98,8 @@ public:
static TArray<FIntPoint> GetAvailableResolutionsByMonitorId(const int32 id);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
static TArray<FIntPoint> FilterResolutionsViaAspectRatio(const TArray<FIntPoint>& resolutions, const FIntPoint& aspectRatio);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
static FIntPoint FilterClosestResolution(const TArray<FIntPoint>& resolutions, const FIntPoint& target);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Resolution")
static void SetResolution(class UCustomGameSettings* settings, const FIntPoint& resolution);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Resolution")