Menu #8

Merged
oleg.petruny merged 9 commits from Menu into master 2025-01-13 18:54:47 +00:00
83 changed files with 1474 additions and 183 deletions

View File

@ -1,16 +1,20 @@
[/Script/Lost_Edge.CustomGameSettings]
bUseMotionBlur=False
bShowFps=False
bMouseInverted=False
fMouseSensetivity=1.000000
fMasterVolume=0.500000
fMusicVolume=1.000000
fEffectsVolume=1.000000
fVoicesVolume=1.000000
fMenuVolume=1.000000
bUseVSync=False
bUseDynamicResolution=False
bUseDynamicResolution=True
ResolutionSizeX=1920
ResolutionSizeY=1080
LastUserConfirmedResolutionSizeX=1920
LastUserConfirmedResolutionSizeY=1080
WindowPosX=-1
WindowPosY=-1
WindowPosX=0
WindowPosY=0
FullscreenMode=1
LastConfirmedFullscreenMode=1
PreferredFullscreenMode=1
@ -18,10 +22,10 @@ Version=5
AudioQualityLevel=0
LastConfirmedAudioQualityLevel=0
FrameRateLimit=0.000000
DesiredScreenWidth=1280
DesiredScreenHeight=720
LastUserConfirmedDesiredScreenWidth=1280
LastUserConfirmedDesiredScreenHeight=720
DesiredScreenWidth=1920
DesiredScreenHeight=1080
LastUserConfirmedDesiredScreenWidth=1920
LastUserConfirmedDesiredScreenHeight=1080
LastRecommendedScreenWidth=-1.000000
LastRecommendedScreenHeight=-1.000000
LastCPUBenchmarkResult=-1.000000

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,14 +2,16 @@
using UnrealBuildTool;
public class Lost_Edge : ModuleRules {
public Lost_Edge(ReadOnlyTargetRules Target) : base(Target) {
public class Lost_Edge : ModuleRules
{
public Lost_Edge(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OpenCV" });
PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput", "UMG", "RHI", "RenderCore", "Lost_EdgeShaders", "PakFile", //"TextureCompressor",
"LevelSequence", "MovieScene", "HTTP", "Json" }); // "Slate", "SlateCore"
"LevelSequence", "MovieScene", "HTTP", "Json", "ApplicationCore" }); // "Slate", "SlateCore"
// UE_LOG(LogTemp, Log, TEXT("capture: %s"), (capture ? TEXT("true") : TEXT("false")));
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("1"));

View File

@ -27,14 +27,6 @@ void ACameraModeBase::BeginPlay()
Super::BeginPlay();
auto world = GetWorld();
if(auto gameSettings = UCustomGameSettings::Get())
{
if(auto camera = FindComponentByClass<UCameraComponent>())
{
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
}
}
void ACameraModeBase::Tick(float DeltaTime)

View File

@ -29,6 +29,16 @@ FText UCommonFunctions::GetKeyDisplayName(FKey key)
return key.GetDisplayName(false);
}
int32 UCommonFunctions::StringIndexInTextArray(const TArray<FText>& array, const FString& value)
{
FString v = value.ToLower();
for(int32 i = 0; i < array.Num(); ++i)
if(FTextInspector::GetSourceString(array[i])->ToLower().Equals(v))
return i;
return -1;
}
void UCommonFunctions::DestroyActorRecursively(AActor* actor)
{
TArray<AActor*> childs;
@ -95,6 +105,91 @@ FWorldDilationChangedDelegate& UCommonFunctions::GetWorldDilationChangedDelegate
return SlowMotion::worldDilationChangedDelegate;
}
TArray<FString> UCommonFunctions::IntArrayToStringArray(const TArray<int32>& in)
{
TArray<FString> result;
result.Reserve(in.Num());
for(int32 i : in)
result.Add(FString::FromInt(i));
return MoveTemp(result);
}
TArray<int32> UCommonFunctions::StringArrayToIntArray(const TArray<FString>& in)
{
TArray<int32> result;
result.Reserve(in.Num());
for(auto& i : in)
result.Add(FCString::Atoi(*i));
return MoveTemp(result);
}
FString UCommonFunctions::IntPointToString(const FIntPoint& in)
{
FString result = FString::Printf(TEXT("%dx%d"), in.X, in.Y);
return MoveTemp(result);
}
FIntPoint UCommonFunctions::StringToIntPoint(const FString& in)
{
FIntPoint result{};
const FRegexPattern rgxP(FRegexPattern(TEXT("[0-9]+")));
FRegexMatcher rgx = FRegexMatcher(rgxP, in);
if(rgx.FindNext())
result.X = FCString::Atoi(*in.Mid(rgx.GetMatchBeginning(), rgx.GetMatchEnding() - rgx.GetMatchBeginning()));
if(rgx.FindNext())
result.Y = FCString::Atoi(*in.Mid(rgx.GetMatchBeginning(), rgx.GetMatchEnding() - rgx.GetMatchBeginning()));
return MoveTemp(result);
}
TArray<FString> UCommonFunctions::IntPointArrayToStringArray(const TArray<FIntPoint>& in)
{
TArray<FString> result;
result.Reserve(in.Num());
for(auto& i : in)
result.Add(IntPointToString(i));
return MoveTemp(result);
}
TArray<FIntPoint> UCommonFunctions::StringArrayToIntPointArray(const TArray<FString>& in)
{
TArray<FIntPoint> result;
result.Reserve(in.Num());
for(auto& i : in)
result.Add(StringToIntPoint(i));
return MoveTemp(result);
}
int32 UCommonFunctions::GetLongestCharCount(TArray<FString>& in)
{
int32 result = 0;
for(auto& i : in)
if(i.Len() > result)
result = i.Len();
return result;
}
void UCommonFunctions::SortIntPointArray(TArray<FIntPoint>& in)
{
in.Sort([](const FIntPoint& a, const FIntPoint& b)
{
return a.X < b.X || a.Y < b.Y;
});
}
int32 UCommonFunctions::GreatestCommonDivisor(int32 a, int32 b)
{
int32 temp;
while(b != 0)
{
temp = b;
b = a % b;
a = temp;
}
return a;
}
void UCommonFunctions::SlowMotionTick()
{
const UWorld* world = UCustomGameInstance::Get()->GetWorld();

View File

@ -25,6 +25,9 @@ public:
UFUNCTION(BlueprintPure)
static FText GetKeyDisplayName(struct FKey key);
UFUNCTION(BlueprintPure)
static int32 StringIndexInTextArray(const TArray<FText>& array, const FString& value);
/** Recursively destroy actor and all its childs (the default Destroy doesn't have consistent behavior) */
UFUNCTION(BlueprintCallable, Category = Actor)
static void DestroyActorRecursively(class AActor* actor);
@ -41,6 +44,34 @@ public:
UFUNCTION(BlueprintPure, Category = TypeCasts)
static TArray<FString> IntArrayToStringArray(const TArray<int32>& in);
UFUNCTION(BlueprintPure, Category = TypeCasts)
static TArray<int32> StringArrayToIntArray(const TArray<FString>& in);
UFUNCTION(BlueprintPure, Category = TypeCasts)
static FString IntPointToString(const FIntPoint& in);
UFUNCTION(BlueprintPure, Category = TypeCasts)
static FIntPoint StringToIntPoint(const FString& in);
UFUNCTION(BlueprintPure, Category = TypeCasts)
static TArray<FString> IntPointArrayToStringArray(const TArray<FIntPoint>& in);
UFUNCTION(BlueprintPure, Category = TypeCasts)
static TArray<FIntPoint> StringArrayToIntPointArray(const TArray<FString>& in);
UFUNCTION(BlueprintPure, Category = TypeCasts)
static void SortIntPointArray(UPARAM(ref) TArray<FIntPoint>& in);
UFUNCTION(BlueprintPure, Category = String)
static int32 GetLongestCharCount(UPARAM(ref) TArray<FString>& in);
UFUNCTION(BlueprintPure, Category = Math)
static int32 GreatestCommonDivisor(int32 a, int32 b);
UFUNCTION(BlueprintPure)
static TArray<int32> GetRandomIntArray(int32 size = 16, int32 min = 0, int32 max = 16);

View File

@ -0,0 +1,63 @@
// Oleg Petruny proprietary.
#include "CommonInspectors.h"
UEnum* UEnumInspector::GetEnumByName(const FString& name)
{
static TMap<FString, UEnum*> map;
if(map.Contains(name))
return map[name];
UEnum* enumPtr = FindObject<UEnum>((UPackage*)-1, *name, true);
map.Add(name, enumPtr);
return enumPtr;
}
TArray<FText> UEnumInspector::GetEnumDisplayNames(const UEnum* enumPtr)
{
if(!enumPtr)
return {};
auto enumPtrProxy = static_cast<const UDEPRECATED_EnumInspectorProxy*>(enumPtr);
TArray<FText> result;
for(int32 i = 0; i < enumPtrProxy->Names.Num() - 1; ++i) // last UEnum value is Num counter
result.Add(enumPtr->GetDisplayNameTextByIndex(enumPtrProxy->Names[i].Value));
return MoveTemp(result);
}
TArray<uint8> UEnumInspector::GetEnumValues(const UEnum* enumPtr)
{
if(!enumPtr)
return {};
auto enumPtrProxy = static_cast<const UDEPRECATED_EnumInspectorProxy*>(enumPtr);
TArray<uint8> result;
for(int32 i = 0; i < enumPtrProxy->Names.Num() - 1; ++i) // last UEnum value is Num counter
result.Add(enumPtrProxy->Names[i].Value);
return MoveTemp(result);
}
int32 UEnumInspector::GetEnumValueByValueId(const UEnum* enumPtr, const int32 id)
{
if(!enumPtr)
return 0;
auto enumPtrProxy = static_cast<const UDEPRECATED_EnumInspectorProxy*>(enumPtr);
if(id < enumPtrProxy->Names.Num())
return enumPtrProxy->Names[id].Value;
return -1;
}
int32 UEnumInspector::GetEnumValueIdByValue(const UEnum* enumPtr, const int32 value)
{
if(!enumPtr)
return 0;
auto enumPtrProxy = static_cast<const UDEPRECATED_EnumInspectorProxy*>(enumPtr);
for(int32 i = 0; i < enumPtrProxy->Names.Num(); ++i)
if(enumPtrProxy->Names[i].Value == value)
return i;
return int32();
}

View File

@ -0,0 +1,34 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "CommonInspectors.generated.h"
UCLASS(Deprecated)
class UDEPRECATED_EnumInspectorProxy : public UEnum
{
GENERATED_BODY()
friend class UEnumInspector;
};
UCLASS()
class UEnumInspector : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintPure, Category = Enum)
static UEnum* GetEnumByName(const FString& name);
UFUNCTION(BlueprintPure, Category = Enum)
static TArray<FText> GetEnumDisplayNames(UPARAM(meta = (DisplayName = "enum")) const UEnum* enumPtr);
UFUNCTION(BlueprintPure, Category = Enum)
static TArray<uint8> GetEnumValues(UPARAM(meta = (DisplayName = "enum")) const UEnum* enumPtr);
UFUNCTION(BlueprintPure, Category = Enum)
static int32 GetEnumValueByValueId(UPARAM(meta = (DisplayName = "enum")) const UEnum* enumPtr, const int32 id);
UFUNCTION(BlueprintPure, Category = Enum)
static int32 GetEnumValueIdByValue(UPARAM(meta = (DisplayName = "enum")) const UEnum* enumPtr, const int32 value);
};

