2024-06-06 14:30:02 +02:00
|
|
|
/**
|
|
|
|
|
* @file
|
|
|
|
|
*
|
|
|
|
|
* @author Mamadou Babaei <mamadou@senseglove.com>
|
|
|
|
|
*
|
|
|
|
|
* @section LICENSE
|
|
|
|
|
*
|
|
|
|
|
* (The MIT License)
|
|
|
|
|
*
|
2026-02-04 16:07:33 +01:00
|
|
|
* Copyright (c) 2020 - 2026 SenseGlove
|
2024-06-06 14:30:02 +02:00
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
* copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
|
* SOFTWARE.
|
|
|
|
|
*
|
|
|
|
|
* @section DESCRIPTION
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "SenseGlove/GameFramework/SGGameUserSettings.h"
|
|
|
|
|
|
2024-06-27 12:15:58 +02:00
|
|
|
#include "Engine/Engine.h"
|
|
|
|
|
#include "HAL/IConsoleManager.h"
|
2024-06-27 11:57:44 +02:00
|
|
|
#include "Misc/ConfigCacheIni.h"
|
2024-06-16 09:37:52 +02:00
|
|
|
#include "Runtime/Launch/Resources/Version.h"
|
2024-06-06 15:50:11 +02:00
|
|
|
#include "Scalability.h"
|
|
|
|
|
|
2024-06-06 14:30:02 +02:00
|
|
|
#include "SGSettings/SGSettings.h"
|
|
|
|
|
|
|
|
|
|
struct USGGameUserSettings::FImpl
|
|
|
|
|
{
|
|
|
|
|
/************************
|
|
|
|
|
* Static methods
|
|
|
|
|
************************/
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
static float GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
int32 InQualityLevel,
|
|
|
|
|
Scalability::EQualityLevelBehavior Behavior = Scalability::EQualityLevelBehavior::EAbsolute);
|
|
|
|
|
|
2024-06-06 14:30:02 +02:00
|
|
|
/************************
|
|
|
|
|
* Owner object
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
USGGameUserSettings* Owner;
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
* Constructor / Destructor
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
explicit FImpl(USGGameUserSettings* InOwner);
|
|
|
|
|
~FImpl();
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
* Default copy constructor & copy assignment operator
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
FImpl(const FImpl& Rhs) = default;
|
|
|
|
|
FImpl& operator=(const FImpl& Rhs) = default;
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
* Methods
|
|
|
|
|
************************/
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
bool DoesCurrentSettingsMatch(ESGEngineScalabilitySettings Scalability) const;
|
2024-06-06 14:30:02 +02:00
|
|
|
};
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
float USGGameUserSettings::FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
const int32 InQualityLevel, const Scalability::EQualityLevelBehavior Behavior)
|
|
|
|
|
{
|
|
|
|
|
if (!ensureAlwaysMsgf(GConfig, TEXT("Invalid GConfig!")))
|
|
|
|
|
{
|
|
|
|
|
return 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TArray<FString> ResolutionValueStrings;
|
|
|
|
|
GConfig->GetSingleLineArray(TEXT("ScalabilitySettings"), TEXT("PerfIndexValues_ResolutionQuality"),
|
|
|
|
|
ResolutionValueStrings, GScalabilityIni);
|
|
|
|
|
|
|
|
|
|
if (ResolutionValueStrings.Num() == 0)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogConsoleResponse, Display,
|
|
|
|
|
TEXT("Failed to find resolution value strings in scalability ini. Falling back to the default."));
|
|
|
|
|
return 100.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No negative levels!
|
|
|
|
|
int32 QualityLevel = FMath::Max(0, InQualityLevel);
|
|
|
|
|
if (Behavior == Scalability::EQualityLevelBehavior::ERelativeToMax)
|
|
|
|
|
{
|
|
|
|
|
QualityLevel = FMath::Max(ResolutionValueStrings.Num() - 1 - QualityLevel, 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
QualityLevel = FMath::Clamp(QualityLevel, 0, ResolutionValueStrings.Num() - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FCString::Atof(*ResolutionValueStrings[QualityLevel]);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:30:02 +02:00
|
|
|
USGGameUserSettings::USGGameUserSettings(const FObjectInitializer& ObjectInitializer)
|
|
|
|
|
: Super(ObjectInitializer),
|
|
|
|
|
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
USGGameUserSettings* USGGameUserSettings::GetInstance()
|
|
|
|
|
{
|
|
|
|
|
USGGameUserSettings* Instance{GEngine ? Cast<USGGameUserSettings>(GEngine->GetGameUserSettings()) : nullptr};
|
|
|
|
|
ensureAlwaysMsgf(Instance, TEXT("Invalid GameUserSettings!"));
|
|
|
|
|
return Instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESGEngineScalabilitySettings USGGameUserSettings::GetEngineScalabilitySettings() const
|
|
|
|
|
{
|
2024-06-06 15:50:11 +02:00
|
|
|
const bool bDoesCurrentSettingsMatchLow = Pimpl->DoesCurrentSettingsMatch(ESGEngineScalabilitySettings::Low);
|
2024-06-06 14:30:02 +02:00
|
|
|
if (bDoesCurrentSettingsMatchLow)
|
|
|
|
|
{
|
|
|
|
|
return ESGEngineScalabilitySettings::Low;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
const bool bDoesCurrentSettingsMatchMedium = Pimpl->DoesCurrentSettingsMatch(ESGEngineScalabilitySettings::Medium);
|
2024-06-06 14:30:02 +02:00
|
|
|
if (bDoesCurrentSettingsMatchMedium)
|
|
|
|
|
{
|
|
|
|
|
return ESGEngineScalabilitySettings::Medium;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
const bool bDoesCurrentSettingsMatchHigh = Pimpl->DoesCurrentSettingsMatch(ESGEngineScalabilitySettings::High);
|
2024-06-06 14:30:02 +02:00
|
|
|
if (bDoesCurrentSettingsMatchHigh)
|
|
|
|
|
{
|
|
|
|
|
return ESGEngineScalabilitySettings::High;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
const bool bDoesCurrentSettingsMatchEpic = Pimpl->DoesCurrentSettingsMatch(ESGEngineScalabilitySettings::Epic);
|
2024-06-06 14:30:02 +02:00
|
|
|
if (bDoesCurrentSettingsMatchEpic)
|
|
|
|
|
{
|
|
|
|
|
return ESGEngineScalabilitySettings::Epic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool bDoesCurrentSettingsMatchCinematic = Pimpl->DoesCurrentSettingsMatch(
|
2024-06-06 15:50:11 +02:00
|
|
|
ESGEngineScalabilitySettings::Cinematic);
|
2024-06-06 14:30:02 +02:00
|
|
|
if (bDoesCurrentSettingsMatchCinematic)
|
|
|
|
|
{
|
|
|
|
|
return ESGEngineScalabilitySettings::Cinematic;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
return ESGEngineScalabilitySettings::Custom;
|
2024-06-06 14:30:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void USGGameUserSettings::SetEngineScalabilitySettings(ESGEngineScalabilitySettings Scalability)
|
|
|
|
|
{
|
2024-06-06 15:50:11 +02:00
|
|
|
if (!ensureAlwaysMsgf(Scalability != ESGEngineScalabilitySettings::Custom,
|
|
|
|
|
TEXT("Cannot set the engine scalability directly to custom!"
|
|
|
|
|
" It should be either: Low, Medium, High, Epic, Cinematic,"
|
|
|
|
|
" or Auto (determined by hardware benchmarking)!")))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-16 18:25:54 +02:00
|
|
|
const FSGHardwareBenchmarkingSettings& Settings{
|
|
|
|
|
USGSettings::GetInstance()->GetGameUserSettings().HardwareBenchmarkingSettings
|
2024-06-07 00:06:38 +02:00
|
|
|
};
|
2024-06-06 14:30:02 +02:00
|
|
|
|
|
|
|
|
if (IsDirty())
|
|
|
|
|
{
|
|
|
|
|
ValidateSettings();
|
|
|
|
|
ConfirmVideoMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Scalability != ESGEngineScalabilitySettings::Auto)
|
|
|
|
|
{
|
|
|
|
|
const int32 ScalabilityValue = static_cast<int32>(Scalability);
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
const float ResolutionScaleNormalized = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
ScalabilityValue, Scalability::EQualityLevelBehavior::EAbsolute);
|
|
|
|
|
SetResolutionScaleNormalized(ResolutionScaleNormalized);
|
2024-06-06 14:30:02 +02:00
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
ScalabilityQuality.SetViewDistanceQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetAntiAliasingQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetShadowQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetGlobalIlluminationQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetReflectionQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetPostProcessQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetTextureQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetEffectsQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetFoliageQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetShadingQuality(ScalabilityValue);
|
|
|
|
|
ScalabilityQuality.SetLandscapeQuality(ScalabilityValue);
|
2024-06-06 14:30:02 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RunHardwareBenchmark(
|
2024-06-07 00:06:38 +02:00
|
|
|
Settings.WorkScale,
|
|
|
|
|
Settings.CPUMultiplier,
|
|
|
|
|
Settings.GPUMultiplier);
|
2024-06-06 14:30:02 +02:00
|
|
|
ApplyHardwareBenchmarkResults();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConfirmVideoMode();
|
|
|
|
|
ApplySettings(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
USGGameUserSettings::FImpl::FImpl(USGGameUserSettings* InOwner)
|
|
|
|
|
: Owner(InOwner)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
USGGameUserSettings::FImpl::~FImpl() = default;
|
|
|
|
|
|
2024-06-06 15:50:11 +02:00
|
|
|
bool USGGameUserSettings::FImpl::DoesCurrentSettingsMatch(const ESGEngineScalabilitySettings Scalability) const
|
2024-06-06 14:30:02 +02:00
|
|
|
{
|
2024-06-06 15:50:11 +02:00
|
|
|
static const float ResolutionScaleNormalizedLow = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
static_cast<int32>(ESGEngineScalabilitySettings::Low));
|
|
|
|
|
static const float ResolutionScaleNormalizedMedium = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
static_cast<int32>(ESGEngineScalabilitySettings::Medium));
|
|
|
|
|
static const float ResolutionScaleNormalizedHigh = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
static_cast<int32>(ESGEngineScalabilitySettings::High));
|
|
|
|
|
static const float ResolutionScaleNormalizedEpic = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
static_cast<int32>(ESGEngineScalabilitySettings::Epic));
|
|
|
|
|
static const float ResolutionScaleNormalizedCinematic = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
static_cast<int32>(ESGEngineScalabilitySettings::Cinematic));
|
|
|
|
|
|
|
|
|
|
float ResolutionScaleNormalized = 0.0f;
|
|
|
|
|
switch (Scalability)
|
|
|
|
|
{
|
|
|
|
|
case ESGEngineScalabilitySettings::Low:
|
|
|
|
|
ResolutionScaleNormalized = ResolutionScaleNormalizedLow;
|
|
|
|
|
break;
|
|
|
|
|
case ESGEngineScalabilitySettings::Medium:
|
|
|
|
|
ResolutionScaleNormalized = ResolutionScaleNormalizedMedium;
|
|
|
|
|
break;
|
|
|
|
|
case ESGEngineScalabilitySettings::High:
|
|
|
|
|
ResolutionScaleNormalized = ResolutionScaleNormalizedHigh;
|
|
|
|
|
break;
|
|
|
|
|
case ESGEngineScalabilitySettings::Epic:
|
|
|
|
|
ResolutionScaleNormalized = ResolutionScaleNormalizedEpic;
|
|
|
|
|
break;
|
|
|
|
|
case ESGEngineScalabilitySettings::Cinematic:
|
|
|
|
|
ResolutionScaleNormalized = ResolutionScaleNormalizedCinematic;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ensureAlwaysMsgf(false, TEXT("Login Error: the execution flow should never reach here!"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int32 ScalabilityValue = static_cast<int32>(Scalability);
|
|
|
|
|
|
|
|
|
|
const float CurrentResolutionScaleNormalized = FImpl::GetRenderScaleLevelFromQualityLevel(
|
|
|
|
|
ScalabilityValue, Scalability::EQualityLevelBehavior::EAbsolute);
|
|
|
|
|
|
|
|
|
|
const int32 CurrentViewDistanceQuality = Owner->ScalabilityQuality.ViewDistanceQuality;
|
|
|
|
|
const int32 CurrentAntiAliasingQuality = Owner->ScalabilityQuality.AntiAliasingQuality;
|
|
|
|
|
const int32 CurrentShadowQuality = Owner->ScalabilityQuality.ShadowQuality;
|
|
|
|
|
const int32 CurrentGlobalIlluminationQuality = Owner->ScalabilityQuality.GlobalIlluminationQuality;
|
|
|
|
|
const int32 CurrentReflectionQuality = Owner->ScalabilityQuality.ReflectionQuality;
|
|
|
|
|
const int32 CurrentPostProcessingQuality = Owner->ScalabilityQuality.PostProcessQuality;
|
|
|
|
|
const int32 CurrentTextureQuality = Owner->ScalabilityQuality.TextureQuality;
|
|
|
|
|
const int32 CurrentEffectQuality = Owner->ScalabilityQuality.EffectsQuality;
|
|
|
|
|
const int32 CurrentFoliageQuality = Owner->ScalabilityQuality.FoliageQuality;
|
|
|
|
|
const int32 CurrentShadingQuality = Owner->ScalabilityQuality.ShadingQuality;
|
|
|
|
|
const int32 CurrentLandscapeQuality = Owner->ScalabilityQuality.LandscapeQuality;
|
2024-06-06 14:30:02 +02:00
|
|
|
|
|
|
|
|
if (FMath::IsNearlyEqual(CurrentResolutionScaleNormalized, ResolutionScaleNormalized)
|
2024-06-06 15:50:11 +02:00
|
|
|
&& CurrentViewDistanceQuality == ScalabilityValue
|
|
|
|
|
&& CurrentAntiAliasingQuality == ScalabilityValue
|
|
|
|
|
&& CurrentShadowQuality == ScalabilityValue
|
|
|
|
|
&& CurrentGlobalIlluminationQuality == ScalabilityValue
|
|
|
|
|
&& CurrentReflectionQuality == ScalabilityValue
|
|
|
|
|
&& CurrentPostProcessingQuality == ScalabilityValue
|
|
|
|
|
&& CurrentTextureQuality == ScalabilityValue
|
|
|
|
|
&& CurrentEffectQuality == ScalabilityValue
|
|
|
|
|
&& CurrentFoliageQuality == ScalabilityValue
|
|
|
|
|
&& CurrentShadingQuality == ScalabilityValue
|
2026-02-17 16:03:02 +01:00
|
|
|
&& CurrentLandscapeQuality == ScalabilityValue)
|
2024-06-06 14:30:02 +02:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void USGGameUserSettings::FImplDeleter::operator()(const FImpl* P) const
|
|
|
|
|
{
|
|
|
|
|
delete P;
|
|
|
|
|
}
|