This commit is contained in:
Jordon Brooks 2024-05-16 01:39:54 +01:00
parent 3f43bdb16b
commit 80ea24a694
Signed by: jordon
GPG key ID: DBD9758CD53E786A
2 changed files with 125 additions and 57 deletions

View file

@ -8,7 +8,6 @@
#include "GameFramework/GameUserSettings.h" #include "GameFramework/GameUserSettings.h"
UHarmonyLinkGraphics* UHarmonyLinkGraphics::_INSTANCE = nullptr; UHarmonyLinkGraphics* UHarmonyLinkGraphics::_INSTANCE = nullptr;
FString UHarmonyLinkGraphics::_IniLocation = "HarmonyLink";
int32 UHarmonyLinkGraphics::_TickRate = 1; int32 UHarmonyLinkGraphics::_TickRate = 1;
TMap<FName, TMap<FName, FHLConfigValue>> UHarmonyLinkGraphics::_DefaultSettings = { TMap<FName, TMap<FName, FHLConfigValue>> UHarmonyLinkGraphics::_DefaultSettings = {
@ -38,6 +37,7 @@ UHarmonyLinkGraphics::UHarmonyLinkGraphics()
_bAutomaticSwitch = true; _bAutomaticSwitch = true;
FWorldDelegates::OnPostWorldInitialization.AddUObject(this, &UHarmonyLinkGraphics::OnPostWorldInitialization); FWorldDelegates::OnPostWorldInitialization.AddUObject(this, &UHarmonyLinkGraphics::OnPostWorldInitialization);
FWorldDelegates::OnPreWorldFinishDestroy.AddUObject(this, &UHarmonyLinkGraphics::OnWorldEnd);
} }
UHarmonyLinkGraphics::~UHarmonyLinkGraphics() UHarmonyLinkGraphics::~UHarmonyLinkGraphics()
@ -64,7 +64,7 @@ bool UHarmonyLinkGraphics::LoadSettingsFromConfig()
// Load the configuration from the INI file // Load the configuration from the INI file
FConfigFile ConfigFile; FConfigFile ConfigFile;
const FString Filename = GetDefaultConfigFilename(); const FString Filename = GetConfigDirectoryFile();
if (!GConfig) if (!GConfig)
{ {
@ -158,7 +158,7 @@ void UHarmonyLinkGraphics::SaveConfig() const
SaveSection(Profile.Value); SaveSection(Profile.Value);
} }
const FString Filename = GetDefaultConfigFilename(); const FString Filename = GetConfigDirectoryFile();
UE_LOG(LogHarmonyLink, Log, TEXT("Flushing file: '%s'"), *Filename); UE_LOG(LogHarmonyLink, Log, TEXT("Flushing file: '%s'"), *Filename);
GConfig->Flush(false, Filename); GConfig->Flush(false, Filename);
} }
@ -272,7 +272,9 @@ void UHarmonyLinkGraphics::DestroySettings()
{ {
if (_INSTANCE) if (_INSTANCE)
{ {
UE_LOG(LogHarmonyLink, Log, TEXT("Destroying UHarmonyLinkGraphics."))
FWorldDelegates::OnPostWorldInitialization.RemoveAll(_INSTANCE); FWorldDelegates::OnPostWorldInitialization.RemoveAll(_INSTANCE);
FWorldDelegates::OnPreWorldFinishDestroy.RemoveAll(_INSTANCE);
_INSTANCE->RemoveFromRoot(); _INSTANCE->RemoveFromRoot();
_INSTANCE->MarkAsGarbage(); _INSTANCE->MarkAsGarbage();
_INSTANCE = nullptr; _INSTANCE = nullptr;
@ -290,36 +292,54 @@ void UHarmonyLinkGraphics::Init()
// BUG: Remove this before release! // BUG: Remove this before release!
if (!BatteryStatus.HasBattery) if (!BatteryStatus.HasBattery)
{ {
ApplyProfile(EProfile::BATTERY); ApplyProfileInternal(EProfile::BATTERY);
} }
} }
void UHarmonyLinkGraphics::Tick() void UHarmonyLinkGraphics::Tick()
{ {
Async(EAsyncExecution::Thread, [this]()
{
const FBattery BatteryStatus = UHarmonyLinkLibrary::GetBatteryStatus();
if (BatteryStatus.BatteryPercent != _LastBatteryPercentage)
{
// Ensure thread-safe broadcasting
Async(EAsyncExecution::TaskGraphMainThread, [this, BatteryStatus]()
{
OnBatteryLevelChanged.Broadcast(BatteryStatus.BatteryPercent);
});
}
if (!_bAutomaticSwitch) if (!_bAutomaticSwitch)
{ {
return; return;
} }
const FBattery BatteryStatus = UHarmonyLinkLibrary::GetBatteryStatus();
if (BatteryStatus.HasBattery) if (BatteryStatus.HasBattery)
{ {
if (BatteryStatus.IsACConnected) if (BatteryStatus.IsACConnected)
{ {
if (_ActiveProfile != EProfile::CHARGING) if (_ActiveProfile != EProfile::CHARGING)
{ {
ApplyProfile(EProfile::CHARGING); Async(EAsyncExecution::TaskGraphMainThread, [this]()
{
ApplyProfileInternal(EProfile::CHARGING);
});
} }
} }
else else
{ {
if (_ActiveProfile != EProfile::BATTERY) if (_ActiveProfile != EProfile::BATTERY)
{ {
ApplyProfile(EProfile::BATTERY); Async(EAsyncExecution::TaskGraphMainThread, [this]()
{
ApplyProfileInternal(EProfile::BATTERY);
});
} }
} }
} }
});
} }
void UHarmonyLinkGraphics::CreateDefaultConfigFile() void UHarmonyLinkGraphics::CreateDefaultConfigFile()
@ -332,11 +352,22 @@ void UHarmonyLinkGraphics::CreateDefaultConfigFile()
UE_LOG(LogHarmonyLink, Log, TEXT("Default config file created.")); UE_LOG(LogHarmonyLink, Log, TEXT("Default config file created."));
} }
void UHarmonyLinkGraphics::SaveSection(FSettingsProfile& SettingsProfile, const bool bFlush) const FString UHarmonyLinkGraphics::GetConfigDirectoryFile()
{
FString ConfigFileName = "HarmonyLink.ini"; // Replace with your actual config file name
#if WITH_EDITOR
return FPaths::Combine(FPaths::ProjectSavedDir(), TEXT("Config"), ConfigFileName);
#else
return FPaths::Combine(FPaths::ProjectConfigDir(), ConfigFileName);
#endif
}
void UHarmonyLinkGraphics::SaveSection(FSettingsProfile& SettingsProfile, const bool bFlush)
{ {
if (GConfig) if (GConfig)
{ {
const FString Filename = GetDefaultConfigFilename(); const FString Filename = GetConfigDirectoryFile();
for (const auto& Setting : SettingsProfile.Settings) for (const auto& Setting : SettingsProfile.Settings)
{ {
FString TypeString; FString TypeString;
@ -396,35 +427,7 @@ void UHarmonyLinkGraphics::LoadDefaults()
} }
} }
void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS) bool UHarmonyLinkGraphics::ApplyProfileInternal(const EProfile Profile)
{
if (!World)
{
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to Hook into World Initialisation!"))
return;
}
if (World->IsGameWorld())
{
if (UHarmonyLinkGraphics* Settings = GetSettings())
{
if (World->IsPlayInEditor())
{
Settings->LoadConfig(true);
}
if (!World->GetTimerManager().TimerExists(Settings->_TickTimerHandle) || !World->GetTimerManager().IsTimerActive(Settings->_TickTimerHandle))
{
World->GetTimerManager().SetTimer(Settings->_TickTimerHandle, [Settings]
{
Settings->Tick();
}, _TickRate, true);
}
}
}
}
bool UHarmonyLinkGraphics::ApplyProfile(const EProfile Profile)
{ {
// If the profile is None, revert to the original user game settings // If the profile is None, revert to the original user game settings
if (Profile == EProfile::NONE) if (Profile == EProfile::NONE)
@ -485,6 +488,62 @@ bool UHarmonyLinkGraphics::ApplyProfile(const EProfile Profile)
return true; return true;
} }
void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS)
{
if (!World)
{
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to Hook into World Initialisation!"))
return;
}
if (World->IsGameWorld())
{
if (UHarmonyLinkGraphics* Settings = GetSettings())
{
if (World->IsPlayInEditor())
{
Settings->LoadConfig(true);
}
if (!World->GetTimerManager().TimerExists(Settings->_TickTimerHandle) || !World->GetTimerManager().IsTimerActive(Settings->_TickTimerHandle))
{
World->GetTimerManager().SetTimer(Settings->_TickTimerHandle, [Settings]
{
Settings->Tick();
}, _TickRate, true);
}
}
}
}
void UHarmonyLinkGraphics::OnWorldEnd(UWorld* World)
{
if (!World)
{
UE_LOG(LogHarmonyLink, Error, TEXT("World Already destroyed"))
return;
}
if(World->GetTimerManager().TimerExists(_TickTimerHandle))
{
World->GetTimerManager().ClearTimer(_TickTimerHandle);
}
// Ensure we safely destroy our singleton instance
DestroySettings();
}
bool UHarmonyLinkGraphics::ApplyProfile(const EProfile Profile, const bool bDisableAuto)
{
// Manual profile change, turn off automatic switching
if (bDisableAuto)
{
_bAutomaticSwitch = false;
}
return ApplyProfileInternal(Profile);
}
void UHarmonyLinkGraphics::ApplySetting(const TPair<FName, FHLConfigValue>& Setting) void UHarmonyLinkGraphics::ApplySetting(const TPair<FName, FHLConfigValue>& Setting)
{ {
// Apply the setting based on the key (CVar) // Apply the setting based on the key (CVar)

View file

@ -11,6 +11,7 @@
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProfileChanged, EProfile, Profile); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProfileChanged, EProfile, Profile);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAutomaticSwitchChanged, bool, bAutomaticSwich); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAutomaticSwitchChanged, bool, bAutomaticSwich);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnBatteryLevelChanged, int32, BatteryPercent);
/** /**
* *
@ -30,6 +31,9 @@ public:
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
FOnAutomaticSwitchChanged OnAutomaticSwitchChanged; FOnAutomaticSwitchChanged OnAutomaticSwitchChanged;
UPROPERTY(BlueprintAssignable)
FOnBatteryLevelChanged OnBatteryLevelChanged;
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings") UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
void LoadConfig(const bool bForceReload = false); void LoadConfig(const bool bForceReload = false);
@ -40,7 +44,7 @@ public:
void SetSetting(EProfile Profile, FName Setting, FHLConfigValue Value); void SetSetting(EProfile Profile, FName Setting, FHLConfigValue Value);
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings") UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
bool ApplyProfile(EProfile Profile); bool ApplyProfile(EProfile Profile, const bool bDisableAuto = true);
/** Returns the game local machine settings (resolution, windowing mode, scalability settings, etc...) */ /** Returns the game local machine settings (resolution, windowing mode, scalability settings, etc...) */
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings") UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
@ -64,25 +68,30 @@ private:
void Init(); void Init();
void Tick(); void Tick();
void CreateDefaultConfigFile(); void CreateDefaultConfigFile();
static FString GetConfigDirectoryFile();
bool LoadSettingsFromConfig(); bool LoadSettingsFromConfig();
bool LoadSection(const FConfigFile& ConfigFile, const TPair<EProfile, FName> Profile); bool LoadSection(const FConfigFile& ConfigFile, const TPair<EProfile, FName> Profile);
void SaveSection(FSettingsProfile& SettingsProfile, const bool bFlush = false) const; static void SaveSection(FSettingsProfile& SettingsProfile, const bool bFlush = false);
void LoadDefaults(); void LoadDefaults();
bool ApplyProfileInternal(EProfile Profile);
void OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS); void OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS);
void OnWorldEnd(UWorld* World);
static void ResetInstance(); static void ResetInstance();
// Note: Turning off HarmonyLink Settings requires game restart
static void ApplySetting(const TPair<FName, FHLConfigValue>& Setting); static void ApplySetting(const TPair<FName, FHLConfigValue>& Setting);
// Debugging // Debugging
void DebugPrintProfiles() const; void DebugPrintProfiles() const;
static void PrintDebugSection(FSettingsProfile& SettingsProfile); static void PrintDebugSection(FSettingsProfile& SettingsProfile);
static FString _IniLocation;
uint8 _bAutomaticSwitch :1; uint8 _bAutomaticSwitch :1;
int32 _LastBatteryPercentage = 0;
// How many times to query HarmonyLinkLib for hardware info // How many times to query HarmonyLinkLib for hardware info
static int32 _TickRate; static int32 _TickRate;