View File

@ -0,0 +1,10 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
namespace CommonTexts
{
const FText Default = NSLOCTEXT("CommonTexts", "Default", "Default");
}

View File

@ -6,10 +6,17 @@
#include "Kismet/KismetSystemLibrary.h"
#include "ContentLoader.h"
#include "CustomGameSettings.h"
#include "Levels/LevelBase.h"
#include "PlayerBase.h"
#include "SaveData.h"
namespace
{
constexpr auto saveName = TEXT("Save");
constexpr int32 saveIndex = 0;
}
UCustomGameInstance* UCustomGameInstance::instance = nullptr;
void UCustomGameInstance::Init()
@ -17,8 +24,28 @@ void UCustomGameInstance::Init()
UGameInstance::Init();
instance = this;
contentLoader = NewObject<UContentLoader>(this);
saveData = Cast<USaveData>(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass()));
for(auto& _class : globalInstancesClasses)
{
UObject* gi = NewObject<UObject>(_class);
gi->AddToRoot();
globalInstances.Add(_class.Get(), gi);
}
globalInstancesClasses.Empty();
if(auto save = UGameplayStatics::LoadGameFromSlot(saveName, saveIndex))
saveData = Cast<USaveData>(save);
else
saveData = Cast<USaveData>(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass()));
}
void UCustomGameInstance::Shutdown()
{
if(auto settings = UCustomGameSettings::Get())
settings->SaveSettings();
Super::Shutdown();
}
UCustomGameInstance* UCustomGameInstance::Get()
@ -34,6 +61,22 @@ UContentLoader* UCustomGameInstance::GetContentLoader()
return nullptr;
}
UObject* UCustomGameInstance::GetGlobalInstance(UClass* _class)
{
if(auto GI = Get())
return *(GI->globalInstances.Find(_class));
return nullptr;
}
bool UCustomGameInstance::IsGameSaved()
{
if(auto GI = Get())
return GI->saveData != nullptr;
return false;
}
void UCustomGameInstance::SaveGame(FName checkpointName)
{
auto levelScript = ALevelBase::Get();
@ -56,12 +99,12 @@ void UCustomGameInstance::SaveGame(FName checkpointName)
else
saveData->playerRightPocketItem = FName(TEXT(""));
UGameplayStatics::SaveGameToSlot(saveData, TEXT("Save"), 0);
UGameplayStatics::SaveGameToSlot(saveData, saveName, saveIndex);
}
void UCustomGameInstance::LoadGame()
{
saveData = Cast<USaveData>(UGameplayStatics::LoadGameFromSlot(TEXT("Save"), 0));
saveData = Cast<USaveData>(UGameplayStatics::LoadGameFromSlot(saveName, saveIndex));
if(!saveData)
return;

View File

@ -20,17 +20,24 @@ class UCustomGameInstance : public UGameInstance
public:
/** Instantiates content loader, dummy save data and applies settings */
virtual void Init() override;
/** Saves settings */
virtual void Shutdown() override;
UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Custom Game Instance"))
static UCustomGameInstance* Get();
UFUNCTION(BlueprintPure)
static class UContentLoader* GetContentLoader();
UFUNCTION(BlueprintPure)
static UObject* GetGlobalInstance(UClass* _class);
/** Return true is save data are present and valid */
UFUNCTION(BlueprintPure)
static bool IsGameSaved();
UFUNCTION(BlueprintCallable, Category = Save)
void SaveGame(FName checkpointName);
UFUNCTION(BlueprintCallable, Category = Save)
void LoadGame();
UFUNCTION(BlueprintCallable)
void ExitGame();
@ -46,4 +53,7 @@ protected:
UPROPERTY()
class UContentLoader* contentLoader;
UPROPERTY(EditDefaultsOnly)
TSet<TSubclassOf<UObject>> globalInstancesClasses;
TMap<UClass*, UObject*> globalInstances;
};

View File

@ -4,12 +4,43 @@
#include "Kismet/GameplayStatics.h"
#include "GraphicsSettingsHelper.h"
#include "MainGameModeBase.h"
#include "Widgets/WidgetsManager.h"
namespace
{
/** Graphics */
constexpr bool bDefaultShowFps = false;
/** Audio */
constexpr float fDefaultMasterVolume = 0.4f;
constexpr float fDefaultMusicVolume = 1.0f;
constexpr float fDefaultEffectsVolume = 1.0f;
constexpr float fDefaultVoicesVolume = 1.0f;
constexpr float fDefaultMenuVolume = 1.0f;
/** Game */
constexpr float fDefaultMouseSensetivity = 0.5f;
constexpr bool bDefaultMouseInverted = false;
}
UCustomGameSettings::UCustomGameSettings(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer)
{
bUseMotionBlur = false;
bShowFps = false;
bMouseInverted = false;
fMouseSensetivity = 1.0f;
/** Graphics */
bShowFps = GetDefaultShowFps();
UGraphicsSettingsHelper::SetDefaults(this);
/** Audio */
fMasterVolume = GetDefaultMasterVolume();
fMusicVolume = GetDefaultMusicVolume();
fEffectsVolume = GetDefaultEffectsVolume();
fVoicesVolume = GetDefaultVoicesVolume();
fMenuVolume = GetDefaultMenuVolume();
/** Game */
fMouseSensetivity = GetDefaultMouseSensetivity();
bMouseInverted = GetDefaultMouseInverted();
}
UCustomGameSettings* UCustomGameSettings::Get()
@ -17,12 +48,111 @@ UCustomGameSettings* UCustomGameSettings::Get()
return Cast<UCustomGameSettings>(UGameUserSettings::GetGameUserSettings());
}
void UCustomGameSettings::LoadSettings(bool bForceReload)
{
Super::LoadSettings(bForceReload);
UpdateResolutionQuality();
}
void UCustomGameSettings::ApplySettings(bool bCheckForCommandLineOverrides)
{
Super::ApplySettings(bCheckForCommandLineOverrides);
UGraphicsSettingsHelper::ApplySettings(this);
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
if(bShowFps)
WM->ShowFpsCount();
else
WM->HideFpsCount();
}
}
LOST_EDGE_API bool UCustomGameSettings::GetDefaultShowFps() const
{
return bDefaultShowFps;
}
/** Audio */
inline float UCustomGameSettings::GetDefaultMasterVolume() const
{
return fDefaultMasterVolume;
}
inline float UCustomGameSettings::GetDefaultMusicVolume() const
{
return fDefaultMusicVolume;
}
inline float UCustomGameSettings::GetDefaultEffectsVolume() const
{
return fDefaultEffectsVolume;
}
inline float UCustomGameSettings::GetDefaultVoicesVolume() const
{
return fDefaultVoicesVolume;
}
inline float UCustomGameSettings::GetDefaultMenuVolume() const
{
return fDefaultMenuVolume;
}
float UCustomGameSettings::GetMasterVolume() const
{
return fMasterVolume;
}
float UCustomGameSettings::GetMusicVolume() const
{
return fMusicVolume;
}
float UCustomGameSettings::GetEffectsVolume() const
{
return fEffectsVolume;
}
float UCustomGameSettings::GetVoicesVolume() const
{
return fVoicesVolume;
}
float UCustomGameSettings::GetMenuVolume() const
{
return fMenuVolume;
}
void UCustomGameSettings::SetMasterVolume(float value)
{
fMasterVolume = FMath::Clamp(value, 0.0f, 1.0f);
}
void UCustomGameSettings::SetMusicVolume(float value)
{
fMusicVolume = FMath::Clamp(value, 0.0f, 1.0f);
}
void UCustomGameSettings::SetEffectsVolume(float value)
{
fEffectsVolume = FMath::Clamp(value, 0.0f, 1.0f);
}
void UCustomGameSettings::SetVoicesVolume(float value)
{
fVoicesVolume = FMath::Clamp(value, 0.0f, 1.0f);
}
void UCustomGameSettings::SetMenuVolume(float value)
{
fMenuVolume = FMath::Clamp(value, 0.0f, 1.0f);
}
/** Game */
inline float UCustomGameSettings::GetDefaultMouseSensetivity() const
{
return fDefaultMouseSensetivity;
}
float UCustomGameSettings::GetMouseSensetivity() const
{
return fMouseSensetivity;
}
void UCustomGameSettings::SetMouseSensetivity(float value)
{
fMouseSensetivity = FMath::Clamp(value, 0.1f, 2.0f);
}
float UCustomGameSettings::GetMouseSensetivity() const
inline bool UCustomGameSettings::GetDefaultMouseInverted() const
{
return fMouseSensetivity;
return bDefaultMouseInverted;
}

View File

@ -10,40 +10,108 @@
* Manages custom game settings.
* Mouse sensetivity and inversion, motion blur usage, fps show.
*/
UCLASS(Config = Game, defaultconfig)
UCLASS(defaultconfig)
class UCustomGameSettings : public UGameUserSettings
{
GENERATED_UCLASS_BODY()
GENERATED_BODY()
friend class UGraphicsSettingsHelper;
public:
// Is auto defined by UE but implementation is in cpp
//UCustomGameSettings(const FObjectInitializer& ObjectInitializer);
UCustomGameSettings(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintPure, Category = Settings, meta = (DisplayName = "Get Custom Game Settings"))
UFUNCTION(BlueprintPure, Category = "Settings", meta = (DisplayName = "Get Custom Game Settings"))
static UCustomGameSettings* Get();
virtual void LoadSettings(bool bForceReload = false) override;
virtual void ApplySettings(bool bCheckForCommandLineOverrides) override;
/** Graphics */
UFUNCTION(BlueprintPure, Category = "Settings|Graphics")
LOST_EDGE_API inline bool GetDefaultShowFps() const;
UPROPERTY(Config, BlueprintReadWrite, Category = "Settings|Graphics")
bool bShowFps;
/**
* Audio
* All values are clamped in [0.0 - 1.0]
*/
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
LOST_EDGE_API inline float GetDefaultMasterVolume() const; // UFUNCTION doesn't support constexpr functions
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
LOST_EDGE_API inline float GetDefaultMusicVolume() const; // UFUNCTION doesn't support constexpr functions
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
LOST_EDGE_API inline float GetDefaultEffectsVolume() const; // UFUNCTION doesn't support constexpr functions
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
LOST_EDGE_API inline float GetDefaultVoicesVolume() const; // UFUNCTION doesn't support constexpr functions
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
LOST_EDGE_API inline float GetDefaultMenuVolume() const; // UFUNCTION doesn't support constexpr functions
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
float GetMasterVolume() const;
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
float GetMusicVolume() const;
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
float GetEffectsVolume() const;
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
float GetVoicesVolume() const;
UFUNCTION(BlueprintPure, Category = "Settings|Audio")
float GetMenuVolume() const;
UFUNCTION(BlueprintCallable, Category = "Settings|Audio")
void SetMasterVolume(float value);
UFUNCTION(BlueprintCallable, Category = "Settings|Audio")
void SetMusicVolume(float value);
UFUNCTION(BlueprintCallable, Category = "Settings|Audio")
void SetEffectsVolume(float value);
UFUNCTION(BlueprintCallable, Category = "Settings|Audio")
void SetVoicesVolume(float value);
UFUNCTION(BlueprintCallable, Category = "Settings|Audio")
void SetMenuVolume(float value);
/** Game */
UFUNCTION(BlueprintPure, Category = "Settings|Game")
LOST_EDGE_API inline float GetDefaultMouseSensetivity() const;
/** Returns mouse sensetivity multiplier in [0.1 - 2.0] */
UFUNCTION(BlueprintPure, Category = "Settings|Game")
float GetMouseSensetivity() const;
/**
* Sets mouse sensetivity multiplier
* @param value [0.1 - 2.0]
*/
UFUNCTION(BlueprintCallable, Category = Settings)
UFUNCTION(BlueprintCallable, Category = "Settings|Game")
void SetMouseSensetivity(float value);
/** Returns mouse sensetivity multiplier in [0.1 - 2.0] */
UFUNCTION(BlueprintCallable, Category = Settings)
float GetMouseSensetivity() const;
UPROPERTY(Config, BlueprintReadWrite)
bool bUseMotionBlur;
UPROPERTY(Config, BlueprintReadWrite)
bool bShowFps;
UPROPERTY(Config, BlueprintReadWrite)
UFUNCTION(BlueprintPure, Category = "Settings|Game")
LOST_EDGE_API inline bool GetDefaultMouseInverted() const;
UPROPERTY(Config, BlueprintReadWrite, Category = "Settings|Game")
bool bMouseInverted;
protected:
/** Graphics */
UPROPERTY(Config)
int32 eAntiAliasingMethod;
/** Audio */
UPROPERTY(Config)
float fMasterVolume;
UPROPERTY(Config)
float fMusicVolume;
UPROPERTY(Config)
float fEffectsVolume;
UPROPERTY(Config)
float fVoicesVolume;
UPROPERTY(Config)
float fMenuVolume;
/** Game */
UPROPERTY(Config)
float fMouseSensetivity;
};

View File

@ -33,6 +33,13 @@ void ACustomPlayerController::AppendInputContext(TSoftObjectPtr<class UInputMapp
subsystem->AddMappingContext(context.LoadSynchronous(), 0);
}
void ACustomPlayerController::ApplyMouseSettings()
{
if(auto settings = UCustomGameSettings::Get())
for(auto& context : contexts)
ApplyMouseSettings(context, settings);
}
void ACustomPlayerController::BeginPlay()
{
Super::BeginPlay();
@ -71,15 +78,19 @@ void ACustomPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason)
Super::EndPlay(EndPlayReason);
}
void ACustomPlayerController::ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context)
void ACustomPlayerController::ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context, UCustomGameSettings* settings)
{
auto gameSettings = UCustomGameSettings::Get();
if(!gameSettings)
return;
if(!settings)
{
settings = UCustomGameSettings::Get();
if(!settings)
return;
}
if(!context.LoadSynchronous())
return;
bool contextChanged = false;
for(auto& mapping : context.LoadSynchronous()->GetMappings())
{
if(mapping.Key != EKeys::Mouse2D)
@ -87,20 +98,27 @@ void ACustomPlayerController::ApplyMouseSettings(TSoftObjectPtr<class UInputMapp
for(auto& modifier : mapping.Modifiers)
{
if(gameSettings->bMouseInverted)
if(auto negate_modifier = Cast<UInputModifierNegate>(modifier))
{
if(auto negate_modifier = Cast<UInputModifierNegate>(modifier))
{
negate_modifier->bY = !negate_modifier->bY;
continue;
}
negate_modifier->bY = !settings->bMouseInverted;
contextChanged = true;
}
else if(auto scalar_modifier = Cast<UInputModifierScalar>(modifier))
{
scalar_modifier->Scalar = FVector{ settings->GetMouseSensetivity() };
contextChanged = true;
}
if(auto scalar_modifier = Cast<UInputModifierScalar>(modifier))
scalar_modifier->Scalar = FVector{ gameSettings->GetMouseSensetivity() * 0.5 };
}
}
UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext(context.LoadSynchronous());
if(contextChanged)
{
if(subsystem)
{
FModifyContextOptions options;
subsystem->RequestRebuildControlMappings(options, EInputMappingRebuildType::RebuildWithFlush);
}
}
}
void ACustomPlayerController::OnAnyKeyPressed(FKey key)

View File

@ -30,6 +30,10 @@ public:
UFUNCTION(BlueprintCallable)
static void AppendInputContext(TSoftObjectPtr<class UInputMappingContext> context);
/** Applies mouse settings to all loaded contexts */
UFUNCTION(BlueprintCallable)
static void ApplyMouseSettings();
FPlayerAnyKeyPressedDelegate onAnyKeyPressed;
FPlayerAnyKeyReleasedDelegate onAnyKeyReleased;
@ -38,7 +42,8 @@ protected:
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
private:
static void ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context);
/** Applies mouse settings to the specific context */
static void ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context, class UCustomGameSettings* settings = nullptr);
void OnAnyKeyPressed(FKey key);
void OnAnyKeyReleased(FKey key);

View File

@ -0,0 +1,514 @@
// Oleg Petruny proprietary.
#include "GraphicsSettingsHelper.h"
#include "GenericPlatform/GenericApplication.h"
#include "CommonFunctions.h"
#include "CommonTexts.h"
#include "CustomGameSettings.h"
#include <optional>
namespace
{
const FIntPoint ipDefaultWindowPosition = { 0, 0 };
std::optional<FIntPoint> ipPreviousWindowPosition;
constexpr int32 iDefaultMonitorId = 0;
const FIntPoint ipDefaultResolution = { 1920, 1080 };
std::optional<FIntPoint> ipPreviousResolution;
constexpr float fDefaultResolutionScale = 100.0f;
constexpr int32 iDefaultFrameRateLimit = 120;
constexpr EDisplayMode eDefaultDisplayMode = EDisplayMode::Fullscreen;
std::optional<EDisplayMode> ePreviousDisplayMode;
constexpr bool bDefaultVSyncEnabled = false;
constexpr int32 eDefaultAntiAliasingMethod = static_cast<int32>(ELostEdgeAntiAliasingMethod::FXAA);
}
bool UGraphicsSettingsHelper::AreSettingsRestorable(UCustomGameSettings* settings)
{
return ipPreviousWindowPosition.has_value()
|| ipPreviousResolution.has_value()
|| ePreviousDisplayMode.has_value();
}
void UGraphicsSettingsHelper::RestoreGraphicsSettings(UCustomGameSettings* settings)
{
if(ipPreviousWindowPosition.has_value())
SetWindowPosition(settings, ipPreviousWindowPosition.value());
if(ipPreviousResolution.has_value())
SetResolution(settings, ipPreviousResolution.value());
if(ePreviousDisplayMode.has_value())
SetDisplayMode(settings, ePreviousDisplayMode.value());
}
void UGraphicsSettingsHelper::SetDefaults(UCustomGameSettings* settings)
{
{
FIntPoint pos = GetDefaultWindowPosition(settings);
settings->WindowPosX = pos.X;
settings->WindowPosY = pos.Y;
}
{
FIntPoint res = GetDefaultResolution(settings);
settings->ResolutionSizeX = res.X;
settings->ResolutionSizeY = res.Y;
}
settings->bUseDynamicResolution = true;
settings->FrameRateLimit = GetDefaultFrameRateLimit(settings);
settings->SetResolutionScaleValueEx(fDefaultResolutionScale);
settings->FullscreenMode = DisplayToWindowMode(GetDefaultDisplayMode(settings));
settings->eAntiAliasingMethod = eDefaultAntiAliasingMethod;
}
void UGraphicsSettingsHelper::ApplySettings(UCustomGameSettings* settings)
{
if(!settings)
return;
if(GEngine && GEngine->GameViewport)
if(auto window = GEngine->GameViewport->GetWindow())
window->MoveWindowTo(settings->GetWindowPosition());
GEngine->Exec(UCustomGameSettings::Get()->GetWorld(), *FString::Printf(TEXT("r.AntiAliasingMethod %d"), settings->eAntiAliasingMethod));
}
FIntPoint UGraphicsSettingsHelper::GetDefaultWindowPosition([[maybe_unused]] UCustomGameSettings* settings)
{
return ipDefaultWindowPosition;
}
FIntPoint UGraphicsSettingsHelper::GetWindowPosition([[maybe_unused]] UCustomGameSettings* settings)
{
if(GEngine && GEngine->GameViewport)
{
if(auto window = GEngine->GameViewport->GetWindow())
{
auto pos = window->GetPositionInScreen();
return { (int32)pos.X, (int32)pos.Y };
}
}
return GetDefaultWindowPosition(settings);
}
void UGraphicsSettingsHelper::SetWindowPosition(UCustomGameSettings* settings, const FIntPoint& pos)
{
if(settings)
{
if(ipPreviousWindowPosition == pos)
ipPreviousWindowPosition.reset();
else
ipPreviousWindowPosition = GetWindowPosition(settings);
settings->SetWindowPosition(pos.X, pos.Y);
}
}
void UGraphicsSettingsHelper::RestoreWindowPosition(UCustomGameSettings* settings)
{
if(!ipPreviousWindowPosition.has_value())
return;
SetWindowPosition(settings, ipPreviousWindowPosition.value());
}
int32 UGraphicsSettingsHelper::GetDefaultMonitorId([[maybe_unused]] UCustomGameSettings* settings)
{
return iDefaultMonitorId;
}
int32 UGraphicsSettingsHelper::GetMonitorId([[maybe_unused]] UCustomGameSettings* settings)
{
int32 currentWidth = 0;
if(GEngine && GEngine->GameViewport)
currentWidth = GEngine->GameViewport->GetWindow()->GetPositionInScreen().X;
auto monitors = GetAvailableMonitors();
int32 i = 0;
for(; i < monitors.Num(); ++i)
{
if(currentWidth <= monitors[i].NativeWidth)
return i;
else
currentWidth -= monitors[i].NativeWidth;
}
return GetDefaultMonitorId(settings);
}
int32 UGraphicsSettingsHelper::GetPrimaryMonitorId()
{
auto monitors = GetAvailableMonitors();
for(int32 i = 0; i < monitors.Num(); i++)
if(monitors[i].bIsPrimary)
return i;
return GetDefaultMonitorId(nullptr);
}
TArray<FString> UGraphicsSettingsHelper::GetAvailableMonitorsNames()
{
auto monitors = GetAvailableMonitors();
TArray<FString> names;
names.Reserve(monitors.Num());
for(int32 i = 0; i < monitors.Num(); ++i)
names.Add(FString::Printf(TEXT("%d - %s"), i + 1, *monitors[i].Name));
return MoveTemp(names);
}
TArray<FMonitorInfo> UGraphicsSettingsHelper::GetAvailableMonitors()
{
FDisplayMetrics FDM;
FDisplayMetrics::RebuildDisplayMetrics(FDM);
return MoveTemp(FDM.MonitorInfo);
}
void UGraphicsSettingsHelper::SetMonitor(UCustomGameSettings* settings, const int32 id)
{
auto monitors = GetAvailableMonitors();
if(id >= monitors.Num())
return;
int32 windowNewX = 0.0f;
for(int32 i = 0; i < id; ++i)
windowNewX += monitors[i].NativeWidth;
FIntPoint currentRes = GEngine->GameViewport->Viewport->GetSizeXY();
FIntPoint nativeRes = FIntPoint{ monitors[id].NativeWidth, monitors[id].NativeHeight };
SetWindowPosition(settings, FIntPoint{
(nativeRes.X - currentRes.X) / 2 + windowNewX,
(nativeRes.Y - currentRes.Y) / 2
});
}
void UGraphicsSettingsHelper::RestoreMonitor(UCustomGameSettings* settings)
{
RestoreWindowPosition(settings);
}
FIntPoint UGraphicsSettingsHelper::GetDefaultResolution([[maybe_unused]] UCustomGameSettings* settings)
{
return ipDefaultResolution;
}
FIntPoint UGraphicsSettingsHelper::GetResolution([[maybe_unused]] UCustomGameSettings* settings)
{
if(GEngine
&& GEngine->GameViewport
&& GEngine->GameViewport->Viewport)
return GEngine->GameViewport->Viewport->GetSizeXY();
return GetNativeResolutionByMonitorId(GetMonitorId(settings));
}
FIntPoint UGraphicsSettingsHelper::GetNativeResolutionByMonitorId(const int32 id)
{
auto monitors = GetAvailableMonitors();
if(id < monitors.Num())
return { monitors[id].NativeWidth, monitors[id].NativeHeight };
return GetDefaultResolution(nullptr);
}
TArray<FResolutionAndRefreshRates> UGraphicsSettingsHelper::GetAllAvailableResolutionsAndRefreshRates()
{
TArray<FScreenResolutionRHI> buffer;
if(!RHIGetAvailableResolutions(buffer, false) || buffer.Num() == 0)
return { {GetResolution(nullptr), {GetDefaultFrameRateLimit(nullptr)}} };
TArray<FResolutionAndRefreshRates> result;
int32 lastWidth = 0;
int32 lastHeight = 0;
FIntPoint currentResolution = GetResolution(nullptr);
bool currentInfoPresent = false;
for(auto& i : buffer)
{
if(currentResolution.X == i.Width && currentResolution.Y == i.Height)
currentInfoPresent = true;
if(lastWidth != i.Width || lastHeight != i.Height)
{
result.Add({ {static_cast<int32>(i.Width), static_cast<int32>(i.Height)}, {static_cast<int32>(i.RefreshRate)} });
lastHeight = i.Height;
lastWidth = i.Width;
}
else
{
result[result.Num() - 1].refreshRates.Add(static_cast<int32>(i.RefreshRate));
}
}
if(!currentInfoPresent)
if(auto settings = UCustomGameSettings::Get())
result.Add({ currentResolution, { static_cast<int32>(settings->GetFrameRateLimit()) } });
return MoveTemp(result);
}
TArray<FIntPoint> UGraphicsSettingsHelper::GetAllAvailableResolutions()
{
TArray<FScreenResolutionRHI> buffer;
if(!RHIGetAvailableResolutions(buffer, false) || buffer.Num() == 0)
return { {GetResolution(nullptr), {GetDefaultFrameRateLimit(nullptr)}} };
TArray<FIntPoint> result;
result.Reserve(buffer.Num() + 1);
int32 lastWidth = 0;
int32 lastHeight = 0;
for(auto& i : buffer)
{
if(lastWidth != i.Width || lastHeight != i.Height)
{
result.Add({ static_cast<int32>(i.Width), static_cast<int32>(i.Height) });
lastHeight = i.Height;
lastWidth = i.Width;
}
}
FIntPoint currentResolution = GetResolution(nullptr);
if(!result.Contains(currentResolution))
result.Add(currentResolution);
return MoveTemp(result);
}
TArray<FIntPoint> UGraphicsSettingsHelper::GetAvailableResolutionsByMonitorId(const int32 id)
{
auto resolutions = GetAllAvailableResolutions();
FIntPoint nativeRes = GetNativeResolutionByMonitorId(id);
TArray<FIntPoint> result;
result.Reserve(resolutions.Num() + 1);
for(auto& i : resolutions)
{
if(i.X > nativeRes.X && i.Y > nativeRes.Y)
continue;
result.Add(i);
}
if(id == GetMonitorId(nullptr))
{
FIntPoint currentResolution = GetResolution(nullptr);
if(!result.Contains(currentResolution))
result.Add(currentResolution);
}
return MoveTemp(result);
}
TArray<FIntPoint> UGraphicsSettingsHelper::FilterResolutionsViaAspectRatio(const TArray<FIntPoint>& resolutions, const FIntPoint& aspectRatio)
{
TArray<FIntPoint> result;
for(FIntPoint i : resolutions)
if(i.X % aspectRatio.X == 0 && i.Y % aspectRatio.Y == 0)
result.Add(i);
return MoveTemp(result);
}
void UGraphicsSettingsHelper::SetResolution(UCustomGameSettings* settings, const FIntPoint& resolution)
{
if(!settings)
return;
if(ipPreviousResolution.has_value() && ipPreviousResolution == resolution)
ipPreviousResolution.reset();
else
ipPreviousResolution = resolution;
settings->SetScreenResolution(resolution);
}
void UGraphicsSettingsHelper::RestoreResolution(UCustomGameSettings* settings)
{
if(!ipPreviousResolution.has_value())
return;
SetResolution(settings, ipPreviousResolution.value());
}
float UGraphicsSettingsHelper::GetDefaultResolutionScaleFast(UCustomGameSettings* settings)
{
return fDefaultResolutionScale;
}
int32 UGraphicsSettingsHelper::GetDefaultFrameRateLimit([[maybe_unused]] UCustomGameSettings* settings)
{
return iDefaultFrameRateLimit;
}
TArray<int32> UGraphicsSettingsHelper::GetAvailableFrameRateLimitsForResolution(const FIntPoint& resolution)
{
auto resAndRates = GetAllAvailableResolutionsAndRefreshRates();
for(auto& i : resAndRates)
{
if(i.resolution == resolution)
{
if(resolution == GetResolution(nullptr))
if(auto settings = UCustomGameSettings::Get())
if(!i.refreshRates.Contains(settings->GetFrameRateLimit()))
i.refreshRates.Add(settings->GetFrameRateLimit());
if(!i.refreshRates.Contains(GetDefaultFrameRateLimit(nullptr)))
i.refreshRates.Add(GetDefaultFrameRateLimit(nullptr));
if(!i.refreshRates.Contains(0))
i.refreshRates.Add(0);
i.refreshRates.Sort();
return MoveTemp(i.refreshRates);
}
}
return { GetDefaultFrameRateLimit(nullptr) };
}
FIntPoint UGraphicsSettingsHelper::GetDefaultAspectRatio([[maybe_unused]] UCustomGameSettings* settings)
{
return GetAspectRatioFromResolution(GetDefaultResolution(settings));
}
FIntPoint UGraphicsSettingsHelper::GetAspectRatio([[maybe_unused]] UCustomGameSettings* settings)
{
return GetAspectRatioFromResolution(GetResolution(settings));
}
FIntPoint UGraphicsSettingsHelper::GetAspectRatioFromResolution(const FIntPoint& resolution)
{
int32 gcd = UCommonFunctions::GreatestCommonDivisor(resolution.X, resolution.Y);
return { resolution.X / gcd, resolution.Y / gcd };
}
FIntPoint UGraphicsSettingsHelper::GetAspectRatioOfMonitor(const int32 monitor)
{
return GetAspectRatioFromResolution(GetNativeResolutionByMonitorId(monitor));
}
TArray<FIntPoint> UGraphicsSettingsHelper::GetAvailableAspectRatiousOfMonitor(const int32 monitor)
{
TArray<FIntPoint> resolutions = GetAvailableResolutionsByMonitorId(monitor);
if(resolutions.Num() == 0)
return { GetAspectRatio(nullptr) };
TSet<FIntPoint> aspects;
for(auto& i : resolutions)
{
aspects.Add(GetAspectRatioFromResolution(i));
UE_LOG(LogTemp, Log, TEXT("%dx%d = %dx%d"), i.X, i.Y, GetAspectRatioFromResolution(i).X, GetAspectRatioFromResolution(i).Y);
}
aspects.Add(GetAspectRatioFromResolution(GetResolution(nullptr)));
TArray<FIntPoint> result = aspects.Array();
UCommonFunctions::SortIntPointArray(result);
return MoveTemp(result);
}
EDisplayMode UGraphicsSettingsHelper::GetDefaultDisplayMode([[maybe_unused]] UCustomGameSettings* settings)
{
return eDefaultDisplayMode;
}
EDisplayMode UGraphicsSettingsHelper::GetDisplayMode(UCustomGameSettings* settings)
{
if(!settings)
return GetDefaultDisplayMode(settings);
return WindowToDisplayMode(settings->GetFullscreenMode());
}
EDisplayMode UGraphicsSettingsHelper::TextToDisplayMode(const FText& in)
{
static const UEnum* enumPtr = FindObject<UEnum>((UPackage*)-1, TEXT("EDisplayMode"), true);
if(!enumPtr)
return GetDefaultDisplayMode(nullptr);
return static_cast<EDisplayMode>(enumPtr->GetValueByName(FName{ *FTextInspector::GetSourceString(in) }));
}
FText UGraphicsSettingsHelper::DisplayModeToText(const EDisplayMode mode)
{
static const UEnum* enumPtr = FindObject<UEnum>((UPackage*)-1, TEXT("EDisplayMode"), true);
if(!enumPtr)
return CommonTexts::Default;
return enumPtr->GetDisplayNameTextByIndex(static_cast<int32>(mode));
}
void UGraphicsSettingsHelper::SetDisplayMode(UCustomGameSettings* settings, const EDisplayMode mode)
{
if(!settings)
return;
if(ePreviousDisplayMode.has_value() && ePreviousDisplayMode == mode)
ePreviousDisplayMode.reset();
else
ePreviousDisplayMode = mode;
settings->SetFullscreenMode(DisplayToWindowMode(mode));
}
void UGraphicsSettingsHelper::RestoreDisplayMode(UCustomGameSettings* settings)
{
if(!ePreviousDisplayMode.has_value())
return;
SetDisplayMode(settings, ePreviousDisplayMode.value());
}
bool UGraphicsSettingsHelper::GetDefaultVSyncEnabled(UCustomGameSettings* settings)
{
return bDefaultVSyncEnabled;
}
int32 UGraphicsSettingsHelper::GetDefaultAntiAliasingMethod(UCustomGameSettings* settings)
{
return eDefaultAntiAliasingMethod;
}
int32 UGraphicsSettingsHelper::GetAntiAliasingMethod(UCustomGameSettings* settings)
{
static const auto cvar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.AntiAliasingMethod"));
if(cvar)
return cvar->GetInt();
return -1;
}
void UGraphicsSettingsHelper::SetAntiAliasingMethod(UCustomGameSettings* settings, int32 method)
{
if(!settings)
return;
settings->eAntiAliasingMethod = FMath::Clamp(method, static_cast<int32>(ELostEdgeAntiAliasingMethod::None), static_cast<int32>(ELostEdgeAntiAliasingMethod::MSAA));
}
inline constexpr EDisplayMode UGraphicsSettingsHelper::WindowToDisplayMode(const EWindowMode::Type mode)
{
switch(mode)
{
case EWindowMode::Type::WindowedFullscreen:
return EDisplayMode::Borderless;
case EWindowMode::Type::Windowed:
return EDisplayMode::Windowed;
case EWindowMode::Type::Fullscreen:
default:
return EDisplayMode::Fullscreen;
}
}
inline constexpr EWindowMode::Type UGraphicsSettingsHelper::DisplayToWindowMode(const EDisplayMode mode)
{
switch(mode)
{
case EDisplayMode::Borderless:
return EWindowMode::Type::WindowedFullscreen;
case EDisplayMode::Windowed:
return EWindowMode::Type::Windowed;
case EDisplayMode::Fullscreen:
default:
return EWindowMode::Type::Fullscreen;
}
}

View File

@ -0,0 +1,149 @@
// Oleg Petruny proprietary.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GraphicsSettingsHelper.generated.h"
USTRUCT(BlueprintType, Category = "Settings|Graphics|Structs")
struct FResolutionAndRefreshRates
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FIntPoint resolution;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<int32> refreshRates;
};
/** Redefine of EWindowType, because it has duplicate without blueprint macro */
UENUM(BlueprintType, Category = "Settings|Graphics|Enums")
enum class EDisplayMode : uint8
{
Fullscreen = 0 UMETA(DisplayName = "Fullscreen"),
Borderless = 1 UMETA(DisplayName = "Borderless"),
Windowed = 2 UMETA(DisplayName = "Windowed")
};
UENUM(BlueprintType)
enum class ELostEdgeAntiAliasingMethod : uint8
{
None = AAM_None UMETA(DisplayName = "None"),
FXAA = AAM_FXAA UMETA(DisplayName = "FXAA"),
TAA = AAM_TemporalAA UMETA(DisplayName = "TAA"),
MSAA = AAM_MSAA UMETA(DisplayName = "MSAA")
};
/**
* Helper for trivial and complex graphic settings.
* Most of functions work without settings pointer. It is there just for Blueprint call convinience.
* Helps with window position, monitor selection, resolution, resolution scale, frame rate limit, aspect ratio, display mode.
*
*/
UCLASS()
class UGraphicsSettingsHelper : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintPure, Category = "Settings|Graphics", meta = (DisplayName = "Are Graphics Settings Restorable"))
static bool AreSettingsRestorable(class UCustomGameSettings* settings);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics")
static void RestoreGraphicsSettings(class UCustomGameSettings* settings);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics", meta = (DisplayName = "Set Graphics Defaults"))
static void SetDefaults(class UCustomGameSettings* settings);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics", meta = (DisplayName = "Apply Graphics Settings"))
static void ApplySettings(class UCustomGameSettings* settings);
protected: // Window position setting is on the thin edge of user safeness, therefore protected. Please use SetMonitor().
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Window")
static FIntPoint GetDefaultWindowPosition(class UCustomGameSettings* settings); // inline functions need API macro, but API macro with static inline function results in "no definition"
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Window")
static FIntPoint GetWindowPosition(class UCustomGameSettings* settings);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Window")
static void SetWindowPosition(class UCustomGameSettings* settings, const FIntPoint& pos);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Window")
static void RestoreWindowPosition(class UCustomGameSettings* settings);
public:
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Monitor")
static int32 GetDefaultMonitorId(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Monitor")
static int32 GetMonitorId(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Monitor")
static int32 GetPrimaryMonitorId();
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Monitor")
static TArray<FString> GetAvailableMonitorsNames();
static TArray<FMonitorInfo> GetAvailableMonitors();
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Monitor")
static void SetMonitor(class UCustomGameSettings* settings, const int32 id);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Monitor")
static void RestoreMonitor(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
static FIntPoint GetDefaultResolution(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
static FIntPoint GetResolution(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
static FIntPoint GetNativeResolutionByMonitorId(const int32 id);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics")
static TArray<FResolutionAndRefreshRates> GetAllAvailableResolutionsAndRefreshRates();
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
static TArray<FIntPoint> GetAllAvailableResolutions();
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution")
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(BlueprintCallable, Category = "Settings|Graphics|Resolution")
static void SetResolution(class UCustomGameSettings* settings, const FIntPoint& resolution);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Resolution")
static void RestoreResolution(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Resolution Scale")
static float GetDefaultResolutionScaleFast(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Frame Rate Limit")
static int32 GetDefaultFrameRateLimit(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Frame Rate Limit")
static TArray<int32> GetAvailableFrameRateLimitsForResolution(const FIntPoint& resolution);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Aspect Ratio")
static FIntPoint GetDefaultAspectRatio(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Aspect Ratio")
static FIntPoint GetAspectRatio(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Aspect Ratio")
static FIntPoint GetAspectRatioFromResolution(const FIntPoint& resolution);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Aspect Ratio")
static FIntPoint GetAspectRatioOfMonitor(const int32 monitor);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Aspect Ratio")
static TArray<FIntPoint> GetAvailableAspectRatiousOfMonitor(const int32 monitor);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Display Mode")
static EDisplayMode GetDefaultDisplayMode(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Display Mode")
static EDisplayMode GetDisplayMode(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Display Mode")
static EDisplayMode TextToDisplayMode(const FText& in);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Display Mode")
static FText DisplayModeToText(const EDisplayMode mode);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Display Mode")
static void SetDisplayMode(class UCustomGameSettings* settings, const EDisplayMode mode);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Display Mode")
static void RestoreDisplayMode(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|VSync")
static bool GetDefaultVSyncEnabled(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Anti Aliasing")
static int32 GetDefaultAntiAliasingMethod(class UCustomGameSettings* settings);
UFUNCTION(BlueprintPure, Category = "Settings|Graphics|Anti Aliasing")
static int32 GetAntiAliasingMethod(class UCustomGameSettings* settings);
UFUNCTION(BlueprintCallable, Category = "Settings|Graphics|Anti Aliasing")
static void SetAntiAliasingMethod(class UCustomGameSettings* settings, int32 method);
private:
inline constexpr static EDisplayMode WindowToDisplayMode(const EWindowMode::Type mode);
inline constexpr static EWindowMode::Type DisplayToWindowMode(const EDisplayMode mode);
};

View File

@ -85,12 +85,6 @@ void APlayerBase::BeginPlay()
cameraManager->ViewPitchMax = maxPitch;
}
auto gameSettings = UCustomGameSettings::Get();
if(gameSettings && camera)
{
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
LoadInteractablesActivators();
}
@ -371,16 +365,22 @@ void APlayerBase::ShowMenu()
if(GetWorld()->IsPaused())
{
WM->HideMainMenu();
playerController->SetShowMouseCursor(false);
playerController->SetInputMode(FInputModeGameOnly{});
if(auto PC = ACustomPlayerController::Get())
{
PC->SetShowMouseCursor(false);
PC->SetInputMode(FInputModeGameOnly{});
}
UnlockPlayer(FPlayerLock::All());
UGameplayStatics::SetGamePaused(GetWorld(), false);
}
else
{
WM->ShowMainMenu();
playerController->SetShowMouseCursor(true);
playerController->SetInputMode(FInputModeGameAndUI{});
if(auto PC = ACustomPlayerController::Get())
{
PC->SetShowMouseCursor(true);
PC->SetInputMode(FInputModeGameAndUI{});
}
LockPlayer(FPlayerLock::All());
UGameplayStatics::SetGamePaused(GetWorld(), true);
}

View File

@ -113,7 +113,6 @@ protected:
UFUNCTION(BlueprintCallable, Category = Character)
void ShowMenu();
class APlayerController* playerController;
UPROPERTY(EditAnywhere)
float moveSpeed = 200;
UPROPERTY(EditAnywhere)

View File

@ -0,0 +1,62 @@
// Oleg Petruny proprietary.
#include "ComboBoxText.h"
void UComboBoxText::PostInitProperties()
{
Super::PostInitProperties();
SetOptionsAsText(_DefaultOptions);
_DefaultOptions.Empty();
OnSelectionChanged.AddDynamic(this, &UComboBoxText::UpdateButtonPadding);
auto& style = GetWidgetStyle();
buttonNormalLeftPadding = style.ComboButtonStyle.ButtonStyle.NormalPadding.Left;
buttonPressedLeftPadding = style.ComboButtonStyle.ButtonStyle.PressedPadding.Left;
}
void UComboBoxText::SetOptionsAsText(const TArray<FText>& options)
{
ClearSelection();
Options.Empty(options.Num());
for(auto& o : options)
Options.Add(MakeShareable(new FString(o.ToString())));
RefreshOptions();
PostOptionsSet();
}
void UComboBoxText::SetOptionsAsString(const TArray<FString>& options)
{
ClearSelection();
Options.Empty(options.Num());
for(auto& o : options)
Options.Add(MakeShareable(new FString(o)));
RefreshOptions();
PostOptionsSet();
}
TArray<FString> UComboBoxText::GetOptions()
{
TArray<FString> result;
result.Reserve(Options.Num());
for(auto& o : Options)
result.Add(*o);
return MoveTemp(result);
}
void UComboBoxText::PostOptionsSet()
{
longestCharCount = 0;
for(auto& o : Options)
if(o->Len() > longestCharCount)
longestCharCount = o->Len();
}
void UComboBoxText::UpdateButtonPadding(FString SelectedItem, ESelectInfo::Type SelectionType)
{
const int32 len = longestCharCount - SelectedItem.Len();
auto style = GetWidgetStyle();
float padding = GetFont().Size * (static_cast<float>(len));
style.ComboButtonStyle.ButtonStyle.NormalPadding.Left = padding + buttonNormalLeftPadding;
style.ComboButtonStyle.ButtonStyle.PressedPadding.Left = padding + buttonPressedLeftPadding;
SetWidgetStyle(style);
}

View File

@ -0,0 +1,36 @@
// Oleg Petruny proprietary.
#pragma once
#include "Components/ComboBoxString.h"
#include "ComboBoxText.generated.h"
UCLASS(Blueprintable, meta = (DisplayName = "ComboBox (Text)"), MinimalAPI)
class UComboBoxText : public UComboBoxString
{
GENERATED_BODY()
public:
virtual void PostInitProperties() override;
UFUNCTION(BlueprintCallable)
void SetOptionsAsText(const TArray<FText>& options);
UFUNCTION(BlueprintCallable)
void SetOptionsAsString(const TArray<FString>& options);
UFUNCTION(BlueprintPure)
TArray<FString> GetOptions();
protected:
void PostOptionsSet();
UFUNCTION()
void UpdateButtonPadding(FString SelectedItem, ESelectInfo::Type SelectionType);
UPROPERTY(EditAnywhere, Category = ComboBoxTextDefault)
TArray<FText> _DefaultOptions;
int32 longestCharCount;
float buttonNormalLeftPadding, buttonPressedLeftPadding;
};

View File

@ -11,16 +11,6 @@
bool UMainMenuWidget::Initialize()
{
if(ButtonLoadLastSave)
{
auto GI = UCustomGameInstance::Get();
if(GI && GI->saveData)
{
ButtonLoadLastSave->SetIsEnabled(true);
ButtonLoadLastSave->SetRenderOpacity(1.0f);
}
}
//FWidgetAnimationDynamicEvent closeFinished;
//closeFinished.BindDynamic(this, &UMainMenuWidget::Closed);
//BindToAnimationFinished(closeAnimation, closeFinished);

View File

@ -30,24 +30,9 @@ public:
UPROPERTY(BlueprintAssignable)
FMainMenuClosedDelegate OnMainMenuClosedDelegate;
UPROPERTY(meta = (BindWidget))
class UMainMenuButtonWidget* ButtonContinue;
UPROPERTY(meta = (BindWidget))
class UMainMenuButtonWidget* ButtonLoadLastSave;
UPROPERTY(meta = (BindWidget))
class UMainMenuButtonWidget* ButtonNewGame;
UPROPERTY(meta = (BindWidget))
class UMainMenuButtonWidget* ButtonOptions;
UPROPERTY(meta = (BindWidget))
class UMainMenuButtonWidget* ButtonCredits;
UPROPERTY(meta = (BindWidget))
class UMainMenuButtonWidget* ButtonExit;
UPROPERTY(Transient, meta = (BindWidgetAnim))
class UWidgetAnimation* showFullAnimation;
UPROPERTY(Transient, meta = (BindWidgetAnim))
class UWidgetAnimation* showFastAnimation;
UPROPERTY(Transient, meta = (BindWidgetAnim))
UPROPERTY(BlueprintReadOnly, Transient, meta = (BindWidgetAnim))
class UWidgetAnimation* extendAnimation;
UPROPERTY(BlueprintReadOnly, Transient, meta = (BindWidgetAnim))
class UWidgetAnimation* closeAnimation;
protected:

View File

@ -3,6 +3,7 @@
#include "ResolutionResponsiveWidget.h"
#include "Components/PanelSlot.h"
#include "GraphicsSettingsHelper.h"
#include "UnrealClient.h"
bool UResolutionResponsiveWidget::Initialize()

View File

@ -10,6 +10,7 @@
#include "UObject/ScriptInterface.h"
#include "CustomGameInstance.h"
#include "CustomGameSettings.h"
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "Interactable/Modificators/InventoryInteractableModificator.h"
@ -98,6 +99,12 @@ void UWidgetsManager::Init()
journalWidget->SetVisibility(ESlateVisibility::Hidden);
journalWidget->AddToViewport();
}
if(auto settings = UCustomGameSettings::Get())
{
if(settings->bShowFps)
ShowFpsCount();
}
}
}
@ -156,6 +163,27 @@ void UWidgetsManager::HideMainMenu()
void UWidgetsManager::ShowFpsCount()
{
if(fpsCountWidget)
return;
if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
fpsCountWidget = CreateWidget<UUserWidget>(PC, fpsCountWidgetClass);
fpsCountWidget->AddToViewport();
}
void UWidgetsManager::HideFpsCount()
{
if(!fpsCountWidget)
return;
fpsCountWidget->RemoveFromViewport();
fpsCountWidget = nullptr;
}
void UWidgetsManager::ShowInteractionHints(const UInteractableModificator* modificator)
{
if(interactableHintWidgetManager)

View File

@ -30,6 +30,9 @@ public:
void ShowMainMenu(bool pause = true);
void HideMainMenu();
void ShowFpsCount();
void HideFpsCount();
UFUNCTION(BlueprintCallable, Category = WidgetsManager)
void ShowInteractionHints(const class UInteractableModificator* modificator = nullptr);
UFUNCTION(BlueprintCallable, Category = WidgetsManager)
@ -70,6 +73,10 @@ protected:
TSubclassOf<class UMainMenuWidget> mainMenuWidgetClass;
class UMainMenuWidget* mainMenuWidget = nullptr;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UUserWidget> fpsCountWidgetClass;
class UUserWidget* fpsCountWidget = nullptr;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidgetManager> interactableHintWidgetManagerClass; // hidden in cutscene
class UInteractableHintWidgetManager* interactableHintWidgetManager = nullptr;